diff --git a/core/AppInfo/Application.php b/core/AppInfo/Application.php index e2c56eff419a3..e02fefb4636bd 100644 --- a/core/AppInfo/Application.php +++ b/core/AppInfo/Application.php @@ -40,7 +40,6 @@ use OCP\IURLGenerator; use OCP\IUserSession; use OCP\L10N\IFactory; -use OCP\Server; use OCP\User\Events\BeforeUserDeletedEvent; use OCP\User\Events\PasswordUpdatedEvent; use OCP\User\Events\UserDeletedEvent; @@ -116,25 +115,23 @@ public function registerNavigationEntries( INavigationManager $navigationManager, IUserSession $userSession, IURLGenerator $urlGenerator, + IFactory $factory, ): void { if (!$userSession->isLoggedIn()) { return; } - $l = Server::get(IFactory::class)->get('core'); + $l = $factory->get('core'); // Register the logout button in the user settings - $logoutUrl = \OC_User::getLogoutUrl($urlGenerator); - if ($logoutUrl !== '') { - $navigationManager->add([ - 'type' => 'settings', - 'id' => 'logout', - 'order' => 99999, - 'href' => $logoutUrl, - 'name' => $l->t('Log out'), - 'icon' => $urlGenerator->imagePath('core', 'actions/logout.svg'), - ]); - } + $logoutUrl = $urlGenerator->getLogoutUrl(); + $navigationManager->add([ + 'type' => 'settings', + 'id' => 'logout', + 'order' => 99999, + 'href' => $logoutUrl, + 'name' => $l->t('Log out'), + 'icon' => $urlGenerator->imagePath('core', 'actions/logout.svg'), + ]); } - } diff --git a/lib/private/URLGenerator.php b/lib/private/URLGenerator.php index 968978ac8432e..611e70988c182 100644 --- a/lib/private/URLGenerator.php +++ b/lib/private/URLGenerator.php @@ -10,30 +10,36 @@ namespace OC; use OC\Route\Router; +use OC\Security\CSRF\CsrfTokenManager; use OCA\Theming\ThemingDefaults; use OCP\App\AppPathNotFoundException; use OCP\App\IAppManager; +use OCP\Authentication\IApacheBackend; use OCP\ICacheFactory; use OCP\IConfig; use OCP\INavigationManager; use OCP\IRequest; use OCP\IURLGenerator; +use OCP\IUser; +use OCP\IUserManager; use OCP\IUserSession; use OCP\Server; +use OCP\User\Backend\ICustomLogout; use Override; use RuntimeException; class URLGenerator implements IURLGenerator { + /** @var non-empty-string|null $baseUrl */ private ?string $baseUrl = null; private ?IAppManager $appManager = null; private ?INavigationManager $navigationManager = null; public function __construct( - private IConfig $config, + private readonly IConfig $config, public IUserSession $userSession, - private ICacheFactory $cacheFactory, - private IRequest $request, - private Router $router, + private readonly ICacheFactory $cacheFactory, + private readonly IRequest $request, + private readonly Router $router, ) { } @@ -53,28 +59,11 @@ private function getNavigationManager(): INavigationManager { return $this->navigationManager; } - /** - * Creates an url using a defined route - * - * @param string $routeName - * @param array $arguments args with param=>value, will be appended to the returned url - * @return string the url - * - * Returns a url to the given route. - */ #[\Override] public function linkToRoute(string $routeName, array $arguments = []): string { return $this->router->generate($routeName, $arguments); } - /** - * Creates an absolute url using a defined route - * @param string $routeName - * @param array $arguments args with param=>value, will be appended to the returned url - * @return string the url - * - * Returns an absolute url to the given route. - */ #[\Override] public function linkToRouteAbsolute(string $routeName, array $arguments = []): string { return $this->getAbsoluteURL($this->linkToRoute($routeName, $arguments)); @@ -104,17 +93,6 @@ public function linkToOCSRouteAbsolute(string $routeName, array $arguments = []) return $this->getAbsoluteURL($route); } - /** - * Creates an url - * - * @param string $appName app - * @param string $file file - * @param array $args array with param=>value, will be appended to the returned url - * The value of $args will be urlencoded - * @return string the url - * - * Returns a url to the given app and file. - */ #[\Override] public function linkTo(string $appName, string $file, array $args = []): string { $frontControllerActive = ($this->config->getSystemValueBool('htaccess.IgnoreFrontController', false) || getenv('front_controller_active') === 'true'); @@ -154,16 +132,6 @@ public function linkTo(string $appName, string $file, array $args = []): string return $urlLinkTo; } - /** - * Creates path to an image - * - * @param string $appName app - * @param string $file image name - * @throws \RuntimeException If the image does not exist - * @return string the url - * - * Returns the path to the image. - */ #[\Override] public function imagePath(string $appName, string $file): string { $cache = $this->cacheFactory->createDistributed('imagePath-' . md5($this->getBaseUrl()) . '-'); @@ -242,11 +210,6 @@ public function imagePath(string $appName, string $file): string { throw new RuntimeException('image not found: image:' . $file . ' webroot:' . \OC::$WEBROOT . ' serverroot:' . \OC::$SERVERROOT); } - /** - * Makes an URL absolute - * @param string $url the url in the Nextcloud host - * @return string the absolute version of the url - */ #[\Override] public function getAbsoluteURL(string $url): string { $separator = str_starts_with($url, '/') ? '' : '/'; @@ -262,21 +225,12 @@ public function getAbsoluteURL(string $url): string { return $this->getBaseUrl() . $separator . $url; } - /** - * @param string $key - * @return string url to the online documentation - */ #[\Override] public function linkToDocs(string $key): string { $theme = Server::get('ThemingDefaults'); return $theme->buildDocLinkToKey($key); } - /** - * Returns the URL of the default page based on the system configuration - * and the apps visible for the current user - * @return string - */ #[\Override] public function linkToDefaultPageUrl(): string { // Deny the redirect if the URL contains a @ @@ -308,9 +262,6 @@ public function linkToDefaultPageUrl(): string { return $this->getAbsoluteURL($href); } - /** - * @return string base url of the current request - */ #[\Override] public function getBaseUrl(): string { // BaseUrl can be equal to 'http(s)://' during the first steps of the initial setup. @@ -320,9 +271,6 @@ public function getBaseUrl(): string { return $this->baseUrl; } - /** - * @return string webroot part of the base url - */ #[\Override] public function getWebroot(): string { return \OC::$WEBROOT; @@ -335,4 +283,37 @@ public function linkToRemote(string $service): string { $remoteBase . (($service[strlen($service) - 1] !== '/') ? '/' : '') ); } + + #[Override] + public function getLogoutUrl(): string { + $apacheBackend = null; + foreach (Server::get(IUserManager::class)->getBackends() as $backend) { + if ($backend instanceof IApacheBackend) { + if ($backend->isSessionActive()) { + $apacheBackend = $backend; + break; + } + } + } + + if ($apacheBackend) { + return $apacheBackend->getLogoutUrl(); + } + + $user = $this->userSession->getUser(); + if ($user instanceof IUser) { + $backend = $user->getBackend(); + if ($backend instanceof ICustomLogout) { + $logoutUrl = $backend->getLogoutUrl(); + if ($logoutUrl !== '') { + return $logoutUrl; + } + } + } + + $logoutUrl = $this->linkToRoute('core.login.logout'); + $logoutUrl .= '?requesttoken=' . urlencode(Server::get(CsrfTokenManager::class)->getToken()->getEncryptedValue()); + + return $logoutUrl; + } } diff --git a/lib/private/User/Manager.php b/lib/private/User/Manager.php index 0c8fac6c0cb62..9a06ab03ed9a0 100644 --- a/lib/private/User/Manager.php +++ b/lib/private/User/Manager.php @@ -40,7 +40,6 @@ use OCP\UserInterface; use OCP\Util; use Psr\Log\LoggerInterface; -use RuntimeException; /** * Class Manager @@ -871,21 +870,11 @@ public function getExistingUser(string $userId, ?string $displayName = null): IU #[\Override] public function getAvatarUrlLight(string $userId, int $size): string { - $url = ($this->urlGenerator ??= Server::get(IURLGenerator::class))->linkToRouteAbsolute('core.avatar.getAvatar', ['userId' => $userId, 'size' => $size]); - if ($url === '') { - throw new RuntimeException('The URL is empty.'); - } - - return $url; + return ($this->urlGenerator ??= Server::get(IURLGenerator::class))->linkToRouteAbsolute('core.avatar.getAvatar', ['userId' => $userId, 'size' => $size]); } #[\Override] public function getAvatarUrlDark(string $userId, int $size): string { - $url = ($this->urlGenerator ??= Server::get(IURLGenerator::class))->linkToRouteAbsolute('core.avatar.getAvatarDark', ['userId' => $userId, 'size' => $size]); - if ($url === '') { - throw new RuntimeException('The URL is empty.'); - } - - return $url; + return ($this->urlGenerator ??= Server::get(IURLGenerator::class))->linkToRouteAbsolute('core.avatar.getAvatarDark', ['userId' => $userId, 'size' => $size]); } } diff --git a/lib/private/legacy/OC_User.php b/lib/private/legacy/OC_User.php index 1cc3b343832b1..fccb08a710cc6 100644 --- a/lib/private/legacy/OC_User.php +++ b/lib/private/legacy/OC_User.php @@ -6,7 +6,6 @@ * SPDX-License-Identifier: AGPL-3.0-only */ use OC\Authentication\Token\IProvider; -use OC\Security\CSRF\CsrfTokenManager; use OC\SystemConfig; use OC\User\Database; use OC\User\DisabledUserException; @@ -22,12 +21,10 @@ use OCP\IRequest; use OCP\ISession; use OCP\IURLGenerator; -use OCP\IUser; use OCP\IUserManager; use OCP\IUserSession; use OCP\Server; use OCP\Session\Exceptions\SessionNotAvailableException; -use OCP\User\Backend\ICustomLogout; use OCP\User\Events\BeforeUserLoggedInEvent; use OCP\User\Events\UserLoggedInEvent; use OCP\UserInterface; @@ -276,25 +273,10 @@ public static function isIncognitoMode(): bool { /** * Returns the current logout URL valid for the currently logged-in user + * @return non-empty-string */ public static function getLogoutUrl(IURLGenerator $urlGenerator): string { - $backend = self::findFirstActiveUsedBackend(); - if ($backend) { - return $backend->getLogoutUrl(); - } - - $user = Server::get(IUserSession::class)->getUser(); - if ($user instanceof IUser) { - $backend = $user->getBackend(); - if ($backend instanceof ICustomLogout) { - return $backend->getLogoutUrl(); - } - } - - $logoutUrl = $urlGenerator->linkToRoute('core.login.logout'); - $logoutUrl .= '?requesttoken=' . urlencode(Server::get(CsrfTokenManager::class)->getToken()->getEncryptedValue()); - - return $logoutUrl; + return $urlGenerator->getLogoutUrl(); } /** diff --git a/lib/public/Authentication/IApacheBackend.php b/lib/public/Authentication/IApacheBackend.php index 1e6b7bafa47b9..d8cbb3886a00c 100644 --- a/lib/public/Authentication/IApacheBackend.php +++ b/lib/public/Authentication/IApacheBackend.php @@ -19,23 +19,23 @@ interface IApacheBackend { /** * In case the user has been authenticated by a module true is returned. * - * @return boolean whether the module reports a user as currently logged in. + * @return bool whether the module reports a user as currently logged in. * @since 6.0.0 */ - public function isSessionActive(); + public function isSessionActive(): bool; /** * Gets the current logout URL * - * @return string + * @return non-empty-string * @since 12.0.3 */ - public function getLogoutUrl(); + public function getLogoutUrl(): string; /** * Return the id of the current user * @return string * @since 6.0.0 */ - public function getCurrentUserId(); + public function getCurrentUserId(): string; } diff --git a/lib/public/IURLGenerator.php b/lib/public/IURLGenerator.php index 46fcc6081ce81..79ebf72a04f71 100644 --- a/lib/public/IURLGenerator.php +++ b/lib/public/IURLGenerator.php @@ -40,7 +40,7 @@ interface IURLGenerator { /** * Returns the URL for a route - * @param string $routeName the name of the route + * @param non-empty-string $routeName the name of the route * @param array $arguments an array with arguments which will be filled into the url * @return string the url * @since 6.0.0 @@ -49,9 +49,9 @@ public function linkToRoute(string $routeName, array $arguments = []): string; /** * Returns the absolute URL for a route - * @param string $routeName the name of the route + * @param non-empty-string $routeName the name of the route * @param array $arguments an array with arguments which will be filled into the url - * @return string the absolute url + * @return non-empty-string the absolute url * @since 8.0.0 */ public function linkToRouteAbsolute(string $routeName, array $arguments = []): string; @@ -65,7 +65,7 @@ public function linkToRouteAbsolute(string $routeName, array $arguments = []): s public function linkToOCSRouteAbsolute(string $routeName, array $arguments = []): string; /** - * Returns an URL for an image or file + * Returns a URL for an image or file * @param string $appName the name of the app * @param string $file the name of the file * @param array $args array with param=>value, will be appended to the returned url @@ -86,9 +86,9 @@ public function linkTo(string $appName, string $file, array $args = []): string; public function imagePath(string $appName, string $file): string; /** - * Makes an URL absolute + * Makes a URL absolute * @param string $url the url in the ownCloud host - * @return string the absolute version of the url + * @return non-empty-string the absolute version of the url * @since 6.0.0 */ public function getAbsoluteURL(string $url): string; @@ -109,7 +109,7 @@ public function linkToDocs(string $key): string; public function linkToDefaultPageUrl(): string; /** - * @return string base url of the current request + * @return non-empty-string base url of the current request * @since 13.0.0 */ public function getBaseUrl(): string; @@ -126,4 +126,12 @@ public function getWebroot(): string; * @since 34.0.0 */ public function linkToRemote(string $service): string; + + /** + * Return the url to the logout action. + * + * @return non-empty-string + * @since 35.0.0 + */ + public function getLogoutUrl(): string; }