<?php
namespace App\Controller;
use App\Entity\File;
use App\Entity\FileGroup;
use App\Entity\User;
use App\Entity\Workspace;
use App\Form\FileType;
use App\Repository\FileRepository;
use App\Service\BlockChainService;
use App\Service\FileValidatorService;
use App\Service\IpfsService;
use App\Utils\Datatable;
use Exception;
use GuzzleHttp\Exception\GuzzleException;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
/**
* @Route("/filegroup/{fileGroup}/file")
*/
class FileController extends AbstractController
{
/**
* @Route("/list", name="file_index", methods={"GET"})
* @IsGranted("FILE_GROUP_SHOW", subject="fileGroup")
* @param FileGroup $fileGroup
* @return Response
*/
public function index(FileGroup $fileGroup): Response
{
return $this->render('file/index.html.twig', [
'fileGroup' => $fileGroup,
'files' => $fileGroup->getFiles(),
]);
}
/**
* @Route("/fetch/list", name="fetch_file_list", methods={"GET"})#
* @IsGranted("FILE_GROUP_SHOW", subject="fileGroup")
* @param Request $request
* @param Datatable $datatable
* @param FileRepository $fileRepository
* @param FileGroup $fileGroup
* @return Response
*/
public function fetchFileList(Request $request, Datatable $datatable, FileRepository $fileRepository, FileGroup $fileGroup): Response
{
if (!$request->isXmlHttpRequest()) {
throw $this->createAccessDeniedException("Not an ajax request!");
}
/** @var User $user */
$user = $this->getUser();
/** @var Workspace $workspace */
$workspace = $user->getWorkspace();
$datatables = $datatable
->withColumnType([ // list column in order
'id' => ['alias' => 'f'],
'clientFileName' => ['alias' => 'f', 'twig' => 'components/datatable.ellipse.twig'],
'fileName' => ['alias' => 'f', 'columnName' => 'name'],
'created' => ['alias' => 'f', 'twig' => 'components/datatable.datetime.twig'],
'version' => ['alias' => 'f'],
'size' => ['alias' => 'f', 'twig' => 'components/datatable.filesize.twig'],
'name' => ['alias' => 'fg'],
'rollCount' => ['alias' => '', 'twig' => 'file/datatable.badge.twig']
])
->withOptions([
'fileGroup' => $fileGroup->getId()
])
->renderActionView('file/datatable.action.twig') // provide custom twig to render action column
->isFile(true)
->withQueryBuilder($fileRepository->fetchFileList($fileGroup->getId(), $workspace))
->withRequestParams($request->query->all());
return new JsonResponse($datatables->getResponse());
}
public function onKernelResponse(ResponseEvent $event)
{
$response = $event->getResponse();
$response->headers->set('Content-Security-Policy', "default-src 'self'; script-src 'self'");
}
/**
* @Route("/create/{nonce}", name="file_create", methods={"GET", "POST"})
* @IsGranted("FILE_CREATE")
* @param Request $request
* @param $nonce
* @param FileGroup $fileGroup
* @param BlockChainService $blockChainService
* @return Response
* @throws Exception
*/
public function create(Request $request, FileGroup $fileGroup, BlockChainService $blockChainService, FileValidatorService $fileValidatorService, $nonce): Response
{
if ($request->isMethod('GET') && !$request->isXmlHttpRequest()) {
throw $this->createAccessDeniedException("Not an ajax request!");
}
/** @var User $user */
$user = $this->getUser();
/** @var Workspace $workspace */
$workspace = $user->getWorkspace();
$file = new File();
$file->addFileGroup($fileGroup);
$file->setWorkspace($workspace);
$form = $this->createForm(FileType::class, $file, [
'action' => $this->generateUrl('file_create', ['fileGroup' => $fileGroup->getId(),'nonce' => $nonce]),
'method' => 'POST',
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
if($form->get('url')->getData() === null){
$this->addFlash("success", "File Invalid!");
return $this->redirectToRoute('file_index', ['fileGroup' => $fileGroup->getId()]);
} else {
$em = $this->getDoctrine()->getManager();
foreach ($file->getFileGroups() as $fGroup) {
$fGroup->addFile($file);
$em->persist($fGroup);
}
$em->persist($file);
$em->flush();
$blockChainService->registerFirmware($file);
return $this->redirectToRoute('file_index', ['fileGroup' => $fileGroup->getId()]);
}
}
return $this->render(
'file/new.html.twig',
[
'fileGroup' => $fileGroup,
'nonce' => urldecode(str_replace('?2F?', '%2F', $nonce)),
'file' => $file,
'form' => $form->createView()
]
);
}
/**
* @Route("/store-file", name="file_store_file", methods={"POST"})
* @IsGranted("FILE_CREATE")
* @param Request $request
* @param IpfsService $ipfsService
* @return Response
* @throws GuzzleException
*/
public function storeFile(Request $request, IpfsService $ipfsService, FileValidatorService $fileValidatorService): Response
{
if (!$request->isXmlHttpRequest()) {
throw $this->createAccessDeniedException("Not an ajax request!");
}
/**
* @var UploadedFile $requestFile
*/
$requestFile = $request->files->get('file');
$response = new Response();
try {
$fileValidatorService->validate($requestFile);
$response->setContent(json_encode([
'cid' => $ipfsService->upload($requestFile),
'size' => $requestFile->getSize(),
'client_name' => $requestFile->getClientOriginalName(),
'error' => null
]));
} catch (Exception $exception) {
$response->setContent(json_encode([
'cid' => null,
'size' => null,
'client_name' => null,
'error' => $exception->getMessage()
]));
}
$response->headers->set('Content-Type', 'application/json');
return $response;
}
/**
* @Route("/edit/{id}", name="file_edit", methods={"GET"})
* @IsGranted("FILE_EDIT", subject="file")
* @param Request $request
* @param File $file
* @param FileGroup $fileGroup
* @return Response
*/
public function edit(Request $request, File $file, FileGroup $fileGroup): Response
{
if ($request->isMethod('GET') && !$request->isXmlHttpRequest()) {
throw $this->createAccessDeniedException("Not an ajax request!");
}
$form = $this->createForm(FileType::class, $file, [
'action' => $this->generateUrl('file_update', ['fileGroup' => $fileGroup->getId(), 'id' => $file->getId()]),
'method' => 'POST',
]);
$form->handleRequest($request);
return $this->render(
'file/edit.html.twig',
[
'fileGroup' => $fileGroup,
'file' => $file,
'form' => $form->createView()
]
);
}
/**
* @Route("/show/{id}", name="file_show", methods={"GET"})
* @IsGranted("FILE_SHOW", subject="file")
* @param Request $request
* @param File $file
* @param FileGroup $fileGroup
* @return Response
*/
public function show(Request $request, File $file, FileGroup $fileGroup): Response
{
if ($request->isMethod('GET') && !$request->isXmlHttpRequest()) {
throw $this->createAccessDeniedException("Not an ajax request!");
}
return $this->render(
'file/show.html.twig',
[
'fileGroup' => $fileGroup,
'file' => $file,
]
);
}
/**
* @Route("/fix/{id}", name="file_bc_fix", methods={"GET"})
* @IsGranted("FILE_EDIT", subject="file")
* @param File $file
* @param FileGroup $fileGroup
* @param BlockChainService $blockChainService
* @return Response
* @throws Exception
*/
public function bcFix(File $file, FileGroup $fileGroup, BlockChainService $blockChainService): Response
{
$blockChainService->registerFirmware($file);
return $this->redirectToRoute('file_index', ['fileGroup' => $fileGroup->getId()]);
}
/**
* @Route("/update/{id}", name="file_update", methods={"POST"})
* @IsGranted("FILE_EDIT", subject="file")
* @param Request $request
* @param File $file
* @param FileRepository $fileRepository
* @param FileGroup $fileGroup
* @param BlockChainService $blockChainService
* @return Response
* @throws Exception
*/
public function update(Request $request, File $file, FileRepository $fileRepository, FileGroup $fileGroup, BlockChainService $blockChainService): Response
{
$em = $this->getDoctrine()->getManager();
$form = $this->createForm(FileType::class, $file, [
'action' => $this->generateUrl('file_update', ['fileGroup' => $fileGroup->getId(), 'id' => $file->getId()]),
'method' => 'POST',
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$fileRepository->removeFileFromAllGroups($file);
foreach ($file->getFileGroups() as $fGroup) {
$fGroup->addFile($file);
$em->persist($fGroup);
}
$em->flush();
$blockChainService->registerFirmware($file);
}
return $this->redirectToRoute('file_index', ['fileGroup' => $fileGroup->getId()]);
}
/**
* @Route("/delete/{id}", name="file_delete", methods={"DELETE"})
* @IsGranted("FILE_DELETE", subject="file")
* @param Request $request
* @param File $file
* @param FileGroup $fileGroup
* @param BlockChainService $blockChainService
* @return Response
* @throws Exception
*/
public function delete(Request $request, File $file, FileGroup $fileGroup, BlockChainService $blockChainService): Response
{
if ($this->isCsrfTokenValid('delete' . $file->getId(), $request->request->get('_token'))) {
$blockChainService->removeFirmware($file);
}
return $this->redirectToRoute('file_index', ['fileGroup' => $fileGroup->getId()]);
}
/**
* @Route("/delete-bulk", name="file_delete_bulk", methods={"POST"})
* @IsGranted("FILE_MULTI_DELETE")
* @param Request $request
* @param FileRepository $fileRepository
* @param FileGroup $fileGroup
* @param BlockChainService $blockChainService
* @return Response
* @throws Exception
*/
public function deleteBulk(Request $request, FileRepository $fileRepository, FileGroup $fileGroup, BlockChainService $blockChainService): Response
{
/** @var User $user */
$user = $this->getUser();
$data = explode(
',',
$request->request->get('data_ids')
);
foreach ($data as $id) {
$file = $fileRepository->findOneBy(['id' => $id, 'workspace' => $user->getWorkspace()]);
if (is_object($file)) {
if (count($file->getRollouts()) === 0) {
$fileRepository->removeFileFromAllGroups($file);
$blockChainService->removeFirmware($file);
}
}
}
return $this->redirectToRoute('file_index', ['fileGroup' => $fileGroup->getId()]);
}
}