235 lines
9.7 KiB
PHP
235 lines
9.7 KiB
PHP
<?php
|
|
|
|
namespace App\Service;
|
|
|
|
use App\Entity\Apps;
|
|
use App\Entity\Roles;
|
|
use App\Entity\User;
|
|
use App\Entity\UserOrganizatonApp;
|
|
use App\Entity\UsersOrganizations;
|
|
use App\Service\ActionService;
|
|
use App\Service\UserService;
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
use Symfony\Bundle\SecurityBundle\Security;
|
|
|
|
class UserOrganizationAppService
|
|
{
|
|
public function __construct(private readonly EntityManagerInterface $entityManager, private readonly ActionService $actionService, private readonly Security $security, private readonly UserService $userService)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Groups UserOrganizationApp entities by Application
|
|
* and prepares data for Twig.
|
|
*
|
|
* @param UserOrganizatonApp[] $userOrgApps
|
|
* @return array
|
|
*/
|
|
public function groupUserOrganizationAppsByApplication(array $userOrgApps): array
|
|
{
|
|
$grouped = [];
|
|
|
|
foreach ($userOrgApps as $uoa) {
|
|
|
|
$app = $uoa->getApplication();
|
|
$appId = $app->getId();
|
|
$roleEntity = $uoa->getRole();
|
|
|
|
if (!isset($grouped[$appId])) {
|
|
$grouped[$appId] = [
|
|
'uoId' => $uoa->getUserOrganization()->getId(),
|
|
'application' => $app,
|
|
'roles' => [],
|
|
'rolesArray' => [],
|
|
'selectedRoleIds' => [],
|
|
];
|
|
}
|
|
|
|
$grouped[$appId]['roles'][] = [
|
|
'id' => $roleEntity->getId(),
|
|
'name' => $roleEntity->getName(),
|
|
];
|
|
$grouped[$appId]['selectedRoleIds'][] = $roleEntity->getId();
|
|
}
|
|
|
|
// Load all possible roles once
|
|
$allRoles = $this->entityManager->getRepository(Roles::class)->findAll();
|
|
|
|
foreach ($grouped as &$appGroup) {
|
|
foreach ($allRoles as $role) {
|
|
// exclude SUPER ADMIN from assignable roles if current user is just ADMIN
|
|
if ($this->security->isGranted('ROLE_ADMIN')
|
|
&& !$this->security->isGranted('ROLE_SUPER_ADMIN')
|
|
&& $role->getName() === 'SUPER ADMIN') {
|
|
continue;
|
|
}
|
|
|
|
$appGroup['rolesArray'][] = [
|
|
'id' => $role->getId(),
|
|
'name' => $role->getName(),
|
|
];
|
|
}
|
|
}
|
|
|
|
return array_values($grouped);
|
|
}
|
|
|
|
/**
|
|
* Deactivates all the UserOrganizationApp entities for a given UserOrganization.
|
|
*
|
|
* @param UsersOrganizations $userOrganization
|
|
* @return void
|
|
*/
|
|
public function deactivateAllUserOrganizationsAppLinks(UsersOrganizations $userOrganization, Apps $app = null): void
|
|
{
|
|
if($app) {
|
|
$uoas = $this->entityManager->getRepository(UserOrganizatonApp::class)->findBy(['userOrganization' => $userOrganization, 'application' => $app, 'isActive' => true]);
|
|
} else {
|
|
$uoas = $this->entityManager->getRepository(UserOrganizatonApp::class)->findBy(['userOrganization' => $userOrganization, 'isActive' => true]);
|
|
}
|
|
foreach ($uoas as $uoa) {
|
|
$uoa->setIsActive(false);
|
|
$this->actionService->createAction("Deactivate UOA link", $userOrganization->getUsers(),
|
|
$userOrganization->getOrganization(), "App: " . $uoa->getApplication()->getName() . ", Role: " . $uoa->getRole()->getName());
|
|
$this->entityManager->persist($uoa);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Synchronizes user roles for a specific application within an organization.
|
|
*
|
|
* This method handles the complete lifecycle of user-application role assignments:
|
|
* - Activates/deactivates existing role links based on selection
|
|
* - Creates new role assignments for newly selected roles
|
|
* - Updates the user's global Symfony security roles when ADMIN/SUPER_ADMIN roles are assigned
|
|
*
|
|
* @param UsersOrganizations $uo The user-organization relationship
|
|
* @param Apps $application The target application
|
|
* @param array $selectedRoleIds Array of role IDs that should be active for this user-app combination
|
|
* @param User $actingUser The user performing this action (for audit logging)
|
|
*
|
|
* @return void
|
|
*
|
|
* @throws \Exception If role entities cannot be found or persisted
|
|
*/
|
|
public function syncRolesForUserOrganizationApp(
|
|
UsersOrganizations $uo,
|
|
Apps $application,
|
|
array $selectedRoleIds,
|
|
User $actingUser
|
|
): void {
|
|
|
|
// Fetch existing UserOrganizationApp links for this user and application
|
|
$uoas = $this->entityManager->getRepository(UserOrganizatonApp::class)->findBy([
|
|
'userOrganization' => $uo,
|
|
'application' => $application,
|
|
]);
|
|
|
|
$currentRoleIds = [];
|
|
// Process existing role links - activate or deactivate based on selection
|
|
foreach ($uoas as $uoa) {
|
|
$roleId = $uoa->getRole()->getId();
|
|
$currentRoleIds[] = $roleId;
|
|
$roleName = $uoa->getRole()->getName();
|
|
|
|
if (in_array((string) $roleId, $selectedRoleIds, true)) {
|
|
// Role is selected - ensure it's active
|
|
if (!$uoa->isActive()) {
|
|
$uoa->setIsActive(true);
|
|
$this->entityManager->persist($uoa);
|
|
$this->actionService->createAction(
|
|
"Re-activate user role for application",
|
|
$actingUser,
|
|
$uo->getOrganization(),
|
|
"App: {$application->getName()}, Role: $roleName for user {$uo->getUsers()->getUserIdentifier()}"
|
|
);
|
|
// Sync Admins roles to user's global Symfony security roles
|
|
if (in_array($roleName, ['ADMIN', 'SUPER ADMIN'], true)) {
|
|
$this->userService->syncUserRoles($uo->getUsers(), $roleName, true);
|
|
}
|
|
// Ensure ADMIN role is assigned if SUPER ADMIN is activated
|
|
if ($roleName === 'SUPER ADMIN') {
|
|
$this->ensureAdminRoleForSuperAdmin($uoa);
|
|
}
|
|
}
|
|
} else {
|
|
// Role is not selected - ensure it's inactive
|
|
if ($uoa->isActive()) {
|
|
$uoa->setIsActive(false);
|
|
$this->entityManager->persist($uoa);
|
|
|
|
$this->actionService->createAction(
|
|
"Deactivate user role for application",
|
|
$actingUser,
|
|
$uo->getOrganization(),
|
|
"App: {$application->getName()}, Role: $roleName for user {$uo->getUsers()->getUserIdentifier()}"
|
|
);
|
|
// Sync Admins roles to user's global Symfony security roles
|
|
if (in_array($roleName, ['ADMIN', 'SUPER ADMIN'], true)) {
|
|
$this->userService->syncUserRoles($uo->getUsers(), $roleName, false);
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
// Create new role assignments for roles that don't exist yet
|
|
foreach ($selectedRoleIds as $roleId) {
|
|
if (!in_array($roleId, $currentRoleIds)) {
|
|
$role = $this->entityManager->getRepository(Roles::class)->find($roleId);
|
|
if ($role) {
|
|
// Create new user-organization-application role link
|
|
$newUoa = new UserOrganizatonApp();
|
|
$newUoa->setUserOrganization($uo);
|
|
$newUoa->setApplication($application);
|
|
$newUoa->setRole($role);
|
|
$newUoa->setIsActive(true);
|
|
|
|
// Sync Admins roles to user's global Symfony security roles
|
|
if (in_array($role->getName(), ['ADMIN', 'SUPER ADMIN'], true)) {
|
|
$this->userService->syncUserRoles($uo->getUsers(), $role->getName(), true);
|
|
}
|
|
// Ensure ADMIN role is assigned if SUPER ADMIN is activated
|
|
if ($role->getName() === 'SUPER ADMIN') {
|
|
$this->ensureAdminRoleForSuperAdmin($newUoa);
|
|
}
|
|
$this->entityManager->persist($newUoa);
|
|
$this->actionService->createAction("New user role for application",
|
|
$actingUser,
|
|
$uo->getOrganization(),
|
|
"App: {$application->getName()}, Role: {$role->getName()} for user {$uo->getUsers()->getUserIdentifier()}");
|
|
}
|
|
}
|
|
}
|
|
$this->entityManager->flush();
|
|
}
|
|
|
|
/**
|
|
* Attribute the role Admin to the user if the user has the role Super Admin
|
|
*
|
|
* @param UserOrganizatonApp $uoa
|
|
*
|
|
* @return void
|
|
*/
|
|
public function ensureAdminRoleForSuperAdmin(UserOrganizatonApp $uoa): void
|
|
{
|
|
$uoaAdmin = $this->entityManager->getRepository(UserOrganizatonApp::class)->findOneBy([
|
|
'userOrganization' => $uoa->getUserOrganization(),
|
|
'application' => $uoa->getApplication(),
|
|
'role' => $this->entityManager->getRepository(Roles::class)->findOneBy(['name' => 'ADMIN'])
|
|
]);
|
|
if(!$uoaAdmin) {
|
|
$uoaAdmin = new UserOrganizatonApp();
|
|
$uoaAdmin->setUserOrganization($uoa->getUserOrganization());
|
|
$uoaAdmin->setApplication($uoa->getApplication());
|
|
$uoaAdmin->setRole($this->entityManager->getRepository(Roles::class)->findOneBy(['name' => 'ADMIN']));
|
|
$uoaAdmin->setIsActive(true);
|
|
$this->entityManager->persist($uoaAdmin);
|
|
}
|
|
// If the ADMIN role link exists but is inactive, activate it
|
|
if ($uoaAdmin && !$uoaAdmin->isActive()) {
|
|
$uoaAdmin->setIsActive(true);
|
|
}
|
|
}
|
|
}
|