added invoice voter (#316)

This commit is contained in:
Kevin Papst
2018-09-22 22:38:51 +02:00
committed by GitHub
parent 53f82a808b
commit 71aa899f77
8 changed files with 299 additions and 30 deletions

View File

@@ -77,6 +77,7 @@ class InvoiceController extends AbstractController
/**
* @Route(path="/", name="invoice", methods={"GET"})
* @Security("is_granted('view', 'invoice')")
*
* @param Request $request
* @return \Symfony\Component\HttpFoundation\Response
@@ -110,6 +111,7 @@ class InvoiceController extends AbstractController
/**
* @Route(path="/print", name="invoice_print", methods={"GET"})
* @Security("is_granted('create', 'invoice')")
*
* @param Request $request
* @return \Symfony\Component\HttpFoundation\Response
@@ -209,8 +211,7 @@ class InvoiceController extends AbstractController
/**
* @Route(path="/template", defaults={"page": 1}, name="admin_invoice_template", methods={"GET", "POST"})
* @Route(path="/template/page/{page}", requirements={"page": "[1-9]\d*"}, name="admin_invoice_template_paginated", methods={"GET", "POST"})
*
* TODO permission
* @Security("is_granted('view', 'invoice_template')")
*
* @param $page
* @return \Symfony\Component\HttpFoundation\Response
@@ -227,8 +228,7 @@ class InvoiceController extends AbstractController
/**
* @Route(path="/template/{id}/edit", name="admin_invoice_template_edit", methods={"GET", "POST"})
*
* TODO permission
* @Security("is_granted('edit', template)")
*
* @param InvoiceTemplate $template
* @param Request $request
@@ -242,8 +242,7 @@ class InvoiceController extends AbstractController
/**
* @Route(path="/template/create", name="admin_invoice_template_create", methods={"GET", "POST"})
*
* TODO permission
* @Security("is_granted('create', 'invoice_template')")
*
* @param Request $request
* @return \Symfony\Component\HttpFoundation\Response
@@ -261,9 +260,8 @@ class InvoiceController extends AbstractController
/**
* The route to delete an existing template.
*
* TODO permission
*
* @Route(path="/template/{id}/delete", name="admin_invoice_template_delete", methods={"GET", "POST"})
* @Security("is_granted('delete', template)")
*
* @param InvoiceTemplate $template
* @param Request $request

View File

@@ -0,0 +1,61 @@
<?php
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\Security;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
class AclDecisionManager
{
/**
* @var AccessDecisionManagerInterface
*/
protected $decisionManager;
/**
* AbstractVoter constructor.
* @param AccessDecisionManagerInterface $decisionManager
*/
public function __construct(AccessDecisionManagerInterface $decisionManager)
{
$this->decisionManager = $decisionManager;
}
/**
* @param TokenInterface $token
* @return bool
*/
public function isFullyAuthenticated(TokenInterface $token)
{
if ($this->decisionManager->decide($token, ['IS_AUTHENTICATED_FULLY'])) {
return true;
}
return false;
}
/**
* @param TokenInterface $token
* @param string|array $roles
* @return bool
*/
public function hasRole(TokenInterface $token, $roles)
{
if (!is_array($roles)) {
$roles = [$roles];
}
if ($this->decisionManager->decide($token, $roles)) {
return true;
}
return false;
}
}

View File

@@ -9,8 +9,8 @@
namespace App\Voter;
use App\Security\AclDecisionManager;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
/**
@@ -19,15 +19,15 @@ use Symfony\Component\Security\Core\Authorization\Voter\Voter;
abstract class AbstractVoter extends Voter
{
/**
* @var AccessDecisionManagerInterface
* @var AclDecisionManager
*/
protected $decisionManager;
/**
* AbstractVoter constructor.
* @param AccessDecisionManagerInterface $decisionManager
* @param AclDecisionManager $decisionManager
*/
public function __construct(AccessDecisionManagerInterface $decisionManager)
public function __construct(AclDecisionManager $decisionManager)
{
$this->decisionManager = $decisionManager;
}
@@ -38,11 +38,7 @@ abstract class AbstractVoter extends Voter
*/
protected function isFullyAuthenticated(TokenInterface $token)
{
if ($this->decisionManager->decide($token, ['IS_AUTHENTICATED_FULLY'])) {
return true;
}
return false;
return $this->decisionManager->isFullyAuthenticated($token);
}
/**
@@ -52,10 +48,6 @@ abstract class AbstractVoter extends Voter
*/
protected function hasRole($role, TokenInterface $token)
{
if ($this->decisionManager->decide($token, [$role])) {
return true;
}
return false;
return $this->decisionManager->hasRole($token, [$role]);
}
}

136
src/Voter/InvoiceVoter.php Normal file
View File

@@ -0,0 +1,136 @@
<?php
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\Voter;
use App\Entity\InvoiceTemplate;
use App\Entity\User;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
/**
* A voter to check permissions on Invoices.
*/
class InvoiceVoter extends AbstractVoter
{
public const VIEW = 'view';
public const EDIT = 'edit';
public const CREATE = 'create';
public const DELETE = 'delete';
public const ALLOWED_ATTRIBUTES = [
self::VIEW,
self::CREATE,
self::EDIT,
self::DELETE
];
public const ALLOWED_SUBJECTS = [
'invoice',
'invoice_template'
];
/**
* @param string $attribute
* @param mixed $subject
* @return bool
*/
protected function supports($attribute, $subject)
{
if (!in_array($attribute, self::ALLOWED_ATTRIBUTES)) {
return false;
}
if (!$subject instanceof InvoiceTemplate) {
if (!is_string($subject) || !in_array($subject, self::ALLOWED_SUBJECTS)) {
return false;
}
}
return true;
}
/**
* @param string $attribute
* @param string|InvoiceTemplate $subject
* @param TokenInterface $token
* @return bool
*/
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
{
$user = $token->getUser();
if (!$user instanceof User) {
return false;
}
switch ($attribute) {
case self::VIEW:
return $this->canView($user, $token);
case self::CREATE:
return $this->canCreate($user, $token);
case self::EDIT:
return $this->canEdit($user, $token);
case self::DELETE:
return $this->canDelete($token);
}
return false;
}
/**
* @param User $user
* @param TokenInterface $token
* @return bool
*/
protected function canView(User $user, TokenInterface $token)
{
if ($this->canEdit($user, $token)) {
return true;
}
return false;
}
/**
* @param User $user
* @param TokenInterface $token
* @return bool
*/
protected function canCreate(User $user, TokenInterface $token)
{
if ($this->canDelete($token)) {
return true;
}
return false;
}
/**
* @param User $user
* @param TokenInterface $token
* @return bool
*/
protected function canEdit(User $user, TokenInterface $token)
{
if ($this->canDelete($token)) {
return true;
}
return false;
}
/**
* @param TokenInterface $token
* @return bool
*/
protected function canDelete(TokenInterface $token)
{
return $this->isFullyAuthenticated($token) && $this->hasRole('ROLE_TEAMLEAD', $token);
}
}