Completed
Push — master ( a1a590...8f8784 )
by Julito
18:16 queued 16s
created

SessionVoter::sessionIsAvailableByDuration()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 37
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 20
nc 5
nop 2
dl 0
loc 37
rs 9.6
c 0
b 0
f 0
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
namespace Chamilo\CoreBundle\Security\Authorization\Voter;
6
7
use Chamilo\CoreBundle\Entity\Session;
8
use Chamilo\CoreBundle\Entity\User;
9
use Chamilo\CoreBundle\Manager\SettingsManager;
10
use Chamilo\CoreBundle\Repository\CourseRepository;
11
use Doctrine\ORM\EntityManagerInterface;
12
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
13
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
14
use Symfony\Component\Security\Core\Security;
15
use Symfony\Component\Security\Core\User\UserInterface;
16
17
/**
18
 * Class SessionVoter.
19
 */
20
class SessionVoter extends Voter
21
{
22
    public const VIEW = 'VIEW';
23
    public const EDIT = 'EDIT';
24
    public const DELETE = 'DELETE';
25
26
    private $entityManager;
27
    private $courseManager;
28
    private $security;
29
    private $settingsManager;
30
31
    public function __construct(
32
        EntityManagerInterface $entityManager,
33
        CourseRepository $courseManager,
34
        Security $security,
35
        SettingsManager $settingsManager
36
    ) {
37
        $this->entityManager = $entityManager;
38
        $this->courseManager = $courseManager;
39
        $this->security = $security;
40
        $this->settingsManager = $settingsManager;
41
    }
42
43
    public function supports(string $attribute, $subject): bool
44
    {
45
        $options = [
46
            self::VIEW,
47
            self::EDIT,
48
            self::DELETE,
49
        ];
50
51
        return $subject instanceof Session && in_array($attribute, $options);
52
    }
53
54
    /**
55
     * Check if user has access to a session.
56
     *
57
     * {@inheritdoc}
58
     */
59
    protected function voteOnAttribute(string $attribute, $session, TokenInterface $token): bool
60
    {
61
        /** @var User $user */
62
        $user = $token->getUser();
63
64
        // Make sure there is a user object (i.e. that the user is logged in)
65
        if (!$user instanceof UserInterface) {
66
            return false;
67
        }
68
69
        // Admins have access to everything
70
        if ($this->security->isGranted('ROLE_ADMIN')) {
71
            return true;
72
        }
73
74
        // Checks if the current course was set up
75
        // $session->getCurrentCourse() is set in the class CourseListener
76
        /** @var Session $session */
77
        $currentCourse = $session->getCurrentCourse();
78
79
        switch ($attribute) {
80
            case self::VIEW:
81
                $userIsGeneralCoach = $session->isUserGeneralCoach($user);
82
                $userIsCourseCoach = $session->hasCoachInCourseWithStatus($user, $currentCourse);
83
                $userIsStudent = $session->hasUserInCourse($user, $currentCourse, Session::STUDENT);
84
85
                if (empty($session->getDuration())) {
86
                    // General coach.
87
                    if ($userIsGeneralCoach && $session->isActiveForCoach()) {
88
                        $user->addRole(ResourceNodeVoter::ROLE_CURRENT_SESSION_COURSE_TEACHER);
89
90
                        return true;
91
                    }
92
93
                    // Course-Coach access.
94
                    if ($userIsCourseCoach && $session->isActiveForCoach()) {
95
                        $user->addRole(ResourceNodeVoter::ROLE_CURRENT_SESSION_COURSE_TEACHER);
96
97
                        return true;
98
                    }
99
100
                    // Student access
101
                    if ($userIsStudent && $session->isActiveForStudent()) {
102
                        $user->addRole(ResourceNodeVoter::ROLE_CURRENT_SESSION_COURSE_STUDENT);
103
104
                        //$token->setUser($user);
105
106
                        return true;
107
                    }
108
                }
109
110
                if ($this->sessionIsAvailableByDuration($session, $user)) {
111
                    if ($userIsGeneralCoach) {
112
                        $user->addRole(ResourceNodeVoter::ROLE_CURRENT_SESSION_COURSE_TEACHER);
113
114
                        return true;
115
                    }
116
117
                    if ($userIsCourseCoach) {
118
                        $user->addRole(ResourceNodeVoter::ROLE_CURRENT_SESSION_COURSE_TEACHER);
119
120
                        return true;
121
                    }
122
123
                    if ($userIsStudent) {
124
                        $user->addRole(ResourceNodeVoter::ROLE_CURRENT_SESSION_COURSE_STUDENT);
125
126
                        return true;
127
                    }
128
                }
129
130
                return false;
131
            case self::EDIT:
132
            case self::DELETE:
133
                $canEdit = $this->canEditSession($user, $session, false);
134
135
                if ($canEdit) {
136
                    $user->addRole(ResourceNodeVoter::ROLE_CURRENT_SESSION_COURSE_TEACHER);
137
138
                    return true;
139
                }
140
141
                return false;
142
        }
143
144
        // User don't have access to the session
145
        return false;
146
    }
147
148
    /**
149
     * @return bool
150
     */
151
    private function sessionIsAvailableByDuration(Session $session, User $user)
152
    {
153
        $duration = $session->getDuration() * 24 * 60 * 60;
154
        $courseAccess = \CourseManager::getFirstCourseAccessPerSessionAndUser(
155
            $session->getId(),
156
            $user->getId()
157
        );
158
159
        // If there is a session duration but there is no previous
160
        // access by the user, then the session is still available
161
        if (0 == count($courseAccess)) {
162
            return true;
163
        }
164
165
        $currentTime = time();
166
        $firstAccess = 0;
167
168
        if (isset($courseAccess['login_course_date'])) {
169
            $firstAccess = api_strtotime(
170
                $courseAccess['login_course_date'],
171
                'UTC'
172
            );
173
        }
174
175
        $userDurationData = \SessionManager::getUserSession(
176
            $user->getId(),
177
            $session->getId()
178
        );
179
        $userDuration = 0;
180
181
        if (isset($userDurationData['duration'])) {
182
            $userDuration = (int) $userDurationData['duration'] * 24 * 60 * 60;
183
        }
184
185
        $totalDuration = $firstAccess + $duration + $userDuration;
186
187
        return $totalDuration > $currentTime;
188
    }
189
190
    /**
191
     * @param bool $checkSession
192
     */
193
    private function canEditSession(User $user, Session $session, $checkSession = true): bool
194
    {
195
        if (!$this->allowToManageSessions()) {
196
            return false;
197
        }
198
199
        if ($this->security->isGranted('ROLE_ADMIN') && $this->allowed($user, $session)) {
200
            return true;
201
        }
202
203
        if ($checkSession) {
204
            if ($this->allowed($user, $session)) {
205
                return true;
206
            }
207
208
            return false;
209
        }
210
211
        return true;
212
    }
213
214
    private function allowToManageSessions(): bool
215
    {
216
        if ($this->allowManageAllSessions()) {
217
            return true;
218
        }
219
220
        $setting = $this->settingsManager->getSetting('session.allow_teachers_to_create_sessions');
221
222
        if ('true' === $setting && $this->security->isGranted('ROLE_TEACHER')) {
223
            return true;
224
        }
225
226
        return false;
227
    }
228
229
    private function allowManageAllSessions(): bool
230
    {
231
        if ($this->security->isGranted('ROLE_ADMIN') || $this->security->isGranted('ROLE_SESSION_MANAGER')) {
232
            return true;
233
        }
234
235
        return false;
236
    }
237
238
    /**
239
     * @return bool
240
     */
241
    private function allowed(User $user, Session $session)
242
    {
243
        if ($this->security->isGranted('ROLE_ADMIN')) {
244
            return true;
245
        }
246
247
        if ($this->security->isGranted('ROLE_SESSION_MANAGER') &&
248
            'true' !== $this->settingsManager->getSetting('session.allow_session_admins_to_manage_all_sessions')
249
        ) {
250
            if ($session->getSessionAdmin()->getId() !== $user->getId()) {
251
                return false;
252
            }
253
        }
254
255
        if ($this->security->isGranted('ROLE_ADMIN') &&
256
            'true' === $this->settingsManager->getSetting('session.allow_teachers_to_create_sessions')
257
        ) {
258
            if ($session->getGeneralCoach()->getId() !== $user->getId()) {
259
                return false;
260
            }
261
        }
262
263
        return true;
264
    }
265
}
266