diff --git a/apps/user_status/lib/Controller/StatusesController.php b/apps/user_status/lib/Controller/StatusesController.php index 44688c390232b..a4daf45c7f9cb 100644 --- a/apps/user_status/lib/Controller/StatusesController.php +++ b/apps/user_status/lib/Controller/StatusesController.php @@ -18,7 +18,9 @@ use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCS\OCSNotFoundException; use OCP\AppFramework\OCSController; +use OCP\EventDispatcher\IEventDispatcher; use OCP\IRequest; +use OCP\User\Events\UserEnumerationFilterEvent; use OCP\UserStatus\IUserStatus; /** @@ -37,7 +39,8 @@ class StatusesController extends OCSController { public function __construct( string $appName, IRequest $request, - private StatusService $service, + private readonly StatusService $service, + private readonly IEventDispatcher $eventDispatcher, ) { parent::__construct($appName, $request); } @@ -56,6 +59,15 @@ public function __construct( public function findAll(?int $limit = null, ?int $offset = null): DataResponse { $allStatuses = $this->service->findAll($limit, $offset); + $users = array_map(fn (UserStatus $userStatus): string => $userStatus->getUserId(), $allStatuses); + $event = new UserEnumerationFilterEvent($users); + $this->eventDispatcher->dispatchTyped($event); + + if ($users !== $event->getUsers()) { + $removedUsers = $event->getFilteredOutUsers(); + $allStatuses = array_filter($allStatuses, fn (UserStatus $userStatus): bool => in_array($userStatus->getUserId(), $removedUsers, true)); + } + return new DataResponse(array_values(array_map(function ($userStatus) { return $this->formatStatus($userStatus); }, $allStatuses))); diff --git a/apps/user_status/lib/Service/StatusService.php b/apps/user_status/lib/Service/StatusService.php index 1a26f755fb17e..f352453c374b2 100644 --- a/apps/user_status/lib/Service/StatusService.php +++ b/apps/user_status/lib/Service/StatusService.php @@ -81,7 +81,7 @@ public function __construct( /** * @param int|null $limit * @param int|null $offset - * @return UserStatus[] + * @return list */ public function findAll(?int $limit = null, ?int $offset = null): array { // Return empty array if user enumeration is disabled or limited to groups @@ -91,9 +91,9 @@ public function findAll(?int $limit = null, ?int $offset = null): array { return []; } - return array_map(function ($status) { + return array_values(array_map(function ($status) { return $this->processStatus($status); - }, $this->mapper->findAll($limit, $offset)); + }, $this->mapper->findAll($limit, $offset))); } /** diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 0598416ae7eb5..652a18ce33e3c 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -1073,6 +1073,7 @@ 'OCP\\User\\Events\\UserConfigChangedEvent' => $baseDir . '/lib/public/User/Events/UserConfigChangedEvent.php', 'OCP\\User\\Events\\UserCreatedEvent' => $baseDir . '/lib/public/User/Events/UserCreatedEvent.php', 'OCP\\User\\Events\\UserDeletedEvent' => $baseDir . '/lib/public/User/Events/UserDeletedEvent.php', + 'OCP\\User\\Events\\UserEnumerationFilterEvent' => $baseDir . '/lib/public/User/Events/UserEnumerationFilterEvent.php', 'OCP\\User\\Events\\UserFirstTimeLoggedInEvent' => $baseDir . '/lib/public/User/Events/UserFirstTimeLoggedInEvent.php', 'OCP\\User\\Events\\UserIdAssignedEvent' => $baseDir . '/lib/public/User/Events/UserIdAssignedEvent.php', 'OCP\\User\\Events\\UserIdUnassignedEvent' => $baseDir . '/lib/public/User/Events/UserIdUnassignedEvent.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index e200f5cfc04b9..506ed6e89f41c 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -1114,6 +1114,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\User\\Events\\UserConfigChangedEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/UserConfigChangedEvent.php', 'OCP\\User\\Events\\UserCreatedEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/UserCreatedEvent.php', 'OCP\\User\\Events\\UserDeletedEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/UserDeletedEvent.php', + 'OCP\\User\\Events\\UserEnumerationFilterEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/UserEnumerationFilterEvent.php', 'OCP\\User\\Events\\UserFirstTimeLoggedInEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/UserFirstTimeLoggedInEvent.php', 'OCP\\User\\Events\\UserIdAssignedEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/UserIdAssignedEvent.php', 'OCP\\User\\Events\\UserIdUnassignedEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/UserIdUnassignedEvent.php', diff --git a/lib/public/User/Events/UserEnumerationFilterEvent.php b/lib/public/User/Events/UserEnumerationFilterEvent.php new file mode 100644 index 0000000000000..f26312180d2a3 --- /dev/null +++ b/lib/public/User/Events/UserEnumerationFilterEvent.php @@ -0,0 +1,66 @@ + $initialUsers */ + private readonly array $initialUsers; + + /** + * @param list $users + * @since 31.0.14 + */ + public function __construct( + private array $users, + ) { + $this->initialUsers = $users; + parent::__construct(); + } + + /** + * @return list + * @since 31.0.14 + */ + public function getUsers(): array { + return $this->users; + } + + /** + * @param list $users + * @since 31.0.14 + */ + public function setUsers(array $users): void { + $this->users = $users; + } + + /** + * Get the users what were filtered out by one of the listeners of this event. + * + * @return array, string> $users + * @since 31.0.14 + */ + public function getFilteredOutUsers(): array { + return array_diff($this->initialUsers, $this->users); + } +}