diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 303871feadc40..709fcf9c437d9 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -168,6 +168,7 @@ 'OCP\\Authentication\\Exceptions\\PasswordUnavailableException' => $baseDir . '/lib/public/Authentication/Exceptions/PasswordUnavailableException.php', 'OCP\\Authentication\\Exceptions\\WipeTokenException' => $baseDir . '/lib/public/Authentication/Exceptions/WipeTokenException.php', 'OCP\\Authentication\\IAlternativeLogin' => $baseDir . '/lib/public/Authentication/IAlternativeLogin.php', + 'OCP\\Authentication\\IAlternativeLoginProvider' => $baseDir . '/lib/public/Authentication/IAlternativeLoginProvider.php', 'OCP\\Authentication\\IApacheBackend' => $baseDir . '/lib/public/Authentication/IApacheBackend.php', 'OCP\\Authentication\\IProvideUserSecretBackend' => $baseDir . '/lib/public/Authentication/IProvideUserSecretBackend.php', 'OCP\\Authentication\\LoginCredentials\\ICredentials' => $baseDir . '/lib/public/Authentication/LoginCredentials/ICredentials.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index 8dad797c6e962..65854d9292150 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -209,6 +209,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\Authentication\\Exceptions\\PasswordUnavailableException' => __DIR__ . '/../../..' . '/lib/public/Authentication/Exceptions/PasswordUnavailableException.php', 'OCP\\Authentication\\Exceptions\\WipeTokenException' => __DIR__ . '/../../..' . '/lib/public/Authentication/Exceptions/WipeTokenException.php', 'OCP\\Authentication\\IAlternativeLogin' => __DIR__ . '/../../..' . '/lib/public/Authentication/IAlternativeLogin.php', + 'OCP\\Authentication\\IAlternativeLoginProvider' => __DIR__ . '/../../..' . '/lib/public/Authentication/IAlternativeLoginProvider.php', 'OCP\\Authentication\\IApacheBackend' => __DIR__ . '/../../..' . '/lib/public/Authentication/IApacheBackend.php', 'OCP\\Authentication\\IProvideUserSecretBackend' => __DIR__ . '/../../..' . '/lib/public/Authentication/IProvideUserSecretBackend.php', 'OCP\\Authentication\\LoginCredentials\\ICredentials' => __DIR__ . '/../../..' . '/lib/public/Authentication/LoginCredentials/ICredentials.php', diff --git a/lib/private/AppFramework/Bootstrap/RegistrationContext.php b/lib/private/AppFramework/Bootstrap/RegistrationContext.php index 6b68b4b755285..ec880706da251 100644 --- a/lib/private/AppFramework/Bootstrap/RegistrationContext.php +++ b/lib/private/AppFramework/Bootstrap/RegistrationContext.php @@ -16,6 +16,7 @@ use OCP\AppFramework\Middleware; use OCP\AppFramework\Services\InitialStateProvider; use OCP\Authentication\IAlternativeLogin; +use OCP\Authentication\IAlternativeLoginProvider; use OCP\Calendar\ICalendarProvider; use OCP\Calendar\Resource\IBackend as IResourceBackend; use OCP\Calendar\Room\IBackend as IRoomBackend; @@ -44,6 +45,7 @@ use OCP\TextProcessing\IProvider as ITextProcessingProvider; use OCP\Translation\ITranslationProvider; use OCP\UserMigration\IMigrator as IUserMigrator; +use Override; use Psr\Log\LoggerInterface; use RuntimeException; use Throwable; @@ -95,6 +97,9 @@ class RegistrationContext { /** @var ServiceRegistration[] */ private $alternativeLogins = []; + /** @var ServiceRegistration[] */ + private array $alternativeLoginProviders = []; + /** @var ServiceRegistration[] */ private $initialStates = []; @@ -251,6 +256,14 @@ public function registerAlternativeLogin(string $class): void { ); } + #[Override] + public function registerAlternativeLoginProvider(string $class): void { + $this->context->registerAlternativeLoginProvider( + $this->appId, + $class + ); + } + public function registerInitialStateProvider(string $class): void { $this->context->registerInitialState( $this->appId, @@ -495,6 +508,10 @@ public function registerAlternativeLogin(string $appId, string $class): void { $this->alternativeLogins[] = new ServiceRegistration($appId, $class); } + public function registerAlternativeLoginProvider(string $appId, string $class): void { + $this->alternativeLoginProviders[] = new ServiceRegistration($appId, $class); + } + public function registerInitialState(string $appId, string $class): void { $this->initialStates[] = new ServiceRegistration($appId, $class); } @@ -828,6 +845,13 @@ public function getAlternativeLogins(): array { return $this->alternativeLogins; } + /** + * @return ServiceRegistration[] + */ + public function getAlternativeLoginProviders(): array { + return $this->alternativeLoginProviders; + } + /** * @return ServiceRegistration[] */ diff --git a/lib/private/legacy/OC_App.php b/lib/private/legacy/OC_App.php index 76e5fda71fb11..1343e47ea92cd 100644 --- a/lib/private/legacy/OC_App.php +++ b/lib/private/legacy/OC_App.php @@ -19,6 +19,7 @@ use OCP\App\AppPathNotFoundException; use OCP\App\IAppManager; use OCP\Authentication\IAlternativeLogin; +use OCP\Authentication\IAlternativeLoginProvider; use OCP\BackgroundJob\IJobList; use OCP\EventDispatcher\IEventDispatcher; use OCP\IAppConfig; @@ -41,6 +42,8 @@ * upgrading and removing apps. */ class OC_App { + + /** @var list */ private static array $altLogin = []; private static array $alreadyRegistered = []; public const supportedApp = 300; @@ -300,12 +303,55 @@ public static function registerLogIn(array $entry): void { } /** - * @return array + * @return list */ public static function getAlternativeLogIns(): array { /** @var Coordinator $bootstrapCoordinator */ $bootstrapCoordinator = Server::get(Coordinator::class); + foreach ($bootstrapCoordinator->getRegistrationContext()->getAlternativeLoginProviders() as $registration) { + if (!in_array(IAlternativeLoginProvider::class, class_implements($registration->getService()), true)) { + Server::get(LoggerInterface::class)->error('Alternative login option {option} does not implement {interface} and is therefore ignored.', [ + 'option' => $registration->getService(), + 'interface' => IAlternativeLoginProvider::class, + 'app' => $registration->getAppId(), + ]); + continue; + } + + try { + /** @var IAlternativeLoginProvider $provider */ + $provider = Server::get($registration->getService()); + } catch (ContainerExceptionInterface $e) { + Server::get(LoggerInterface::class)->error('Alternative login option {option} can not be initialized.', + [ + 'exception' => $e, + 'option' => $registration->getService(), + 'app' => $registration->getAppId(), + ]); + continue; + } + + foreach ($provider->getAlternativeLogins() as $alternativeLogin) { + try { + $alternativeLogin->load(); + + self::$altLogin[] = [ + 'name' => $alternativeLogin->getLabel(), + 'href' => $alternativeLogin->getLink(), + 'class' => $alternativeLogin->getClass(), + ]; + } catch (Throwable $e) { + Server::get(LoggerInterface::class)->error('Alternative login option {option} had an error while loading.', + [ + 'exception' => $e, + 'option' => $registration->getService(), + 'app' => $registration->getAppId(), + ]); + } + } + } + foreach ($bootstrapCoordinator->getRegistrationContext()->getAlternativeLogins() as $registration) { if (!in_array(IAlternativeLogin::class, class_implements($registration->getService()), true)) { Server::get(LoggerInterface::class)->error('Alternative login option {option} does not implement {interface} and is therefore ignored.', [ diff --git a/lib/public/AppFramework/Bootstrap/IRegistrationContext.php b/lib/public/AppFramework/Bootstrap/IRegistrationContext.php index 85ba659111145..fa83eda180179 100644 --- a/lib/public/AppFramework/Bootstrap/IRegistrationContext.php +++ b/lib/public/AppFramework/Bootstrap/IRegistrationContext.php @@ -161,9 +161,21 @@ public function registerSearchProvider(string $class): void; * @return void * * @since 20.0.0 + * @deprecated 34.0.0 Use registerAlternativeLoginProvider instead. */ public function registerAlternativeLogin(string $class): void; + /** + * Register an alternative login options provider + * + * It is allowed to register more than one option per app. + * + * @param class-string<\OCP\Authentication\IAlternativeLoginProvider> $class + * + * @since 34.0.0 + */ + public function registerAlternativeLoginProvider(string $class): void; + /** * Register an initialstate provider * diff --git a/lib/public/Authentication/IAlternativeLoginProvider.php b/lib/public/Authentication/IAlternativeLoginProvider.php new file mode 100644 index 0000000000000..818f87165045d --- /dev/null +++ b/lib/public/Authentication/IAlternativeLoginProvider.php @@ -0,0 +1,22 @@ + + * @since 34.0.0 + */ + public function getAlternativeLogins(): array; +}