diff --git a/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php b/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php index bfccb2fe20eaf..6fa4e1fc8cd3d 100644 --- a/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php +++ b/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php @@ -44,7 +44,6 @@ use OCP\Security\Signature\IIncomingSignedRequest; use OCP\Security\Signature\ISignatureManager; use OCP\Share\Exceptions\ShareNotFound; -use OCP\Util; use Psr\Log\LoggerInterface; /** @@ -414,21 +413,12 @@ public function receiveNotification($notificationType, $resourceType, $providerI } /** - * map login name to internal LDAP UID if a LDAP backend is in use - * - * @param string $uid - * @return string mixed + * Map login name to internal LDAP UID if an LDAP backend is in use */ - private function mapUid($uid) { - // FIXME this should be a method in the user management instead + private function mapUid(string $uid): string { $this->logger->debug('shareWith before, ' . $uid, ['app' => $this->appName]); - Util::emitHook( - '\OCA\Files_Sharing\API\Server2Server', - 'preLoginNameUsedAsUserName', - ['uid' => &$uid] - ); + $uid = $this->userManager->getUserNameFromLoginName($uid); $this->logger->debug('shareWith after, ' . $uid, ['app' => $this->appName]); - return $uid; } diff --git a/apps/federatedfilesharing/lib/AddressHandler.php b/apps/federatedfilesharing/lib/AddressHandler.php index 4588e6da288e6..ac4874e14d8f2 100644 --- a/apps/federatedfilesharing/lib/AddressHandler.php +++ b/apps/federatedfilesharing/lib/AddressHandler.php @@ -11,7 +11,7 @@ use OCP\HintException; use OCP\IL10N; use OCP\IURLGenerator; -use OCP\Util; +use OCP\IUserManager; /** * Class AddressHandler - parse, modify and construct federated sharing addresses @@ -22,26 +22,23 @@ class AddressHandler { /** * AddressHandler constructor. - * - * @param IURLGenerator $urlGenerator - * @param IL10N $l - * @param ICloudIdManager $cloudIdManager */ public function __construct( - private IURLGenerator $urlGenerator, - private IL10N $l, - private ICloudIdManager $cloudIdManager, + private readonly IURLGenerator $urlGenerator, + private readonly IL10N $l, + private readonly ICloudIdManager $cloudIdManager, + private readonly IUserManager $userManager, ) { } /** - * split user and remote from federated cloud id + * Split user and remote from federated cloud id. * * @param string $address federated share address * @return array [user, remoteURL] * @throws HintException */ - public function splitUserRemote($address) { + public function splitUserRemote(string $address): array { try { $cloudId = $this->cloudIdManager->resolveCloudId($address); return [$cloudId->getUser(), $cloudId->getRemote()]; @@ -52,55 +49,36 @@ public function splitUserRemote($address) { } /** - * generate remote URL part of federated ID + * Generate remote URL part of federated ID * * @return string url of the current server */ - public function generateRemoteURL() { + public function generateRemoteURL(): string { return $this->urlGenerator->getAbsoluteURL('/'); } /** - * check if two federated cloud IDs refer to the same user + * Check if two federated cloud IDs refer to the same user * - * @param string $user1 - * @param string $server1 - * @param string $user2 - * @param string $server2 * @return bool true if both users and servers are the same */ - public function compareAddresses($user1, $server1, $user2, $server2) { + public function compareAddresses(string $user1, string $server1, string $user2, string $server2): bool { $normalizedServer1 = strtolower($this->removeProtocolFromUrl($server1)); $normalizedServer2 = strtolower($this->removeProtocolFromUrl($server2)); - if (rtrim($normalizedServer1, '/') === rtrim($normalizedServer2, '/')) { - // FIXME this should be a method in the user management instead - Util::emitHook( - '\OCA\Files_Sharing\API\Server2Server', - 'preLoginNameUsedAsUserName', - ['uid' => &$user1] - ); - Util::emitHook( - '\OCA\Files_Sharing\API\Server2Server', - 'preLoginNameUsedAsUserName', - ['uid' => &$user2] - ); - - if ($user1 === $user2) { - return true; - } + if (rtrim($normalizedServer1, '/') !== rtrim($normalizedServer2, '/')) { + return false; } - return false; + $user1 = $this->userManager->getUserNameFromLoginName($user1); + $user2 = $this->userManager->getUserNameFromLoginName($user2); + return $user1 === $user2; } /** - * remove protocol from URL - * - * @param string $url - * @return string + * Remove protocol from URL */ - public function removeProtocolFromUrl($url) { + public function removeProtocolFromUrl(string $url): string { if (str_starts_with($url, 'https://')) { return substr($url, strlen('https://')); } elseif (str_starts_with($url, 'http://')) { @@ -111,17 +89,9 @@ public function removeProtocolFromUrl($url) { } /** - * check if the url contain the protocol (http or https) - * - * @param string $url - * @return bool + * Check if the url contain the protocol (http or https). */ - public function urlContainProtocol($url) { - if (str_starts_with($url, 'https://') - || str_starts_with($url, 'http://')) { - return true; - } - - return false; + public function urlContainProtocol(string $url): bool { + return str_starts_with($url, 'https://') || str_starts_with($url, 'http://'); } } diff --git a/apps/federatedfilesharing/lib/OCM/CloudFederationProviderFiles.php b/apps/federatedfilesharing/lib/OCM/CloudFederationProviderFiles.php index 3ae6366fabe63..634ee26ba770d 100644 --- a/apps/federatedfilesharing/lib/OCM/CloudFederationProviderFiles.php +++ b/apps/federatedfilesharing/lib/OCM/CloudFederationProviderFiles.php @@ -122,11 +122,7 @@ public function shareReceived(ICloudFederationShare $share): string { if ($shareType === IShare::TYPE_USER) { $this->logger->debug('shareWith before, ' . $shareWith, ['app' => 'files_sharing']); - Util::emitHook( - '\OCA\Files_Sharing\API\Server2Server', - 'preLoginNameUsedAsUserName', - ['uid' => &$shareWith] - ); + $shareWith = $this->userManager->getUserNameFromLoginName($shareWith); $this->logger->debug('shareWith after, ' . $shareWith, ['app' => 'files_sharing']); $user = $this->userManager->get($shareWith); diff --git a/apps/files_external/composer/composer/autoload_classmap.php b/apps/files_external/composer/composer/autoload_classmap.php index ea66a333a15a4..b90435eead44d 100644 --- a/apps/files_external/composer/composer/autoload_classmap.php +++ b/apps/files_external/composer/composer/autoload_classmap.php @@ -37,6 +37,7 @@ 'OCA\\Files_External\\Controller\\StoragesController' => $baseDir . '/../lib/Controller/StoragesController.php', 'OCA\\Files_External\\Controller\\UserGlobalStoragesController' => $baseDir . '/../lib/Controller/UserGlobalStoragesController.php', 'OCA\\Files_External\\Controller\\UserStoragesController' => $baseDir . '/../lib/Controller/UserStoragesController.php', + 'OCA\\Files_External\\Event\\LoadAdditionalBackendEvent' => $baseDir . '/../lib/Event/LoadAdditionalBackendEvent.php', 'OCA\\Files_External\\Event\\StorageCreatedEvent' => $baseDir . '/../lib/Event/StorageCreatedEvent.php', 'OCA\\Files_External\\Event\\StorageDeletedEvent' => $baseDir . '/../lib/Event/StorageDeletedEvent.php', 'OCA\\Files_External\\Event\\StorageUpdatedEvent' => $baseDir . '/../lib/Event/StorageUpdatedEvent.php', diff --git a/apps/files_external/composer/composer/autoload_static.php b/apps/files_external/composer/composer/autoload_static.php index 37b3bb4052449..58eeccae1712b 100644 --- a/apps/files_external/composer/composer/autoload_static.php +++ b/apps/files_external/composer/composer/autoload_static.php @@ -52,6 +52,7 @@ class ComposerStaticInitFiles_External 'OCA\\Files_External\\Controller\\StoragesController' => __DIR__ . '/..' . '/../lib/Controller/StoragesController.php', 'OCA\\Files_External\\Controller\\UserGlobalStoragesController' => __DIR__ . '/..' . '/../lib/Controller/UserGlobalStoragesController.php', 'OCA\\Files_External\\Controller\\UserStoragesController' => __DIR__ . '/..' . '/../lib/Controller/UserStoragesController.php', + 'OCA\\Files_External\\Event\\LoadAdditionalBackendEvent' => __DIR__ . '/..' . '/../lib/Event/LoadAdditionalBackendEvent.php', 'OCA\\Files_External\\Event\\StorageCreatedEvent' => __DIR__ . '/..' . '/../lib/Event/StorageCreatedEvent.php', 'OCA\\Files_External\\Event\\StorageDeletedEvent' => __DIR__ . '/..' . '/../lib/Event/StorageDeletedEvent.php', 'OCA\\Files_External\\Event\\StorageUpdatedEvent' => __DIR__ . '/..' . '/../lib/Event/StorageUpdatedEvent.php', diff --git a/apps/files_external/lib/Event/LoadAdditionalBackendEvent.php b/apps/files_external/lib/Event/LoadAdditionalBackendEvent.php new file mode 100644 index 0000000000000..d6401ded24609 --- /dev/null +++ b/apps/files_external/lib/Event/LoadAdditionalBackendEvent.php @@ -0,0 +1,17 @@ +backendProviders[] = $provider; } - private function callForRegistrations() { + private function callForRegistrations(): void { static $eventSent = false; if (!$eventSent) { - Server::get(IEventDispatcher::class)->dispatch( - 'OCA\\Files_External::loadAdditionalBackends', - new GenericEvent() - ); + Server::get(IEventDispatcher::class)->dispatchTyped(new LoadAdditionalBackendEvent()); $eventSent = true; } } - private function loadBackendProviders() { + private function loadBackendProviders(): void { $this->callForRegistrations(); foreach ($this->backendProviders as $provider) { - $this->registerBackends($provider->getBackends()); + foreach ($provider->getBackends() as $backend) { + $this->registerBackend($backend); + } } $this->backendProviders = []; } @@ -94,27 +93,25 @@ private function loadBackendProviders() { * Register an auth mechanism provider * * @since 9.1.0 - * @param IAuthMechanismProvider $provider */ - public function registerAuthMechanismProvider(IAuthMechanismProvider $provider) { + public function registerAuthMechanismProvider(IAuthMechanismProvider $provider): void { $this->authMechanismProviders[] = $provider; } - private function loadAuthMechanismProviders() { + private function loadAuthMechanismProviders(): void { $this->callForRegistrations(); foreach ($this->authMechanismProviders as $provider) { - $this->registerAuthMechanisms($provider->getAuthMechanisms()); + foreach ($provider->getAuthMechanisms() as $mechanism) { + $this->registerAuthMechanism($mechanism); + } } $this->authMechanismProviders = []; } /** * Register a backend - * - * @deprecated 9.1.0 use registerBackendProvider() - * @param Backend $backend */ - public function registerBackend(Backend $backend) { + private function registerBackend(Backend $backend): void { if (!$this->isAllowedUserBackend($backend)) { $backend->removeVisibility(BackendService::VISIBILITY_PERSONAL); } @@ -123,22 +120,10 @@ public function registerBackend(Backend $backend) { } } - /** - * @deprecated 9.1.0 use registerBackendProvider() - * @param Backend[] $backends - */ - public function registerBackends(array $backends) { - foreach ($backends as $backend) { - $this->registerBackend($backend); - } - } /** * Register an authentication mechanism - * - * @deprecated 9.1.0 use registerAuthMechanismProvider() - * @param AuthMechanism $authMech */ - public function registerAuthMechanism(AuthMechanism $authMech) { + private function registerAuthMechanism(AuthMechanism $authMech): void { if (!$this->isAllowedAuthMechanism($authMech)) { $authMech->removeVisibility(BackendService::VISIBILITY_PERSONAL); } @@ -147,22 +132,12 @@ public function registerAuthMechanism(AuthMechanism $authMech) { } } - /** - * @deprecated 9.1.0 use registerAuthMechanismProvider() - * @param AuthMechanism[] $mechanisms - */ - public function registerAuthMechanisms(array $mechanisms) { - foreach ($mechanisms as $mechanism) { - $this->registerAuthMechanism($mechanism); - } - } - /** * Get all backends * - * @return Backend[] + * @return array */ - public function getBackends() { + public function getBackends(): array { $this->loadBackendProviders(); // only return real identifiers, no aliases $backends = []; @@ -177,7 +152,7 @@ public function getBackends() { * * @return Backend[] */ - public function getAvailableBackends() { + public function getAvailableBackends(): array { return array_filter($this->getBackends(), fn (Backend $backend) => $backend->checkRequiredDependencies() === []); } diff --git a/apps/user_ldap/composer/composer/autoload_classmap.php b/apps/user_ldap/composer/composer/autoload_classmap.php index a1743773f49eb..eb306579ba72c 100644 --- a/apps/user_ldap/composer/composer/autoload_classmap.php +++ b/apps/user_ldap/composer/composer/autoload_classmap.php @@ -58,6 +58,7 @@ 'OCA\\User_LDAP\\LDAPProvider' => $baseDir . '/../lib/LDAPProvider.php', 'OCA\\User_LDAP\\LDAPProviderFactory' => $baseDir . '/../lib/LDAPProviderFactory.php', 'OCA\\User_LDAP\\LDAPUtility' => $baseDir . '/../lib/LDAPUtility.php', + 'OCA\\User_LDAP\\Listener\\LoadAdditionalBackendListener' => $baseDir . '/../lib/Listener/LoadAdditionalBackendListener.php', 'OCA\\User_LDAP\\LoginListener' => $baseDir . '/../lib/LoginListener.php', 'OCA\\User_LDAP\\Mapping\\AbstractMapping' => $baseDir . '/../lib/Mapping/AbstractMapping.php', 'OCA\\User_LDAP\\Mapping\\GroupMapping' => $baseDir . '/../lib/Mapping/GroupMapping.php', diff --git a/apps/user_ldap/composer/composer/autoload_static.php b/apps/user_ldap/composer/composer/autoload_static.php index af3ddfbdf020a..231e5b364f6e8 100644 --- a/apps/user_ldap/composer/composer/autoload_static.php +++ b/apps/user_ldap/composer/composer/autoload_static.php @@ -73,6 +73,7 @@ class ComposerStaticInitUser_LDAP 'OCA\\User_LDAP\\LDAPProvider' => __DIR__ . '/..' . '/../lib/LDAPProvider.php', 'OCA\\User_LDAP\\LDAPProviderFactory' => __DIR__ . '/..' . '/../lib/LDAPProviderFactory.php', 'OCA\\User_LDAP\\LDAPUtility' => __DIR__ . '/..' . '/../lib/LDAPUtility.php', + 'OCA\\User_LDAP\\Listener\\LoadAdditionalBackendListener' => __DIR__ . '/..' . '/../lib/Listener/LoadAdditionalBackendListener.php', 'OCA\\User_LDAP\\LoginListener' => __DIR__ . '/..' . '/../lib/LoginListener.php', 'OCA\\User_LDAP\\Mapping\\AbstractMapping' => __DIR__ . '/..' . '/../lib/Mapping/AbstractMapping.php', 'OCA\\User_LDAP\\Mapping\\GroupMapping' => __DIR__ . '/..' . '/../lib/Mapping/GroupMapping.php', diff --git a/apps/user_ldap/lib/AppInfo/Application.php b/apps/user_ldap/lib/AppInfo/Application.php index 220a11715faea..7d50909ac494c 100644 --- a/apps/user_ldap/lib/AppInfo/Application.php +++ b/apps/user_ldap/lib/AppInfo/Application.php @@ -8,16 +8,15 @@ */ namespace OCA\User_LDAP\AppInfo; -use Closure; -use OCA\Files_External\Service\BackendService; +use OCA\Files_External\Event\LoadAdditionalBackendEvent; use OCA\User_LDAP\Events\GroupBackendRegistered; use OCA\User_LDAP\Events\UserBackendRegistered; use OCA\User_LDAP\Group_Proxy; use OCA\User_LDAP\GroupPluginManager; -use OCA\User_LDAP\Handler\ExtStorageConfigHandler; use OCA\User_LDAP\Helper; use OCA\User_LDAP\ILDAPWrapper; use OCA\User_LDAP\LDAP; +use OCA\User_LDAP\Listener\LoadAdditionalBackendListener; use OCA\User_LDAP\LoginListener; use OCA\User_LDAP\Notification\Notifier; use OCA\User_LDAP\SetupChecks\LdapConnection; @@ -29,7 +28,6 @@ use OCP\AppFramework\Bootstrap\IBootContext; use OCP\AppFramework\Bootstrap\IBootstrap; use OCP\AppFramework\Bootstrap\IRegistrationContext; -use OCP\AppFramework\IAppContainer; use OCP\AppFramework\Services\IAppConfig; use OCP\Config\IUserConfig; use OCP\EventDispatcher\IEventDispatcher; @@ -41,7 +39,6 @@ use OCP\Notification\IManager as INotificationManager; use OCP\Share\IManager as IShareManager; use OCP\User\Events\PostLoginEvent; -use OCP\Util; use Psr\Container\ContainerInterface; use Psr\Log\LoggerInterface; @@ -76,6 +73,7 @@ function (ContainerInterface $c) { false ); $context->registerEventListener(PostLoginEvent::class, LoginListener::class); + $context->registerEventListener(LoadAdditionalBackendEvent::class, LoadAdditionalBackendListener::class); $context->registerSetupCheck(LdapInvalidUuids::class); $context->registerSetupCheck(LdapConnection::class); } @@ -83,7 +81,7 @@ function (ContainerInterface $c) { public function boot(IBootContext $context): void { $context->injectFn(function ( INotificationManager $notificationManager, - IAppContainer $appContainer, + ContainerInterface $appContainer, IEventDispatcher $dispatcher, IUserManager $userManager, IGroupManager $groupManager, @@ -100,32 +98,10 @@ public function boot(IBootContext $context): void { $groupManager->addBackend($groupBackend); $userBackendRegisteredEvent = new UserBackendRegistered($userBackend, $userPluginManager); - $dispatcher->dispatch('OCA\\User_LDAP\\User\\User::postLDAPBackendAdded', $userBackendRegisteredEvent); $dispatcher->dispatchTyped($userBackendRegisteredEvent); $groupBackendRegisteredEvent = new GroupBackendRegistered($groupBackend, $groupPluginManager); $dispatcher->dispatchTyped($groupBackendRegisteredEvent); } }); - - $context->injectFn(Closure::fromCallable([$this, 'registerBackendDependents'])); - - Util::connectHook( - '\OCA\Files_Sharing\API\Server2Server', - 'preLoginNameUsedAsUserName', - '\OCA\User_LDAP\Helper', - 'loginName2UserName' - ); - } - - private function registerBackendDependents(IAppContainer $appContainer, IEventDispatcher $dispatcher): void { - $dispatcher->addListener( - 'OCA\\Files_External::loadAdditionalBackends', - function () use ($appContainer): void { - $storagesBackendService = $appContainer->get(BackendService::class); - $storagesBackendService->registerConfigHandler('home', function () use ($appContainer) { - return $appContainer->get(ExtStorageConfigHandler::class); - }); - } - ); } } diff --git a/apps/user_ldap/lib/Helper.php b/apps/user_ldap/lib/Helper.php index 0fb318d57b6f9..10c69799be609 100644 --- a/apps/user_ldap/lib/Helper.php +++ b/apps/user_ldap/lib/Helper.php @@ -281,23 +281,4 @@ public function sanitizeDN($dn) { public function DNasBaseParameter($dn) { return str_ireplace('\\5c', '\\', $dn); } - - /** - * listens to a hook thrown by server2server sharing and replaces the given - * login name by a username, if it matches an LDAP user. - * - * @param array $param contains a reference to a $uid var under 'uid' key - * @throws \Exception - */ - public static function loginName2UserName($param): void { - if (!isset($param['uid'])) { - throw new \Exception('key uid is expected to be set in $param'); - } - - $userBackend = Server::get(User_Proxy::class); - $uid = $userBackend->loginName2UserName($param['uid']); - if ($uid !== false) { - $param['uid'] = $uid; - } - } } diff --git a/apps/user_ldap/lib/Listener/LoadAdditionalBackendListener.php b/apps/user_ldap/lib/Listener/LoadAdditionalBackendListener.php new file mode 100644 index 0000000000000..451a3ae32098d --- /dev/null +++ b/apps/user_ldap/lib/Listener/LoadAdditionalBackendListener.php @@ -0,0 +1,37 @@ + + */ +class LoadAdditionalBackendListener implements IEventListener { + public function __construct( + private readonly BackendService $storagesBackendService, + private readonly ContainerInterface $container, + ) { + } + + public function handle(Event $event): void { + if (!$event instanceof LoadAdditionalBackendEvent) { + return; + } + + $this->storagesBackendService->registerConfigHandler('home', fn () => $this->container->get(ExtStorageConfigHandler::class)); + } +} diff --git a/apps/user_ldap/lib/User_LDAP.php b/apps/user_ldap/lib/User_LDAP.php index 22475ceccab6e..d1e1b857cef01 100644 --- a/apps/user_ldap/lib/User_LDAP.php +++ b/apps/user_ldap/lib/User_LDAP.php @@ -69,8 +69,8 @@ public function canChangeAvatar($uid) { * @return string|false * @throws \Exception */ - public function loginName2UserName($loginName, bool $forceLdapRefetch = false) { - $cacheKey = 'loginName2UserName-' . $loginName; + public function getUserNameFromLoginName($loginName, bool $forceLdapRefetch = false) { + $cacheKey = 'getUserNameFromLoginName-' . $loginName; $username = $this->access->connection->getFromCache($cacheKey); $knownDn = $username ? $this->access->username2dn($username) : false; @@ -136,7 +136,7 @@ public function getLDAPUserByLoginName($loginName) { * @return false|string */ public function checkPassword($uid, $password) { - $username = $this->loginName2UserName($uid, true); + $username = $this->getUserNameFromLoginName($uid, true); if ($username === false) { return false; } diff --git a/apps/user_ldap/lib/User_Proxy.php b/apps/user_ldap/lib/User_Proxy.php index 6a01ab3483019..21902615f6505 100644 --- a/apps/user_ldap/lib/User_Proxy.php +++ b/apps/user_ldap/lib/User_Proxy.php @@ -14,16 +14,27 @@ use OCP\Notification\IManager as INotificationManager; use OCP\User\Backend\ICountMappedUsersBackend; use OCP\User\Backend\IGetDisplayNameBackend; +use OCP\User\Backend\IGetUserNameFromLoginNameBackend; use OCP\User\Backend\ILimitAwareCountUsersBackend; use OCP\User\Backend\IPropertyPermissionBackend; use OCP\User\Backend\IProvideEnabledStateBackend; use OCP\UserInterface; +use Override; use Psr\Log\LoggerInterface; /** * @template-extends Proxy */ -class User_Proxy extends Proxy implements IUserBackend, UserInterface, IUserLDAP, ILimitAwareCountUsersBackend, ICountMappedUsersBackend, IProvideEnabledStateBackend, IGetDisplayNameBackend, IPropertyPermissionBackend { +class User_Proxy extends Proxy implements + IUserBackend, + UserInterface, + IUserLDAP, + ILimitAwareCountUsersBackend, + ICountMappedUsersBackend, + IProvideEnabledStateBackend, + IGetDisplayNameBackend, + IPropertyPermissionBackend, + IGetUserNameFromLoginNameBackend { public function __construct( private Helper $helper, ILDAPWrapper $ldap, @@ -217,15 +228,10 @@ public function checkPassword($uid, $password) { return $this->handleRequest($uid, 'checkPassword', [$uid, $password]); } - /** - * returns the username for the given login name, if available - * - * @param string $loginName - * @return string|false - */ - public function loginName2UserName($loginName) { + #[Override] + public function getUserNameFromLoginName(string $loginName): string|false { $id = 'LOGINNAME,' . $loginName; - return $this->handleRequest($id, 'loginName2UserName', [$loginName]); + return $this->handleRequest($id, 'getUserNameFromLoginName', [$loginName]); } /** diff --git a/apps/user_ldap/tests/User_LDAPTest.php b/apps/user_ldap/tests/User_LDAPTest.php index 4720b0a570935..3332897fab76d 100644 --- a/apps/user_ldap/tests/User_LDAPTest.php +++ b/apps/user_ldap/tests/User_LDAPTest.php @@ -1072,11 +1072,11 @@ public function testLoginName2UserNameSuccess(): void { $this->connection->expects($this->exactly(2)) ->method('getFromCache') - ->with($this->equalTo('loginName2UserName-' . $loginName)) + ->with($this->equalTo('getUserNameFromLoginName-' . $loginName)) ->willReturnOnConsecutiveCalls(null, $username); $this->connection->expects($this->once()) ->method('writeToCache') - ->with($this->equalTo('loginName2UserName-' . $loginName), $this->equalTo($username)); + ->with($this->equalTo('getUserNameFromLoginName-' . $loginName), $this->equalTo($username)); $backend = new User_LDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex); $user = $this->createMock(User::class); @@ -1094,11 +1094,11 @@ public function testLoginName2UserNameSuccess(): void { ->method('getAttributes') ->willReturn(['dn', 'uid', 'mail', 'displayname']); - $name = $backend->loginName2UserName($loginName); + $name = $backend->getUserNameFromLoginName($loginName); $this->assertSame($username, $name); // and once again to verify that caching works - $backend->loginName2UserName($loginName); + $backend->getUserNameFromLoginName($loginName); } public function testLoginName2UserNameNoUsersOnLDAP(): void { @@ -1115,22 +1115,22 @@ public function testLoginName2UserNameNoUsersOnLDAP(): void { $this->connection->expects($this->exactly(2)) ->method('getFromCache') - ->with($this->equalTo('loginName2UserName-' . $loginName)) + ->with($this->equalTo('getUserNameFromLoginName-' . $loginName)) ->willReturnOnConsecutiveCalls(null, false); $this->connection->expects($this->once()) ->method('writeToCache') - ->with($this->equalTo('loginName2UserName-' . $loginName), false); + ->with($this->equalTo('getUserNameFromLoginName-' . $loginName), false); $this->userManager->expects($this->any()) ->method('getAttributes') ->willReturn(['dn', 'uid', 'mail', 'displayname']); $backend = new User_LDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex); - $name = $backend->loginName2UserName($loginName); + $name = $backend->getUserNameFromLoginName($loginName); $this->assertSame(false, $name); // and once again to verify that caching works - $backend->loginName2UserName($loginName); + $backend->getUserNameFromLoginName($loginName); } public function testLoginName2UserNameOfflineUser(): void { @@ -1148,11 +1148,11 @@ public function testLoginName2UserNameOfflineUser(): void { $this->connection->expects($this->exactly(2)) ->method('getFromCache') - ->with($this->equalTo('loginName2UserName-' . $loginName)) + ->with($this->equalTo('getUserNameFromLoginName-' . $loginName)) ->willReturnOnConsecutiveCalls(null, false); $this->connection->expects($this->once()) ->method('writeToCache') - ->with($this->equalTo('loginName2UserName-' . $loginName), $this->equalTo(false)); + ->with($this->equalTo('getUserNameFromLoginName-' . $loginName), $this->equalTo(false)); $this->userManager->expects($this->any()) ->method('get') @@ -1163,11 +1163,11 @@ public function testLoginName2UserNameOfflineUser(): void { ->willReturn(['dn', 'uid', 'mail', 'displayname']); $backend = new User_LDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex); - $name = $backend->loginName2UserName($loginName); + $name = $backend->getUserNameFromLoginName($loginName); $this->assertSame(false, $name); // and once again to verify that caching works - $backend->loginName2UserName($loginName); + $backend->getUserNameFromLoginName($loginName); } /** diff --git a/build/psalm-baseline.xml b/build/psalm-baseline.xml index 4b115a7e3555f..2ad75297a2fd3 100644 --- a/build/psalm-baseline.xml +++ b/build/psalm-baseline.xml @@ -30,15 +30,6 @@ - - - &$uid] - )]]> - - @@ -1114,20 +1105,6 @@ - - - &$user1] - )]]> - &$user2] - )]]> - - @@ -1154,11 +1131,6 @@ - &$shareWith] - )]]> @@ -1395,18 +1367,6 @@ - - - - - - - - - - - - - @@ -2491,21 +2450,6 @@ getCode()]]> - - - - - - - - - - @@ -2915,11 +2859,6 @@ - &$user] - )]]> @@ -2995,11 +2934,6 @@ session->get(self::WEBAUTHN_LOGIN))]]> - &$uid] - )]]> diff --git a/core/Controller/LostController.php b/core/Controller/LostController.php index d956f3427f279..9333623fdb506 100644 --- a/core/Controller/LostController.php +++ b/core/Controller/LostController.php @@ -41,7 +41,6 @@ use OCP\Security\VerificationToken\InvalidTokenException; use OCP\Security\VerificationToken\IVerificationToken; use OCP\Server; -use OCP\Util; use Psr\Log\LoggerInterface; use function array_filter; use function count; @@ -159,11 +158,7 @@ public function email(string $user): JSONResponse { return new JSONResponse($this->error($this->l10n->t('Unsupported email length (>255)'))); } - Util::emitHook( - '\OCA\Files_Sharing\API\Server2Server', - 'preLoginNameUsedAsUserName', - ['uid' => &$user] - ); + $user = $this->userManager->getUserNameFromLoginName($user); // FIXME: use HTTP error codes try { diff --git a/core/Controller/WebAuthnController.php b/core/Controller/WebAuthnController.php index d7255831e88de..c3f45ddeb7b0f 100644 --- a/core/Controller/WebAuthnController.php +++ b/core/Controller/WebAuthnController.php @@ -20,7 +20,7 @@ use OCP\AppFramework\Http\JSONResponse; use OCP\IRequest; use OCP\ISession; -use OCP\Util; +use OCP\IUserManager; use Psr\Log\LoggerInterface; use Webauthn\PublicKeyCredentialRequestOptions; @@ -36,6 +36,7 @@ public function __construct( private LoggerInterface $logger, private WebAuthnChain $webAuthnChain, private URLGenerator $urlGenerator, + private IUserManager $userManager, ) { parent::__construct($appName, $request); } @@ -47,12 +48,7 @@ public function startAuthentication(string $loginName): JSONResponse { $this->logger->debug('Starting WebAuthn login'); $this->logger->debug('Converting login name to UID'); - $uid = $loginName; - Util::emitHook( - '\OCA\Files_Sharing\API\Server2Server', - 'preLoginNameUsedAsUserName', - ['uid' => &$uid] - ); + $uid = $this->userManager->getUserNameFromLoginName($loginName); $this->logger->debug('Got UID: ' . $uid); $publicKeyCredentialRequestOptions = $this->webAuthnManger->startAuthentication($uid, $this->request->getServerHost()); diff --git a/lib/base.php b/lib/base.php index a11334c50cfd7..83aa384fe3b37 100644 --- a/lib/base.php +++ b/lib/base.php @@ -821,14 +821,6 @@ public static function init(): void { Server::get(\OCP\IUserManager::class)->registerBackend(new \OC\User\Database()); Server::get(\OCP\IGroupManager::class)->addBackend(new \OC\Group\Database()); - // Subscribe to the hook - \OCP\Util::connectHook( - '\OCA\Files_Sharing\API\Server2Server', - 'preLoginNameUsedAsUserName', - '\OC\User\Database', - 'preLoginNameUsedAsUserName' - ); - //setup extra user backends if (!\OCP\Util::needUpgrade()) { OC_User::setupBackends(); diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 35992e16837d2..1c78a98a9bb37 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -1012,6 +1012,7 @@ 'OCP\\User\\Backend\\IGetDisplayNameBackend' => $baseDir . '/lib/public/User/Backend/IGetDisplayNameBackend.php', 'OCP\\User\\Backend\\IGetHomeBackend' => $baseDir . '/lib/public/User/Backend/IGetHomeBackend.php', 'OCP\\User\\Backend\\IGetRealUIDBackend' => $baseDir . '/lib/public/User/Backend/IGetRealUIDBackend.php', + 'OCP\\User\\Backend\\IGetUserNameFromLoginNameBackend' => $baseDir . '/lib/public/User/Backend/IGetUserNameFromLoginNameBackend.php', 'OCP\\User\\Backend\\ILimitAwareCountUsersBackend' => $baseDir . '/lib/public/User/Backend/ILimitAwareCountUsersBackend.php', 'OCP\\User\\Backend\\IPasswordConfirmationBackend' => $baseDir . '/lib/public/User/Backend/IPasswordConfirmationBackend.php', 'OCP\\User\\Backend\\IPasswordHashBackend' => $baseDir . '/lib/public/User/Backend/IPasswordHashBackend.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index 79c4de8f32767..55db5ea2721d5 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -1053,6 +1053,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\User\\Backend\\IGetDisplayNameBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IGetDisplayNameBackend.php', 'OCP\\User\\Backend\\IGetHomeBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IGetHomeBackend.php', 'OCP\\User\\Backend\\IGetRealUIDBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IGetRealUIDBackend.php', + 'OCP\\User\\Backend\\IGetUserNameFromLoginNameBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IGetUserNameFromLoginNameBackend.php', 'OCP\\User\\Backend\\ILimitAwareCountUsersBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/ILimitAwareCountUsersBackend.php', 'OCP\\User\\Backend\\IPasswordConfirmationBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IPasswordConfirmationBackend.php', 'OCP\\User\\Backend\\IPasswordHashBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IPasswordHashBackend.php', diff --git a/lib/private/Authentication/Listeners/LoginFailedListener.php b/lib/private/Authentication/Listeners/LoginFailedListener.php index 7e46d2e7b246b..8dd3300655cfd 100644 --- a/lib/private/Authentication/Listeners/LoginFailedListener.php +++ b/lib/private/Authentication/Listeners/LoginFailedListener.php @@ -15,7 +15,6 @@ use OCP\EventDispatcher\IEventDispatcher; use OCP\EventDispatcher\IEventListener; use OCP\IUserManager; -use OCP\Util; /** * @template-implements IEventListener @@ -35,11 +34,7 @@ public function handle(Event $event): void { $this->dispatcher->dispatchTyped(new AnyLoginFailedEvent($event->getLoginName(), $event->getPassword())); $uid = $event->getLoginName(); - Util::emitHook( - '\OCA\Files_Sharing\API\Server2Server', - 'preLoginNameUsedAsUserName', - ['uid' => &$uid] - ); + $uid = $this->userManager->getUserNameFromLoginName($uid); if ($this->userManager->userExists($uid)) { $this->dispatcher->dispatchTyped(new LoginFailedEvent($uid)); } diff --git a/lib/private/Files/Filesystem.php b/lib/private/Files/Filesystem.php index fcefbac5e24fa..db91d0b02f1bc 100644 --- a/lib/private/Files/Filesystem.php +++ b/lib/private/Files/Filesystem.php @@ -133,6 +133,10 @@ class Filesystem { * @param string $path */ public const signal_delete = 'delete'; + public const signal_post_delete = 'post_delete'; + + public const signal_touch = 'touch'; + public const signal_post_touch = 'post_touch'; /** * parameters definitions for signals @@ -150,6 +154,9 @@ class Filesystem { public const signal_delete_mount = 'delete_mount'; public const signal_param_mount_type = 'mounttype'; public const signal_param_users = 'users'; + public const signal_setup = 'setup'; + public const signal_pre_setup = 'preSetup'; + public const signal_post_init_mountpoints = 'post_initMountPoints'; private static ?StorageFactory $loader = null; diff --git a/lib/private/Files/Node/HookConnector.php b/lib/private/Files/Node/HookConnector.php index 1149951174cbf..2638043c7dc41 100644 --- a/lib/private/Files/Node/HookConnector.php +++ b/lib/private/Files/Node/HookConnector.php @@ -44,25 +44,25 @@ public function __construct( } public function viewToNode() { - Util::connectHook('OC_Filesystem', 'write', $this, 'write'); - Util::connectHook('OC_Filesystem', 'post_write', $this, 'postWrite'); + Util::connectHook(Filesystem::CLASSNAME, Filesystem::signal_write, $this, 'write'); + Util::connectHook(Filesystem::CLASSNAME, Filesystem::signal_post_write, $this, 'postWrite'); - Util::connectHook('OC_Filesystem', 'create', $this, 'create'); - Util::connectHook('OC_Filesystem', 'post_create', $this, 'postCreate'); + Util::connectHook(Filesystem::CLASSNAME, 'create', $this, 'create'); + Util::connectHook(Filesystem::CLASSNAME, 'post_create', $this, 'postCreate'); - Util::connectHook('OC_Filesystem', 'delete', $this, 'delete'); - Util::connectHook('OC_Filesystem', 'post_delete', $this, 'postDelete'); + Util::connectHook(Filesystem::CLASSNAME, 'delete', $this, 'delete'); + Util::connectHook(Filesystem::CLASSNAME, 'post_delete', $this, 'postDelete'); - Util::connectHook('OC_Filesystem', 'rename', $this, 'rename'); - Util::connectHook('OC_Filesystem', 'post_rename', $this, 'postRename'); + Util::connectHook(Filesystem::CLASSNAME, 'rename', $this, 'rename'); + Util::connectHook(Filesystem::CLASSNAME, 'post_rename', $this, 'postRename'); - Util::connectHook('OC_Filesystem', 'copy', $this, 'copy'); - Util::connectHook('OC_Filesystem', 'post_copy', $this, 'postCopy'); + Util::connectHook(Filesystem::CLASSNAME, 'copy', $this, 'copy'); + Util::connectHook(Filesystem::CLASSNAME, 'post_copy', $this, 'postCopy'); - Util::connectHook('OC_Filesystem', 'touch', $this, 'touch'); - Util::connectHook('OC_Filesystem', 'post_touch', $this, 'postTouch'); + Util::connectHook(Filesystem::CLASSNAME, 'touch', $this, 'touch'); + Util::connectHook(Filesystem::CLASSNAME, 'post_touch', $this, 'postTouch'); - Util::connectHook('OC_Filesystem', 'read', $this, 'read'); + Util::connectHook(Filesystem::CLASSNAME, 'read', $this, 'read'); } public function write($arguments) { diff --git a/lib/private/User/Database.php b/lib/private/User/Database.php index 7877deff62f37..0f65523ffdf01 100644 --- a/lib/private/User/Database.php +++ b/lib/private/User/Database.php @@ -14,7 +14,6 @@ use OCP\EventDispatcher\IEventDispatcher; use OCP\IConfig; use OCP\IDBConnection; -use OCP\IUserManager; use OCP\Security\Events\ValidatePasswordPolicyEvent; use OCP\Security\IHasher; use OCP\Server; @@ -24,11 +23,13 @@ use OCP\User\Backend\IGetDisplayNameBackend; use OCP\User\Backend\IGetHomeBackend; use OCP\User\Backend\IGetRealUIDBackend; +use OCP\User\Backend\IGetUserNameFromLoginNameBackend; use OCP\User\Backend\ILimitAwareCountUsersBackend; use OCP\User\Backend\IPasswordHashBackend; use OCP\User\Backend\ISearchKnownUsersBackend; use OCP\User\Backend\ISetDisplayNameBackend; use OCP\User\Backend\ISetPasswordBackend; +use Override; /** * Class for user management in a SQL Database (e.g. MySQL, SQLite) @@ -43,8 +44,8 @@ class Database extends ABackend implements ILimitAwareCountUsersBackend, ISearchKnownUsersBackend, IGetRealUIDBackend, - IPasswordHashBackend { - + IPasswordHashBackend, + IGetUserNameFromLoginNameBackend { private CappedMemoryCache $cache; private IConfig $config; private ?IDBConnection $dbConnection; @@ -491,13 +492,8 @@ public function countUsers(int $limit = 0): int|false { return (int)$result; } - /** - * returns the username for the given login name in the correct casing - * - * @param string $loginName - * @return string|false - */ - public function loginName2UserName($loginName) { + #[Override] + public function getUserNameFromLoginName(string $loginName): string|false { if ($this->userExists($loginName)) { return $this->cache[$loginName]['uid']; } @@ -510,28 +506,10 @@ public function loginName2UserName($loginName) { * * @return string the name of the backend to be shown */ - public function getBackendName() { + public function getBackendName(): string { return 'Database'; } - public static function preLoginNameUsedAsUserName($param) { - if (!isset($param['uid'])) { - throw new \Exception('key uid is expected to be set in $param'); - } - - $backends = Server::get(IUserManager::class)->getBackends(); - foreach ($backends as $backend) { - if ($backend instanceof Database) { - /** @var Database $backend */ - $uid = $backend->loginName2UserName($param['uid']); - if ($uid !== false) { - $param['uid'] = $uid; - return; - } - } - } - } - public function getRealUID(string $uid): string { if (!$this->userExists($uid)) { throw new \RuntimeException($uid . ' does not exist'); diff --git a/lib/private/User/Manager.php b/lib/private/User/Manager.php index 5c899b7892f21..4fe3e2334f12d 100644 --- a/lib/private/User/Manager.php +++ b/lib/private/User/Manager.php @@ -29,6 +29,7 @@ use OCP\User\Backend\ICountMappedUsersBackend; use OCP\User\Backend\ICountUsersBackend; use OCP\User\Backend\IGetRealUIDBackend; +use OCP\User\Backend\IGetUserNameFromLoginNameBackend; use OCP\User\Backend\ILimitAwareCountUsersBackend; use OCP\User\Backend\IProvideEnabledStateBackend; use OCP\User\Backend\ISearchKnownUsersBackend; @@ -36,6 +37,7 @@ use OCP\User\Events\UserCreatedEvent; use OCP\UserInterface; use OCP\Util; +use Override; use Psr\Log\LoggerInterface; /** @@ -837,4 +839,18 @@ public function getSeenUsers(int $offset = 0, ?int $limit = null): \Iterator { public function getExistingUser(string $userId, ?string $displayName = null): IUser { return new LazyUser($userId, $this, $displayName); } + + #[Override] + public function getUserNameFromLoginName(string $loginName): string { + $userName = $loginName; + foreach ($this->getBackends() as $backend) { + if ($backend instanceof IGetUserNameFromLoginNameBackend) { + $newUserName = $backend->getUserNameFromLoginName($loginName); + if ($newUserName !== false) { + $userName = $newUserName; + } + } + } + return $userName; + } } diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php index 811c5ba4bc326..9aaa7b3047478 100644 --- a/lib/private/User/Session.php +++ b/lib/private/User/Session.php @@ -473,11 +473,7 @@ private function isTokenAuthEnforced(): bool { } protected function isTwoFactorEnforced($username) { - Util::emitHook( - '\OCA\Files_Sharing\API\Server2Server', - 'preLoginNameUsedAsUserName', - ['uid' => &$username] - ); + $username = $this->manager->getUserNameFromLoginName($username); $user = $this->manager->get($username); if (is_null($user)) { $users = $this->manager->getByEmail($username); diff --git a/lib/private/legacy/OC_Hook.php b/lib/private/legacy/OC_Hook.php index 888057a7aca23..2912667d3aa88 100644 --- a/lib/private/legacy/OC_Hook.php +++ b/lib/private/legacy/OC_Hook.php @@ -5,15 +5,82 @@ * SPDX-FileCopyrightText: 2016 ownCloud, Inc. * SPDX-License-Identifier: AGPL-3.0-only */ + +use OC\Files\Filesystem; use OC\ServerNotAvailableException; use OCP\HintException; use OCP\Server; +use OCP\Share; use Psr\Log\LoggerInterface; class OC_Hook { public static $thrownExceptions = []; - private static $registered = []; + private static array $registered = []; + + private static array $allowList = [ + [Filesystem::CLASSNAME, Filesystem::signal_read], + [Filesystem::CLASSNAME, Filesystem::signal_create], + [Filesystem::CLASSNAME, Filesystem::signal_post_create], + [Filesystem::CLASSNAME, Filesystem::signal_update], + [Filesystem::CLASSNAME, Filesystem::signal_post_update], + [Filesystem::CLASSNAME, Filesystem::signal_write], + [Filesystem::CLASSNAME, Filesystem::signal_post_write], + [Filesystem::CLASSNAME, Filesystem::signal_delete], + [Filesystem::CLASSNAME, Filesystem::signal_post_delete], + [Filesystem::CLASSNAME, Filesystem::signal_rename], + [Filesystem::CLASSNAME, Filesystem::signal_post_rename], + [Filesystem::CLASSNAME, Filesystem::signal_copy], + [Filesystem::CLASSNAME, Filesystem::signal_post_copy], + [Filesystem::CLASSNAME, Filesystem::signal_touch], + [Filesystem::CLASSNAME, Filesystem::signal_post_touch], + [Filesystem::CLASSNAME, Filesystem::signal_delete_mount], + [Filesystem::CLASSNAME, Filesystem::signal_create_mount], + [Filesystem::CLASSNAME, Filesystem::signal_setup], + [Filesystem::CLASSNAME, Filesystem::signal_pre_setup], + [Filesystem::CLASSNAME, Filesystem::signal_post_init_mountpoints], + [Filesystem::CLASSNAME, 'umount'], + [Share::class,'share_link_access'], + [Share::class,'pre_unshare'], + [Share::class,'post_unshare'], + [Share::class,'post_unshareFromSelf'], + [Share::class,'pre_shared'], + [Share::class,'post_shared'], + [Share::class,'post_set_expiration_date'], + [Share::class,'post_update_password'], + [Share::class,'post_update_permissions'], + ['\OC\Share','verifyExpirationDate'], + ['\OC\Files\Storage\Shared','fopen'], + ['\OC\Files\Storage\Shared','file_get_contents'], + ['\OC\Files\Storage\Shared','file_put_contents'], + [\OCA\Files_Trashbin\Trashbin::class,'post_moveToTrash'], + [\OCA\Files_Trashbin\Trashbin::class,'post_restore'], + ['\OCP\Trashbin','preDeleteAll'], + ['\OCP\Trashbin','deleteAll'], + ['\OCP\Versions','rollback'], + ['\OCP\Versions','preDelete'], + ['\OCP\Versions','delete'], + [OC_User::class,'pre_createUser'], + [OC_User::class,'post_createUser'], + [OC_User::class,'pre_deleteUser'], + [OC_User::class,'post_deleteUser'], + [OC_User::class,'pre_setPassword'], + [OC_User::class,'post_setPassword'], + [OC_User::class,'pre_login'], + [OC_User::class,'post_login'], + [OC_User::class,'logout'], + [OC_User::class,'changeUser'], + ['\OC\User','assignedUserId'], + ['\OC\User','preUnassignedUserId'], + ['\OC\User','postUnassignedUserId'], + [OC\Files\Cache\Scanner::class,'scan_file'], + [OC\Files\Cache\Scanner::class,'post_scan_file'], + ['Scanner','removeFromCache'], + ['Scanner','addToCache'], + ['Scanner','correctFolderSize'], + ['\OC\Core\LostPassword\Controller\LostController','post_passwordReset'], + ['\OC\Core\LostPassword\Controller\LostController','pre_passwordReset'], + ]; /** * connects a function to a hook @@ -22,13 +89,23 @@ class OC_Hook { * @param string $signalName name of signal * @param string|object $slotClass class name of slot * @param string $slotName name of slot - * @return bool * * This function makes it very easy to connect to use hooks. * * TODO: write example */ - public static function connect($signalClass, $signalName, $slotClass, $slotName) { + public static function connect(string $signalClass, string $signalName, string|object $slotClass, string $slotName): bool { + if (str_starts_with($signalClass, '/')) { + $signalName = substr($signalClass, 1); + } + $found = array_find(self::$allowList, function ($allowed) use ($signalClass, $signalName) { + [$allowedClass, $allowedSignal] = $allowed; + return $allowedClass === $signalClass && $allowedSignal === $signalName; + }) !== null; + + if (!$found) { + throw new \RuntimeException("The signal $signalClass::$signalName is no longer emitted in server. Listening to it is NOOP."); + } // If we're trying to connect to an emitting class that isn't // yet registered, register it if (!array_key_exists($signalClass, self::$registered)) { @@ -68,7 +145,10 @@ public static function connect($signalClass, $signalName, $slotClass, $slotName) * * TODO: write example */ - public static function emit($signalClass, $signalName, $params = []) { + public static function emit(string $signalClass, string $signalName, $params = []): bool { + if (str_starts_with($signalClass, '/')) { + $signalName = substr($signalClass, 1); + } // Return false if no hook handlers are listening to this // emitting class if (!array_key_exists($signalClass, self::$registered)) { @@ -101,12 +181,13 @@ public static function emit($signalClass, $signalName, $params = []) { } /** - * clear hooks - * @param string $signalClass - * @param string $signalName + * Clear hooks */ - public static function clear($signalClass = '', $signalName = '') { + public static function clear(string $signalClass = '', string $signalName = ''): void { if ($signalClass) { + if (str_starts_with($signalClass, '/')) { + $signalName = substr($signalClass, 1); + } if ($signalName) { self::$registered[$signalClass][$signalName] = []; } else { @@ -121,7 +202,7 @@ public static function clear($signalClass = '', $signalName = '') { * DO NOT USE! * For unit tests ONLY! */ - public static function getHooks() { + public static function getHooks(): array { return self::$registered; } } diff --git a/lib/private/legacy/OC_User.php b/lib/private/legacy/OC_User.php index ddd426da942e4..46f6e98dca5c9 100644 --- a/lib/private/legacy/OC_User.php +++ b/lib/private/legacy/OC_User.php @@ -147,7 +147,7 @@ public static function setupBackends() { public static function loginWithApache(IApacheBackend $backend): bool { $uid = $backend->getCurrentUserId(); $run = true; - OC_Hook::emit('OC_User', 'pre_login', ['run' => &$run, 'uid' => $uid, 'backend' => $backend]); + Util::emitHook('OC_User', 'pre_login', ['run' => &$run, 'uid' => $uid, 'backend' => $backend]); if ($uid) { if (self::getUser() !== $uid) { @@ -196,7 +196,7 @@ public static function loginWithApache(IApacheBackend $backend): bool { // completed before we can safely create the users folder. // For example encryption needs to initialize the users keys first // before we can create the user folder with the skeleton files - OC_Hook::emit( + Util::emitHook( 'OC_User', 'post_login', [ diff --git a/lib/public/IUserManager.php b/lib/public/IUserManager.php index 4d4006282aac7..85bdc257a2176 100644 --- a/lib/public/IUserManager.php +++ b/lib/public/IUserManager.php @@ -266,4 +266,11 @@ public function getSeenUsers(int $offset = 0, ?int $limit = null): \Iterator; * @since 33.0.0 */ public function getExistingUser(string $userId, ?string $displayName = null): IUser; + + /** + * Get the username of a user based on its login name. + * + * @since 34.0.0 + */ + public function getUserNameFromLoginName(string $loginName): string; } diff --git a/lib/public/User/Backend/IGetUserNameFromLoginNameBackend.php b/lib/public/User/Backend/IGetUserNameFromLoginNameBackend.php new file mode 100644 index 0000000000000..a1c61bf5b3a83 --- /dev/null +++ b/lib/public/User/Backend/IGetUserNameFromLoginNameBackend.php @@ -0,0 +1,15 @@ +with($this->equalTo('foo')) ->willReturn(true); $backend->expects($this->never()) - ->method('loginName2UserName'); + ->method('getUserNameFromLoginName'); $manager = new Manager($this->config, $this->cacheFactory, $this->eventDispatcher, $this->logger); $manager->registerBackend($backend); @@ -228,7 +228,7 @@ public function testGetOneBackendDoNotTranslateLoginNames(): void { ->with($this->equalTo('bLeNdEr')) ->willReturn(true); $backend->expects($this->never()) - ->method('loginName2UserName'); + ->method('getUserNameFromLoginName'); $manager = new Manager($this->config, $this->cacheFactory, $this->eventDispatcher, $this->logger); $manager->registerBackend($backend); @@ -243,7 +243,7 @@ public function testSearchOneBackend(): void { ->with($this->equalTo('fo')) ->willReturn(['foo', 'afoo', 'Afoo1', 'Bfoo']); $backend->expects($this->never()) - ->method('loginName2UserName'); + ->method('getUserNameFromLoginName'); $manager = new Manager($this->config, $this->cacheFactory, $this->eventDispatcher, $this->logger); $manager->registerBackend($backend); @@ -263,7 +263,7 @@ public function testSearchTwoBackendLimitOffset(): void { ->with($this->equalTo('fo'), $this->equalTo(3), $this->equalTo(1)) ->willReturn(['foo1', 'foo2']); $backend1->expects($this->never()) - ->method('loginName2UserName'); + ->method('getUserNameFromLoginName'); $backend2 = $this->createMock(\Test\Util\User\Dummy::class); $backend2->expects($this->once()) @@ -271,7 +271,7 @@ public function testSearchTwoBackendLimitOffset(): void { ->with($this->equalTo('fo'), $this->equalTo(3), $this->equalTo(1)) ->willReturn(['foo3']); $backend2->expects($this->never()) - ->method('loginName2UserName'); + ->method('getUserNameFromLoginName'); $manager = new Manager($this->config, $this->cacheFactory, $this->eventDispatcher, $this->logger); $manager->registerBackend($backend1); @@ -348,7 +348,7 @@ public function testCreateUserSingleBackendNotExists(): void { ->with($this->equalTo('foo')) ->willReturn(false); $backend->expects($this->never()) - ->method('loginName2UserName'); + ->method('getUserNameFromLoginName'); $manager = new Manager($this->config, $this->cacheFactory, $this->eventDispatcher, $this->logger); $manager->registerBackend($backend); diff --git a/tests/lib/Util/User/Dummy.php b/tests/lib/Util/User/Dummy.php index 4a85f92981ce1..e7633eec2d86c 100644 --- a/tests/lib/Util/User/Dummy.php +++ b/tests/lib/Util/User/Dummy.php @@ -53,7 +53,7 @@ public function checkPassword($uid, $password): string|false { return false; } - public function loginName2UserName($loginName): string|false { + public function getUserNameFromLoginName($loginName): string|false { if (isset($this->users[strtolower($loginName)])) { return strtolower($loginName); }