329 lines
15 KiB
PHP
329 lines
15 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\Service\ActionService;
|
|
use App\Service\OrganizationsService;
|
|
use App\Service\UserOrganizationService;
|
|
use App\Service\UserService;
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
use Exception;
|
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
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)
|
|
{
|
|
}
|
|
|
|
#[Route(path: '/', name: 'index', methods: ['GET'])]
|
|
public function index(): Response
|
|
{
|
|
$this->denyAccessUnlessGranted('ROLE_ADMIN');
|
|
$user = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier());
|
|
|
|
if ($this->isGranted("ROLE_SUPER_ADMIN")) {
|
|
$organizations = $this->entityManager->getRepository(Organizations::class)->findBy(['isDeleted' => false]);
|
|
|
|
|
|
} else {
|
|
//get all the UO of the user
|
|
$uos = $this->entityManager->getRepository(UsersOrganizations::class)->findBy(['users' => $user]);
|
|
$organizations = [];
|
|
$roleAdmin = $this->entityManager->getRepository(Roles::class)->findOneBy(['name' => 'ADMIN']);
|
|
foreach ($uos as $uo) {
|
|
$uoaAdmin = $this->entityManager->getRepository(UserOrganizatonApp::class)->findOneBy(['userOrganization' => $uo, 'role' => $roleAdmin]);
|
|
if ($uoaAdmin) {
|
|
$organizations[] = $uo->getOrganization();
|
|
}
|
|
}
|
|
if(count($organizations) === 1 && $organizations[0]->isActive() === true){
|
|
return $this->redirectToRoute('organization_show', ['id' => $organizations[0]->getId()]);
|
|
}
|
|
|
|
}
|
|
// Map the entities for tabulator
|
|
$organizationsData = array_map(function($org) {
|
|
return [
|
|
'id' => $org->getId(),
|
|
'name' => $org->getName(),
|
|
'email' => $org->getEmail(),
|
|
'logoUrl' => $org->getLogoUrl() ? $org->getLogoUrl() : null, // or prepend base URL if needed
|
|
'active' => $org->isActive(),
|
|
'showUrl' => $this->generateUrl('organization_show', ['id' => $org->getId()]),
|
|
];
|
|
}, $organizations);
|
|
return $this->render('organization/index.html.twig', [
|
|
'organizationsData' => $organizationsData,
|
|
]);
|
|
}
|
|
|
|
#[Route(path: '/new', name: 'new', methods: ['GET', 'POST'])]
|
|
public function new(Request $request)
|
|
{
|
|
$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->organizationService->handleLogo($organization, $logoFile);
|
|
}
|
|
try {
|
|
$this->entityManager->persist($organization);
|
|
$this->entityManager->flush();
|
|
$this->actionService->createAction("Create Organization", $actingUser, $organization, $organization->getName());
|
|
return $this->redirectToRoute('organization_index');
|
|
} catch (Exception $e) {
|
|
$this->addFlash('error', 'Error creating organization: ' . $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)
|
|
{
|
|
$this->denyAccessUnlessGranted('ROLE_ADMIN');
|
|
$actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier());
|
|
$organization = $this->entityManager->getRepository(Organizations::class)->find($id);
|
|
if (!$organization) {
|
|
$this->addFlash('error', self::NOT_FOUND);
|
|
return $this->redirectToRoute('organization_index');
|
|
}
|
|
if (!$this->isGranted("ROLE_SUPER_ADMIN")) {
|
|
//check if the user is admin of the organization
|
|
$user = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier());
|
|
$uo = $this->entityManager->getRepository(UsersOrganizations::class)->findOneBy(['users' => $user, 'organization' => $organization]);
|
|
if (!$uo) {
|
|
$this->addFlash('error', self::ACCESS_DENIED);
|
|
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->addFlash('error', self::ACCESS_DENIED);
|
|
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->actionService->createAction("Edit Organization", $actingUser, $organization, $organization->getName());
|
|
return $this->redirectToRoute('organization_index');
|
|
} catch (Exception $e) {
|
|
$this->addFlash('error', 'Error editing organization: ' . $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)
|
|
{
|
|
$this->denyAccessUnlessGranted('ROLE_ADMIN');
|
|
$organization = $this->entityManager->getRepository(Organizations::class)->find($id);
|
|
$actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier());
|
|
if (!$organization) {
|
|
$this->addFlash('error', self::NOT_FOUND);
|
|
return $this->redirectToRoute('organization_index');
|
|
}
|
|
//check if the user is admin of the organization
|
|
if (!$this->isGranted("ROLE_SUPER_ADMIN") && !$this->userService->isAdminOfOrganization($organization)) {
|
|
$this->createNotFoundException(self::NOT_FOUND);
|
|
}
|
|
$newUO = $this->entityManager->getRepository(UsersOrganizations::class)->findNewestUO($organization);
|
|
$newUsers = [];
|
|
foreach ($newUO as $uo) {
|
|
$newUsers[] = $uo->getUsers();
|
|
}
|
|
$adminUO = $this->entityManager->getRepository(UsersOrganizations::class)->findAdminsInOrganization($organization);
|
|
$adminUsers = [];
|
|
foreach ($adminUO as $uo) {
|
|
$adminUsers[] = $uo->getUsers();
|
|
}
|
|
$uos = $this->entityManager
|
|
->getRepository(UsersOrganizations::class)
|
|
->findBy(['organization' => $organization]);
|
|
|
|
$users = $this->userService->formatOrgUsers($uos);
|
|
|
|
$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]);
|
|
$activities = $this->actionService->formatActivities($actions);
|
|
|
|
$this->actionService->createAction("View Organization", $actingUser, $organization, $organization->getName());
|
|
return $this->render('organization/show.html.twig', [
|
|
'organization' => $organization,
|
|
'newUsers' => $newUsers,
|
|
'adminUsers' => $adminUsers,
|
|
'users' => $users,
|
|
'applications' => $apps,
|
|
'activities' => $activities,
|
|
]);
|
|
}
|
|
|
|
#[Route(path: '/delete/{id}', name: 'delete', methods: ['POST'])]
|
|
public function delete($id)
|
|
{
|
|
$this->denyAccessUnlessGranted("ROLE_ADMIN");
|
|
$actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier());
|
|
$organization = $this->entityManager->getRepository(Organizations::class)->find($id);
|
|
if (!$organization) {
|
|
throw $this->createNotFoundException(self::NOT_FOUND);
|
|
}
|
|
$organization->setIsActive(false);
|
|
$organization->setIsDeleted(true);
|
|
// Deactivate all associated UsersOrganizations
|
|
$this->userOrganizationService->deactivateAllUserOrganizationLinks($actingUser, null, $organization);
|
|
|
|
$this->entityManager->persist($organization);
|
|
$this->actionService->createAction("Delete Organization", $actingUser, $organization, $organization->getName());
|
|
return $this->redirectToRoute('organization_index');
|
|
}
|
|
|
|
#[Route(path: '/deactivate/{id}', name: 'deactivate', methods: ['POST'])]
|
|
public function deactivate($id){
|
|
$this->denyAccessUnlessGranted("ROLE_SUPER_ADMIN");
|
|
$actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier());
|
|
$organization = $this->entityManager->getRepository(Organizations::class)->find($id);
|
|
if (!$organization) {
|
|
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());
|
|
return $this->redirectToRoute('organization_index');
|
|
}
|
|
|
|
#[Route(path: '/activate/{id}', name: 'activate', methods: ['POST'])]
|
|
public function activate($id){
|
|
$this->denyAccessUnlessGranted("ROLE_SUPER_ADMIN");
|
|
$actingUser = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier());
|
|
$organization = $this->entityManager->getRepository(Organizations::class)->find($id);
|
|
if (!$organization) {
|
|
throw $this->createNotFoundException(self::NOT_FOUND);
|
|
}
|
|
$organization->setIsActive(true);
|
|
$this->entityManager->persist($organization);
|
|
$this->actionService->createAction("Activate Organization", $actingUser, $organization, $organization->getName());
|
|
return $this->redirectToRoute('organization_index');
|
|
}
|
|
|
|
// API endpoint to fetch organization data for Tabulator
|
|
#[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));
|
|
|
|
$sorters = $request->query->all('sorters');
|
|
$filters = $request->query->all('filters');
|
|
|
|
|
|
$user = $this->userService->getUserByIdentifier($this->getUser()->getUserIdentifier());
|
|
|
|
$qb = $this->entityManager->getRepository(Organizations::class)->createQueryBuilder('o')
|
|
->where('o.isDeleted = :del')->setParameter('del', false);
|
|
|
|
// Example: apply filters (basic equals/like)
|
|
foreach ($filters as $f) {
|
|
if (!isset($f['field'], $f['type'])) { continue; }
|
|
$param = 'p_' . $f['field'];
|
|
if ($f['type'] === 'like' || $f['type'] === 'contains') {
|
|
$qb->andWhere("LOWER(o.{$f['field']}) LIKE :$param")
|
|
->setParameter($param, '%' . mb_strtolower((string)$f['value']) . '%');
|
|
} elseif ($f['type'] === '=') {
|
|
$qb->andWhere("o.{$f['field']} = :$param")
|
|
->setParameter($param, $f['value']);
|
|
}
|
|
}
|
|
|
|
// Example: apply sorters
|
|
foreach ($sorters as $s) {
|
|
if (!isset($s['field'], $s['dir'])) { continue; }
|
|
$dir = strtolower($s['dir']) === 'desc' ? 'DESC' : 'ASC';
|
|
$qb->addOrderBy('o.' . $s['field'], $dir);
|
|
}
|
|
|
|
// 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);
|
|
|
|
// Tabulator expects: data, last_page (total pages), or total row count depending on config
|
|
$lastPage = (int)ceil($total / $size);
|
|
|
|
return $this->json([
|
|
'data' => $data,
|
|
'last_page' => $lastPage,
|
|
'total' => $total, // optional, useful for debugging
|
|
]);
|
|
}
|
|
|
|
|
|
}
|