Passed
Pull Request — master (#5576)
by Angel Fernando Quiroz
07:15
created

SessionVoter::allowManageAllSessions()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 1
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
/* For licensing terms, see /license.txt */
6
7
namespace Chamilo\CoreBundle\Security\Authorization\Voter;
8
9
use Chamilo\CoreBundle\Entity\Session;
10
use Chamilo\CoreBundle\Entity\User;
11
use Chamilo\CoreBundle\Settings\SettingsManager;
12
use Symfony\Bundle\SecurityBundle\Security;
13
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
14
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
15
use Symfony\Component\Security\Core\User\UserInterface;
16
17
/**
18
 * @todo remove legacy code.
19
 *
20
 * @extends Voter<'VIEW'|'EDIT'|'DELETE', Session>
21
 */
22
class SessionVoter extends Voter
23
{
24
    public const VIEW = 'VIEW';
25
    public const EDIT = 'EDIT';
26
    public const DELETE = 'DELETE';
27
28
    public function __construct(
29
        private readonly Security $security,
30
        private readonly SettingsManager $settingsManager
31
    ) {}
32
33
    protected function supports(string $attribute, $subject): bool
34
    {
35
        $options = [
36
            self::VIEW,
37
            self::EDIT,
38
            self::DELETE,
39
        ];
40
41
        return $subject instanceof Session && \in_array($attribute, $options, true);
42
    }
43
44
    /**
45
     * Check if user has access to a session.
46
     *
47
     * {@inheritdoc}
48
     */
49
    protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
50
    {
51
        /** @var User $user */
52
        $user = $token->getUser();
53
54
        // Make sure there is a user object (i.e. that the user is logged in)
55
        if (!$user instanceof UserInterface) {
56
            return false;
57
        }
58
59
        // Admins have access to everything.
60
        if ($this->security->isGranted('ROLE_ADMIN')) {
61
            return true;
62
        }
63
64
        // Checks if the current course was set up
65
        // $session->getCurrentCourse() is set in the class CidReqListener.
66
        /** @var Session $session */
67
        $session = $subject;
68
        $currentCourse = $session->getCurrentCourse();
69
70
        // Course checks.
71
        if ($currentCourse && $currentCourse->isHidden()) {
72
            return false;
73
        }
74
75
        switch ($attribute) {
76
            case self::VIEW:
77
                // @todo improve performance.
78
                $userIsGeneralCoach = $session->hasUserAsGeneralCoach($user);
79
                if (null === $currentCourse) {
80
                    $userIsStudent = $session->getSessionRelCourseByUser($user, Session::STUDENT)->count() > 0;
81
                    $userIsCourseCoach = $session->hasCoachInCourseList($user); // The current course will be checked in CourseVoter.
82
                } else {
83
                    $userIsCourseCoach = $session->hasCourseCoachInCourse($user, $currentCourse);
84
                    $userIsStudent = $session->hasUserInCourse($user, $currentCourse, Session::STUDENT);
85
                }
86
87
                $visibilityForUser = $session->setAccessVisibilityByUser($user);
88
89
                if ($userIsStudent && Session::LIST_ONLY == $visibilityForUser) {
90
                    return false;
91
                }
92
93
                if ($userIsGeneralCoach || $userIsCourseCoach) {
94
                    $user->addRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_SESSION_TEACHER);
95
                } elseif ($userIsStudent) { // Student access.
96
                    $user->addRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_SESSION_STUDENT);
97
                }
98
99
                if (
100
                    ($userIsGeneralCoach || $userIsCourseCoach || $userIsStudent)
101
                    && $visibilityForUser != Session::INVISIBLE
102
                ) {
103
                    return true;
104
                }
105
106
                return false;
107
108
            case self::EDIT:
109
            case self::DELETE:
110
                $canEdit = $this->canEditSession($user, $session, false);
111
112
                if ($canEdit) {
113
                    $user->addRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_SESSION_TEACHER);
114
115
                    return true;
116
                }
117
118
                return false;
119
        }
120
121
        // User don't have access to the session
122
        return false;
123
    }
124
125
    private function canEditSession(User $user, Session $session, bool $checkSession = true): bool
126
    {
127
        if (!$this->allowToManageSessions()) {
128
            return false;
129
        }
130
131
        if ($this->security->isGranted('ROLE_ADMIN') && $this->allowed($user, $session)) {
132
            return true;
133
        }
134
135
        if ($checkSession) {
136
            return $this->allowed($user, $session);
137
        }
138
139
        return true;
140
    }
141
142
    private function allowToManageSessions(): bool
143
    {
144
        if ($this->allowManageAllSessions()) {
145
            return true;
146
        }
147
148
        $setting = $this->settingsManager->getSetting('session.allow_teachers_to_create_sessions');
149
150
        return 'true' === $setting && $this->security->isGranted('ROLE_TEACHER');
151
    }
152
153
    private function allowManageAllSessions(): bool
154
    {
155
        return $this->security->isGranted('ROLE_ADMIN') || $this->security->isGranted('ROLE_SESSION_MANAGER');
156
    }
157
158
    private function allowed(User $user, Session $session): bool
159
    {
160
        if ($this->security->isGranted('ROLE_ADMIN')) {
161
            return true;
162
        }
163
164
        if ($this->security->isGranted('ROLE_SESSION_MANAGER')
165
            && 'true' !== $this->settingsManager->getSetting('session.allow_session_admins_to_manage_all_sessions')
166
            && !$session->hasUserAsSessionAdmin($user)
167
        ) {
168
            return false;
169
        }
170
171
        if ($this->security->isGranted('ROLE_TEACHER')
172
            && 'true' === $this->settingsManager->getSetting('session.allow_teachers_to_create_sessions')
173
            && !$session->hasUserAsGeneralCoach($user)
174
        ) {
175
            return false;
176
        }
177
178
        return true;
179
    }
180
}
181