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

namespace Source\UseCases\Users\Authenticate;

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

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

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

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

31 32
    protected string $salt;

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

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

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

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

Jacob Priddy's avatar
Jacob Priddy committed
61 62
        if (!$user ||
            !$user->getPassword() ||
63
            !$user->isActiveForDate(Carbon::now()) ||
Jacob Priddy's avatar
Jacob Priddy committed
64
            !$user->getPassword()->matches($password)) {
65 66 67
            /*
             * We must have found a user, they must be active, and their password must be correct
             */
68
            throw new AuthenticationException();
Jacob Priddy's avatar
Jacob Priddy committed
69 70
        }

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

73
        $response = new ResponseModel($user, $token->getRaw(), $token->getToken());
Jacob Priddy's avatar
Jacob Priddy committed
74 75 76

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

78 79 80
    /**
     * @inheritDoc
     */
Jacob Priddy's avatar
Jacob Priddy committed
81 82
    public function handToSaml(array $options = []): string
    {
Jacob Priddy's avatar
Jacob Priddy committed
83
        return $this->saml->login($options);
84 85 86 87 88
    }

    /**
     * @inheritDoc
     */
Jacob Priddy's avatar
Jacob Priddy committed
89 90
    public function handleSamlLogin(Presenter $presenter): void
    {
Jacob Priddy's avatar
Jacob Priddy committed
91 92 93 94 95 96 97 98 99 100 101
        $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) {
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
            $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
124 125 126 127 128 129
        }

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

130 131 132 133
        if (!$user->isActiveForDate(Carbon::now())) {
            throw new AuthorizationException();
        }

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

136
        $response = new ResponseModel($user, $token->getRaw(), $token->getToken());
Jacob Priddy's avatar
Jacob Priddy committed
137 138

        $presenter->present($response);
139 140 141 142 143
    }

    /**
     * @inheritDoc
     */
Jacob Priddy's avatar
Jacob Priddy committed
144 145
    public function samlLogout(?string $token): string
    {
Jacob Priddy's avatar
Jacob Priddy committed
146
        if ($token) {
147
            $this->tokens->invalidateToken(HashedSearchable::hash($this->salt, $token));
Jacob Priddy's avatar
Jacob Priddy committed
148 149 150
        }

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