profileDirectory = $profileDirectory; } /** * Generate a random password for a new user until they set their own. * @throws RandomException */ public function generateRandomPassword(): string { $length = 50; // Length of the password $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()_+'; $charactersLength = strlen($characters); $randomPassword = ''; for ($i = 0; $i < $length; $i++) { $randomPassword .= $characters[random_int(0, $charactersLength - 1)]; } return $randomPassword; } /** * Check if the user is currently connected. * This method check if the user is currently connected to one of the applications. * * @param String $userIdentifier * @return bool */ public function isUserConnected(string $userIdentifier): bool { $now = new DateTimeImmutable(); $tokens = $this->entityManager->getRepository(AccessToken::class)->findBy([ 'userIdentifier' => $userIdentifier, 'revoked' => false ]); foreach ($tokens as $token) { // Assuming $token->getExpiry() returns a DateTimeInterface if ($token->getExpiry() > $now) { return true; } } return false; } /** * Check if the user have the rights to access the page * * @param User $user * @param bool $skipSelfCheck * @return bool * @throws Exception */ public function hasAccessTo(User $user, bool $skipSelfCheck = false): bool { if (!$skipSelfCheck && $user->getUserIdentifier() === $this->security->getUser()->getUserIdentifier()) { return true; } $userOrganization = $this->entityManager->getRepository(UsersOrganizations::class)->findBy(['users' => $user]); if ($userOrganization) { foreach ($userOrganization as $uo) { if ($this->isAdminOfOrganization($uo)) { return true; } } } if ($this->security->isGranted('ROLE_SUPER_ADMIN')) { return true; } return false; } /** * Check if the user is an admin of the organization * A user is considered an admin of an organization if they have the 'ROLE_ADMIN' AND have the link to the * entity role 'ROLE_ADMIN' in the UsersOrganizationsApp entity * (if he is admin for any application of the organization). * * @param UsersOrganizations $usersOrganizations * @return bool * @throws Exception */ public function isAdminOfOrganization(UsersOrganizations $usersOrganizations): bool { $actingUser = $this->getUserByIdentifier($this->security->getUser()->getUserIdentifier()); $uo = $this->entityManager->getRepository(UsersOrganizations::class)->findOneBy(['users' => $actingUser]); $roleAdmin = $this->entityManager->getRepository(Roles::class)->findOneBy(['name' => 'ADMIN']); if ($uo) { $uoa = $this->entityManager->getRepository(UserOrganizatonApp::class)->findOneBy(['userOrganization' => $uo, 'role' => $roleAdmin, 'isActive' => true]); if ($uoa && $this->security->isGranted('ROLE_ADMIN')) { return true; } } return false; } /** * Get the Organizations id where the user is admin * * @param User $user * @return array * @throws Exception */ public function getAdminOrganizationsIds(User $user): array { $orgIds = []; try { $uo = $this->entityManager->getRepository(UsersOrganizations::class)->findBy(['users' => $user]); $roleAdmin = $this->entityManager->getRepository(Roles::class)->findOneBy(['name' => 'ADMIN']); if ($uo) { foreach ($uo as $u) { $uoa = $this->entityManager->getRepository(UserOrganizatonApp::class)->findOneBy(['userOrganization' => $u, 'role' => $roleAdmin, 'isActive' => true]); if ($uoa && $this->security->isGranted('ROLE_ADMIN')) { $orgIds[] = $u->getOrganization()->getId(); } } } } catch (EntityNotFoundException $e) { throw new EntityNotFoundException("Error while fetching organizations ids where the user is admin"); } return array_unique($orgIds); } /** * Get the user by their identifier. * * @param string $userIdentifier * @return User|null * @throws Exception */ public function getUserByIdentifier(string $userIdentifier): ?User { $user = $this->entityManager->getRepository(User::class)->findOneBy(['email' => $userIdentifier]); if (!$user) { throw new EntityNotFoundException(self::NOT_FOUND); } return $user; } /** * Get users grouped by their organizations for the index page. * This method should return an array of users grouped by their organizations. * * @return array */ public function groupByOrganization(array $usersOrganizations): array { $grouped = []; foreach ($usersOrganizations as $userOrg) { $org = $userOrg->getOrganization(); if (!$org) { continue; } $orgId = $org->getId(); $orgName = $org->getName(); if (!isset($grouped[$orgId])) { $grouped[$orgId] = [ 'id' => $orgId, 'name' => $orgName, 'users' => [], ]; } $user = $userOrg->getUsers(); $grouped[$orgId]['users'][] = [ 'entity' => $user, 'connected' => $this->isUserConnected($user->getUserIdentifier()), 'isActive' => (bool)$userOrg->isActive() ]; } return $grouped; } /** * Format users without organization for admin view. * * @param array $users * @return array */ public function formatNoOrgUsersAsAssoc(array $noOrgUsers): array { $group = [ 'id' => null, 'name' => 'Utilisateurs', 'users' => [], ]; foreach ($noOrgUsers as $user) { $group['users'][] = [ 'entity' => $user, 'connected' => $this->isUserConnected($user->getUserIdentifier()), ]; } // Use a fixed key (e.g., 0 or 'none') to avoid collisions with real org IDs return ['none' => $group]; } public function handleProfilePicture(User $user, $logoFile): void { // Get file extension $extension = $logoFile->guessExtension(); // Create custom filename: userNameUserSurname_ddmmyyhhmmss $customFilename = $user->getName() . $user->getSurname() . '_' . date('dmyHis') . '.' . $extension; // Define upload directory $uploadDirectory = $this->profileDirectory; // Create directory if it doesn't exist if (!is_dir($uploadDirectory) && !mkdir($uploadDirectory, 0755, true) && !is_dir($uploadDirectory)) { throw new DirectoryCouldNotBeCreatedException(sprintf('Directory "%s" was not created', $uploadDirectory)); } try { // Move the file to the upload directory $logoFile->move($uploadDirectory, $customFilename); // Update user entity with the file path (relative to public directory) $user->setPictureUrl('uploads/profile/' . $customFilename); } catch (FileException $e) { // Handle upload error throw new FileException('File upload failed: ' . $e->getMessage()); } } }