diff --git a/lib/AlternativeLogin/AlternativeLogin.php b/lib/AlternativeLogin/AlternativeLogin.php new file mode 100644 index 00000000..1f65eff9 --- /dev/null +++ b/lib/AlternativeLogin/AlternativeLogin.php @@ -0,0 +1,35 @@ +name; + } + + public function getLink(): string { + return $this->href; + } + + public function getClass(): string { + return ''; + } + + public function load(): void { + } +} diff --git a/lib/AlternativeLogin/AlternativeLoginProvider.php b/lib/AlternativeLogin/AlternativeLoginProvider.php new file mode 100644 index 00000000..05870152 --- /dev/null +++ b/lib/AlternativeLogin/AlternativeLoginProvider.php @@ -0,0 +1,59 @@ +request->getParam('redirect_url'); + $absoluteRedirectUrl = !empty($redirectUrl) ? $this->urlGenerator->getAbsoluteURL($redirectUrl) : $redirectUrl; + $providers = $this->providerMapper->getProviders(); + $customLoginLabel = $this->config->getSystemValue('user_oidc', [])['login_label'] ?? ''; + foreach ($providers as $provider) { + $alternativeLogins[] = new AlternativeLogin( + $customLoginLabel + ? preg_replace('/{name}/', $provider->getIdentifier(), $customLoginLabel) + : $this->l10n->t('Login with %1s', [$provider->getIdentifier()]), + $this->urlGenerator->linkToRoute(Application::APP_ID . '.login.login', ['providerId' => $provider->getId(), 'redirectUrl' => $absoluteRedirectUrl]), + ); + } + + if ($this->id4MeService->getID4ME()) { + $alternativeLogins[] = new AlternativeLogin( + 'ID4ME', + $this->urlGenerator->linkToRoute(Application::APP_ID . '.id4me.login'), + ); + } + + return $alternativeLogins; + } +} diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 9842067f..0a421c6c 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -11,6 +11,7 @@ use Exception; use OC_App; use OCA\Files\Event\LoadAdditionalScriptsEvent; +use OCA\UserOIDC\AlternativeLogin\AlternativeLoginProvider; use OCA\UserOIDC\Db\ProviderMapper; use OCA\UserOIDC\Event\ExchangedTokenRequestedEvent; use OCA\UserOIDC\Event\ExternalTokenRequestedEvent; @@ -70,6 +71,14 @@ public function register(IRegistrationContext $context): void { if (class_exists(\OCP\Authentication\Events\TokenInvalidatedEvent::class)) { $context->registerEventListener(\OCP\Authentication\Events\TokenInvalidatedEvent::class, TokenInvalidatedListener::class); } + + if (version_compare($config->getSystemValueString('version', '0.0.0'), '34.0.0', '>=')) { + /** + * @psalm-suppress UndefinedInterfaceMethod + * @psalm-suppress MissingDependency + */ + $context->registerAlternativeLoginProvider(AlternativeLoginProvider::class); + } } public function boot(IBootContext $context): void { @@ -83,7 +92,9 @@ public function boot(IBootContext $context): void { try { $context->injectFn(\Closure::fromCallable([$this, 'registerRedirect'])); - $context->injectFn(\Closure::fromCallable([$this, 'registerLogin'])); + if (version_compare($this->getContainer()->get(IConfig::class)->getSystemValueString('version', '0.0.0'), '34.0.0', '<')) { + $context->injectFn(\Closure::fromCallable([$this, 'registerLogin'])); + } } catch (Throwable $e) { } } @@ -93,7 +104,6 @@ private function checkLoginToken(TokenService $tokenService): void { } private function registerRedirect(IRequest $request, IURLGenerator $urlGenerator, SettingsService $settings, ProviderMapper $providerMapper): void { - $providers = $this->getCachedProviders($providerMapper); $redirectUrl = $request->getParam('redirect_url'); $absoluteRedirectUrl = !empty($redirectUrl) ? $urlGenerator->getAbsoluteURL($redirectUrl) : $redirectUrl; @@ -104,13 +114,16 @@ private function registerRedirect(IRequest $request, IURLGenerator $urlGenerator } catch (Exception $e) { // in case any errors happen when checking for the path do not apply redirect logic as it is only needed for the login } - if ($isDefaultLogin && !$settings->getAllowMultipleUserBackEnds() && count($providers) === 1) { - $targetUrl = $urlGenerator->linkToRoute(self::APP_ID . '.login.login', [ - 'providerId' => $providers[0]->getId(), - 'redirectUrl' => $absoluteRedirectUrl - ]); - header('Location: ' . $targetUrl); - exit(); + if ($isDefaultLogin && !$settings->getAllowMultipleUserBackEnds()) { + $providers = $this->getCachedProviders($providerMapper); + if (count($providers) === 1) { + $targetUrl = $urlGenerator->linkToRoute(self::APP_ID . '.login.login', [ + 'providerId' => $providers[0]->getId(), + 'redirectUrl' => $absoluteRedirectUrl + ]); + header('Location: ' . $targetUrl); + exit(); + } } } diff --git a/psalm.xml b/psalm.xml index 20f5ade4..f24d6c1e 100644 --- a/psalm.xml +++ b/psalm.xml @@ -48,6 +48,7 @@ + diff --git a/tests/integration/Test.php b/tests/integration/Test.php index 33ee6051..675ca23b 100644 --- a/tests/integration/Test.php +++ b/tests/integration/Test.php @@ -65,12 +65,11 @@ private function cleanupUser(string $userId): void { public function testAlternativeLogins() { - self::assertEquals([ - [ - 'name' => 'Login with nextcloudci', - 'href' => '/index.php/apps/user_oidc/login/1' - ] - ], OC_App::getAlternativeLogIns()); + $alternativeLogins = OC_App::getAlternativeLogIns(); + self::assertCount(1, $alternativeLogins); + $alternativeLogin = $alternativeLogins[0]; + self::assertEquals('Login with nextcloudci', $alternativeLogin['name']); + self::assertEquals('/index.php/apps/user_oidc/login/1', $alternativeLogin['href']); } public function testLoginRedirect() {