V-Beta-1.0.0
Vision is out of alpha !
This commit is contained in:
78
src/Security/Voter/CommentVoter.php
Normal file
78
src/Security/Voter/CommentVoter.php
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace App\Security\Voter;
|
||||
|
||||
use App\Security\Voter\Tools\VoterInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
|
||||
class CommentVoter extends VoterInterface
|
||||
{
|
||||
protected function supports(string $attribute, $subject): bool
|
||||
{
|
||||
|
||||
return in_array($attribute, ['edit', 'delete'])
|
||||
&& $subject instanceof \App\Entity\Comment;
|
||||
}
|
||||
|
||||
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
|
||||
{
|
||||
|
||||
//first, check if user is valid and has permissions
|
||||
if (!$this->checkUser($token->getUser())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//then set prefix
|
||||
$this->setPermissionsPrefix('comment');
|
||||
|
||||
switch ($attribute) {
|
||||
case 'edit':
|
||||
return $this->canEdit($subject);
|
||||
break;
|
||||
case 'delete':
|
||||
return $this->canDelete($subject);
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function canEdit($subject)
|
||||
{
|
||||
//user appartient au groupe du commentaire
|
||||
if ($subject->getMainGroup() === $this->user->getMainGroup()) {
|
||||
if ($subject->getCreator() === $this->user) { //c'est son propre commentaire
|
||||
return $this->hasPermission('EDIT');
|
||||
}
|
||||
|
||||
return $this->hasPermission('EDIT_GROUP');
|
||||
}
|
||||
|
||||
//user n'appartient pas au groupe du commentaire
|
||||
if ($subject->getMainGroup() !== $this->user->getMainGroup()) {
|
||||
return $this->hasPermission('EDIT_OTHERGROUP');
|
||||
}
|
||||
|
||||
return false; //false by default
|
||||
}
|
||||
|
||||
private function canDelete($subject)
|
||||
{
|
||||
|
||||
//user appartient au groupe du commentaire
|
||||
if ($subject->getMainGroup() === $this->user->getMainGroup()) {
|
||||
if ($subject->getCreator() === $this->user) { //c'est son propre commentaire
|
||||
return $this->hasPermission('DELETE');
|
||||
}
|
||||
|
||||
return $this->hasPermission('DELETE_GROUP');
|
||||
}
|
||||
|
||||
//user n'appartient pas au groupe du commentaire
|
||||
if ($subject->getMainGroup() !== $this->user->getMainGroup()) {
|
||||
return $this->hasPermission('DELETE_OTHERGROUP');
|
||||
}
|
||||
|
||||
return false; //false by default
|
||||
}
|
||||
}
|
||||
44
src/Security/Voter/DirectoryVoter.php
Normal file
44
src/Security/Voter/DirectoryVoter.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace App\Security\Voter;
|
||||
|
||||
use App\Security\Voter\Tools\VoterInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
|
||||
class DirectoryVoter extends VoterInterface
|
||||
{
|
||||
protected function supports(string $attribute, $subject): bool
|
||||
{
|
||||
return in_array($attribute, ['create', 'edit', 'delete', 'edit_medical', 'merge'])
|
||||
&& $subject instanceof \App\Entity\Directory;
|
||||
}
|
||||
|
||||
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
|
||||
{
|
||||
//first, check if user is valid and has permissions
|
||||
if (!$this->checkUser($token->getUser())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
switch ($attribute) {
|
||||
case 'create':
|
||||
case 'edit':
|
||||
case 'delete':
|
||||
case 'merge':
|
||||
$this->setPermissionsPrefix('directory');
|
||||
return $this->hasPermission($attribute);
|
||||
break;
|
||||
case 'edit_medical':
|
||||
if (!$this->hasPermission('general_medical_view')) {
|
||||
return false;
|
||||
}
|
||||
$this->setPermissionsPrefix('directory');
|
||||
return $this->hasPermission($attribute);
|
||||
break;
|
||||
}
|
||||
|
||||
//finally, check if permission is in permission list of user
|
||||
return $this->hasPermission($attribute);
|
||||
}
|
||||
}
|
||||
178
src/Security/Voter/DocumentVoter.php
Normal file
178
src/Security/Voter/DocumentVoter.php
Normal file
@@ -0,0 +1,178 @@
|
||||
<?php
|
||||
|
||||
namespace App\Security\Voter;
|
||||
|
||||
use App\Security\Voter\Tools\VoterInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
|
||||
class DocumentVoter extends VoterInterface
|
||||
{
|
||||
protected function supports(string $attribute, $subject): bool
|
||||
{
|
||||
return in_array($attribute, ['view', 'create', 'edit', 'delete', 'archive'])
|
||||
&& is_subclass_of($subject, 'App\Entity\Document');
|
||||
}
|
||||
|
||||
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
|
||||
{
|
||||
|
||||
//first, check if user is valid and has permissions
|
||||
if (!$this->checkUser($token->getUser())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//if user is in admin mode, bypass
|
||||
if ($this->user->getAdminMode()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//before all, check if user has specials perms
|
||||
//reset prefix, maybe voter has been used before
|
||||
$this->setPermissionsPrefix(null);
|
||||
|
||||
if ($subject->getNeedLegalAccess() && !$this->hasPermission('general_legal_view')) {
|
||||
return false;
|
||||
}
|
||||
if ($subject->getNeedMedicalAccess() && !$this->hasPermission('general_medical_view')) {
|
||||
return false;
|
||||
}
|
||||
if ($subject->getNeedGroupAdministration() && !$this->hasPermission('group_administrate')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//then set prefix
|
||||
$this->setPermissionsPrefix($subject->getClassShort());
|
||||
|
||||
//Check upon attribute
|
||||
switch ($attribute) {
|
||||
case 'view':
|
||||
return $this->canView($subject);
|
||||
break;
|
||||
case 'create':
|
||||
return $this->canCreate($subject);
|
||||
break;
|
||||
|
||||
case 'edit':
|
||||
//if document is archived, cannot edit
|
||||
if ($subject->getArchive()) {
|
||||
return false;
|
||||
}
|
||||
return $this->canEdit($subject);
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
//if document is archived, cannot delete
|
||||
if ($subject->getArchive()) {
|
||||
return false;
|
||||
}
|
||||
return $this->canDelete($subject);
|
||||
break;
|
||||
case 'archive':
|
||||
return $this->canArchive($subject);
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function canView($subject)
|
||||
{
|
||||
//Document is public
|
||||
if ($subject->getIsPublic()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//Document belong to user main group
|
||||
if ($subject->getMainGroup() === $this->user->getMainGroup()) {
|
||||
//Document has a restricted subGroup, is the user member of this subgroup ? or maybe he has a bypass perm ?
|
||||
if (!$subject->getAllowedSubGroups()->isEmpty() && !$this->hasPermission('group_ignore_subgroups', true)) {
|
||||
return $subject->getAllowedSubGroups()
|
||||
->exists(function ($key, $value) {
|
||||
return $this->user->getSubGroups()->contains($value);
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//Document not belong to user main group, is the user main group allowed ?
|
||||
//if the document as a subGroup, user can't have the subgroup of an other group
|
||||
if ($subject->getMainGroup() !== $this->user->getMainGroup() && $subject->getAllowedSubGroups()->isEmpty()) {
|
||||
return $subject->getAllowedGroups()->contains($this->user->getMainGroup());
|
||||
}
|
||||
|
||||
return false; //false by default
|
||||
}
|
||||
|
||||
private function canCreate()
|
||||
{
|
||||
return $this->hasPermission('CREATE');
|
||||
}
|
||||
|
||||
private function canEdit($subject)
|
||||
{
|
||||
|
||||
//Document belong to user main group
|
||||
if ($subject->getMainGroup() === $this->user->getMainGroup()) {
|
||||
if ($subject->getCreator() === $this->user) { //c'est son propre document
|
||||
return $this->hasPermission('EDIT');
|
||||
}
|
||||
|
||||
return $this->hasPermission('EDIT_GROUP');
|
||||
}
|
||||
|
||||
//Document not belong to user main group
|
||||
if ($subject->getMainGroup() !== $this->user->getMainGroup()) {
|
||||
if ($subject->getAllowedGroups()->contains($this->user->getMainGroup())) {
|
||||
return $this->hasPermission('EDIT_OTHERGROUP');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return false; //false by default
|
||||
}
|
||||
|
||||
private function canDelete($subject)
|
||||
{
|
||||
//Document belong to user main group
|
||||
if ($subject->getMainGroup() === $this->user->getMainGroup()) {
|
||||
if ($subject->getCreator() === $this->user) { //document belong to user
|
||||
return $this->hasPermission('DELETE');
|
||||
}
|
||||
|
||||
return $this->hasPermission('DELETE_GROUP');
|
||||
}
|
||||
|
||||
//Document not belong to user main group
|
||||
if ($subject->getMainGroup() !== $this->user->getMainGroup()) {
|
||||
if ($subject->getAllowedGroups()->contains($this->user->getMainGroup())) {
|
||||
return $this->hasPermission('DELETE_OTHERGROUP');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return false; //false by default
|
||||
}
|
||||
|
||||
private function canArchive($subject)
|
||||
{
|
||||
//Document belong to user main group
|
||||
if ($subject->getMainGroup() === $this->user->getMainGroup()) {
|
||||
if ($subject->getCreator() === $this->user) { //document belong to user
|
||||
return $this->hasPermission('ARCHIVE');
|
||||
}
|
||||
|
||||
return $this->hasPermission('ARCHIVE_GROUP');
|
||||
}
|
||||
|
||||
//Document not belong to user main group
|
||||
if ($subject->getMainGroup() !== $this->user->getMainGroup()) {
|
||||
if ($subject->getAllowedGroups()->contains($this->user->getMainGroup())) {
|
||||
return $this->hasPermission('ARCHIVE_OTHERGROUP');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return false; //false by default
|
||||
}
|
||||
}
|
||||
58
src/Security/Voter/GroupVoter.php
Normal file
58
src/Security/Voter/GroupVoter.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace App\Security\Voter;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Security\Voter\Tools\VoterInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
|
||||
class GroupVoter extends VoterInterface
|
||||
{
|
||||
protected function supports(string $attribute, $subject): bool
|
||||
{
|
||||
|
||||
return in_array($attribute, ['administrate', 'motd', 'fire', 'rank', 'employee', 'sanction'])
|
||||
&& $subject instanceof \App\Entity\Group;
|
||||
}
|
||||
|
||||
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
|
||||
{
|
||||
//first, check if user is valid and has permissions
|
||||
/**
|
||||
* @var User $User
|
||||
*/
|
||||
$User = $token->getUser();
|
||||
if (!$this->checkUser($User)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//then set prefix
|
||||
$this->setPermissionsPrefix('group');
|
||||
|
||||
if ($User->getMainGroup() != $subject && !$User->getAdminMode()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$this->hasPermission('administrate')) {
|
||||
return false;
|
||||
} //base permission
|
||||
|
||||
switch ($attribute) {
|
||||
case 'administrate':
|
||||
return true;
|
||||
break;
|
||||
case 'motd':
|
||||
case 'fire':
|
||||
case 'employee':
|
||||
case 'rank':
|
||||
case 'sanction':
|
||||
return $this->hasPermission($attribute);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
45
src/Security/Voter/NotificationVoter.php
Normal file
45
src/Security/Voter/NotificationVoter.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace App\Security\Voter;
|
||||
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
|
||||
class NotificationVoter extends Voter
|
||||
{
|
||||
protected function supports(string $attribute, $subject): bool
|
||||
{
|
||||
|
||||
return in_array($attribute, ['delete', 'markread'])
|
||||
&& $subject instanceof \App\Entity\Notification;
|
||||
}
|
||||
/**
|
||||
* vote based on Notification
|
||||
*
|
||||
* @param string $attribute
|
||||
* @param Notification $subject
|
||||
* @param TokenInterface $token
|
||||
* @return boolean
|
||||
*/
|
||||
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
|
||||
{
|
||||
$user = $token->getUser();
|
||||
// if the user is anonymous, do not grant access
|
||||
if (!$user instanceof UserInterface) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ... (check conditions and return true to grant permission) ...
|
||||
switch ($attribute) {
|
||||
case 'delete':
|
||||
case 'markread':
|
||||
if ($subject->getReceiver() == $user) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
103
src/Security/Voter/Tools/VoterInterface.php
Normal file
103
src/Security/Voter/Tools/VoterInterface.php
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace App\Security\Voter\Tools;
|
||||
|
||||
use App\Entity\User;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
|
||||
|
||||
abstract class VoterInterface extends Voter
|
||||
{
|
||||
private LoggerInterface $logger;
|
||||
public User $user;
|
||||
public array $userpermissions;
|
||||
public ?string $permissionsPrefix;
|
||||
|
||||
public function __construct(LoggerInterface $logger)
|
||||
{
|
||||
$this->logger = $logger;
|
||||
$this->setPermissionsPrefix(null);
|
||||
}
|
||||
|
||||
public function setPermissionsPrefix(?string $prefix)
|
||||
{
|
||||
$this->permissionsPrefix = $prefix;
|
||||
}
|
||||
|
||||
public function getPermissionsPrefix(): ?string
|
||||
{
|
||||
return $this->permissionsPrefix;
|
||||
}
|
||||
|
||||
public function checkUser(User $User)
|
||||
{
|
||||
$this->user = $User;
|
||||
// if the user is anonymous, do not grant access
|
||||
if (!$this->user instanceof UserInterface) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// if the user has no group or no rank, do not grant access
|
||||
if ($this->user->getMainGroup() == null) {
|
||||
return false;
|
||||
}
|
||||
if ($this->user->getMainRank() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//if user is in admin mode, bypass
|
||||
if ($this->user->getAdminMode()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->userpermissions = $this->user->getMainRank()->getPermissions();
|
||||
|
||||
//if user (rank) has no permissions, do not grant access
|
||||
if ($this->userpermissions == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user has the permission
|
||||
*
|
||||
* @param string $attribute
|
||||
* @param boolean $ignoreprefix
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasPermission(string $attribute, bool $ignoreprefix = false): bool
|
||||
{
|
||||
//if user is in admin mode, bypass
|
||||
if ($this->user->getAdminMode()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$permission = strtolower(
|
||||
(
|
||||
$this->getPermissionsPrefix() != null
|
||||
&& !$ignoreprefix ?
|
||||
$this->getPermissionsPrefix() . '_' : ''
|
||||
) . $attribute
|
||||
);
|
||||
|
||||
|
||||
|
||||
if (in_array($permission, array_map('strtolower', $this->userpermissions))) {
|
||||
return true;
|
||||
}
|
||||
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
|
||||
*/
|
||||
abstract protected function supports(string $attribute, $subject);
|
||||
}
|
||||
Reference in New Issue
Block a user