<?php
/** @noinspection PhpUnused */
namespace App\Controller;
use App\Component\Traits\EntityManagerTrait;
use App\Component\Traits\KernelTrait;
use App\Entity\FtpConfig;
use App\Service\GoogleCloud\StorageService;
use App\Service\MenuService;
use Google\Cloud\Storage\StorageObject;
use Psr\Cache\InvalidArgumentException;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
use Symfony\Contracts\Cache\ItemInterface;
use Symfony\Contracts\Cache\TagAwareCacheInterface;
/**
* @Route("")
*/
class IndexController extends AbstractLelpController
{
use KernelTrait;
use EntityManagerTrait;
private MenuService $menuService;
private StorageService $storageService;
private RoleHierarchyInterface $roleHierarchy;
private TagAwareCacheInterface $cache;
public function __construct(
MenuService $menuService,
StorageService $storageService,
RoleHierarchyInterface $roleHierarchy,
TagAwareCacheInterface $cache
) {
$this->menuService = $menuService;
$this->storageService = $storageService;
$this->roleHierarchy = $roleHierarchy;
$this->cache = $cache;
}
/**
* @Route("/")
*/
public function index(): Response
{
$actionForm = $this->createFormBuilder()
->add('new', SubmitType::class, ['label' => 'Modifier mes informations'])
->getForm();
$user = $this->getUser();
if ($user->getDepots()->isEmpty()) {
$depots = null;
} else {
$depots = $user->getDepots();
}
$user->setDatelastlogin(new \DateTime());
$this->entityManager->persist($user);
$this->entityManager->flush();
return $this->render('index-info.html.twig', [
'user' => $user,
'depots' => $depots,
'actionForm' => $actionForm->createView(),
]);
}
/**
* @Route("/APK/proxidriver.apk")
*
* @return RedirectResponse|Response
*/
public function apk(): RedirectResponse|Response
{
return $this->getBucketFile('EXPORT_APK', 'proxidriver.apk');
}
/**
* @param string|FtpConfig $ftpConfig
*
* @return RedirectResponse|Response
*/
private function getBucketFile($ftpConfig, string $filename): RedirectResponse|Response
{
try {
if (!$ftpConfig instanceof FtpConfig) {
$ftpConfig = $this->repositoryService->getFtpConfig()->findOneByCode($ftpConfig);
}
$objects = $this->storageService->getObjects($ftpConfig, $filename);
if (!$objects->current()) {
$this->addAdminError(
$ftpConfig->getServer()->getUriWithoutPassword().'/'.$ftpConfig->getDistantPath().'/'.$filename
);
throw new \LogicException('Le fichier est introuvable');
}
/** @var StorageObject $o */
$o = $objects->current();
$this->repositoryService->getStatistiqueTelechargementFichier()->incrementCompteur($filename);
$this->entityManager->flush();
$response = new Response();
$response->headers->set('Cache-Control', 'private');
$response->headers->set('Content-Disposition', 'attachment; filename="'.$filename.'";');
$response->headers->set('Content-length', $o->info()['size']);
$response->headers->set('Content-type', $o->info()['contentType']);
$response->sendHeaders();
$response->setContent($o->downloadAsString());
$response->sendContent();
return $response;
} catch (\LogicException $e) {
$this->addFlash('danger', $e->getMessage());
} catch (\Throwable $e) {
$this->addAdminError($e);
}
return $this->redirectToRoute('app_index_index');
}
/**
* @Route("/FILE/{name}")
*
* @param string $name base64 encoded path of the file
*
* @return Response
*/
public function gcsFile(string $name): Response
{
$name = base64_decode($name);
$filename = basename($name);
$ftpConfig = clone $this->repositoryService->getFtpConfig()->findOneByCode('EXPORT');
$ftpConfig->setFileRegex($name);
// Ne pas changer FILES
// C'est le seul répertoire du bucket autorisé pour le téléchargement direct
$ftpConfig->setDistantPath('FILES');
return $this->getBucketFile($ftpConfig, $filename);
}
/**
* @Route("/PDF/{filename}")
* @param $filename
* @return RedirectResponse|Response
*/
public function pdfFilename($filename): RedirectResponse|Response
{
return $this->getBucketFile('EXPORT_PDF', $filename);
}
/**
* @Route("/privacy-policy")
*/
public function privacyPolicy(): Response
{
return $this->render('privacy_policy.html.twig', []);
}
/**
* @Route("/user-roles")
* @param AuthorizationCheckerInterface $authChecker
* @return JsonResponse
* @throws InvalidArgumentException
*/
public function userRoles(AuthorizationCheckerInterface $authChecker): JsonResponse
{
$user = $this->getUser();
if (!$user) {
return $this->json(['roles' => []]);
}
$cacheKey = 'user_roles_'.$user->getId();
$userKey = $user->getId();
$allRoles = $this->cache->get($cacheKey, function (ItemInterface $item) use ($authChecker, $userKey) {
$item->expiresAfter(86400);
$item->tag(['user_'.$userKey]);
$allPossibleRoles = $this->getAllPossibleRoles();
$grantedRoles = [];
foreach ($allPossibleRoles as $role) {
if ($authChecker->isGranted($role)) {
$grantedRoles[] = $role;
}
}
return $grantedRoles;
});
return $this->json([
'roles' => $allRoles,
]);
}
/**
* @throws InvalidArgumentException
*/
private function getAllPossibleRoles(): array
{
return $this->cache->get('all_reachable_roles', function (ItemInterface $item) {
$item->expiresAfter(86400);
$item->tag(['roles_hierarchy']);
$reachableRoles = $this->roleHierarchy->getReachableRoleNames(['ROLE_ADMIN']);
if (!in_array('ROLE_USER', $reachableRoles)) {
$reachableRoles[] = 'ROLE_USER';
}
return array_unique($reachableRoles);
});
}
}