Signed-off-by: Arne Hamann <git@arne.email>
This commit is contained in:
Arne Hamann 2023-01-14 21:20:24 +01:00
Родитель f739970d9e
Коммит 81edfbc6aa
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 280879CB5E2A960B
2 изменённых файлов: 264 добавлений и 0 удалений

Просмотреть файл

@ -14,6 +14,9 @@ return [
['name' => 'page#do_echo', 'url' => '/echo', 'verb' => 'POST'],
['name' => 'page#openGeoLink', 'url' => '/openGeoLink/{url}', 'verb' => 'GET'],
['name' => 'public_favorite_page#sharedFavoritesCategory', 'url' => '/s/favorites/{token}', 'verb' => 'GET'],
['name' => 'PublicPage#showShare', 'url' => '/s/{token}', 'verb' => 'GET'],
['name' => 'PublicPage#showAuthenticate', 'url' => '/s/{token}/authenticate/{redirect}', 'verb' => 'GET'],
['name' => 'PublicPage#authenticate', 'url' => '/s/{token}/authenticate/{redirect}', 'verb' => 'POST'],
// utils
@ -21,6 +24,10 @@ return [
['name' => 'utils#saveOptionValue', 'url' => '/saveOptionValue', 'verb' => 'POST'],
['name' => 'utils#setRoutingSettings', 'url' => '/setRoutingSettings', 'verb' => 'POST'],
['name' => 'utils#getTrafficStyle', 'url' => '/style/traffic', 'verb' => 'GET'],
['name' => 'PublicUtils#getOptionsValues', 'url' => '/s/{token}/getOptionsValues', 'verb' => 'GET'],
['name' => 'PublicUtils#saveOptionValue', 'url' => '/s/{token}/saveOptionValue', 'verb' => 'POST'],
['name' => 'PublicUtils#setRoutingSettings', 'url' => '/s/{token}/setRoutingSettings', 'verb' => 'POST'],
['name' => 'PublicUtils#getTrafficStyle', 'url' => '/s/{token}/style/traffic', 'verb' => 'GET'],
// photos
['name' => 'photos#getPhotosFromDb', 'url' => '/photos', 'verb' => 'GET'],

Просмотреть файл

@ -0,0 +1,257 @@
<?php
/**
* Nextcloud - maps
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @authorVinzenz Rosenkranz <vinzenz.rosenkranz@gmail.com>
* @copyright Vinzenz Rosenkranz 2017
*/
namespace OCA\Maps\Controller;
use OC\InitialStateService;
use OC\Security\CSP\ContentSecurityPolicy;
use OCA\Files\Event\LoadSidebar;
use OCA\Files_Sharing\Event\BeforeTemplateRenderedEvent;
use OCA\Viewer\Event\LoadViewer;
use OCP\AppFramework\AuthPublicShareController;
use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
use OCP\IConfig;
use OCP\ILogger;
use OCP\IRequest;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\IInitialStateService;
use OCP\ISession;
use OCP\IURLGenerator;
use OCP\IUserManager;
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IManager as ShareManager;
class PublicPageController extends AuthPublicShareController {
protected InitialStateService $initialStateService;
protected IConfig $config;
protected ILogger $logger;
protected \OCP\Activity\IManager $activityManager;
protected IEventDispatcher $eventDispatcher;
protected ShareManager $shareManager;
protected IUserManager $userManager;
public function __construct($AppName,
IRequest $request,
IEventDispatcher $eventDispatcher,
IConfig $config,
IInitialStateService $initialStateService,
IURLGenerator $urlGenerator,
ShareManager $shareManager,
IUserManager $userManager,
ISession $session
) {
parent::__construct($AppName, $request, $session, $urlGenerator);
$this->eventDispatcher = $eventDispatcher;
$this->config = $config;
$this->initialStateService = $initialStateService;
$this->shareManager = $shareManager;
$this->userManager = $userManager;
}
public function isValidToken(): bool {
try {
$this->share = $this->shareManager->getShareByToken($this->getToken());
} catch (ShareNotFound $e) {
return false;
}
return true;
}
protected function getPasswordHash(): string {
return $this->share->getPassword();
}
protected function isPasswordProtected(): bool {
return $this->share->getPassword() !== null;
}
/**
* Validate the permissions of the share
*
* @param Share\IShare $share
* @return bool
*/
private function validateShare(\OCP\Share\IShare $share) {
// If the owner is disabled no access to the link is granted
$owner = $this->userManager->get($share->getShareOwner());
if ($owner === null || !$owner->isEnabled()) {
return false;
}
// If the initiator of the share is disabled no access is granted
$initiator = $this->userManager->get($share->getSharedBy());
if ($initiator === null || !$initiator->isEnabled()) {
return false;
}
return $share->getNode()->isReadable() && $share->getNode()->isShareable();
}
/**
* @return \OCP\Files\File|\OCP\Files\Folder
* @throws NotFoundException
*/
private function getShareNode() {
\OC_User::setIncognitoMode(true);
// Check whether share exists
try {
$share = $this->shareManager->getShareByToken($this->getToken());
} catch (ShareNotFound $e) {
// The share does not exists, we do not emit an ShareLinkAccessedEvent
throw new NotFoundException();
}
if (!$this->validateShare($share)) {
throw new NotFoundException();
}
return $share->getNode();
}
/**
* @PublicPage
* @NoCSRFRequired
*/
public function showShare(): TemplateResponse {
$shareNode = $this->getShareNode();
$this->eventDispatcher->dispatch(LoadSidebar::class, new LoadSidebar());
$this->eventDispatcher->dispatch(LoadViewer::class, new LoadViewer());
$params = array('user' => Null);
$this->initialStateService->provideInitialState($this->appName, 'photos', $this->config->getAppValue('photos', 'enabled', 'no') === 'yes');
$response = new TemplateResponse('maps', 'main', $params);
$this->addCsp($response);
return $response;
}
/**
* @PublicPage
* @NoCSRFRequired
*
* Show the authentication page
* The form has to submit to the authenticate method route
*/
public function showAuthenticate(): TemplateResponse {
$templateParameters = ['share' => $this->share];
$this->eventDispatcher->dispatchTyped(new BeforeTemplateRenderedEvent($this->share, BeforeTemplateRenderedEvent::SCOPE_PUBLIC_SHARE_AUTH));
$response = new TemplateResponse('core', 'publicshareauth', $templateParameters, 'guest');
if ($this->share->getSendPasswordByTalk()) {
$csp = new ContentSecurityPolicy();
$csp->addAllowedConnectDomain('*');
$csp->addAllowedMediaDomain('blob:');
$response->setContentSecurityPolicy($csp);
}
return $response;
}
/**
* The template to show when authentication failed
*/
protected function showAuthFailed(): TemplateResponse {
$templateParameters = ['share' => $this->share, 'wrongpw' => true];
$this->eventDispatcher->dispatchTyped(new BeforeTemplateRenderedEvent($this->share, BeforeTemplateRenderedEvent::SCOPE_PUBLIC_SHARE_AUTH));
$response = new TemplateResponse('core', 'publicshareauth', $templateParameters, 'guest');
if ($this->share->getSendPasswordByTalk()) {
$csp = new ContentSecurityPolicy();
$csp->addAllowedConnectDomain('*');
$csp->addAllowedMediaDomain('blob:');
$response->setContentSecurityPolicy($csp);
}
return $response;
}
/**
* The template to show after user identification
*/
protected function showIdentificationResult(bool $success = false): TemplateResponse {
$templateParameters = ['share' => $this->share, 'identityOk' => $success];
$this->eventDispatcher->dispatchTyped(new BeforeTemplateRenderedEvent($this->share, BeforeTemplateRenderedEvent::SCOPE_PUBLIC_SHARE_AUTH));
$response = new TemplateResponse('core', 'publicshareauth', $templateParameters, 'guest');
if ($this->share->getSendPasswordByTalk()) {
$csp = new ContentSecurityPolicy();
$csp->addAllowedConnectDomain('*');
$csp->addAllowedMediaDomain('blob:');
$response->setContentSecurityPolicy($csp);
}
return $response;
}
/**
* @param $response
* @return void
*/
private function addCsp($response): void {
if (class_exists('OCP\AppFramework\Http\ContentSecurityPolicy')) {
$csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
// map tiles
$csp->addAllowedImageDomain('https://*.tile.openstreetmap.org');
$csp->addAllowedImageDomain('https://server.arcgisonline.com');
$csp->addAllowedImageDomain('https://*.cartocdn.com');
$csp->addAllowedImageDomain('https://*.opentopomap.org');
$csp->addAllowedImageDomain('https://*.cartocdn.com');
$csp->addAllowedImageDomain('https://*.ssl.fastly.net');
$csp->addAllowedImageDomain('https://*.openstreetmap.se');
// default routing engine
$csp->addAllowedConnectDomain('https://*.project-osrm.org');
$csp->addAllowedConnectDomain('https://api.mapbox.com');
$csp->addAllowedConnectDomain('https://events.mapbox.com');
$csp->addAllowedConnectDomain('https://graphhopper.com');
$csp->addAllowedChildSrcDomain('blob:');
$csp->addAllowedWorkerSrcDomain('blob:');
$csp->addAllowedScriptDomain('https://unpkg.com');
// allow connections to custom routing engines
$urlKeys = [
'osrmBikeURL',
'osrmCarURL',
'osrmFootURL',
'graphhopperURL'
];
foreach ($urlKeys as $key) {
$url = $this->config->getAppValue('maps', $key);
if ($url !== '') {
$scheme = parse_url($url, PHP_URL_SCHEME);
$host = parse_url($url, PHP_URL_HOST);
$port = parse_url($url, PHP_URL_PORT);
$cleanUrl = $scheme . '://' . $host;
if ($port && $port !== '') {
$cleanUrl .= ':' . $port;
}
$csp->addAllowedConnectDomain($cleanUrl);
}
}
// poi images
$csp->addAllowedImageDomain('https://nominatim.openstreetmap.org');
// search and geocoder
$csp->addAllowedConnectDomain('https://nominatim.openstreetmap.org');
$response->setContentSecurityPolicy($csp);
}
}
}