denyAccessUnlessGranted('ROLE_USER'); $user = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier()); if ($this->isGranted('ROLE_SUPER_ADMIN')) { $uo = $this->uoRepository->findUsersWithOrganization(); $noOrgUsers = $this->userService->formatNoOrgUsersAsAssoc( $this->userRepository->findUsersWithoutOrganization()); $usersByOrganization = $this->userService->groupByOrganization($uo); $usersByOrganization += $noOrgUsers; //Log action $this->actionService->createAction("View all users", $user, null, "All"); } else { $usersByOrganization = []; } return $this->render('user/index.html.twig', [ 'usersByOrganization' => $usersByOrganization, ]); } #[Route('/view/{id}', name: 'show', methods: ['GET'])] public function view(int $id, Request $request): Response { $this->denyAccessUnlessGranted('ROLE_USER'); $actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier()); if ($this->userService->hasAccessTo($actingUser)) { $user = $this->userRepository->find($id); try { $orgId = $request->query->get('organizationId'); if ($orgId) { $orgs = $this->organizationRepository->findBy(['id' => $orgId]); $uo = $this->uoRepository->findBy(['users' => $user, 'organization' => $orgs]); if (!$uo) { throw $this->createNotFoundException(self::NOT_FOUND); } $uoActive = $uo[0]->isActive(); } else { $uo = $this->uoRepository->findBy(['users' => $user, 'isActive' => true]); foreach ($uo as $u) { $orgs[] = $u->getOrganization(); } } $uoa = $this->entityManager->getRepository(UserOrganizatonApp::class)->findBy(['userOrganization' => $uo, 'isActive' => true]); $uoas = $this->userOrganizationAppService->groupUserOrganizationAppsByApplication($uoa); $this->actionService->createAction("View user information", $actingUser, null, $user->getUserIdentifier()); } catch (\Exception $e) { //ignore } } else { throw $this->createAccessDeniedException(self::ACCESS_DENIED); } return $this->render('user/show.html.twig', [ 'user' => $user, 'uoas' => $uoas ?? null, 'orgs' => $orgs ?? null, 'organizationId' => $orgId ?? null, 'uoActive' => $uoActive ?? null// specific for single organization context and deactivate user from said org ]); } #[Route('/edit/{id}', name: 'edit', methods: ['GET', 'POST'])] public function edit(int $id, Request $request): Response { $this->denyAccessUnlessGranted('ROLE_USER'); $actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier()); if ($this->userService->hasAccessTo($actingUser)) { $user = $this->userRepository->find($id); if (!$user) { throw $this->createNotFoundException(self::NOT_FOUND); } $form = $this->createForm(UserForm::class, $user); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { // Handle file upload $picture = $form->get('pictureUrl')->getData(); if ($picture) { $this->userService->handleProfilePicture($user, $picture); } $user->setModifiedAt(new \DateTimeImmutable('now')); $this->entityManager->persist($user); $this->entityManager->flush(); if ($request->get('organizationId')) { $org = $this->organizationRepository->find($request->get('organizationId')); if ($org) { $this->actionService->createAction("Edit user information", $actingUser, $org, $user->getUserIdentifier()); } } else { $this->actionService->createAction("Edit user information", $actingUser, null, $user->getUserIdentifier()); } return $this->redirectToRoute('user_show', ['id' => $user->getId(), 'organizationId' => $request->get('organizationId')]); } return $this->render('user/edit.html.twig', [ 'user' => $user, 'form' => $form->createView(), 'organizationId' => $request->get('organizationId') ]); } throw $this->createAccessDeniedException(self::ACCESS_DENIED); } #[Route('/new', name: 'new', methods: ['GET', 'POST'])] public function new(Request $request): Response { $this->denyAccessUnlessGranted('ROLE_ADMIN'); $actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier()); if ($this->userService->hasAccessTo($actingUser)) { $user = new User(); $form = $this->createForm(UserForm::class, $user); $form->handleRequest($request); $orgId = $request->get('organizationId'); if ($form->isSubmitted() && $form->isValid()) { // Handle file upload $picture = $form->get('pictureUrl')->getData(); if ($picture) { $this->userService->handleProfilePicture($user, $picture); } // else { // $user->setPictureUrl(""); // } //FOR TEST PURPOSES, SETTING A DEFAULT RANDOM PASSWORD $user->setPassword($this->userService->generateRandomPassword()); if ($orgId) { $org = $this->organizationRepository->find($orgId); if ($org) { $uo = new UsersOrganizations(); $uo->setUsers($user); $uo->setOrganization($org); $this->entityManager->persist($uo); $this->actionService->createAction("Create new user", $user, $org, "Added user to organization" . $user->getUserIdentifier() . " for organization " . $org->getName()); } } $this->actionService->createAction("Create new user", $actingUser, null, $user->getUserIdentifier()); $this->entityManager->persist($user); $this->entityManager->flush(); return $this->redirectToRoute('user_index'); } return $this->render('user/new.html.twig', [ 'user' => $user, 'form' => $form->createView(), 'organizationId' => $orgId ]); } throw $this->createAccessDeniedException(self::ACCESS_DENIED); } #[Route('/deactivate/{id}', name: 'deactivate', methods: ['GET', 'POST'])] public function deactivate(int $id): Response { $this->denyAccessUnlessGranted('ROLE_ADMIN'); $actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier()); if ($this->userService->hasAccessTo($actingUser, true)) { $user = $this->userRepository->find($id); if (!$user) { throw $this->createNotFoundException(self::NOT_FOUND); } $user->setIsActive(false); $user->setModifiedAt(new \DateTimeImmutable('now')); $this->userOrganizationService->deactivateAllUserOrganizationLinks($user, $actingUser); if($this->userService->isUserConnected($user->getUserIdentifier())){ $this->userService->revokeUserTokens($user->getUserIdentifier()); } $this->entityManager->persist($user); $this->entityManager->flush(); $this->actionService->createAction("Deactivate user", $actingUser, null, $user->getUserIdentifier()); return $this->redirectToRoute('user_index'); } throw $this->createAccessDeniedException(self::ACCESS_DENIED); } #[Route('/activate/{id}', name: 'activate', methods: ['GET', 'POST'])] public function activate(int $id): Response { $this->denyAccessUnlessGranted('ROLE_ADMIN'); $actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier()); if ($this->userService->hasAccessTo($actingUser, true)) { $user = $this->userRepository->find($id); if (!$user) { throw $this->createNotFoundException(self::NOT_FOUND); } $user->setIsActive(true); $user->setModifiedAt(new \DateTimeImmutable('now')); $this->entityManager->persist($user); $this->entityManager->flush(); $this->actionService->createAction("Activate user", $actingUser, null, $user->getUserIdentifier()); return $this->redirectToRoute('user_index'); } throw $this->createAccessDeniedException(self::ACCESS_DENIED); } #[Route('/organization/deactivate/{id}', name: 'deactivate_organization', methods: ['GET', 'POST'])] public function deactivateUserInOrganization(int $id, Request $request): Response { $this->denyAccessUnlessGranted('ROLE_ADMIN'); $actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier()); if ($this->userService->hasAccessTo($actingUser, true)) { $orgId = $request->get('organizationId'); $org = $this->organizationRepository->find($orgId); if (!$org) { throw $this->createNotFoundException(self::NOT_FOUND); } $user = $this->userRepository->find($id); if (!$user) { throw $this->createNotFoundException(self::NOT_FOUND); } $uo = $this->uoRepository->findOneBy(['users' => $user, 'organization' => $org, 'isActive' => true]); if (!$uo) { throw $this->createNotFoundException(self::NOT_FOUND); } $uo->setIsActive(false); $this->userOrganizationAppService->deactivateAllUserOrganizationsAppLinks($uo); $this->entityManager->persist($uo); $this->entityManager->flush(); $this->actionService->createAction("Deactivate user in organization", $actingUser, $org, $org->getName() . " for user " . $user->getUserIdentifier()); return new Response('', Response::HTTP_NO_CONTENT); //204 } throw $this->createAccessDeniedException(self::ACCESS_DENIED); } #[Route('/organization/activate/{id}', name: 'activate_organization', methods: ['GET', 'POST'])] public function activateUserInOrganization(int $id, Request $request): Response { $this->denyAccessUnlessGranted('ROLE_ADMIN'); $actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier()); if ($this->userService->hasAccessTo($actingUser, true)) { $orgId = $request->get('organizationId'); $org = $this->organizationRepository->find($orgId); if (!$org) { throw $this->createNotFoundException(self::NOT_FOUND); } $user = $this->userRepository->find($id); if (!$user) { throw $this->createNotFoundException(self::NOT_FOUND); } $uo = $this->uoRepository->findOneBy(['users' => $user, 'organization' => $org, 'isActive' => false]); if (!$uo) { throw $this->createNotFoundException(self::NOT_FOUND); } $uo->setIsActive(true); $this->entityManager->persist($uo); $this->entityManager->flush(); $this->actionService->createAction("Activate user in organization", $actingUser, $org, $org->getName() . " for user " . $user->getUserIdentifier()); return $this->redirectToRoute('user_index'); } throw $this->createAccessDeniedException(self::ACCESS_DENIED); } #[Route('/delete/{id}', name: 'delete', methods: ['GET', 'POST'])] public function delete(int $id, Request $request): Response { $this->denyAccessUnlessGranted("ROLE_SUPER_ADMIN"); $actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier()); $user = $this->userRepository->find($id); if (!$user) { throw $this->createNotFoundException(self::NOT_FOUND); } $user->setIsActive(false); $user->setModifiedAt(new \DateTimeImmutable('now')); $this->userOrganizationService->deactivateAllUserOrganizationLinks($user, $actingUser); $user->setIsDeleted(true); if($this->userService->isUserConnected($user)){ $this->userService->revokeUserTokens($user->getUserIdentifier()); } $this->entityManager->persist($user); $this->entityManager->flush(); $this->actionService->createAction("Delete user", $actingUser, null, $user->getUserIdentifier()); return new Response('', Response::HTTP_NO_CONTENT); //204 } #[Route(path: '/application/roles/{id}', name: 'application_role', methods: ['GET', 'POST'])] public function applicationRole(int $id, Request $request): Response { $this->denyAccessUnlessGranted("ROLE_ADMIN"); $actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier()); if ($this->userService->hasAccessTo($actingUser, true)) { $uo = $this->userOrganizationService->getByIdOrFail($id); $application = $this->entityManager->getRepository(Apps::class)->find($request->get('applicationId')); if (!$application) { throw $this->createNotFoundException(self::NOT_FOUND); } $selectedRolesIds = $request->get('roles', []); $roleUser = $this->entityManager->getRepository(Roles::class)->findOneBy(['name' => 'USER']); if (!$roleUser) { throw $this->createNotFoundException('Default role not found'); } if (!empty($selectedRolesIds)) { $this->userOrganizationAppService->syncRolesForUserOrganizationApp( $uo, $application, $selectedRolesIds, $actingUser ); } else { $this->userOrganizationAppService->deactivateAllUserOrganizationsAppLinks($uo, $application); } $user = $uo->getUsers(); return $this->redirectToRoute('user_show', [ 'user' => $user, 'id' => $user->getId(), 'organizationId' => $uo->getOrganization()->getId() ]); } throw $this->createAccessDeniedException(); } /* * AJAX endpoint for user listing with pagination * Get all the users that aren“t deleted and are active */ #[Route(path: '/data', name: 'data', methods: ['GET'])] public function data(Request $request): JsonResponse { $this->denyAccessUnlessGranted("ROLE_ADMIN"); $page = max(1, (int)$request->query->get('page', 1)); $size = max(1, (int)$request->query->get('size', 10)); // Get filter parameters $filters = $request->query->all('filter', []); $repo = $this->userRepository; // Base query $qb = $repo->createQueryBuilder('u') ->where('u.isDeleted = :del')->setParameter('del', false); // Apply filters if (!empty($filters['name'])) { $qb->andWhere('u.surname LIKE :name') ->setParameter('name', '%' . $filters['name'] . '%'); } if (!empty($filters['prenom'])) { $qb->andWhere('u.name LIKE :prenom') ->setParameter('prenom', '%' . $filters['prenom'] . '%'); } if (!empty($filters['email'])) { $qb->andWhere('u.email LIKE :email') ->setParameter('email', '%' . $filters['email'] . '%'); } $countQb = clone $qb; $total = (int)$countQb->select('COUNT(u.id)')->getQuery()->getSingleScalarResult(); // Pagination $offset = ($page - 1) * $size; $rows = $qb->setFirstResult($offset)->setMaxResults($size)->getQuery()->getResult(); // Map to array $data = array_map(function (User $user) { return [ 'id' => $user->getId(), 'pictureUrl' => $user->getPictureUrl(), 'name' => $user->getSurname(), 'prenom' => $user->getName(), 'email' => $user->getEmail(), 'isConnected' => $this->userService->isUserConnected($user->getUserIdentifier()), 'showUrl' => $this->generateUrl('user_show', ['id' => $user->getId()]), 'statut' => $user->isActive(), ]; }, $rows); $lastPage = (int)ceil($total / $size); return $this->json([ 'data' => $data, 'last_page' => $lastPage, 'total' => $total, ]); } #[Route(path: '/indexTest', name: 'indexTest', methods: ['GET'])] public function indexTest(): Response { $actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier()); if ($this->userService->hasAccessTo($actingUser, true) && $this->isGranted("ROLE_ADMIN")) { $totalUsers = $this->userRepository->count(['isDeleted' => false, 'isActive' => true]); return $this->render('user/indexTest.html.twig', [ 'users' => $totalUsers ]); } throw $this->createAccessDeniedException(self::ACCESS_DENIED); } /* * AJAX endpoint for new users listing * Get the 5 most recently created users for an organization */ #[Route(path: '/data/new', name: 'dataNew', methods: ['GET'])] public function dataNew(Request $request): JsonResponse { $actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier()); if ($this->userService->hasAccessTo($actingUser, true) && $this->isGranted("ROLE_ADMIN")) { $orgId = $request->query->get('orgId'); $uos = $this->uoRepository->findBy(['organization' => $orgId, 'isActive' =>true], limit: 5, orderBy: ['createdAt' => 'DESC']); // Map to array (keep isConnected) $data = array_map(function (UsersOrganizations $uo) { $user = $uo->getUsers(); $initials = $user->getName()[0] . $user->getSurname()[0]; return [ 'pictureUrl' => $user->getPictureUrl(), 'email' => $user->getEmail(), 'isConnected' => $this->userService->isUserConnected($user->getUserIdentifier()), 'showUrl' => $this->generateUrl('user_show', ['id' => $user->getId()]), 'initials' => strtoupper($initials), ]; }, $uos); return $this->json([ 'data' => $data, ]); } throw $this->createAccessDeniedException(self::ACCESS_DENIED); } /* * AJAX endpoint for admin users listing * Get all admin users for an organization */ #[Route(path: '/data/admin', name: 'dataAdmin', methods: ['GET'])] public function dataAdmin(Request $request): JsonResponse { $actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier()); if ($this->userService->hasAccessTo($actingUser, true) && $this->isGranted("ROLE_ADMIN")) { $orgId = $request->query->get('orgId'); $uos = $this->uoRepository->findBy(['organization' => $orgId]); $roleAdmin = $this->entityManager->getRepository(Roles::class)->findOneBy(['name' => 'ADMIN']); $users = []; foreach ($uos as $uo) { if ($this->entityManager->getRepository(UserOrganizatonApp::class)->findOneBy(['userOrganization' => $uo, 'role' => $roleAdmin])) { $users[] = $uo; } } // Map to array (keep isConnected) $data = array_map(function (UsersOrganizations $uo) { $user = $uo->getUsers(); $initials = $user->getName()[0] . $user->getSurname()[0]; return [ 'pictureUrl' => $user->getPictureUrl(), 'email' => $user->getEmail(), 'isConnected' => $this->userService->isUserConnected($user->getUserIdentifier()), 'showUrl' => $this->generateUrl('user_show', ['id' => $user->getId()]), 'initials' => strtoupper($initials), ]; }, $users); return $this->json([ 'data' => $data, ]); } throw $this->createAccessDeniedException(self::ACCESS_DENIED); } /* * AJAX endpoint for All users in an organization */ #[Route(path: '/data/organization', name: 'dataUserOrganization', methods: ['GET'])] public function dataUserOrganization(Request $request): JsonResponse { $actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier()); if ($this->userService->hasAccessTo($actingUser, true) && $this->isGranted("ROLE_ADMIN")) { $orgId = $request->query->get('orgId'); $page = max(1, (int)$request->query->get('page', 1)); $size = max(1, (int)$request->query->get('size', 10)); // Optional: read Tabulator remote sort/filter payloads // $sorters = $request->query->all('sorters') ?? []; // $filters = $request->query->all('filters') ?? []; $repo = $this->uoRepository; // Base query $qb = $repo->createQueryBuilder('uo') ->where('uo.organization = :orgId') ->setParameter('orgId', $orgId); $countQb = clone $qb; $total = (int)$countQb->select('COUNT(uo.id)')->getQuery()->getSingleScalarResult(); // Pagination $offset = ($page - 1) * $size; $rows = $qb->setFirstResult($offset)->setMaxResults($size)->getQuery()->getResult(); // Map to array $data = array_map(function (UsersOrganizations $uo) { $user = $uo->getUsers(); return [ 'pictureUrl' => $user->getPictureUrl(), 'name' => $user->getSurname(), 'prenom' => $user->getName(), 'email' => $user->getEmail(), 'isConnected' => $this->userService->isUserConnected($user->getUserIdentifier()), 'statut' => $uo->isActive(), 'showUrl' => $this->generateUrl('user_show', [ 'id' => $user->getId(), 'organizationId' => $uo->getOrganization()->getId(), ]), 'id' => $user->getId(), ]; }, $rows); // Return Tabulator-compatible response $lastPage = (int)ceil($total / $size); return $this->json([ 'data' => $data, 'last_page' => $lastPage, 'total' => $total, ]); } throw $this->createAccessDeniedException(self::ACCESS_DENIED); } }