V-Beta-1.0.0

Vision is out of alpha !
This commit is contained in:
Xbird
2022-02-02 17:46:29 +01:00
parent 797bf35b47
commit 9f22f5b1ee
2297 changed files with 278438 additions and 76 deletions

View 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
}
}

View 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);
}
}

View 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
}
}

View 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;
}
}

View 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;
}
}

View 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);
}