TokenGuard::setRequest()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
3
namespace Mayoz\Token;
4
5
use Illuminate\Http\Request;
6
use Illuminate\Auth\GuardHelpers;
7
use Illuminate\Contracts\Auth\Guard;
8
use Illuminate\Contracts\Auth\UserProvider;
9
10
class TokenGuard implements Guard
11
{
12
    use GuardHelpers;
13
14
    /**
15
     * The request instance.
16
     *
17
     * @var \Illuminate\Http\Request
18
     */
19
    protected $request;
20
21
    /**
22
     * The currently authenticated token.
23
     *
24
     * @var \Illuminate\Database\Eloquent\Model
25
     */
26
    protected $token;
27
28
    /**
29
     * The name of the query string item from the request containing the API token.
30
     *
31
     * @var string
32
     */
33
    protected $inputKey;
34
35
    /**
36
     * The name of the token "column" in persistent storage.
37
     *
38
     * @var string
39
     */
40
    protected $storageKey;
41
42
    /**
43
     * Create a new token guard instance.
44
     *
45
     * @param  \Illuminate\Contracts\Auth\UserProvider  $provider
46
     * @param  \Illuminate\Http\Request  $request
47
     * @return void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
48
     */
49
    public function __construct(UserProvider $provider, Request $request)
0 ignored issues
show
Bug introduced by
You have injected the Request via parameter $request. This is generally not recommended as there might be multiple instances during a request cycle (f.e. when using sub-requests). Instead, it is recommended to inject the RequestStack and retrieve the current request each time you need it via getCurrentRequest().
Loading history...
50
    {
51
        $this->request = $request;
52
        $this->provider = $provider;
53
        $this->inputKey = 'api_token';
54
        $this->storageKey = 'api_token';
55
    }
56
57
    /**
58
     * Get the currently authenticated user.
59
     *
60
     * @return \Illuminate\Contracts\Auth\Authenticatable|null
61
     */
62
    public function user()
63
    {
64
        if (is_null($this->user) && ($token = $this->token()) && $token->isNotExpired()) {
0 ignored issues
show
Bug introduced by
The method isNotExpired() does not seem to exist on object<Illuminate\Contracts\Auth\Authenticatable>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
65
            $this->user = (clone $token)->user;
0 ignored issues
show
Bug introduced by
Accessing user on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
66
        }
67
68
        return $this->user;
69
    }
70
71
    /**
72
     * Get the currently token model.
73
     *
74
     * @return \Illuminate\Database\Eloquent\Model|null
75
     */
76
    public function token()
77
    {
78
        if (is_null($this->token)) {
79
            $this->token = $this->retrieveTokenForRequest(
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->retrieveTokenForR...getTokenCredentials())) can also be of type object<Illuminate\Contracts\Auth\Authenticatable>. However, the property $token is declared as type object<Illuminate\Database\Eloquent\Model>. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
80
                [$this->inputKey => $this->getTokenCredentials()]
81
            );
82
        }
83
84
        return $this->token;
85
    }
86
87
    /**
88
     * Get the token credentials for the current request.
89
     *
90
     * @return string
91
     */
92
    protected function getTokenCredentials()
93
    {
94
        $token = $this->request->get($this->inputKey);
95
96
        if (empty($token)) {
97
            $token = $this->request->bearerToken();
98
        }
99
100
        return $token;
101
    }
102
103
    /**
104
     * Retrieve the token for the current request.
105
     *
106
     * @return \Illuminate\Database\Eloquent\Model|null
107
     */
108
    protected function retrieveTokenForRequest(array $credentials)
109
    {
110
        if (array_key_exists($this->inputKey, $credentials)) {
111
            return $this->provider->retrieveByCredentials(
112
                [$this->storageKey => $credentials[$this->inputKey]]
113
            );
114
        }
115
    }
116
117
    /**
118
     * Validate a user's credentials.
119
     *
120
     * @param  array  $credentials
121
     * @return bool
122
     */
123
    public function validate(array $credentials = [])
124
    {
125
        if ($token = $this->retrieveTokenForRequest($credentials)) {
126
            return $token->isNotExpired();
0 ignored issues
show
Bug introduced by
The method isNotExpired() does not seem to exist on object<Illuminate\Contracts\Auth\Authenticatable>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
127
        }
128
129
        return false;
130
    }
131
132
    /**
133
     * Set the current request instance.
134
     *
135
     * @param  \Illuminate\Http\Request  $request
136
     * @return $this
137
     */
138
    public function setRequest(Request $request)
0 ignored issues
show
Bug introduced by
You have injected the Request via parameter $request. This is generally not recommended as there might be multiple instances during a request cycle (f.e. when using sub-requests). Instead, it is recommended to inject the RequestStack and retrieve the current request each time you need it via getCurrentRequest().
Loading history...
139
    {
140
        $this->request = $request;
141
142
        return $this;
143
    }
144
}
145