Authenticate.php 3.88 KB
Newer Older
Jacob Priddy's avatar
Jacob Priddy committed
1 2 3 4
<?php

namespace Source\UseCases\Users\Authenticate;

5
use Source\Entities\User;
6
use Source\Entities\HashedSearchable;
7
use Source\Gateways\Saml\SamlRepository;
Jacob Priddy's avatar
Jacob Priddy committed
8 9
use Source\Gateways\Users\UsersRepository;
use Source\Gateways\Tokens\TokensRepository;
10
use Source\Exceptions\AuthenticationException;
Jacob Priddy's avatar
Jacob Priddy committed
11

Jacob Priddy's avatar
Jacob Priddy committed
12 13
class Authenticate implements AuthenticateUseCase
{
14 15 16
    /**
     * @var \Source\Gateways\Users\UsersRepository
     */
Jacob Priddy's avatar
Jacob Priddy committed
17 18
    protected UsersRepository $users;

19 20 21
    /**
     * @var \Source\Gateways\Tokens\TokensRepository
     */
Jacob Priddy's avatar
Jacob Priddy committed
22 23
    protected TokensRepository $tokens;

Jacob Priddy's avatar
Jacob Priddy committed
24 25 26 27
    /**
     * @var \Source\Gateways\Saml\SamlRepository
     */
    protected SamlRepository $saml;
28

29 30
    protected string $salt;

31 32 33
    /**
     * @param \Source\Gateways\Users\UsersRepository   $users
     * @param \Source\Gateways\Tokens\TokensRepository $tokens
Jacob Priddy's avatar
Jacob Priddy committed
34
     * @param \Source\Gateways\Saml\SamlRepository     $saml
35
     * @param string                                   $salt
36
     */
37
    public function __construct(UsersRepository $users, TokensRepository $tokens, SamlRepository $saml, string $salt)
Jacob Priddy's avatar
Jacob Priddy committed
38
    {
Jacob Priddy's avatar
Jacob Priddy committed
39
        $this->saml = $saml;
Jacob Priddy's avatar
Jacob Priddy committed
40 41
        $this->users = $users;
        $this->tokens = $tokens;
42
        $this->salt = $salt;
Jacob Priddy's avatar
Jacob Priddy committed
43 44 45 46 47
    }

    /**
     * @inheritDoc
     */
Jacob Priddy's avatar
Jacob Priddy committed
48 49
    public function attempt(Presenter $presenter, array $credentials): void
    {
Jacob Priddy's avatar
Jacob Priddy committed
50 51 52 53
        $email = $credentials['email'] ?? null;
        $password = $credentials['password'] ?? null;

        if (!$email || !$password) {
54
            throw new AuthenticationException();
Jacob Priddy's avatar
Jacob Priddy committed
55 56
        }

Jacob Priddy's avatar
Jacob Priddy committed
57
        $user = $this->users->findByEmail(strtolower($email));
Jacob Priddy's avatar
Jacob Priddy committed
58

Jacob Priddy's avatar
Jacob Priddy committed
59 60 61
        if (!$user ||
            !$user->getPassword() ||
            !$user->getPassword()->matches($password)) {
62
            throw new AuthenticationException();
Jacob Priddy's avatar
Jacob Priddy committed
63 64
        }

65
        $token = $this->tokens->createLoginToken($user->getId(), $this->salt);
Jacob Priddy's avatar
Jacob Priddy committed
66

67
        $response = new ResponseModel($user, $token->getRaw(), $token->getToken());
Jacob Priddy's avatar
Jacob Priddy committed
68 69 70

        $presenter->present($response);
    }
71

72 73 74
    /**
     * @inheritDoc
     */
Jacob Priddy's avatar
Jacob Priddy committed
75 76
    public function handToSaml(array $options = []): string
    {
Jacob Priddy's avatar
Jacob Priddy committed
77
        return $this->saml->login($options);
78 79 80 81 82
    }

    /**
     * @inheritDoc
     */
Jacob Priddy's avatar
Jacob Priddy committed
83 84
    public function handleSamlLogin(Presenter $presenter): void
    {
Jacob Priddy's avatar
Jacob Priddy committed
85 86 87 88 89 90 91 92 93 94 95
        $samlUser = $this->saml->handleLogin();

        if (!$samlUser) {
            throw new UserCreationException();
        }

        // First check to see if the user exists in the database.
        $user = $this->users->findByEmail($samlUser->getEmail());

        // If the user does not exist, create them.
        if (!$user) {
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
            $user = $this->users->create(new User(
                0,
                $samlUser->getFirstName(),
                $samlUser->getLastName(),
                $samlUser->getDisplayName(),
                $samlUser->getEmail(),
                $samlUser->getEmplid()
            ));
        } else {
            $user = $this->users->update($user->getId(), new User(
                $user->getId(),
                $samlUser->getFirstName(),
                $samlUser->getLastName(),
                $samlUser->getDisplayName(),
                $samlUser->getEmail(),
                $samlUser->getEmplid(),
                $user->getPassword(),
                $user->getDoorcode(),
                $user->getExpiresAt(),
                $user->getCreatedAt(),
                $user->getUpdatedAt()
            ));
Jacob Priddy's avatar
Jacob Priddy committed
118 119 120 121 122 123
        }

        if (!$user) {
            throw new UserCreationException();
        }

124
        $token = $this->tokens->createLoginToken($user->getId(), $this->salt);
Jacob Priddy's avatar
Jacob Priddy committed
125

126
        $response = new ResponseModel($user, $token->getRaw(), $token->getToken());
Jacob Priddy's avatar
Jacob Priddy committed
127 128

        $presenter->present($response);
129 130 131 132 133
    }

    /**
     * @inheritDoc
     */
Jacob Priddy's avatar
Jacob Priddy committed
134 135
    public function samlLogout(?string $token): string
    {
Jacob Priddy's avatar
Jacob Priddy committed
136
        if ($token) {
137
            $this->tokens->invalidateToken(HashedSearchable::hash($this->salt, $token));
Jacob Priddy's avatar
Jacob Priddy committed
138 139 140
        }

        return $this->saml->logout();
141
    }
Jacob Priddy's avatar
Jacob Priddy committed
142
}