Easy_solution/src/Controller/OrganizationController.php

371 lines
18 KiB
PHP

<?php
namespace App\Controller;
use App\Entity\Actions;
use App\Entity\Apps;
use App\Entity\Roles;
use App\Entity\User;
use App\Entity\UserOrganizatonApp;
use App\Entity\UsersOrganizations;
use App\Form\OrganizationForm;
use App\Repository\OrganizationsRepository;
use App\Service\ActionService;
use App\Service\AwsService;
use App\Service\LoggerService;
use App\Service\OrganizationsService;
use App\Service\UserOrganizationService;
use App\Service\UserService;
use Doctrine\DBAL\Exception\NonUniqueFieldNameException;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\NonUniqueResultException;
use Exception;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\Routing\Attribute\Route;
use App\Entity\Organizations;
use Symfony\Component\HttpFoundation\Response;
#[Route(path: '/organization', name: 'organization_')]
class OrganizationController extends AbstractController
{
private const NOT_FOUND = 'Entity not found';
private const ACCESS_DENIED = 'Access denied';
public function __construct(private readonly EntityManagerInterface $entityManager,
private readonly UserService $userService,
private readonly OrganizationsService $organizationsService,
private readonly ActionService $actionService,
private readonly UserOrganizationService $userOrganizationService,
private readonly OrganizationsRepository $organizationsRepository,
private readonly AwsService $awsService, private readonly LoggerService $loggerService, private readonly LoggerInterface $logger)
{
}
#[Route(path: '/', name: 'index', methods: ['GET'])]
public function index(): Response
{
$this->denyAccessUnlessGranted('ROLE_ADMIN');
$actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier());
if($this->userService->hasAccessTo($actingUser, true)){
$orgCount = $this->organizationsRepository->count(['isDeleted' => false]);
if(!$this->isGranted("ROLE_SUPER_ADMIN")){
$userUO = $this->entityManager->getRepository(UsersOrganizations::class)->findBy(['users' => $actingUser, 'isActive' => true]);
$uoAdmin = 0;
foreach($userUO as $u){
if($this->userService->isAdminOfOrganization($u->getOrganization())){
$uoAdmin++;
}
}
if($uoAdmin === 1){
return $this->redirectToRoute('organization_show', ['id' => $userUO[0]->getOrganization()->getId()]);
}
}
return $this->render('organization/index.html.twig', [
'hasOrganizations' => $orgCount > 0
]);
}
$this->loggerService->logAccessDenied($actingUser->getId());
throw new AccessDeniedHttpException('Access denied');
}
#[Route(path: '/create', name: 'create', methods: ['GET', 'POST'])]
public function new(Request $request): Response
{
$this->denyAccessUnlessGranted('ROLE_SUPER_ADMIN');
$actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier());
if ($request->isMethod('POST')) {
$organization = new Organizations();
$form = $this->createForm(OrganizationForm::class, $organization);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$logoFile = $form->get('logoUrl')->getData();
if ($logoFile) {
$this->organizationsService->handleLogo($organization, $logoFile);
}
try {
$this->entityManager->persist($organization);
$this->entityManager->flush();
$this->loggerService->logOrganizationInformation($organization->getId(), $actingUser->getId(), "Organization Created");
$this->loggerService->logSuperAdmin($actingUser->getId(), $actingUser->getId(), "Organization Created", $organization->getId());
$this->actionService->createAction("Create Organization", $actingUser, $organization, $organization->getName());
$this->addFlash('success', 'Organisation crée avec succès.');
return $this->redirectToRoute('organization_index');
} catch (Exception $e) {
$this->addFlash('error', 'Erreur lors de la création de l\'organization');
$this->loggerService->logError('Error creating organization', ['acting_user_id' => $actingUser->getId(), 'error' => $e->getMessage()]);
}
}
return $this->render('organization/new.html.twig', [
'form' => $form->createView(),
]);
}
$form = $this->createForm(OrganizationForm::class);
return $this->render('organization/new.html.twig', [
'form' => $form->createView(),
]);
}
#[Route(path: '/edit/{id}', name: 'edit', methods: ['GET', 'POST'])]
public function edit(Request $request, $id): Response
{
$this->denyAccessUnlessGranted('ROLE_ADMIN');
$actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier());
$organization = $this->organizationsRepository->find($id);
if (!$organization) {
$this->loggerService->logEntityNotFound('Organization', [
'org_id' => $id,
'message' => 'Organization not found for edit'], $actingUser->getId()
);
$this->addFlash('error', 'Erreur, l\'organization est introuvable.');
return $this->redirectToRoute('organization_index');
}
if (!$this->isGranted("ROLE_SUPER_ADMIN")) {
//check if the user is admin of the organization
$uo = $this->entityManager->getRepository(UsersOrganizations::class)->findOneBy(['users' => $actingUser, 'organization' => $organization]);
if (!$uo) {
$this->loggerService->logEntityNotFound('UO link', [
'user_id' => $actingUser->getId(),
'org_id' => $organization->getId(),
'message' => 'UO link not found for edit organization'
], $actingUser->getId());
$this->addFlash('error', 'Erreur, accès refusé.');
return $this->redirectToRoute('organization_index');
}
$roleAdmin = $this->entityManager->getRepository(Roles::class)->findOneBy(['name' => 'ADMIN']);
$uoaAdmin = $this->entityManager->getRepository(UserOrganizatonApp::class)->findOneBy(['userOrganization' => $uo, 'role' => $roleAdmin]);
if (!$uoaAdmin) {
$this->loggerService->logEntityNotFound('UOA link', [
'uo_id' => $uo->getId(),
'role_id' => $roleAdmin->getId(),
'message' => 'UOA link not found for edit organization, user is not admin of organization'
], $actingUser->getId());
$this->addFlash('error', 'Erreur, accès refusé.');
return $this->redirectToRoute('organization_index');
}
}
$form = $this->createForm(OrganizationForm::class, $organization);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$logoFile = $form->get('logoUrl')->getData();
if ($logoFile) {
$this->organizationsService->handleLogo($organization, $logoFile);
}
try {
$this->entityManager->persist($organization);
$this->entityManager->flush();
$this->loggerService->logOrganizationInformation($organization->getId(), $actingUser->getId(), "Organization Edited");
if ($this->isGranted("ROLE_SUPER_ADMIN")) {
$this->loggerService->logSuperAdmin($actingUser->getId(), $actingUser->getId(), "Organization Edited", $organization->getId());
}
$this->actionService->createAction("Edit Organization", $actingUser, $organization, $organization->getName());
$this->addFlash('success', 'Organisation modifiée avec succès.');
return $this->redirectToRoute('organization_index');
}catch (Exception $e) {
$this->addFlash('error', 'Erreur lors de la modification de l\'organization');
$this->loggerService->logError('Error editing organization', ['acting_user_id' => $actingUser->getId(), 'error' => $e->getMessage()]);
}
}
return $this->render('organization/edit.html.twig', [
'form' => $form->createView(),
'organization' => $organization,
]);
}
#[Route(path: '/view/{id}', name: 'show', methods: ['GET'])]
public function view($id): Response
{
$this->denyAccessUnlessGranted('ROLE_ADMIN');
$organization = $this->organizationsRepository->find($id);
$actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier());
if (!$organization) {
$this->loggerService->logEntityNotFound('Organization', [
'org_id' => $id,
'message' => 'Organization not found for view'
], $actingUser->getId());
$this->addFlash('error', 'Erreur, l\'organization est introuvable.');
return $this->redirectToRoute('organization_index');
}
//check if the user is admin of the organization
if (!$this->userService->isAdminOfOrganization($organization) && !$this->isGranted("ROLE_SUPER_ADMIN")) {
$this->loggerService->logAccessDenied($actingUser->getId());
$this->addFlash('error', 'Erreur, accès refusé.');
throw new AccessDeniedHttpException('Access denied');
}
$allApps = $this->entityManager->getRepository(Apps::class)->findAll(); // appsAll
$orgApps = $organization->getApps()->toArray(); // apps
$apps = $this->organizationsService->appsAccess($allApps, $orgApps);
$actions = $this->entityManager->getRepository(Actions::class)->findBy(['Organization' => $organization], orderBy: ['date' => 'DESC'], limit: 15);
$activities = $this->actionService->formatActivities($actions);
$this->actionService->createAction("View Organization", $actingUser, $organization, $organization->getName());
return $this->render('organization/show.html.twig', [
'organization' => $organization,
'applications' => $apps,
'activities' => $activities,
]);
}
#[Route(path: '/delete/{id}', name: 'delete', methods: ['POST'])]
public function delete($id): Response
{
$this->denyAccessUnlessGranted("ROLE_ADMIN");
$actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier());
$organization = $this->organizationsRepository->find($id);
if (!$organization) {
$this->loggerService->logEntityNotFound('Organization', [
'org_id' => $id,
'message' => 'Organization not found for delete'
], $actingUser->getId());
$this->addFlash('error', 'Erreur, l\'organization est introuvable.');
throw $this->createNotFoundException(self::NOT_FOUND);
}
try {
$organization->setIsActive(false);
$organization->setIsDeleted(true);
$this->organizationsService->deleteLogo($organization);
// Deactivate all associated UsersOrganizations
$this->userOrganizationService->deactivateAllUserOrganizationLinks($actingUser, null, $organization);
$this->entityManager->persist($organization);
$this->actionService->createAction("Delete Organization", $actingUser, $organization, $organization->getName());
$this->entityManager->flush();
$this->loggerService->logOrganizationInformation($organization->getId(), $actingUser->getId(),'Organization Deleted');
if ($this->isGranted("ROLE_SUPER_ADMIN")) {
$this->loggerService->logSuperAdmin($actingUser->getId(), $actingUser->getId(),'Organization Deleted', $organization->getId());
}
$this->addFlash('success', 'Organisation supprimée avec succès.');
}catch (\Exception $e){
$this->loggerService->logError($actingUser->getId(), ['message' => 'Error deleting organization: '.$e->getMessage()]);
$this->addFlash('error', 'Erreur lors de la suppression de l\'organization.');
}
return $this->redirectToRoute('organization_index');
}
#[Route(path: '/deactivate/{id}', name: 'deactivate', methods: ['POST'])]
public function deactivate($id): Response
{
$this->denyAccessUnlessGranted("ROLE_SUPER_ADMIN");
$actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier());
$organization = $this->organizationsRepository->find($id);
if (!$organization) {
$this->loggerService->logEntityNotFound('Organization', [
'org_id' => $id,
'message' => 'Organization not found for deactivate'
], $actingUser->getId());
$this->addFlash('error', 'Erreur, l\'organization est introuvable.');
throw $this->createNotFoundException(self::NOT_FOUND);
}
$organization->setIsActive(false);
// $this->userOrganizationService->deactivateAllUserOrganizationLinks($actingUser, null, $organization);
$this->entityManager->persist($organization);
$this->actionService->createAction("Deactivate Organization", $actingUser, $organization, $organization->getName());
$this->loggerService->logSuperAdmin($actingUser->getId(), $actingUser->getId(),'Organization deactivated', $organization->getId());
$this->addFlash('success', 'Organisation désactivé avec succès.');
return $this->redirectToRoute('organization_index');
}
#[Route(path: '/activate/{id}', name: 'activate', methods: ['POST'])]
public function activate($id): Response
{
$this->denyAccessUnlessGranted("ROLE_SUPER_ADMIN");
$actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier());
$organization = $this->organizationsRepository->find($id);
if (!$organization) {
$this->loggerService->logEntityNotFound('Organization', [
'org_id' => $id,
'message' => 'Organization not found for activate'
], $actingUser->getId());
$this->addFlash('error', 'Erreur, l\'organization est introuvable.');
throw $this->createNotFoundException(self::NOT_FOUND);
}
$organization->setIsActive(true);
$this->entityManager->persist($organization);
$this->loggerService->logOrganizationInformation($organization->getId(), $actingUser->getId(),'Organization Activated');
$this->loggerService->logSuperAdmin($actingUser->getId(), $actingUser->getId(),'Organization Activated', $organization->getId());
$this->actionService->createAction("Activate Organization", $actingUser, $organization, $organization->getName());
$this->addFlash('success', 'Organisation activée avec succès.');
return $this->redirectToRoute('organization_index');
}
// API endpoint to fetch organization data for Tabulator
#[Route(path: '/data/{id}', 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));
$filters = $request->query->all('filter');
$qb = $this->organizationsRepository->createQueryBuilder('o')
->where('o.isDeleted = :del')->setParameter('del', false);
if (!empty($filters['name'])) {
$qb->andWhere('o.name LIKE :name')
->setParameter('name', '%' . $filters['name'] . '%');
}
if (!empty($filters['email'])) {
$qb->andWhere('o.email LIKE :email')
->setParameter('email', '%' . $filters['email'] . '%');
}
if(!$this->isGranted('ROLE_SUPER_ADMIN')) {
$actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier());
$uo = $this->entityManager->getRepository(UsersOrganizations::class)->findBy(['users' => $actingUser]);
foreach ($uo as $item) {
if($this->userService->isAdminOfOrganization($item->getOrganization())) {
$qb->andWhere('o.id = :orgId')
->setParameter('orgId', $item->getOrganization()->getId());
}
}
}
// Count total
$countQb = clone $qb;
$total = (int)$countQb->select('COUNT(o.id)')->getQuery()->getSingleScalarResult();
// Pagination
$offset = ($page - 1) * $size;
$rows = $qb->setFirstResult($offset)->setMaxResults($size)->getQuery()->getResult();
// Map to array
$data = array_map(function (Organizations $org) {
return [
'id' => $org->getId(),
'name' => $org->getName(),
'email' => $org->getEmail(),
'logoUrl' => $org->getLogoUrl() ?: null,
'active' => $org->isActive(),
'showUrl' => $this->generateUrl('organization_show', ['id' => $org->getId()]),
];
}, $rows);
$lastPage = (int)ceil($total / $size);
return $this->json([
'data' => $data,
'last_page' => $lastPage,
'total' => $total, // optional, useful for debugging
]);
}
}