diff --git a/src/Bundle/ChillMainBundle/Controller/UserExportController.php b/src/Bundle/ChillMainBundle/Controller/UserExportController.php index 2fe199ee6..e1f8b9b20 100644 --- a/src/Bundle/ChillMainBundle/Controller/UserExportController.php +++ b/src/Bundle/ChillMainBundle/Controller/UserExportController.php @@ -31,16 +31,13 @@ final readonly class UserExportController } /** - * @param Request $request - * @param string $_format - * @return Response * @throws \League\Csv\CannotInsertRecord * @throws \League\Csv\Exception * @throws \League\Csv\UnavailableStream * * @Route("/{_locale}/admin/main/users/export/list.{_format}", requirements={"_format": "csv"}, name="chill_main_users_export_list") */ - public function userList(Request $request, string $_format = 'csv'): Response + public function userList(Request $request, string $_format = 'csv'): StreamedResponse { if (!$this->security->isGranted('ROLE_ADMIN')) { throw new AccessDeniedHttpException('Only ROLE_ADMIN can export this list'); @@ -94,4 +91,54 @@ final readonly class UserExportController ); } + /** + * @return StreamedResponse + * @throws \League\Csv\CannotInsertRecord + * @throws \League\Csv\Exception + * @throws \League\Csv\UnavailableStream + * + * @Route("/{_locale}/admin/main/users/export/permissions.{_format}", requirements={"_format": "csv"}, name="chill_main_users_export_permissions") + */ + public function userPermissionsList(string $_format = 'csv'): StreamedResponse + { + if (!$this->security->isGranted('ROLE_ADMIN')) { + throw new AccessDeniedHttpException('Only ROLE_ADMIN can export this list'); + } + + $userPermissions = $this->userRepository->findAllUserACLAsArray(); + + $csv = Writer::createFromPath('php://temp', 'r+'); + $csv->insertOne( + array_map( + fn (string $e) => $this->translator->trans('admin.users.export.' . $e), + [ + 'id', + 'username', + 'email', + 'enabled', + 'center_id', + 'center_name', + 'permissionsGroup_id', + 'permissionsGroup_name', + ] + ) + ); + $csv->insertAll($userPermissions); + + return new StreamedResponse( + function () use ($csv) { + foreach ($csv->chunk(1024) as $chunk) { + echo $chunk; + flush(); + } + }, + Response::HTTP_OK, + [ + 'Content-Encoding' => 'none', + 'Content-Type' => 'text/csv; charset=UTF-8', + 'Content-Disposition' => 'attachment; users.csv', + ] + ); + } + } diff --git a/src/Bundle/ChillMainBundle/Repository/UserRepository.php b/src/Bundle/ChillMainBundle/Repository/UserRepository.php index ac6128042..9bc48d3ab 100644 --- a/src/Bundle/ChillMainBundle/Repository/UserRepository.php +++ b/src/Bundle/ChillMainBundle/Repository/UserRepository.php @@ -123,6 +123,34 @@ final class UserRepository implements UserRepositoryInterface } } + public function findAllUserACLAsArray(): iterable + { + $sql = <<<'SQL' + SELECT + u.id, + u.username, + u.label, + u.enabled, + c.id AS center_id, + c.name AS center_name, + pg.id AS permissionsGroup_id, + pg.name AS permissionsGroup_name + FROM users u + LEFT JOIN user_groupcenter ON u.id = user_groupcenter.user_id + LEFT JOIN group_centers ON user_groupcenter.groupcenter_id = group_centers.id + LEFT JOIN centers c on group_centers.center_id = c.id + LEFT JOIN permission_groups pg on group_centers.permissionsgroup_id = pg.id + ORDER BY u.username, c.name, pg.name + SQL; + + $query = $this->entityManager->getConnection()->executeQuery($sql); + + foreach ($query->iterateAssociative() as $u) { + yield $u; + } + } + + /** * @param mixed|null $limit * @param mixed|null $offset diff --git a/src/Bundle/ChillMainBundle/Repository/UserRepositoryInterface.php b/src/Bundle/ChillMainBundle/Repository/UserRepositoryInterface.php index 99234dbec..b405e2d23 100644 --- a/src/Bundle/ChillMainBundle/Repository/UserRepositoryInterface.php +++ b/src/Bundle/ChillMainBundle/Repository/UserRepositoryInterface.php @@ -28,11 +28,25 @@ interface UserRepositoryInterface extends ObjectRepository public function countByUsernameOrEmail(string $pattern): int; /** + * Find a list of all users. + * + * The main purpose for this method is to provide a lightweight list of all users in the database. + * * @param string $lang The lang to display all the translatable string (no fallback if not present) - * @return iterable + * @return iterable */ public function findAllAsArray(string $lang): iterable; + /** + * Find a list of permissions associated to each users. + * + * The main purpose for this method is to provide a lightweight list of all permissions group and center + * associated to each user. + * + * @return iterable + */ + public function findAllUserACLAsArray(): iterable; + /** * @return array|User[] */ diff --git a/src/Bundle/ChillMainBundle/Resources/views/User/index.html.twig b/src/Bundle/ChillMainBundle/Resources/views/User/index.html.twig index 446607a45..c5cd73d18 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/User/index.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/User/index.html.twig @@ -106,6 +106,7 @@ diff --git a/src/Bundle/ChillMainBundle/translations/messages.fr.yml b/src/Bundle/ChillMainBundle/translations/messages.fr.yml index d65cc7fab..13c300fdd 100644 --- a/src/Bundle/ChillMainBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillMainBundle/translations/messages.fr.yml @@ -614,6 +614,7 @@ absence: admin: users: export_list_csv: Liste des utilisateurs (format CSV) + export_permissions_csv: Association utilisateurs - groupes de permissions - centre (format CSV) export: id: Identifiant username: Nom d'utilisateur @@ -634,3 +635,7 @@ admin: mainLocation_id: Identifiant localisation principale mainLocation_name: Localisation principale absenceStart: Absent à partir du + center_id: Identifiant du centre + center_name: Centre + permissionsGroup_id: Identifiant du groupe de permissions + permissionsGroup_name: Groupe de permissions