Commit b41ee749 authored by Dominique Merle's avatar Dominique Merle 💬
Browse files

Implement one more scenario about deleting polls.

parent 4a8d6313
......@@ -111,7 +111,7 @@ class MainFeatureContext extends BaseFeatureContext
/**
* @Then /^there should(?: now)?(?: still)?(?: only)? be (?P<thatMuch>.+) majority judgment polls? in the database$/ui
* @Then /^(?:qu')?il(?: ne)? d(?:oi|evrai)t(?: maintenant)? y avoir (?P<thatMuch>.+) scrutins? au jugement majoritaire dans la base de données$/ui
* @Then /^(?:qu')?il(?: ne)? d(?:oi|evrai)t(?: maintenant)?(?: encore)? y avoir (?P<thatMuch>.+) scrutins? au jugement majoritaire dans la base de données$/ui
*/
public function thereShouldBeSomeLimajuPollsInTheDatabase($thatMuch)
{
......@@ -123,7 +123,7 @@ class MainFeatureContext extends BaseFeatureContext
/**
* fixme: en step
* Then /^there should(?: now)?(?: still)?(?: only)? be (?P<thatMuch>.+) majority judgment polls? in the database$/ui
* @Then /^(?:que?' ?)?(?P<actor>.+?)(?: ne)? d(?:oi|evrai)t(?: maintenant)? avoir (?P<thatMuch>.+) votes? sur le scrutin(?: au jugement majoritaire)? titré "(?P<title>.+?)"$/ui
* @Then /^(?:que?' ?)?(?P<actor>.+?)(?: ne)? d(?:oi|evrai)t(?: maintenant)?(?: encore)? avoir (?P<thatMuch>.+) votes? sur le scrutin(?: au jugement majoritaire)? titré "(?P<title>.+?)"$/ui
*/
public function actorShouldHaveSomeLimajuPollOptionVotesForPoll($actor, $thatMuch, $title)
{
......
......@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace App\Controller;
use App\Entity\LimajuPollTally;
use App\Repository\LimajuPollRepository;
use App\Tally\Bot\TallyBotInterface;
use Doctrine\ORM\EntityManagerInterface;
......@@ -33,6 +34,7 @@ final class GetTallyController
$this->container = $container;
}
public function __invoke(
string $id,
Request $request,
......@@ -43,9 +45,10 @@ final class GetTallyController
$poll = $pollRepository->find($id);
$tally = "standard";
$tally = new LimajuPollTally();
$tallyBot = $this->getTallyBot($tally);
$tallyType = "standard";
$tallyBot = $this->getTallyBot($tallyType);
$tallyOutput = $tallyBot->tallyVotesOnLimajuPoll($poll);
$votesCount = $tallyOutput->countVotes();
......@@ -55,7 +58,9 @@ final class GetTallyController
return new JsonResponse(['error' => $error], Response::HTTP_BAD_REQUEST);
}
return new JsonResponse($tallyOutput, Response::HTTP_OK);
$tally->standard = $tallyOutput;
return new JsonResponse($tally, Response::HTTP_OK);
}
/**
......
......@@ -4,27 +4,26 @@
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiSubresource;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use ApiPlatform\Core\Annotation\ApiResource;
use Symfony\Component\Serializer\Annotation\Groups;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
/**
* A Liquid Majority Judgment Poll.
*
* @ApiResource(
* itemOperations={
* "post"={
* "denormalization_context"={"groups"={"create"}},
* "get"={
* "normalization_context"={"groups"={"read"}},
* },
* "delete"={
* "access_control"="is_granted('can_delete', object)",
* },
* "get",
* "put",
* "delete",
* },
* denormalizationContext = { "groups" = { "create" } },
* @ApiResource(
* collectionOperations = {
* "post"={
* "denormalization_context"={"groups"={"create"}},
......@@ -36,7 +35,6 @@ use Doctrine\ORM\Mapping as ORM;
class LimajuPoll
{
const MENTION_EXCELLENT = 'bonega';
const MENTION_VERY_GOOD = 'trebona';
const MENTION_GOOD = 'bona';
......@@ -72,6 +70,13 @@ class LimajuPoll
*/
private $options;
/**
* @Groups({ "none" })
* @ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="limajuPolls")
*/
private $author;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function __construct()
......@@ -129,6 +134,18 @@ class LimajuPoll
return $this;
}
public function getAuthor(): ?User
{
return $this->author;
}
public function setAuthor(?User $author): self
{
$this->author = $author;
return $this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Should we do it like this in the end?
......
......@@ -4,12 +4,27 @@
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
/**
* @ApiResource()
* @ApiResource(
* itemOperations={
* "get"={
* "normalization_context"={"groups"={"vote:read"}},
* },
* "delete"={
* "access_control"="is_granted('can_delete', object)",
* },
* },
* collectionOperations = {
* "post"={
* "denormalization_context"={"groups"={"vote:create"}},
* "normalization_context"={"groups"={"vote:read"}},
* },
* }
* )
* @ORM\Entity(repositoryClass="App\Repository\LimajuPollOptionVoteRepository")
*/
class LimajuPollOptionVote
......@@ -25,7 +40,7 @@ class LimajuPollOptionVote
/**
* The Majority Judgment Poll Option the author is giving a mention to.
*
* @Groups({ "create", "read" })
* @Groups({ "vote:create", "vote:read" })
* @ORM\ManyToOne(targetEntity="App\Entity\LimajuPollOption", inversedBy="votes")
* @ORM\JoinColumn(nullable=false)
*/
......@@ -38,7 +53,7 @@ class LimajuPollOptionVote
* This is optional, and some polls may require all participants to be logged in.
* For anonymous votes, this may be null.
*
* @Groups({ "read" })
* @Groups({ "none" })
* @ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="limajuPollOptionVotes")
* @ORM\JoinColumn(nullable=true)
*/
......@@ -48,7 +63,7 @@ class LimajuPollOptionVote
/**
* The name of the author of the vote, if any was specified.
*
* @Groups({ "create", "read", "update" })
* @Groups({ "vote:create", "vote:read", "vote:update" })
* @ORM\Column(type="string", length=32, nullable=true)
*/
private $author_name;
......@@ -57,7 +72,7 @@ class LimajuPollOptionVote
/**
* The mention attributed by the author to the option.
*
* @Groups({ "create", "read", "update" })
* @Groups({ "vote:create", "vote:read", "vote:update" })
* @ORM\Column(type="string", length=16)
*/
private $mention;
......
......@@ -2,19 +2,17 @@
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use MsgPhp\Domain\DomainCollection;
use MsgPhp\Domain\GenericDomainCollection;
use MsgPhp\User\User as BaseUser;
use MsgPhp\User\UserId;
use MsgPhp\Domain\Event\DomainEventHandler;
use MsgPhp\Domain\Event\DomainEventHandlerTrait;
use MsgPhp\User\Credential\EmailPassword;
use MsgPhp\User\Model\EmailPasswordCredential;
use MsgPhp\User\Model\ResettablePassword;
use MsgPhp\User\Model\RolesField;
use ApiPlatform\Core\Annotation\ApiResource;
use MsgPhp\User\User as BaseUser;
use MsgPhp\User\UserId;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Serializer\Annotation\Groups;
......@@ -46,12 +44,21 @@ class User extends BaseUser implements DomainEventHandler, UserInterface
*/
public $name;
/**
* Authored Limaju Polls.
*
* @Groups({ "never" })
* @ORM\OneToMany(targetEntity="App\Entity\LimajuPoll", mappedBy="author")
*/
private $limajuPolls;
public function __construct(UserId $id, string $email, string $password)
{
$this->id = $id;
// $this->name = $name;
$this->credential = new EmailPassword($email, $password);
$this->limajuPolls = new ArrayCollection();
}
public function getId(): UserId
......@@ -83,4 +90,35 @@ class User extends BaseUser implements DomainEventHandler, UserInterface
* the plain-text password is stored on this object.
*/
public function eraseCredentials() {}
/**
* @return Collection|LimajuPoll[]
*/
public function getLimajuPolls(): Collection
{
return $this->limajuPolls;
}
public function addLimajuPoll(LimajuPoll $limajuPoll): self
{
if (!$this->limajuPolls->contains($limajuPoll)) {
$this->limajuPolls[] = $limajuPoll;
$limajuPoll->setAuthor($this);
}
return $this;
}
public function removeLimajuPoll(LimajuPoll $limajuPoll): self
{
if ($this->limajuPolls->contains($limajuPoll)) {
$this->limajuPolls->removeElement($limajuPoll);
// set the owning side to null (unless already changed)
if ($limajuPoll->getAuthor() === $this) {
$limajuPoll->setAuthor(null);
}
}
return $this;
}
}
......@@ -6,17 +6,16 @@ namespace App\EventSubscriber;
use ApiPlatform\Core\EventListener\EventPriorities;
use App\Application;
use App\Entity\LimajuPoll;
use App\Entity\LimajuPollOptionVote;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
use Symfony\Component\HttpKernel\Event\ViewEvent;
use Symfony\Component\HttpKernel\KernelEvents;
/**
* This is how we hook in API Platform to set the author, during creation, of
* - LimajuPoll
* - LimajuPollOptionVote
*
* This only works for REST
......@@ -72,6 +71,10 @@ final class SetAuthorOfEntityIfNeeded implements EventSubscriberInterface
// $method = $event->getRequest()->getMethod();
if ($entity instanceof LimajuPoll) {
$entity->setAuthor($this->application->getAuthenticatedUser());
}
if ($entity instanceof LimajuPollOptionVote) {
$entity->setAuthor($this->application->getAuthenticatedUser());
}
......
<?php
namespace App\Security;
use App\Application;
use App\Entity\LimajuPoll;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
/**
* This bouncer's job is to tell who can get in and who can't.
*
*
* Class Bouncer
* @package App\Security
*/
class PollBouncer extends Voter
{
const CAN_DELETE = "can_delete";
/**
* @var AuthorizationCheckerInterface
*/
private $authorizationChecker;
/**
* @var Application
*/
private $app;
/**
* Bouncer constructor.
* @param Application $app
* @param AuthorizationCheckerInterface $authorizationChecker
*/
public function __construct(
Application $app,
AuthorizationCheckerInterface $authorizationChecker
) {
$this->authorizationChecker = $authorizationChecker;
$this->app = $app;
}
public function canCurrentUserEditPoll(LimajuPoll $poll, string $password='') : bool
{
if ($this->authorizationChecker->isGranted('ROLE_ADMIN')) {
return true;
}
if ('' == $password) {
if ( ! $this->authorizationChecker->isGranted('ROLE_USER')) {
return false;
} else {
}
} else {
// TODO
}
return false;
}
/**
* Determines if the attribute and subject are supported by this voter.
*
* @param string $attribute An attribute
* @param mixed $subject The subject to secure, e.g. an object the user wants to access or any other PHP type
*
* @return bool True if the attribute and subject are supported, false otherwise
*/
protected function supports($attribute, $subject)
{
if ( ! $subject instanceof LimajuPoll) {
return false;
}
if ( ! in_array($attribute, array(self::CAN_DELETE))) {
return false;
}
return true;
}
/**
* Perform a single access check operation on a given attribute, subject and token.
* It is safe to assume that $attribute and $subject already passed the "supports()" method check.
*
* @param string $attribute
* @param mixed $subject
*
* @return bool
*/
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
{
$roles = $token->getRoleNames();
if (self::CAN_DELETE == $attribute) {
if ($subject instanceof LimajuPoll) {
if (in_array('ROLE_ADMIN', $roles)) {
return true;
}
if ($subject->getAuthor() === $this->app->getAuthenticatedUser()) {
return true;
}
}
}
return false;
}
}
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment