diff --git a/app/Resources/views/admin/blog/new.html.twig b/app/Resources/views/admin/blog/new.html.twig index 0a879c5c0..34918cf05 100644 --- a/app/Resources/views/admin/blog/new.html.twig +++ b/app/Resources/views/admin/blog/new.html.twig @@ -9,7 +9,6 @@ {{ form_row(form.title) }} {{ form_row(form.summary) }} {{ form_row(form.content) }} - {{ form_row(form.authorEmail) }} {{ form_row(form.publishedAt) }} diff --git a/app/Resources/views/admin/blog/show.html.twig b/app/Resources/views/admin/blog/show.html.twig index 312568c30..d69e83090 100644 --- a/app/Resources/views/admin/blog/show.html.twig +++ b/app/Resources/views/admin/blog/show.html.twig @@ -17,7 +17,7 @@ {{ 'label.author'|trans }} -

{{ post.authorEmail }}

+

{{ post.author.email }}

{{ 'label.published_at'|trans }} diff --git a/app/Resources/views/blog/index.xml.twig b/app/Resources/views/blog/index.xml.twig index 5a09bd0c5..9c551100d 100644 --- a/app/Resources/views/blog/index.xml.twig +++ b/app/Resources/views/blog/index.xml.twig @@ -15,7 +15,7 @@ {{ url('blog_post', {'slug': post.slug}) }} {{ url('blog_post', {'slug': post.slug}) }} {{ post.publishedAt|date(format='r', timezone='GMT') }} - {{ post.authorEmail }} + {{ post.author.email }} {% endfor %} diff --git a/app/Resources/views/blog/post_show.html.twig b/app/Resources/views/blog/post_show.html.twig index 5c98299e8..f481448c3 100644 --- a/app/Resources/views/blog/post_show.html.twig +++ b/app/Resources/views/blog/post_show.html.twig @@ -32,7 +32,7 @@

- {{ comment.authorEmail }} {{ 'post.commented_on'|trans }} + {{ comment.author.email }} {{ 'post.commented_on'|trans }} {# it's not mandatory to set the timezone in localizeddate(). This is done to avoid errors when the 'intl' PHP extension is not available and the application is forced to use the limited "intl polyfill", which only supports UTC and GMT #} @@ -50,7 +50,7 @@ {% endblock %} {% block sidebar %} - {% if app.user and post.isAuthor(app.user) %} + {% if post.isAuthor(app.user) %}
{{ 'action.edit_post'|trans }} diff --git a/src/AppBundle/Controller/Admin/BlogController.php b/src/AppBundle/Controller/Admin/BlogController.php index 91cf18fdd..98042098c 100644 --- a/src/AppBundle/Controller/Admin/BlogController.php +++ b/src/AppBundle/Controller/Admin/BlogController.php @@ -55,7 +55,7 @@ class BlogController extends Controller public function indexAction() { $entityManager = $this->getDoctrine()->getManager(); - $posts = $entityManager->getRepository(Post::class)->findBy(['authorEmail' => $this->getUser()->getEmail()], ['publishedAt' => 'DESC']); + $posts = $entityManager->getRepository(Post::class)->findBy(['author' => $this->getUser()], ['publishedAt' => 'DESC']); return $this->render('admin/blog/index.html.twig', ['posts' => $posts]); } @@ -73,7 +73,7 @@ public function indexAction() public function newAction(Request $request) { $post = new Post(); - $post->setAuthorEmail($this->getUser()->getEmail()); + $post->setAuthor($this->getUser()); // See http://symfony.com/doc/current/book/forms.html#submitting-forms-with-multiple-buttons $form = $this->createForm(PostType::class, $post) @@ -122,7 +122,7 @@ public function showAction(Post $post) // This security check can also be performed: // 1. Using an annotation: @Security("post.isAuthor(user)") // 2. Using a "voter" (see http://symfony.com/doc/current/cookbook/security/voters_data_permission.html) - if (null === $this->getUser() || !$post->isAuthor($this->getUser())) { + if (!$post->isAuthor($this->getUser())) { throw $this->createAccessDeniedException('Posts can only be shown to their authors.'); } @@ -139,7 +139,7 @@ public function showAction(Post $post) */ public function editAction(Post $post, Request $request) { - if (null === $this->getUser() || !$post->isAuthor($this->getUser())) { + if (!$post->isAuthor($this->getUser())) { throw $this->createAccessDeniedException('Posts can only be edited by their authors.'); } diff --git a/src/AppBundle/Controller/BlogController.php b/src/AppBundle/Controller/BlogController.php index f19ee1f8c..50a4330f7 100644 --- a/src/AppBundle/Controller/BlogController.php +++ b/src/AppBundle/Controller/BlogController.php @@ -99,7 +99,7 @@ public function commentNewAction(Request $request, Post $post) if ($form->isSubmitted() && $form->isValid()) { /** @var Comment $comment */ $comment = $form->getData(); - $comment->setAuthorEmail($this->getUser()->getEmail()); + $comment->setAuthor($this->getUser()); $comment->setPost($post); $entityManager = $this->getDoctrine()->getManager(); diff --git a/src/AppBundle/DataFixtures/ORM/LoadFixtures.php b/src/AppBundle/DataFixtures/ORM/LoadFixtures.php index 48b7adca2..9f0f42f18 100644 --- a/src/AppBundle/DataFixtures/ORM/LoadFixtures.php +++ b/src/AppBundle/DataFixtures/ORM/LoadFixtures.php @@ -14,7 +14,7 @@ use AppBundle\Entity\Comment; use AppBundle\Entity\Post; use AppBundle\Entity\User; -use Doctrine\Common\DataFixtures\FixtureInterface; +use Doctrine\Common\DataFixtures\AbstractFixture; use Doctrine\Common\Persistence\ObjectManager; use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\DependencyInjection\ContainerAwareTrait; @@ -32,7 +32,7 @@ * @author Ryan Weaver * @author Javier Eguiluz */ -class LoadFixtures implements FixtureInterface, ContainerAwareInterface +class LoadFixtures extends AbstractFixture implements ContainerAwareInterface { use ContainerAwareTrait; @@ -55,6 +55,7 @@ private function loadUsers(ObjectManager $manager) $encodedPassword = $passwordEncoder->encodePassword($johnUser, 'kitten'); $johnUser->setPassword($encodedPassword); $manager->persist($johnUser); + $this->addReference('john-user', $johnUser); $annaAdmin = new User(); $annaAdmin->setUsername('anna_admin'); @@ -63,6 +64,7 @@ private function loadUsers(ObjectManager $manager) $encodedPassword = $passwordEncoder->encodePassword($annaAdmin, 'kitten'); $annaAdmin->setPassword($encodedPassword); $manager->persist($annaAdmin); + $this->addReference('anna-admin', $annaAdmin); $manager->flush(); } @@ -76,13 +78,13 @@ private function loadPosts(ObjectManager $manager) $post->setSummary($this->getRandomPostSummary()); $post->setSlug($this->container->get('slugger')->slugify($post->getTitle())); $post->setContent($this->getPostContent()); - $post->setAuthorEmail('anna_admin@symfony.com'); + $post->setAuthor($this->getReference('anna-admin')); $post->setPublishedAt(new \DateTime('now - '.$i.'days')); foreach (range(1, 5) as $j) { $comment = new Comment(); - $comment->setAuthorEmail('john_user@symfony.com'); + $comment->setAuthor($this->getReference('john-user')); $comment->setPublishedAt(new \DateTime('now + '.($i + $j).'seconds')); $comment->setContent($this->getRandomCommentContent()); $comment->setPost($post); diff --git a/src/AppBundle/Entity/Comment.php b/src/AppBundle/Entity/Comment.php index 32163fafe..b97235d5c 100644 --- a/src/AppBundle/Entity/Comment.php +++ b/src/AppBundle/Entity/Comment.php @@ -60,14 +60,6 @@ class Comment */ private $content; - /** - * @var string - * - * @ORM\Column(type="string") - * @Assert\Email - */ - private $authorEmail; - /** * @var \DateTime * @@ -76,6 +68,14 @@ class Comment */ private $publishedAt; + /** + * @var User + * + * @ORM\ManyToOne(targetEntity="AppBundle\Entity\User") + * @ORM\JoinColumn(nullable=false) + */ + private $author; + public function __construct() { $this->publishedAt = new \DateTime(); @@ -109,27 +109,30 @@ public function setContent($content) $this->content = $content; } - public function getAuthorEmail() + public function getPublishedAt() { - return $this->authorEmail; + return $this->publishedAt; } - /** - * @param string $authorEmail - */ - public function setAuthorEmail($authorEmail) + public function setPublishedAt(\DateTime $publishedAt) { - $this->authorEmail = $authorEmail; + $this->publishedAt = $publishedAt; } - public function getPublishedAt() + /** + * @return User + */ + public function getAuthor() { - return $this->publishedAt; + return $this->author; } - public function setPublishedAt(\DateTime $publishedAt) + /** + * @param User $author + */ + public function setAuthor(User $author) { - $this->publishedAt = $publishedAt; + $this->author = $author; } public function getPost() diff --git a/src/AppBundle/Entity/Post.php b/src/AppBundle/Entity/Post.php index ac20731cf..7482d243c 100644 --- a/src/AppBundle/Entity/Post.php +++ b/src/AppBundle/Entity/Post.php @@ -71,14 +71,6 @@ class Post */ private $content; - /** - * @var string - * - * @ORM\Column(type="string") - * @Assert\Email - */ - private $authorEmail; - /** * @var \DateTime * @@ -87,6 +79,14 @@ class Post */ private $publishedAt; + /** + * @var User + * + * @ORM\ManyToOne(targetEntity="AppBundle\Entity\User") + * @ORM\JoinColumn(nullable=false) + */ + private $author; + /** * @var Comment[]|ArrayCollection * @@ -149,35 +149,38 @@ public function setContent($content) $this->content = $content; } - public function getAuthorEmail() + public function getPublishedAt() { - return $this->authorEmail; + return $this->publishedAt; } - /** - * @param string $authorEmail - */ - public function setAuthorEmail($authorEmail) + public function setPublishedAt(\DateTime $publishedAt) { - $this->authorEmail = $authorEmail; + $this->publishedAt = $publishedAt; } /** - * Is the given User the author of this Post? + * @return User */ - public function isAuthor(User $user) + public function getAuthor() { - return $user->getEmail() === $this->getAuthorEmail(); + return $this->author; } - public function getPublishedAt() + /** + * @param User $author + */ + public function setAuthor(User $author) { - return $this->publishedAt; + $this->author = $author; } - public function setPublishedAt(\DateTime $publishedAt) + /** + * Is the given User the author of this Post? + */ + public function isAuthor(User $user = null) { - $this->publishedAt = $publishedAt; + return $user === $this->author; } public function getComments() diff --git a/src/AppBundle/EventListener/CommentNotificationListener.php b/src/AppBundle/EventListener/CommentNotificationListener.php index ff28cae0a..037fccfe3 100644 --- a/src/AppBundle/EventListener/CommentNotificationListener.php +++ b/src/AppBundle/EventListener/CommentNotificationListener.php @@ -11,6 +11,7 @@ namespace AppBundle\EventListener; +use AppBundle\Entity\Comment; use Symfony\Component\EventDispatcher\GenericEvent; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Translation\TranslatorInterface; @@ -63,6 +64,7 @@ public function __construct(\Swift_Mailer $mailer, UrlGeneratorInterface $urlGen */ public function onCommentCreated(GenericEvent $event) { + /** @var Comment $comment */ $comment = $event->getSubject(); $post = $comment->getPost(); @@ -82,7 +84,7 @@ public function onCommentCreated(GenericEvent $event) // See http://symfony.com/doc/current/email.html#sending-emails $message = \Swift_Message::newInstance() ->setSubject($subject) - ->setTo($post->getAuthorEmail()) + ->setTo($post->getAuthor()->getEmail()) ->setFrom($this->sender) ->setBody($body, 'text/html') ; diff --git a/src/AppBundle/Form/PostType.php b/src/AppBundle/Form/PostType.php index 74e4ce139..45e6ac0a2 100644 --- a/src/AppBundle/Form/PostType.php +++ b/src/AppBundle/Form/PostType.php @@ -52,9 +52,6 @@ public function buildForm(FormBuilderInterface $builder, array $options) 'attr' => ['rows' => 20], 'label' => 'label.content', ]) - ->add('authorEmail', null, [ - 'label' => 'label.author_email', - ]) ->add('publishedAt', DateTimePickerType::class, [ 'label' => 'label.published_at', ]) diff --git a/tests/AppBundle/Controller/Admin/BlogControllerTest.php b/tests/AppBundle/Controller/Admin/BlogControllerTest.php index 3128663d3..99b68072e 100644 --- a/tests/AppBundle/Controller/Admin/BlogControllerTest.php +++ b/tests/AppBundle/Controller/Admin/BlogControllerTest.php @@ -70,4 +70,26 @@ public function testIndex() 'The backend homepage displays all the available posts.' ); } + + /** + * @dataProvider getPostUrls + */ + public function testOnlyAuthorCanAccessToThePostInTheBackend($method, $url, $statusCode) + { + $client = static::createClient([], [ + 'PHP_AUTH_USER' => 'anna_admin', + 'PHP_AUTH_PW' => 'kitten', + ]); + + $client->request($method, $url); + + $this->assertEquals($statusCode, $client->getResponse()->getStatusCode()); + } + + public function getPostUrls() + { + yield ['GET', '/en/admin/post/1', Response::HTTP_OK]; + yield ['GET', '/en/admin/post/1/edit', Response::HTTP_OK]; + yield ['POST', '/en/admin/post/1/delete', Response::HTTP_FOUND]; + } } diff --git a/var/data/blog.sqlite b/var/data/blog.sqlite index b0d6ff89d..f15d78071 100644 Binary files a/var/data/blog.sqlite and b/var/data/blog.sqlite differ