Passed
Push — master ( 262c23...1cc54c )
by Angel Fernando Quiroz
09:24
created

ResourceAclHelper::init()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 48
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 27
c 0
b 0
f 0
nc 2
nop 2
dl 0
loc 48
rs 9.488
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
declare(strict_types=1);
6
7
namespace Chamilo\CoreBundle\Helpers;
8
9
use Chamilo\CoreBundle\Entity\ResourceLink;
10
use Chamilo\CoreBundle\Entity\ResourceRight;
11
use Chamilo\CoreBundle\Entity\User;
12
use Chamilo\CoreBundle\Security\Authorization\Voter\ResourceFileVoter;
13
use Chamilo\CoreBundle\Security\Authorization\Voter\ResourceNodeVoter;
14
use Laminas\Permissions\Acl\Acl;
15
use Laminas\Permissions\Acl\Resource\GenericResource;
16
use Laminas\Permissions\Acl\Role\GenericRole;
17
use Symfony\Bundle\SecurityBundle\Security;
18
use Symfony\Component\Security\Acl\Permission\MaskBuilder;
19
use Symfony\Component\Security\Core\Authentication\Token\NullToken;
20
use Symfony\Component\Security\Core\User\UserInterface;
21
22
readonly class ResourceAclHelper
23
{
24
    public function __construct(
25
        private Security $security,
26
    ) { }
27
28
    /**
29
     * @param iterable<int, ResourceRight> $rights
30
     */
31
    private function init(
32
        ResourceLink $resourceLink,
33
        iterable $rights,
34
    ): Acl {
35
        // Creating roles
36
        $anon = new GenericRole('IS_AUTHENTICATED_ANONYMOUSLY');
37
        $userRole = new GenericRole('ROLE_USER');
38
        $student = new GenericRole('ROLE_STUDENT');
39
        $teacher = new GenericRole('ROLE_TEACHER');
40
        $studentBoss = new GenericRole('ROLE_STUDENT_BOSS');
41
42
        $currentStudent = new GenericRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_STUDENT);
43
        $currentTeacher = new GenericRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_TEACHER);
44
45
        $currentStudentGroup = new GenericRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_GROUP_STUDENT);
46
        $currentTeacherGroup = new GenericRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_GROUP_TEACHER);
47
48
        $currentStudentSession = new GenericRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_SESSION_STUDENT);
49
        $currentTeacherSession = new GenericRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_SESSION_TEACHER);
50
51
        // Setting Simple ACL.
52
        $acl = (new Acl())
53
            ->addRole($anon)
54
            ->addRole($userRole)
55
            ->addRole($student)
56
            ->addRole($teacher)
57
            ->addRole($studentBoss)
58
59
            ->addRole($currentStudent)
60
            ->addRole($currentTeacher, ResourceNodeVoter::ROLE_CURRENT_COURSE_STUDENT)
61
62
            ->addRole($currentStudentSession)
63
            ->addRole($currentTeacherSession, ResourceNodeVoter::ROLE_CURRENT_COURSE_SESSION_STUDENT)
64
65
            ->addRole($currentStudentGroup)
66
            ->addRole($currentTeacherGroup, ResourceNodeVoter::ROLE_CURRENT_COURSE_GROUP_STUDENT)
67
        ;
68
69
        // Add a security resource.
70
        $acl->addResource(new GenericResource((string) $resourceLink->getId()));
71
72
        // Check all the right this link has.
73
        // Set rights from the ResourceRight.
74
        foreach ($rights as $right) {
75
            $acl->allow($right->getRole(), null, (string) $right->getMask());
76
        }
77
78
        return $acl;
79
    }
80
81
    /**
82
     * @param iterable<int, ResourceRight> $rights
83
     */
84
    public function isAllowed(
85
        string $attribute,
86
        ResourceLink $resourceLink,
87
        iterable $rights,
88
    ): bool {
89
        $acl = $this->init($resourceLink, $rights);
90
91
        $askedMask = (string) self::getPermissionMask([$attribute]);
92
93
        if ($this->security->getToken() instanceof NullToken) {
94
            return (bool) $acl->isAllowed('IS_AUTHENTICATED_ANONYMOUSLY', $resourceLink->getId(), $askedMask);
95
        }
96
97
        $user = $this->security->getUser();
98
99
        $roles = $user instanceof UserInterface ? $user->getRoles() : [];
100
101
        foreach ($roles as $role) {
102
            if ($acl->isAllowed($role, $resourceLink->getId(), $askedMask)) {
103
                return true;
104
            }
105
        }
106
107
        return false;
108
    }
109
110
    public static function getPermissionMask(array $attributes): int
111
    {
112
        $builder = new MaskBuilder();
113
114
        foreach ($attributes as $attribute) {
115
            $builder->add($attribute);
116
        }
117
118
        return $builder->get();
119
    }
120
}