Helpers::unknownErrorResponse()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 0
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Ikechukwukalu\Sanctumauthstarter\Traits;
4
5
use App\Models\User;
0 ignored issues
show
Bug introduced by
The type App\Models\User was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
6
use App\Services\Auth\ThrottleRequestsService;
0 ignored issues
show
Bug introduced by
The type App\Services\Auth\ThrottleRequestsService was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
7
use Carbon\Carbon;
8
use Ikechukwukalu\Sanctumauthstarter\Notifications\UserLogin;
9
use hisorange\BrowserDetect\Parser as Browser;
10
use Illuminate\Http\JsonResponse;
11
use Illuminate\Http\Request;
12
use Illuminate\Support\Facades\Response;
13
use Illuminate\View\View;
14
use Stevebauman\Location\Facades\Location;
15
16
trait Helpers {
17
18
    public ThrottleRequestsService $throttleRequestsService;
19
20
    public function __construct(ThrottleRequestsService $throttleRequestsService)
21
    {
22
        $this->throttleRequestsService = $throttleRequestsService;
23
    }
24
25
    public function httpJsonResponse(string $status, int $status_code, $data): JsonResponse
26
    {
27
        return Response::json([
28
            'status' => $status,
29
            'status_code' => $status_code,
30
            'data' => $data
31
        ], $status_code);
32
    }
33
34
    public function getUserIp(Request $request) {
35
        if ($position = Location::get()) {
36
            return $position->ip;
37
        }
38
39
        $server_keys = [
40
                        'HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR',
41
                        'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP',
42
                        'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED',
43
                        'REMOTE_ADDR'
44
                    ];
45
46
        foreach ($server_keys as $key){
47
            if (array_key_exists($key, $_SERVER) === true) {
48
                foreach (explode(',', $_SERVER[$key]) as $ip) {
49
                    $ip = trim($ip); // just to be safe
50
51
                    if (filter_var($ip, FILTER_VALIDATE_IP,
52
                        FILTER_FLAG_NO_PRIV_RANGE |
53
                        FILTER_FLAG_NO_RES_RANGE) !== false
54
                    ) {
55
                        return $ip;
56
                    }
57
                }
58
            }
59
        }
60
61
        return $request->ip(); // it will return server ip when no client ip found
62
    }
63
64
    public function getUserLoginInformation(): array
65
    {
66
        $info = [];
67
68
        if (Browser::deviceType() === 'Mobile' ||
69
            Browser::deviceType() === 'Tablet') {
70
            $info = [
71
                Browser::deviceFamily(),
72
                Browser::deviceModel()
73
            ];
74
        }
75
76
        if (Browser::deviceType() === 'Desktop') {
77
            $info = [
78
                Browser::browserName(),
79
                Browser::platformName()
80
            ];
81
        }
82
83
        if (Browser::deviceType() === 'Bot') {
84
            $info = [
85
                Browser::userAgent()
86
            ];
87
        }
88
89
        if ($position = Location::get()) {
90
            $info[] = $position->countryName;
91
            $info[] = $position->regionName;
92
            $info[] = $position->cityName;
93
        }
94
95
        return $info;
96
    }
97
98
    public function unknownErrorResponse(): JsonResponse
99
    {
100
        $data = ['message' =>
101
        trans('sanctumauthstarter::general.unknown_error')];
102
103
        return $this->httpJsonResponse(
104
            trans('sanctumauthstarter::general.fail'), 422, $data);
105
    }
106
107
    public function generateSalt(int $length = 9, bool $add_dashes = false, string $available_sets = 'luds'): string
108
    {
109
        [$sets, $salt, $all] = $this->saltsAllVar($available_sets);
110
111
        for($i = 0; $i < $length - count($sets); $i++) {
112
            $salt .= $all[array_rand($all)];
0 ignored issues
show
Bug introduced by
It seems like $all can also be of type true; however, parameter $array of array_rand() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

112
            $salt .= $all[array_rand(/** @scrutinizer ignore-type */ $all)];
Loading history...
113
        }
114
115
        $salt = str_shuffle($salt);
116
        if (!$add_dashes) {
117
            return $salt;
118
        }
119
120
        return $this->addDashes($salt, $length);
121
    }
122
123
    public function requestAttempts(Request $request, string $trans = 'sanctumauthstarter::auth.throttle'): ?array
124
    {
125
        if ($this->throttleRequestsService->hasTooManyAttempts($request)) {
126
            $this->throttleRequestsService->_fireLockoutEvent($request);
127
128
            return ["message" => trans($trans,
129
                        ['seconds' =>
130
                            $this->throttleRequestsService->_limiter()
131
                            ->availableIn(
132
                                    $this->throttleRequestsService
133
                                        ->_throttleKey($request)
134
                                )
135
                        ])
136
                    ];
137
        }
138
139
        $this->throttleRequestsService->incrementAttempts($request);
140
141
        return null;
142
    }
143
144
    public function returnTwoFactorLoginView(array $data = []): View
145
    {
146
        $data['input'] = '2fa_code';
147
148
        if (!array_key_exists("message", $data)) {
149
            $data['message'] = trans('sanctumauthstarter::auth.failed');
150
        }
151
152
        return view('two-factor::login', $data);
153
    }
154
155
    public function userLoginNotification(User $user): void
156
    {
157
        if (config('sanctumauthstarter.login.notify.user', true)) {
158
            $time = Carbon::now()->isoFormat('Do of MMMM YYYY, h:mm:ssa');
159
            $deviceAndLocation = $this->getUserLoginInformation();
160
            $user->notify(new UserLogin($time, $deviceAndLocation));
161
        }
162
    }
163
164
    private function stringSets(string $available_sets): array
165
    {
166
        $sets = [];
167
168
        if (strpos($available_sets, 'l') !== false) {
169
            $sets[] = 'abcdefghjkmnpqrstuvwxyz';
170
        }
171
172
        if (strpos($available_sets, 'u') !== false) {
173
            $sets[] = 'ABCDEFGHJKMNPQRSTUVWXYZ';
174
        }
175
176
        if (strpos($available_sets, 'd') !== false) {
177
            $sets[] = '23456789';
178
        }
179
180
        if (strpos($available_sets, 's') !== false) {
181
            $sets[] = '!@#$%&*?';
182
        }
183
184
        return $sets;
185
    }
186
187
    private function saltsAllVar(string $available_sets): array
188
    {
189
        $sets = $this->stringSets($available_sets);
190
        $salt = '';
191
        $all = '';
192
193
        foreach ($sets as $set)
194
        {
195
            $salt .= $set[array_rand(str_split($set))];
0 ignored issues
show
Bug introduced by
It seems like str_split($set) can also be of type true; however, parameter $array of array_rand() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

195
            $salt .= $set[array_rand(/** @scrutinizer ignore-type */ str_split($set))];
Loading history...
196
            $all .= $set;
197
        }
198
199
        return [$sets, $salt, str_split($all)];
200
    }
201
202
    private function addDashes(string $salt, int $length): string
203
    {
204
        $dash_len = floor(sqrt($length));
205
        $dash_str = '';
206
207
        while(strlen($salt) > $dash_len)
208
        {
209
            $dash_str .= substr($salt, 0, $dash_len) . '-';
0 ignored issues
show
Bug introduced by
$dash_len of type double is incompatible with the type integer|null expected by parameter $length of substr(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

209
            $dash_str .= substr($salt, 0, /** @scrutinizer ignore-type */ $dash_len) . '-';
Loading history...
210
            $salt = substr($salt, $dash_len);
0 ignored issues
show
Bug introduced by
$dash_len of type double is incompatible with the type integer expected by parameter $offset of substr(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

210
            $salt = substr($salt, /** @scrutinizer ignore-type */ $dash_len);
Loading history...
211
        }
212
213
        $dash_str .= $salt;
214
215
        return $dash_str;
216
    }
217
}
218