<?php
namespace App\Controller;
use App\Entity\{Category, Department};
use Doctrine\Persistence\ManagerRegistry;
use App\Service\{DepartmentService, SpecialCharService};
use Symfony\Component\HttpFoundation\{Request, RequestStack, Response};
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
abstract class CoreController extends AbstractController
{
protected $requestStack;
protected $specialCharService;
protected $doctrine;
public function __construct(RequestStack $requestStack, SpecialCharService $specialCharService,
ManagerRegistry $doctrine)
{
$this->requestStack = $requestStack;
$this->specialCharService = $specialCharService;
$this->doctrine = $doctrine;
$request = Request::createFromGlobals();
$currentPath = $request->getPathInfo(); // the URI path being requested
$requestUri = $_SERVER['REQUEST_URI'];
$acl = [
'/' => ['unimes.fr'],
'/direction-des-affaires-financieres-et-comptables' => ['unimes.fr'],
'/direction-des-affaires-financieres-et-comptables/ticket' => ['unimes.fr'],
'/direction-du-patrimoine' => ['unimes.fr'],
'/direction-du-patrimoine/ticket' => ['unimes.fr'],
'/direction-du-patrimoine/reprographie' => ['unimes.fr'],
'/direction-du-patrimoine/reprographie/ticket' => ['unimes.fr'],
'/direction-du-patrimoine/demandes-techniques/ticket' => ['unimes.fr'],
'/direction-du-patrimoine/reservation-de-vehicule/ticket' => ['unimes.fr'],
'/snap' => ['unimes.fr'],
'/snap/ticket' => ['unimes.fr'],
];
if(array_key_exists($currentPath, $acl)) {
// Récupérer les roles autorisés pour la route courante et vérifier que l'utilisateur actuel possède les droits pour y accéder.
$authorizedRoles = $acl[$currentPath];
$this->checkAuthorization($authorizedRoles, $requestUri);
}
}
/**
* Checks if the user is logged in and if they have the right roles to see the homepage
* Tried to use Symfony firewalls and providers but since we don't connect to the database
* to retrieve the user's informations, we get stuck in an infinite loop between homepage and cas
* (User provider won't load a full user with the CAS connection, therefore unable to see if the user's roles fit the ACL)
*
* @param array $authorizedRoles
* @return void
*/
protected function checkAuthorization(array $roles, $requestUri) {
// We save the $user in a variable because we need to clear the session
// So department and categories ids won't be used at the wrong moment
$session = $this->requestStack->getSession();
$user = $session->get('user');
// If $user is set
if ($user) {
// We put them back in the session
$session->set('user', $user);
// $userRole = $user->getEduPersonPrimaryAffiliation();
$email = $user->getEmail();
$endEmail = substr($email, strpos($email, '@') + 1);
// Roles verifications
if (!in_array($endEmail, $roles) && !empty($roles)) {
$session->set('authCode', Response::HTTP_FORBIDDEN);
$session->set('error', [
"statusText" => str_split("Interdit"),
"statusCode" => $session->get('authCode'),
"message" => "Vous ne disposez pas des droits pour accéder à cette ressource. Veuillez contacter le service informatique si vous pensez qu'il y a une erreur.",
"request" => $requestUri,
]);
}
}
else {
$session->set('authCode', Response::HTTP_UNAUTHORIZED);
$session->set('error', [
"statusText" => $this->specialCharService->setTitleSpecialChars("pour accéder à l'application"),
"statusCode" => $session->get('authCode'),
"message" => "Vous ne disposez pas des droits pour accéder à cette ressource. Veuillez contacter le service informatique si vous pensez qu'il y a une erreur.",
"request" => $requestUri,
]);
}
}
/**
* Returns a response if the user should not visit the page
* or a HTTP_OK code if they're allowed to
*
* @param object $session
* @return mixed
*/
protected function getAuthorizationResponse($session) {
if ($session->get('authCode') === Response::HTTP_UNAUTHORIZED) {
return new Response(null, Response::HTTP_UNAUTHORIZED);
}
else if ($session->get('authCode') === Response::HTTP_FORBIDDEN) {
return new Response(null, Response::HTTP_FORBIDDEN);
}
return Response::HTTP_OK;
}
/**
* From the parameters transmitted in the url,
* we fetch the current service and department
* then we set them in the session and return them
*
* @param object $session
* @return array [$department, $category, $service, $serviceId, $sector]
*/
protected function handleUrlParams(object $session) {
$sector = $_GET['sector'];
$service = $_GET['service'];
$serviceId = $_GET['service'];
$session->set('sector', $sector);
$session->set('service', $service);
$category = $this->doctrine->getRepository(Category::class)->findBy(['id' => $service]);
$department = DepartmentService::setDepartment($sector);
$service = $this->specialCharService->setTitleSpecialChars($category[0]);
return [
'department' => $department,
'category' => $category[0],
'service' => $service,
'serviceId' => $serviceId,
'sector' => $sector
];
}
/**
* Creates the object from the wanted Class and the form that matches the object
*
* @param string $class
* @param array $choices
* @return array
*/
protected function createFormUtils(string $class, $choices ) {
// Creates the ticket object
$targetClass = '\App\Entity\\' . $class;
$ticket = new $targetClass();
if (str_contains($class, 'Reprography')) {
$class = 'ReprographyTicket';
}
// Creates the form with data and some config
$form = $this->createForm('App\Form\\' . $class . 'Type'::class, $ticket, [
'data'=> $choices,
'attr' => [
'class' => 'container__form'
],
]);
return [
'form' => $form,
'ticket' => $ticket
];
}
/**
* Identifies if the service or its parent is closed
*
* @param object $category
* @return mixed ( boolean | array )
*/
protected function isServiceOrDepartmentOpen($category) {
// We need to retrieve the department for further verification
$currentDepartment = $this->doctrine->getRepository(Department::class)->findOneBy(['id' => $category->getDepaId()]);
// If the category is set to invisible, it means it's closed
// But we also need to check if the whole department is closed
if ($category->getIsInvisible() === 1 || $currentDepartment->getVisi() === 0) {
// If one of them is closed and the current category has the id 33
if ($category->getId() === '33') {
// Returns the true boolean in order to display the specific error view for the category with the id 33 (BU closed)
return true;
}
$code = Response::HTTP_NOT_FOUND;
$message = "Le service est fermé et ne peut plus recevoir de tickets pour le moment. Veuillez retenter plus tard.";
$statusText = str_split("Internal Server Error");
// Returns the data that will be displayed in the generic error view
return [
"error-data" => [
"statusText" => $statusText,
"statusCode" => $code,
"message" => $message,
],
"error" => new Response(null, $code),
];
}
return false;
}
/**
* Returns the id of the user, depending on if they're logged in or not.
* Form forms that handles files.
*
* @param object $session
* @param array/null $form
* @return string
*/
protected function getUserId($session, $form = null) {
$user = $session->get('user');
if ($user) {
return 'cas-' . $user->getUid();
}
else {
return $form->getData()['ticket']['email'];
}
}
}