324 lines
12 KiB
PHP
324 lines
12 KiB
PHP
<?php
|
|
|
|
namespace App\Controller;
|
|
|
|
use App\Entity\Apps;
|
|
use App\Entity\Roles;
|
|
use App\Entity\User;
|
|
use App\Form\UserForm;
|
|
use App\Entity\UsersOrganizations;
|
|
use App\Service\UserOrganizationService;
|
|
use App\Service\UserService;
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
|
use Symfony\Component\Asset\Packages;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
use Symfony\Component\Routing\Attribute\Route;
|
|
|
|
#[Route(path: '/user', name: 'user_')]
|
|
class UserController extends AbstractController
|
|
{
|
|
private const NOT_FOUND = 'Entity not found';
|
|
private const ACCESS_DENIED = 'Access denied';
|
|
|
|
public function __construct(
|
|
private readonly UserOrganizationService $userOrganizationService,
|
|
private readonly EntityManagerInterface $entityManager,
|
|
private readonly UserService $userService)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* GET /user - List all users (index/collection)
|
|
*/
|
|
#[Route('/', name: 'index', methods: ['GET'])]
|
|
public function index(EntityManagerInterface $entityManager): Response
|
|
{
|
|
if ($this->isGranted('ROLE_SUPER_ADMIN')) {
|
|
$usersByOrganization = $entityManager->getRepository(UsersOrganizations::class)->getActiveUsersGroupedByOrganization();
|
|
|
|
} else{
|
|
$user = $this->getUser();
|
|
if (!$user) {
|
|
return $this->redirectToRoute('app_login');
|
|
}
|
|
$userIdentifier = $user->getUserIdentifier();
|
|
$organizations = $this->entityManager->getRepository(UsersOrganizations::class)->findOrganizationsByUserEmailAndRoleName($userIdentifier, 'ADMIN');
|
|
if(!$organizations) {
|
|
// if user is not admin in any organization, throw access denied
|
|
throw $this->createNotFoundException(self::ACCESS_DENIED);
|
|
}
|
|
$usersByOrganization = $this->entityManager->getRepository(UsersOrganizations::class)
|
|
->findActiveUsersByOrganizations($organizations);
|
|
}
|
|
return $this->render('user/index.html.twig', [
|
|
'usersByOrganization' => $usersByOrganization,
|
|
'controller_name' => 'IndexController',
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* GET /user/{id} - Show specific user (show/member)
|
|
*/
|
|
#[Route('/{id}', name: 'show', requirements: ['id' => '\d+'], methods: ['GET'])]
|
|
public function show(int $id, EntityManagerInterface $entityManager): Response
|
|
{
|
|
if (!$this->isGranted('ROLE_SUPER_ADMIN')) {
|
|
throw $this->createAccessDeniedException(self::ACCESS_DENIED);
|
|
}
|
|
|
|
$user = $entityManager->getRepository(User::class)->find($id);
|
|
if (!$user) {
|
|
throw $this->createNotFoundException(self::NOT_FOUND);
|
|
}
|
|
|
|
$userOrganizations = $this->userOrganizationService->getUserOrganizations($user);
|
|
|
|
return $this->render('user/show.html.twig', [
|
|
'user' => $user,
|
|
'userOrganizations' => $userOrganizations,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* GET /user/new - Show form to create new user and handle submission
|
|
*/
|
|
#[Route('/new', name: 'new', methods: ['GET', 'POST'])]
|
|
public function new(Request $request): Response
|
|
{
|
|
$form = $this->createForm(UserForm::class);
|
|
|
|
$form->handleRequest($request);
|
|
|
|
if ($form->isSubmitted() && $form->isValid()) {
|
|
//Data is a User object. App\Form\NewUserForm is a form type that maps to User entity
|
|
$data = $form->getData();
|
|
// Handle user creation logic here
|
|
|
|
//FOR DEV PURPOSES ONLY
|
|
$data->setPictureUrl("");
|
|
$data->setPassword($this->userService->generateRandomPassword());
|
|
//FOR DEV PURPOSES ONLY
|
|
|
|
$this->entityManager->persist($data);
|
|
$this->entityManager->flush();
|
|
|
|
// Redirect to user index
|
|
return $this->redirectToRoute('user_index');
|
|
}
|
|
|
|
return $this->render('user/new.html.twig', [
|
|
'form' => $form->createView(),
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* GET /user/{id}/edit - Show form to edit user
|
|
*/
|
|
#[Route('/{id}/edit', name: 'edit', requirements: ['id' => '\d+'], methods: ['GET', 'PUT', 'POST'])]
|
|
public function edit(int $id, EntityManagerInterface $entityManager, Request $request): Response
|
|
{
|
|
//Handle access control
|
|
if (!$this->isGranted('ROLE_SUPER_ADMIN')) {
|
|
throw $this->createAccessDeniedException(self::ACCESS_DENIED);
|
|
}
|
|
|
|
//Fetch user by ID and handle not found case
|
|
$user = $entityManager->getRepository(User::class)->find($id);
|
|
if (!$user) {
|
|
throw $this->createNotFoundException(self::NOT_FOUND);
|
|
}
|
|
|
|
//Create form for editing user
|
|
$form = $this->createForm(UserForm::class, $user);
|
|
|
|
//Handle form submission
|
|
$form->handleRequest($request);
|
|
if ($form->isSubmitted() && $form->isValid()) {
|
|
//Persist changes to the user entity
|
|
$entityManager->persist($user);
|
|
$entityManager->flush();
|
|
|
|
//Redirect to user profile after successful edit
|
|
return $this->redirectToRoute('user_show', ['id' => $user->getId()]);
|
|
}
|
|
|
|
return $this->render('user/edit.html.twig', [
|
|
'form' => $form->createView(),
|
|
'user' => $user,
|
|
]);
|
|
}
|
|
|
|
|
|
/**
|
|
* DELETE /user/{id} - Delete user
|
|
*/
|
|
#[Route('/{id}', name: 'setDelete', requirements: ['id' => '\d+'], methods: ['POST'])]
|
|
public function setDelete(int $id, EntityManagerInterface $entityManager): Response
|
|
{
|
|
//This method is used to set a user as deleted without actually removing them from the database.
|
|
|
|
//Handle access control
|
|
if (!$this->isGranted('ROLE_SUPER_ADMIN')) {
|
|
throw $this->createAccessDeniedException(self::ACCESS_DENIED);
|
|
}
|
|
//Fetch user by ID and handle not found case
|
|
$user = $entityManager->getRepository(User::class)->find($id);
|
|
if (!$user) {
|
|
throw $this->createNotFoundException(self::NOT_FOUND);
|
|
}
|
|
|
|
// Handle user deletion logic
|
|
$user->setIsDeleted(true);
|
|
$entityManager->persist($user);
|
|
$entityManager->flush();
|
|
|
|
return $this->redirectToRoute('user_index');
|
|
}
|
|
|
|
/**
|
|
* DELETE /user/{id} - Delete user
|
|
*/
|
|
#[Route('/{id}', name: 'delete', requirements: ['id' => '\d+'], methods: ['DELETE'])]
|
|
public function delete(int $id, EntityManagerInterface $entityManager): Response
|
|
{
|
|
if (!$this->isGranted('ROLE_SUPER_ADMIN')) {
|
|
throw $this->createAccessDeniedException(self::ACCESS_DENIED);
|
|
}
|
|
|
|
$user = $entityManager->getRepository(User::class)->find($id);
|
|
if (!$user) {
|
|
throw $this->createNotFoundException(self::NOT_FOUND);
|
|
}
|
|
|
|
// Handle user deletion logic
|
|
$entityManager->remove($user);
|
|
$entityManager->flush();
|
|
|
|
return $this->redirectToRoute('user_index');
|
|
}
|
|
|
|
|
|
/**
|
|
* GET /user/deactivate/{id} - Deactivate user
|
|
* This method is used to deactivate a user without deleting them.
|
|
* The user will still exist in the database but will not be active.
|
|
*/
|
|
#[Route('/deactivate/{id}', name: 'deactivate', methods: ['GET'])]
|
|
public function deactivate(Request $request, EntityManagerInterface $entityManager): Response
|
|
{
|
|
if ($this->isGranted('ROLE_SUPER_ADMIN')) {
|
|
$userId = $request->attributes->get('id');
|
|
$user = $entityManager->getRepository(User::class)->find($userId);
|
|
if (!$user) {
|
|
throw $this->createNotFoundException(self::NOT_FOUND);
|
|
}
|
|
$user->setIsActive(false);
|
|
$entityManager->persist($user);
|
|
$entityManager->flush();
|
|
return $this->redirectToRoute('user_index');
|
|
}
|
|
return new Response('Unauthorized', Response::HTTP_UNAUTHORIZED);
|
|
}
|
|
|
|
/**
|
|
* Update organization user /userOrganizationEdit/{id} - Update organization user
|
|
* The id parameter is the ID of the UsersOrganizations entity.
|
|
*/
|
|
#[Route('/userOrganizationEdit/{id}', name: 'organization_edit', requirements: ['id' => '\d+'], methods: ['GET', 'POST'])]
|
|
public function userOrganizationEdit(int $id, Request $request, EntityManagerInterface $entityManager, Packages $packages): Response
|
|
{
|
|
$this->denyAccessUnlessGranted('ROLE_SUPER_ADMIN');
|
|
|
|
// get the UsersOrganizations entity by ID and handle not found case same for user
|
|
$userOrganization = $entityManager->getRepository(UsersOrganizations::class)->find($id);
|
|
if (!$userOrganization) {
|
|
throw $this->createNotFoundException(self::NOT_FOUND);
|
|
}
|
|
$user = $userOrganization->getUsers() ?? throw $this->createNotFoundException(self::NOT_FOUND);
|
|
$organization = $userOrganization->getOrganization() ?? throw $this->createNotFoundException(self::NOT_FOUND);
|
|
|
|
//Handle the POST
|
|
if ($request->isMethod('POST')) {
|
|
// Get the selected roles and apps from the request
|
|
$selectedRoles = $request->request->all('roles');
|
|
$selectedApps = $request->request->all('applications');
|
|
|
|
// order in important here. apps MUST be before roles
|
|
$this->userOrganizationService->setUserOrganizationsApps($user, $organization,$selectedApps);
|
|
$this->userOrganizationService->setUserOrganizations($user, $organization, $selectedRoles);
|
|
|
|
|
|
|
|
// Redirect to the user profile after successful update
|
|
return $this->redirectToRoute('user_show', ['id' => $user->getId()]);
|
|
}
|
|
|
|
//Overwrite the userOrganization with the userOrganizationsService for data consistency
|
|
// NULL pointer won't occur here because a valid UsersOrganizations entity was fetched above
|
|
$userOrganization = $this->userOrganizationService->getUserOrganizations($userOrganization->getUsers(), $userOrganization->getOrganization()->getId());
|
|
|
|
// Fetch all roles and apps
|
|
$roles = $entityManager->getRepository(Roles::class)->findAll();
|
|
$apps = $entityManager->getRepository(Apps::class)->findAll();
|
|
if (!$roles) {
|
|
throw $this->createNotFoundException(self::NOT_FOUND);
|
|
}
|
|
if (!$apps) {
|
|
throw $this->createNotFoundException(self::NOT_FOUND);
|
|
}
|
|
|
|
// Map roles and apps to arrays for rendering
|
|
$rolesArray = array_map(static function ($role) {
|
|
return [
|
|
'id' => $role->getId(),
|
|
'name' => $role->getName()
|
|
];
|
|
}, $roles);
|
|
$appsArray = [];
|
|
foreach ($apps as $app) {
|
|
$appsArray[] = [
|
|
'id' => $app->getId(),
|
|
'name' => $app->getName(),
|
|
'icon' => $packages->getUrl($app->getLogoUrl()),
|
|
];
|
|
}
|
|
|
|
// Map selected roles and apps to their IDs for the form
|
|
$selectedRoles = array_map(static function ($role) {
|
|
return $role->getId();
|
|
}, $userOrganization[0]["roles"]);
|
|
$selectedApps = array_map(static function ($app) {
|
|
return $app->getId();
|
|
}, $userOrganization[0]["apps"]);
|
|
|
|
return $this->render('user/organization/edit.html.twig', [
|
|
'userOrganization' => $userOrganization,
|
|
'user' => $user,
|
|
'rolesArray' => $rolesArray,
|
|
'selectedRoleIds' => $selectedRoles,
|
|
'appsArray' => $appsArray,
|
|
'selectedAppIds' => $selectedApps,]);
|
|
}
|
|
|
|
/**
|
|
* GET /user/deactivateOrganization/{id} - Deactivate user
|
|
* This method is used to deactivate a user without deleting them in an organization.
|
|
* The user will still exist in the database but will not be active.
|
|
*/
|
|
#[Route('/organizationDeactivate/{id}', name: 'organization_deactivate', requirements: ['id' => '\d+'], methods: ['GET'])]
|
|
public function deactivateUserOrganization(int $id, Request $request, EntityManagerInterface $entityManager): Response
|
|
{
|
|
$this->denyAccessUnlessGranted('ROLE_ADMIN');
|
|
$userOrganization = $entityManager->getRepository(UsersOrganizations::class)->find($id) ?? throw $this->createNotFoundException(self::NOT_FOUND);
|
|
$user = $userOrganization->getUsers() ?? throw $this->createNotFoundException(self::NOT_FOUND);
|
|
$organization = $userOrganization->getOrganization() ?? throw $this->createNotFoundException(self::NOT_FOUND);
|
|
|
|
$this->userOrganizationService->deactivateAllUserRoles($user, $organization);
|
|
|
|
return $this->redirectToRoute('user_show', ['id' => $user->getId()]);
|
|
}
|
|
|
|
}
|