DoorGuard.php 3.31 KB
Newer Older
1
2
3
4
5
<?php


namespace App\Guards;

6
use Source\Entities\Door;
7
8
9
10
use Illuminate\Http\Request;
use Illuminate\Auth\GuardHelpers;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Contracts\Auth\Authenticatable;
11
use Source\Gateways\Doors\DatabaseDoorsRepository;
12
13
use Source\UseCases\Door\Authenticate\AuthenticateUseCase;
use Source\UseCases\Door\Authenticate\TranslationPresenter;
14

Jacob Priddy's avatar
Jacob Priddy committed
15
16
class DoorGuard implements Guard
{
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
    use GuardHelpers;

    /**
     * The request instance.
     *
     * @var Request
     */
    protected Request $request;

    /**
     * The name of the query string item from the request containing the API token.
     *
     * @var string
     */
    protected string $inputKey;

    /**
     * @var AuthenticateUseCase
     */
    protected AuthenticateUseCase $authenticator;

    /**
     * Create a new authentication guard.
     *
     * @param AuthenticateUseCase $authenticator
     * @param Request             $request
     * @param string              $inputKey
     */
    public function __construct(
        AuthenticateUseCase $authenticator,
        Request $request,
Jacob Priddy's avatar
Jacob Priddy committed
48
49
        $inputKey = 'api_token'
    ) {
50
51
52
53
54
55
56
57
        $this->request = $request;
        $this->inputKey = $inputKey;
        $this->authenticator = $authenticator;
    }

    /**
     * Get the currently authenticated user.
     *
58
     * @return Authenticatable|\Source\Entities\Door|null
59
     */
Jacob Priddy's avatar
Jacob Priddy committed
60
61
    public function user()
    {
62
63
64
65
66
67
68
69
70
        // If we've already retrieved the user for the current request we can just
        // return it back immediately. We do not want to fetch the user data on
        // every call to this method because that would be tremendously slow.
        if ($this->user !== null) {
            return $this->user;
        }

        $token = $this->getTokenForRequest();

Jacob Priddy's avatar
Jacob Priddy committed
71
        $user = $this->retrieveByToken($token);
72
73
74
75

        return $this->user = $user;
    }

76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
    /**
     * @return \Source\Entities\Door|null
     */
    public function getDoor(): ?Door
    {
        /** @var \App\Door|null $door */
        $door = $this->user();

        if ($door) {
            return DatabaseDoorsRepository::makeDoorFromDb($door);
        }

        return null;
    }

91
92
93
94
95
    /**
     * Get the token for the current request.
     *
     * @return string|null
     */
Jacob Priddy's avatar
Jacob Priddy committed
96
    protected function getTokenForRequest(): ?string
Jacob Priddy's avatar
Jacob Priddy committed
97
    {
Jacob Priddy's avatar
Jacob Priddy committed
98
99
100
101
102
103
104
        $token = $this->request->bearerToken();

        if (empty($token)) {
            $token = $this->request->input($this->inputKey);
        }

        return $token;
105
106
107
108
109
110
111
112
    }

    /**
     * Validate a user's credentials.
     *
     * @param array $credentials
     * @return bool
     */
Jacob Priddy's avatar
Jacob Priddy committed
113
114
    public function validate(array $credentials = [])
    {
Jacob Priddy's avatar
Jacob Priddy committed
115
        if (!isset($credentials[$this->inputKey])) {
116
117
118
            return false;
        }

119
        return (bool)$this->retrieveByToken($credentials[$this->inputKey]);
120
121
    }

122
123
124
125
126
    protected function getDoorVersion(): ?string
    {
        return $this->request->header('Door-Controller-Version', null);
    }

127
    /**
Jacob Priddy's avatar
Jacob Priddy committed
128
     * @param string|null $token
129
130
131
     *
     * @return Authenticatable|null
     */
Jacob Priddy's avatar
Jacob Priddy committed
132
    protected function retrieveByToken(?string $token): ?Authenticatable
Jacob Priddy's avatar
Jacob Priddy committed
133
    {
134
135
        $presenter = new TranslationPresenter();

136
137
138
        $version = $this->getDoorVersion();

        $this->authenticator->check($presenter, $token, $version);
139
140
141
142

        return $presenter->getViewModel();
    }
}