security: add download action for attachments - refactor controllers (params)
This commit is contained in:
parent
b3eadc5139
commit
1a01841326
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -5,7 +5,7 @@
|
||||||
/.env.*.local
|
/.env.*.local
|
||||||
/config/secrets/prod/prod.decrypt.private.php
|
/config/secrets/prod/prod.decrypt.private.php
|
||||||
/public/bundles/
|
/public/bundles/
|
||||||
/public/attachments/
|
/private/attachments/
|
||||||
/migrations/
|
/migrations/
|
||||||
/data/
|
/data/
|
||||||
/var/
|
/var/
|
||||||
|
|
|
@ -91,7 +91,7 @@ class MailImportCommand extends Command
|
||||||
$this->em->flush();
|
$this->em->flush();
|
||||||
|
|
||||||
if (!empty($attachments)) {
|
if (!empty($attachments)) {
|
||||||
$attachmentsDirectory = $this->kernel->getProjectDir().'/public/attachments/'.$mailing->getId().'/'.$entity->getId();
|
$attachmentsDirectory = $this->kernel->getProjectDir().'/private/attachments/'.$mailing->getId().'/'.$entity->getId();
|
||||||
|
|
||||||
$filesystem = new Filesystem();
|
$filesystem = new Filesystem();
|
||||||
$filesystem->mkdir($attachmentsDirectory);
|
$filesystem->mkdir($attachmentsDirectory);
|
||||||
|
|
|
@ -39,7 +39,7 @@ class MailingListCommand extends Command
|
||||||
{
|
{
|
||||||
$io = new SymfonyStyle($input, $output);
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
|
||||||
$headers = ['Label', 'Feed', 'Created at', 'Updated at'];
|
$headers = ['Label', 'ID', 'Feed', 'Created at', 'Updated at'];
|
||||||
$rows = [];
|
$rows = [];
|
||||||
|
|
||||||
$entities = $this->repo->findAll([], ['createdAt' => 'DEC']);
|
$entities = $this->repo->findAll([], ['createdAt' => 'DEC']);
|
||||||
|
@ -47,9 +47,10 @@ class MailingListCommand extends Command
|
||||||
foreach ($entities as $entity) {
|
foreach ($entities as $entity) {
|
||||||
$rows[] = [
|
$rows[] = [
|
||||||
$entity->getLabel(),
|
$entity->getLabel(),
|
||||||
|
$entity->getId(),
|
||||||
$this->router->generate(
|
$this->router->generate(
|
||||||
'mailing_rss',
|
'mailing_rss',
|
||||||
['id' => $entity->getId()],
|
['mailing' => $entity->getId()],
|
||||||
UrlGeneratorInterface::ABSOLUTE_URL
|
UrlGeneratorInterface::ABSOLUTE_URL
|
||||||
),
|
),
|
||||||
$entity->getCreatedAt()->format('Y-m-d H:i:s'),
|
$entity->getCreatedAt()->format('Y-m-d H:i:s'),
|
||||||
|
|
38
src/Controller/MailAttachmentController.php
Normal file
38
src/Controller/MailAttachmentController.php
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controller;
|
||||||
|
|
||||||
|
use App\Entity\Mail;
|
||||||
|
use App\Entity\Mailing;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
|
||||||
|
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||||
|
use Symfony\Component\HttpKernel\KernelInterface;
|
||||||
|
use App\Entity\MailAttachment;
|
||||||
|
|
||||||
|
class MailAttachmentController extends AbstractController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @Route("/attachment/{mail}/{attachment}/download", name="attachment_download")
|
||||||
|
* @ParamConverter("attachment", options={"mapping": {"id": "attachment", "mail": "mail"}})
|
||||||
|
*/
|
||||||
|
public function download(MailAttachment $attachment, KernelInterface $kernel): Response
|
||||||
|
{
|
||||||
|
$mail = $attachment->getMail();
|
||||||
|
$mailing = $mail->getMailing();
|
||||||
|
$filename = $attachment->getFilename();
|
||||||
|
|
||||||
|
$path = $kernel->getProjectDir().'/private/attachments/'.$mailing->getId().'/'.$mail->getId().'/'.$filename;
|
||||||
|
|
||||||
|
return new BinaryFileResponse(
|
||||||
|
$path,
|
||||||
|
200,
|
||||||
|
[
|
||||||
|
'Content-Type' => $attachment->getContentType(),
|
||||||
|
'Content-Disposition' => sprintf('inline; filename="%s"', $filename),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,46 +7,38 @@ use App\Entity\Mailing;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\Routing\Annotation\Route;
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
|
||||||
|
|
||||||
class MailController extends AbstractController
|
class MailController extends AbstractController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @Route("/mail/{mailing}/{id}/show", name="mail_show")
|
* @Route("/mail/{mailing}/{mail}/show", name="mail_show")
|
||||||
|
* @ParamConverter("mail", options={"mapping": {"mail": "id", "mailing": "mailing"}})
|
||||||
*/
|
*/
|
||||||
public function show(string $mailing, Mail $mail): Response
|
public function show(Mail $mail): Response
|
||||||
{
|
{
|
||||||
if ($mail->getMailing()->getId() !== $mailing) {
|
|
||||||
throw $this->createNotFoundException();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->render('mail/show.html.twig', [
|
return $this->render('mail/show.html.twig', [
|
||||||
'mail' => $mail,
|
'mail' => $mail,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Route("/mail/{mailing}/{id}/html", name="mail_html")
|
* @Route("/mail/{mailing}/{mail}/html", name="mail_html")
|
||||||
|
* @ParamConverter("mail", options={"mapping": {"mail": "id", "mailing": "mailing"}})
|
||||||
*/
|
*/
|
||||||
public function html(string $mailing, Mail $mail): Response
|
public function html(Mail $mail): Response
|
||||||
{
|
{
|
||||||
if ($mail->getMailing()->getId() !== $mailing) {
|
|
||||||
throw $this->createNotFoundException();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->render('mail/html.html.twig', [
|
return $this->render('mail/html.html.twig', [
|
||||||
'mail' => $mail,
|
'mail' => $mail,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Route("/mail/{mailing}/{id}/text", name="mail_text")
|
* @Route("/mail/{mailing}/{mail}/text", name="mail_text")
|
||||||
|
* @ParamConverter("mail", options={"mapping": {"mail": "id", "mailing": "mailing"}})
|
||||||
*/
|
*/
|
||||||
public function text(string $mailing, Mail $mail): Response
|
public function text(Mail $mail): Response
|
||||||
{
|
{
|
||||||
if ($mail->getMailing()->getId() !== $mailing) {
|
|
||||||
throw $this->createNotFoundException();
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = $this->render('mail/text.html.twig', [
|
$response = $this->render('mail/text.html.twig', [
|
||||||
'mail' => $mail,
|
'mail' => $mail,
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -8,11 +8,13 @@ use Symfony\Component\Routing\Annotation\Route;
|
||||||
use App\Repository\MailRepository;
|
use App\Repository\MailRepository;
|
||||||
use App\Entity\Mailing;
|
use App\Entity\Mailing;
|
||||||
use App\Entity\Mail;
|
use App\Entity\Mail;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
|
||||||
|
|
||||||
class MailingController extends AbstractController
|
class MailingController extends AbstractController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @Route("/mailing/{id}/rss", name="mailing_rss")
|
* @Route("/mailing/{mailing}/rss", name="mailing_rss")
|
||||||
|
* @ParamConverter("mailing", options={"mapping": {"mailing": "id"}})
|
||||||
*/
|
*/
|
||||||
public function rss(Mailing $mailing, MailRepository $mailRepository): Response
|
public function rss(Mailing $mailing, MailRepository $mailRepository): Response
|
||||||
{
|
{
|
||||||
|
|
|
@ -45,22 +45,30 @@
|
||||||
Pièces jointes
|
Pièces jointes
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{{ path('mailing_rss', {mailing: mail.mailing.id}) }}">
|
||||||
|
Afficher le flux RSS
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
<div class="tab-pane fade show active" id="html" role="tabpanel" aria-labelledby="html-tab">
|
<div class="tab-pane fade show active" id="html" role="tabpanel" aria-labelledby="html-tab">
|
||||||
<iframe src="{{ path('mail_html', {mailing: mail.mailing.id, id: mail.id}) }}"></iframe>
|
<iframe src="{{ path('mail_html', {mailing: mail.mailing.id, mail: mail.id}) }}"></iframe>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-pane fade" id="text" role="tabpanel" aria-labelledby="text-tab">
|
<div class="tab-pane fade" id="text" role="tabpanel" aria-labelledby="text-tab">
|
||||||
<iframe src="{{ path('mail_text', {mailing: mail.mailing.id, id: mail.id}) }}"></iframe>
|
<iframe src="{{ path('mail_text', {mailing: mail.mailing.id, mail: mail.id}) }}"></iframe>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-pane fade" id="attachments" role="tabpanel" aria-labelledby="attachments-tab">
|
<div class="tab-pane fade" id="attachments" role="tabpanel" aria-labelledby="attachments-tab">
|
||||||
{% if mail.mailAttachments|length %}
|
{% if mail.mailAttachments|length %}
|
||||||
<ul>
|
<div class="row">
|
||||||
|
<div class="col-4 m-4">
|
||||||
|
<ul class="list-group">
|
||||||
{% for item in mail.mailAttachments %}
|
{% for item in mail.mailAttachments %}
|
||||||
<li>
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||||
<a target="_blank" href="{{ asset('attachments/' ~ mail.mailing.id ~ '/' ~ mail.id ~ '/' ~ item.filename) }}">
|
<a target="_blank" href="{{ path('attachment_download', {mail: mail.id, attachment: item.id}) }}">
|
||||||
{{ item.filename }}
|
{{ item.filename }}
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
@ -70,6 +78,8 @@
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="alert alert-info">
|
<div class="alert alert-info">
|
||||||
Aucune pièce jointe
|
Aucune pièce jointe
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
{% for item in mails %}
|
{% for item in mails %}
|
||||||
<item>
|
<item>
|
||||||
<title><![CDATA[{{ item.subject|raw }}]]></title>
|
<title><![CDATA[{{ item.subject|raw }}]]></title>
|
||||||
<link>{{ absolute_url(path('mail_show', {mailing: mailing.id, id: item.id})) }}</link>
|
<link>{{ absolute_url(path('mail_show', {mailing: mailing.id, mail: item.id})) }}</link>
|
||||||
<description>
|
<description>
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
{% if item.htmlContent %}
|
{% if item.htmlContent %}
|
||||||
|
|
Loading…
Reference in a new issue