Easy_solution/src/Controller/UserController.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()]);
}
}