Passed
Push — master ( b71eb6...1476c0 )
by Angel Fernando Quiroz
08:20
created

SessionVoter::canEditSession()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 15
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 7
c 1
b 0
f 0
nc 4
nop 3
dl 0
loc 15
rs 9.6111
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
                if ($userIsGeneralCoach) {
88
                    $user->addRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_SESSION_TEACHER);
89
                } elseif ($userIsCourseCoach) { // Course-Coach access.
90
                    $user->addRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_SESSION_TEACHER);
91
                } elseif ($userIsStudent) { // Student access.
92
                    $user->addRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_SESSION_STUDENT);
93
                }
94
95
                if (Session::INVISIBLE !== $session->checkAccessVisibility($user)) {
0 ignored issues
show
Bug introduced by
Are you sure the usage of $session->checkAccessVisibility($user) targeting Chamilo\CoreBundle\Entit...checkAccessVisibility() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
96
                    return true;
97
                }
98
99
                return false;
100
101
            case self::EDIT:
102
            case self::DELETE:
103
                $canEdit = $this->canEditSession($user, $session, false);
104
105
                if ($canEdit) {
106
                    $user->addRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_SESSION_TEACHER);
107
108
                    return true;
109
                }
110
111
                return false;
112
        }
113
114
        // User don't have access to the session
115
        return false;
116
    }
117
118
    private function canEditSession(User $user, Session $session, bool $checkSession = true): bool
119
    {
120
        if (!$this->allowToManageSessions()) {
121
            return false;
122
        }
123
124
        if ($this->security->isGranted('ROLE_ADMIN') && $this->allowed($user, $session)) {
125
            return true;
126
        }
127
128
        if ($checkSession) {
129
            return $this->allowed($user, $session);
130
        }
131
132
        return true;
133
    }
134
135
    private function allowToManageSessions(): bool
136
    {
137
        if ($this->allowManageAllSessions()) {
138
            return true;
139
        }
140
141
        $setting = $this->settingsManager->getSetting('session.allow_teachers_to_create_sessions');
142
143
        return 'true' === $setting && $this->security->isGranted('ROLE_TEACHER');
144
    }
145
146
    private function allowManageAllSessions(): bool
147
    {
148
        return $this->security->isGranted('ROLE_ADMIN') || $this->security->isGranted('ROLE_SESSION_MANAGER');
149
    }
150
151
    private function allowed(User $user, Session $session): bool
152
    {
153
        if ($this->security->isGranted('ROLE_ADMIN')) {
154
            return true;
155
        }
156
157
        if ($this->security->isGranted('ROLE_SESSION_MANAGER')
158
            && 'true' !== $this->settingsManager->getSetting('session.allow_session_admins_to_manage_all_sessions')
159
            && !$session->hasUserAsSessionAdmin($user)
160
        ) {
161
            return false;
162
        }
163
164
        if ($this->security->isGranted('ROLE_TEACHER')
165
            && 'true' === $this->settingsManager->getSetting('session.allow_teachers_to_create_sessions')
166
            && !$session->hasUserAsGeneralCoach($user)
167
        ) {
168
            return false;
169
        }
170
171
        return true;
172
    }
173
}
174