UserContext.php 7.62 KB
Newer Older
1
2
3
4
<?php

namespace UnicaenAuth\Service;

5
use UnicaenApp\Exception\RuntimeException;
6
use Zend\ServiceManager\ServiceLocatorAwareInterface;
7
8
use Zend\ServiceManager\ServiceLocatorAwareTrait;
use Zend\Session\Container as SessionContainer;
9
use Zend\Permissions\Acl\Role\RoleInterface;
10
11
use ZfcUser\Entity\UserInterface;
use UnicaenAuth\Entity\Ldap\People;
12
use UnicaenAuth\Acl\NamedRole;
13
14

/**
15
 * Service centralisant des méthodes utiles concernant l'utilisateur authentifié.
16
17
18
19
20
 *
 * @author Laurent LÉCLUSE <laurent.lecluse at unicaen.fr>
 */
class UserContext implements ServiceLocatorAwareInterface
{
21
    use ServiceLocatorAwareTrait;
22
23
24
25
26

    /**
     * @var mixed
     */
    protected $identity;
27

28
    /**
29
     * @var array
30
     */
31
    protected $identityRoles;
32

33
34
35
36
    /**
     * @var SessionContainer
     */
    protected $sessionContainer;
37
38
39
40
41
42
43
44
45
46
47
48
49

    /**
     * Retourne l'utilisateur BDD courant
     *
     * @return UserInterface
     */
    public function getDbUser()
    {
        if (($identity = $this->getIdentity())) {
            if (isset($identity['db']) && $identity['db'] instanceof UserInterface) {
                return $identity['db'];
            }
        }
50

51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
        return null;
    }

    /**
     * Retourne l'utilisateur LDAP courant
     *
     * @return People
     */
    public function getLdapUser()
    {
        if (($identity = $this->getIdentity())) {
            if (isset($identity['ldap']) && $identity['ldap'] instanceof People) {
                return $identity['ldap'];
            }
        }
66

67
68
69
70
        return null;
    }

    /**
71
     * Retourne les données d'identité correspondant à l'utilisateur courant.
72
     *
73
     * @return mixed
74
     */
75
    public function getIdentity()
76
    {
77
78
79
80
81
82
        if (null === $this->identity) {
            $authenticationService = $this->getServiceLocator()->get('Zend\Authentication\AuthenticationService');
            if ($authenticationService->hasIdentity()) {
                $this->identity = $authenticationService->getIdentity();
            }
        }
83

84
85
        return $this->identity;
    }
86

87
    /**
88
     * Retourne tous les rôles de l'utilisateur courant, pas seulement le rôle courant sélectionné.
89
     *
90
91
92
93
94
     * @return array
     */
    public function getIdentityRoles()
    {
        if (null === $this->identityRoles) {
95
96
            $identityProvider = $this->getIdentityProvider();
            $this->identityRoles = $identityProvider->getAllIdentityRoles();
97
        }
98

99
100
        return $this->identityRoles;
    }
101

102
    /**
103
     * Retourne parmi tous les rôles de l'utilisateur courant ceux qui peuvent être sélectionnés.
104
     *
105
106
107
108
     * @return array
     */
    public function getSelectableIdentityRoles()
    {
Bertrand Gauthier's avatar
Bertrand Gauthier committed
109
110
        $filter = function($r) { return !($r instanceof NamedRole && !$r->getSelectable()); };
        $roles  = array_filter($this->getIdentityRoles(), $filter);
111

Bertrand Gauthier's avatar
Bertrand Gauthier committed
112
        return $roles;
113
    }
114

115
    /**
116
     * Si un utilisateur est authentifié, retourne le rôle utilisateur sélectionné,
117
     * ou alors le premier sélectionnable si aucun n'a été sélectionné.
118
119
120
121
     *
     * NB: Si un rôle est spécifié en session comme devant être le prochain rôle sélectionné,
     * c'est lui qui est pris en compte.
     *
122
123
124
125
     * @return mixed
     */
    public function getSelectedIdentityRole()
    {
126
127
128
129
130
131
132
        if ($this->getNextSelectedIdentityRole()) {
            $this->getSessionContainer()->selectedIdentityRole = $this->getNextSelectedIdentityRole();
        }

        if (null === $this->getSessionContainer()->selectedIdentityRole && $this->getIdentity()) {
            $roles = $this->getSelectableIdentityRoles();
            $this->setSelectedIdentityRole(reset($roles));
133
        }
134
135
136
137

        $roleId = $this->getSessionContainer()->selectedIdentityRole;

        $role = $this->normalizedIdentityRole($roleId);
138
139
140
        if ($this->isRoleValid($role)) {
            return $role;
        }
141

142
        return null;
143
    }
144

145
    /**
Bertrand Gauthier's avatar
Bertrand Gauthier committed
146
     * Mémorise en session le rôle spécifié comme étant le rôle courant de l'utilisateur.
147
     *
Bertrand Gauthier's avatar
Bertrand Gauthier committed
148
     * NB: seul l'id du rôle est mémorisé en session.
149
     *
Bertrand Gauthier's avatar
Bertrand Gauthier committed
150
     * @param RoleInterface|string $role
151
     * @return \UnicaenAuth\Service\UserContext
152
     * @throws RuntimeException
153
154
155
156
157
     */
    public function setSelectedIdentityRole($role)
    {
        if ($role) {
            if (!$this->isRoleValid($role)) {
158
                throw new RuntimeException("Rôle spécifié invalide.");
159
            }
Bertrand Gauthier's avatar
Bertrand Gauthier committed
160
161
162
163
            if ($role instanceof RoleInterface) {
                $role = $role->getRoleId();
            }
            $this->getSessionContainer()->selectedIdentityRole = $role;
164
165
166
167
        }
        else {
            unset($this->getSessionContainer()->selectedIdentityRole);
        }
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204

        return $this;
    }

    /**
     * Retourne l'éventuel rôle spécifié en session devant être le prochain rôle sélectionné.
     *
     * @return string|null
     */
    private function getNextSelectedIdentityRole()
    {
        return $this->getSessionContainer()->nextSelectedIdentityRole;
    }

    /**
     * Mémorise en session le rôle devant être le prochain rôle sélectionné.
     *
     * NB: seul l'id du rôle est mémorisé en session ; la durée de vie du stockage est de 1 requête seulement.
     *
     * @param RoleInterface|string $role
     * @return \UnicaenAuth\Service\UserContext
     */
    public function setNextSelectedIdentityRole($role)
    {
        if ($role instanceof RoleInterface) {
            $role = $role->getRoleId();
        }

        if ($role) {
            $this->getSessionContainer()->nextSelectedIdentityRole = $role;
            $this->getSessionContainer()->setExpirationHops(1, 'nextSelectedIdentityRole');

        }
        else {
            unset($this->getSessionContainer()->nextSelectedIdentityRole);
        }

205
206
        return $this;
    }
207

208
209
    /**
     * Recherche le role spécifié parmi les rôles connus au format objets.
210
211
212
     *
     * @param RoleInterface|string $role
     * @return RoleInterface Role trouvé au format objet dans la mesure du possible
213
214
215
     */
    protected function normalizedIdentityRole($role)
    {
Bertrand Gauthier's avatar
Bertrand Gauthier committed
216
        if (!$role || is_object($role)) {
217
218
            return $role;
        }
219

220
221
222
223
224
225
226
227
        foreach ($this->getIdentityRoles() as $r) {
            if ($r instanceof RoleInterface && $role === $r->getRoleId()) {
                return $r;
            }
            if ($role === $r) {
                return $r;
            }
        }
228

229
230
        return $role;
    }
231

232
    /**
233
     * Teste si le rôle spécifié fait partie des rôles disponibles.
234
235
     *
     * @param RoleInterface|string $role
236
     * @return boolean
237
     */
238
    protected function isRoleValid($role)
239
    {
Bertrand Gauthier's avatar
Bertrand Gauthier committed
240
241
242
        if ($role instanceof RoleInterface) {
            $role = $role->getRoleId();
        }
243

244
        foreach ($this->getIdentityRoles() as $r) {
245
            if ($r instanceof RoleInterface) {
246
247
248
249
250
251
                $r = $r->getRoleId();
            }
            if ($role === $r) {
                return true;
            }
        }
252

253
254
        return false;
    }
255

256
    /**
257
     *
258
259
260
261
262
     * @return \UnicaenAuth\Provider\Identity\Chain
     */
    private function getIdentityProvider()
    {
        $authorize = $this->getServiceLocator()->get('BjyAuthorize\Service\Authorize');
263

264
265
        return $authorize->getIdentityProvider(); /* @var $identityProvider \UnicaenAuth\Provider\Identity\Chain */
    }
266

267
    /**
268
     * Retourne le stockage en session utilisé pour mémoriser le profil
269
     * sélectionné par l'utilsateur.
270
     *
271
272
273
274
275
276
277
     * @return SessionContainer
     */
    protected function getSessionContainer()
    {
        if (null === $this->sessionContainer) {
            $this->sessionContainer = new SessionContainer(get_class());
        }
278

279
        return $this->sessionContainer;
280
281
    }
}