AbstractDb.php 3.7 KB
Newer Older
1
2
3
4
5
<?php

namespace UnicaenAuth\Authentication\Adapter;

use UnicaenAuth\Options\Traits\ModuleOptionsAwareTrait;
Bertrand Gauthier's avatar
Bertrand Gauthier committed
6
7
8
use Laminas\Authentication\Result as AuthenticationResult;
use Laminas\EventManager\EventInterface;
use Laminas\Session\Container as SessionContainer;
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use ZfcUser\Authentication\Adapter\AdapterChainEvent;
use ZfcUser\Entity\UserInterface;
use ZfcUser\Mapper\UserInterface as UserMapperInterface;

/**
 * Classe abstraite des adpater d'authentification à partir de la base de données.
 * 
 * Ajout par rapport à la classe mère : si aucune base de données ou table n'existe,
 * l'authentification ne plante pas (i.e. renvoit false).
 *
 * @author Bertrand GAUTHIER <bertrand.gauthier@unicaen.fr>
 */
abstract class AbstractDb extends AbstractAdapter
{
    use ModuleOptionsAwareTrait;

    /**
     * @var string
     */
    protected $type;

    /**
     * @var AdapterChainEvent
     */
    protected $event;

    /**
     * @var UserMapperInterface
     */
    protected $mapper;

    /**
     * @inheritDoc
     */
    public function authenticate(EventInterface $e): bool
    {
        // NB: Dans la version 3.0.0 de zf-commons/zfc-user, cette méthode prend un EventInterface.
        // Mais dans la branche 3.x, c'est un AdapterChainEvent !
        // Si un jour c'est un AdapterChainEvent qui est attendu, plus besoin de faire $e->getTarget().
        $this->event = $e->getTarget();

        if ($this->event->getIdentity()) {
            return true;
        }

        if ($this->isSatisfied()) {
            $storage = $this->getStorage()->read();
            $this->event
                ->setIdentity($storage['identity'])
                ->setCode(AuthenticationResult::SUCCESS)
                ->setMessages(array('Authentication successful.'));
            return true;
        }

        $userObject = $this->fetchUserObject();
        if ($userObject === null) {
            return false;
        }

        if ($this->moduleOptions->getEnableUserState()) {
            // Don't allow user to login if state is not in allowed list
            if (!in_array($userObject->getState(), $this->moduleOptions->getAllowedLoginStates())) {
                $this->event
                    ->setCode(AuthenticationResult::FAILURE_UNCATEGORIZED)
                    ->setMessages(["Ce compte utilisateur a été désactivé"]);
                $this->setSatisfied(false);
                return false;
            }
        }

        $result = $this->authenticateUserObject($userObject);
        if ($result === false) {
            return false;
        }

        // regen the id
        $session = new SessionContainer($this->getStorage()->getNamespace());
        $session->getManager()->regenerateId();

        // Success!
        $identity = $this->createSessionIdentity($userObject->getUsername());
        $this->event->setIdentity($identity);
        $this->setSatisfied(true);
        $storage = $this->getStorage()->read();
        $storage['identity'] = $this->event->getIdentity();
        $this->getStorage()->write($storage);
        $this->event
            ->setCode(AuthenticationResult::SUCCESS)
            ->setMessages(array('Authentication successful.'));

        return true;
    }

    /**
     * @return \ZfcUser\Entity\UserInterface|null
     */
    abstract protected function fetchUserObject(): ?UserInterface;

    /**
     * @param \ZfcUser\Entity\UserInterface $userObject
     * @return bool
     */
    abstract protected function authenticateUserObject(UserInterface $userObject): bool;

    /**
     * setMapper
     *
     * @param UserMapperInterface $mapper
     * @return self
     */
    public function setMapper(UserMapperInterface $mapper): self
    {
        $this->mapper = $mapper;

        return $this;
    }
}