Passed
Pull Request — dev (#1123)
by
unknown
06:52
created

User::getBrowseOrder()   C

Complexity

Conditions 13
Paths 80

Size

Total Lines 39
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 182

Importance

Changes 0
Metric Value
cc 13
eloc 35
nc 80
nop 1
dl 0
loc 39
ccs 0
cts 11
cp 0
crap 182
rs 6.6166
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace App\Models;
4
5
use App\Jobs\SendAccountExpiredEmail;
6
use App\Jobs\SendAccountWillExpireEmail;
7
use App\Jobs\SendInviteEmail;
8
use Carbon\CarbonImmutable;
9
use DariusIII\Token\Token;
10
use Illuminate\Foundation\Auth\User as Authenticatable;
11
use Illuminate\Http\Request;
12
use Illuminate\Notifications\Notifiable;
13
use Illuminate\Support\Arr;
14
use Illuminate\Support\Carbon;
15
use Illuminate\Support\Facades\Hash;
16
use Illuminate\Support\Facades\Password;
17
use Illuminate\Support\Facades\Validator;
18
use Illuminate\Support\Str;
19
use Jrean\UserVerification\Traits\UserVerification;
20
use Junaidnasir\Larainvite\Facades\Invite;
21
use Junaidnasir\Larainvite\InviteTrait;
22
use Spatie\Permission\Models\Role;
23
use Spatie\Permission\Traits\HasRoles;
24
25
/**
26
 * App\Models\User.
27
 *
28
 * App\Models\User.
29
 *
30
 * @property int $id
31
 * @property string $username
32
 * @property string|null $firstname
33
 * @property string|null $lastname
34
 * @property string $email
35
 * @property string $password
36
 * @property int $user_roles_id FK to roles.id
37
 * @property string|null $host
38
 * @property int $grabs
39
 * @property string $rsstoken
40
 * @property \Carbon\Carbon|null $created_at
41
 * @property \Carbon\Carbon|null $updated_at
42
 * @property string|null $resetguid
43
 * @property string|null $lastlogin
44
 * @property string|null $apiaccess
45
 * @property int $invites
46
 * @property int|null $invitedby
47
 * @property int $movieview
48
 * @property int $xxxview
49
 * @property int $musicview
50
 * @property int $consoleview
51
 * @property int $bookview
52
 * @property int $gameview
53
 * @property string|null $saburl
54
 * @property string|null $sabapikey
55
 * @property bool|null $sabapikeytype
56
 * @property bool|null $sabpriority
57
 * @property bool $queuetype Type of queue, Sab or NZBGet
58
 * @property string|null $nzbgeturl
59
 * @property string|null $nzbgetusername
60
 * @property string|null $nzbgetpassword
61
 * @property string|null $nzbvortex_api_key
62
 * @property string|null $nzbvortex_server_url
63
 * @property string $userseed
64
 * @property string $notes
65
 * @property string|null $cp_url
66
 * @property string|null $cp_api
67
 * @property string|null $style
68
 * @property string|null $rolechangedate When does the role expire
69
 * @property string|null $remember_token
70
 * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\ReleaseComment[] $comment
71
 * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\UserDownload[] $download
72
 * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\DnzbFailure[] $failedRelease
73
 * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\Invitation[] $invitation
74
 * @property-read \Illuminate\Notifications\DatabaseNotificationCollection|\Illuminate\Notifications\DatabaseNotification[] $notifications
75
 * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\UsersRelease[] $release
76
 * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\UserRequest[] $request
77
 * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\UserSerie[] $series
78
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereApiaccess($value)
79
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereBookview($value)
80
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereConsoleview($value)
81
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereCpApi($value)
82
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereCpUrl($value)
83
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereCreatedAt($value)
84
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereEmail($value)
85
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereFirstname($value)
86
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereGameview($value)
87
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereGrabs($value)
88
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereHost($value)
89
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereId($value)
90
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereInvitedby($value)
91
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereInvites($value)
92
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereLastlogin($value)
93
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereLastname($value)
94
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereMovieview($value)
95
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereMusicview($value)
96
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereNotes($value)
97
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereNzbgetpassword($value)
98
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereNzbgeturl($value)
99
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereNzbgetusername($value)
100
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereNzbvortexApiKey($value)
101
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereNzbvortexServerUrl($value)
102
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User wherePassword($value)
103
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereQueuetype($value)
104
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereRememberToken($value)
105
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereResetguid($value)
106
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereRolechangedate($value)
107
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereRsstoken($value)
108
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereSabapikey($value)
109
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereSabapikeytype($value)
110
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereSabpriority($value)
111
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereSaburl($value)
112
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereStyle($value)
113
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereUpdatedAt($value)
114
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereUserRolesId($value)
115
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereUsername($value)
116
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereUserseed($value)
117
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereXxxview($value)
118
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereVerified($value)
119
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereApiToken($value)
120
 * @mixin \Eloquent
121
 * @property int $roles_id FK to roles.id
122
 * @property string $api_token
123
 * @property int $rate_limit
124
 * @property string|null $email_verified_at
125
 * @property int $verified
126
 * @property string|null $verification_token
127
 * @property-read \Illuminate\Database\Eloquent\Collection|\Junaidnasir\Larainvite\Models\LaraInviteModel[] $invitationPending
128
 * @property-read \Illuminate\Database\Eloquent\Collection|\Junaidnasir\Larainvite\Models\LaraInviteModel[] $invitationSuccess
129
 * @property-read \Illuminate\Database\Eloquent\Collection|\Junaidnasir\Larainvite\Models\LaraInviteModel[] $invitations
130
 * @property-read \Illuminate\Database\Eloquent\Collection|\Spatie\Permission\Models\Permission[] $permissions
131
 * @property-read \Spatie\Permission\Models\Role $role
132
 * @property-read \Illuminate\Database\Eloquent\Collection|\Spatie\Permission\Models\Role[] $roles
133
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User newModelQuery()
134
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User newQuery()
135
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User permission($permissions)
136
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User query()
137
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User role($roles, $guard = null)
138
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereEmailVerifiedAt($value)
139
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereRateLimit($value)
140
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereRolesId($value)
141
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereVerificationToken($value)
142
 */
143
class User extends Authenticatable
144
{
145
    use Notifiable, UserVerification, HasRoles, InviteTrait;
146
147
    public const ERR_SIGNUP_BADUNAME = -1;
148
    public const ERR_SIGNUP_BADPASS = -2;
149
    public const ERR_SIGNUP_BADEMAIL = -3;
150
    public const ERR_SIGNUP_UNAMEINUSE = -4;
151
    public const ERR_SIGNUP_EMAILINUSE = -5;
152
    public const ERR_SIGNUP_BADINVITECODE = -6;
153
    public const ERR_SIGNUP_BADCAPTCHA = -7;
154
    public const SUCCESS = 1;
155
156
    public const ROLE_USER = 1;
157
    public const ROLE_ADMIN = 2;
158
    public const ROLE_DISABLED = 3;
159
    public const ROLE_MODERATOR = 4;
160
161
    /**
162
     * Users SELECT queue type.
163
     */
164
    public const QUEUE_NONE = 0;
165
    public const QUEUE_SABNZBD = 1;
166
    public const QUEUE_NZBGET = 2;
167
168
    /**
169
     * @var string
170
     */
171
    protected $table = 'users';
172
173
    /**
174
     * @var bool
175
     */
176
    protected $dateFormat = false;
177
178
    /**
179
     * @var array
180
     */
181
    protected $hidden = ['remember_token', 'password'];
182
183
    /**
184
     * @var array
185
     */
186
    protected $guarded = [];
187
188
    /**
189
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
190
     */
191
    public function role()
192
    {
193
        return $this->belongsTo(Role::class, 'roles_id');
194
    }
195
196
    /**
197
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
198
     */
199
    public function request()
200
    {
201
        return $this->hasMany(UserRequest::class, 'users_id');
202
    }
203
204
    /**
205
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
206
     */
207
    public function download()
208
    {
209
        return $this->hasMany(UserDownload::class, 'users_id');
210
    }
211
212
    /**
213
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
214
     */
215
    public function release()
216
    {
217
        return $this->hasMany(UsersRelease::class, 'users_id');
218
    }
219
220
    /**
221
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
222
     */
223
    public function series()
224
    {
225
        return $this->hasMany(UserSerie::class, 'users_id');
226
    }
227
228
    /**
229
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
230
     */
231
    public function invitation()
232
    {
233
        return $this->hasMany(Invitation::class, 'users_id');
234
    }
235
236
    /**
237
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
238
     */
239
    public function failedRelease()
240
    {
241
        return $this->hasMany(DnzbFailure::class, 'users_id');
242
    }
243
244
    /**
245
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
246
     */
247
    public function comment()
248
    {
249
        return $this->hasMany(ReleaseComment::class, 'users_id');
250
    }
251
252
    /**
253
     * @param $id
254
     * @throws \Exception
255
     */
256
    public static function deleteUser($id): void
257
    {
258
        self::find($id)->delete();
259
    }
260
261
    /**
262
     * @param string $role
263
     * @param string $username
264
     * @param string $host
265
     * @param string $email
266
     * @return int
267
     */
268
    public static function getCount($role = '', $username = '', $host = '', $email = ''): int
269
    {
270
        $res = self::query()->where('email', '<>', '[email protected]');
271
272
        if ($role !== '') {
273
            $res->where('roles_id', $role);
274
        }
275
276
        if ($username !== '') {
277
            $res->where('username', 'like', '%'.$username.'%');
278
        }
279
280
        if ($host !== '') {
281
            $res->where('host', 'like', '%'.$host.'%');
282
        }
283
284
        if ($email !== '') {
285
            $res->where('email', 'like', '%'.$email.'%');
286
        }
287
288
        return $res->count(['id']);
289
    }
290
291
    /**
292
     * @param  int      $id
293
     * @param  string      $userName
294
     * @param  string      $email
295
     * @param  int     $grabs
296
     * @param  int     $role
297
     * @param  string    $notes
298
     * @param  int     $invites
299
     * @param  int     $movieview
300
     * @param  int    $musicview
301
     * @param  int   $gameview
302
     * @param  int    $xxxview
303
     * @param  int    $consoleview
304
     * @param  int    $bookview
305
     * @param string $queueType
306
     * @param string $nzbgetURL
307
     * @param string $nzbgetUsername
308
     * @param string $nzbgetPassword
309
     * @param string $saburl
310
     * @param string $sabapikey
311
     * @param string $sabpriority
312
     * @param string $sabapikeytype
313
     * @param bool   $nzbvortexServerUrl
314
     * @param bool   $nzbvortexApiKey
315
     * @param bool   $cp_url
316
     * @param bool   $cp_api
317
     * @param string $style
318
     *
319
     * @return int
320
     * @throws \Illuminate\Database\Eloquent\ModelNotFoundException
321
     */
322
    public static function updateUser($id, $userName, $email, $grabs, $role, $notes, $invites, $movieview, $musicview, $gameview, $xxxview, $consoleview, $bookview, $queueType = '', $nzbgetURL = '', $nzbgetUsername = '', $nzbgetPassword = '', $saburl = '', $sabapikey = '', $sabpriority = '', $sabapikeytype = '', $nzbvortexServerUrl = false, $nzbvortexApiKey = false, $cp_url = false, $cp_api = false, $style = 'None'): int
323
    {
324
        $userName = trim($userName);
325
326
        $rateLimit = Role::query()->where('id', $role)->first();
327
328
        $sql = [
329
            'username' => $userName,
330
            'grabs' => $grabs,
331
            'roles_id' => $role,
332
            'notes' => substr($notes, 0, 255),
333
            'invites' => $invites,
334
            'movieview' => $movieview,
335
            'musicview' => $musicview,
336
            'gameview' => $gameview,
337
            'xxxview' => $xxxview,
338
            'consoleview' => $consoleview,
339
            'bookview' => $bookview,
340
            'style' => $style,
341
            'queuetype'  => $queueType,
342
            'nzbgeturl' => $nzbgetURL,
343
            'nzbgetusername' => $nzbgetUsername,
344
            'nzbgetpassword' => $nzbgetPassword,
345
            'saburl' => $saburl,
346
            'sabapikey' => $sabapikey,
347
            'sabapikeytype' => $sabapikeytype,
348
            'sabpriority' => $sabpriority,
349
            'nzbvortex_server_url' => $nzbvortexServerUrl,
350
            'nzbvortex_api_key' => $nzbvortexApiKey,
351
            'cp_url' => $cp_url,
352
            'cp_api' => $cp_api,
353
            'rate_limit' => $rateLimit ? $rateLimit['rate_limit'] : 60,
354
        ];
355
356
        if (! empty($email)) {
357
            $email = trim($email);
358
            $sql += ['email' => $email];
359
        }
360
361
        $user = self::find($id);
362
        $user->update($sql);
363
        $user->syncRoles([$rateLimit['name']]);
364
365
        return self::SUCCESS;
366
    }
367
368
    /**
369
     * @param string $userName
370
     * @return \Illuminate\Database\Eloquent\Model|null|static
371
     */
372
    public static function getByUsername(string $userName)
373
    {
374
        return self::whereUsername($userName)->first();
375
    }
376
377
    /**
378
     * @param string $email
379
     *
380
     * @return \Illuminate\Database\Eloquent\Model|static
381
     * @throws \Illuminate\Database\Eloquent\ModelNotFoundException
382
     */
383
    public static function getByEmail(string $email)
384
    {
385
        return self::whereEmail($email)->first();
386
    }
387
388
    /**
389
     * @param int $uid
390
     * @param int $role
391
     *
392
     * @return bool
393
     */
394
    public static function updateUserRole(int $uid, int $role)
395
    {
396
        $roleQuery = Role::query()->where('id', $role)->first();
397
        $roleName = $roleQuery->name;
398
399
        $user = self::find($uid);
400
        $user->syncRoles([$roleName]);
401
402
        return self::find($uid)->update(['roles_id' => $role]);
403
    }
404
405
    /**
406
     * @param int $uid
407
     * @param $date
408
     * @param int $addYear
409
     */
410
    public static function updateUserRoleChangeDate($uid, $date = '', $addYear = 0): void
411
    {
412
        $user = self::find($uid);
413
        $currRoleExp = $user->rolechangedate ?? now()->toDateTimeString();
414
        if (! empty($date)) {
415
            $user->update(['rolechangedate' => $date]);
416
        }
417
        if (empty($date) && ! empty($addYear)) {
418
            $user->update(['rolechangedate' => Carbon::createFromDate($currRoleExp)->addYears($addYear)]);
419
        }
420
    }
421
422
    public static function updateExpiredRoles(): void
423
    {
424
        $now = CarbonImmutable::now();
425
        $period = [
426
            'day' => $now->addDay(),
427
            'week' => $now->addWeek(),
428
            'month' => $now->addMonth(),
429
        ];
430
431
        foreach ($period as $value) {
432
            $users = self::query()->whereDate('rolechangedate', '=', $value)->get();
433
            $days = $now->diffInDays($value);
434
            foreach ($users as $user) {
435
                SendAccountWillExpireEmail::dispatch($user, $days)->onQueue('emails');
436
            }
437
        }
438
        foreach (self::query()->whereDate('rolechangedate', '<', $now)->get() as $expired) {
439
            $expired->update(['roles_id' => self::ROLE_USER, 'rolechangedate' => null]);
440
            $expired->syncRoles(['User']);
441
            SendAccountExpiredEmail::dispatch($expired)->onQueue('emails');
442
        }
443
    }
444
445
    /**
446
     * @param        $start
447
     * @param        $offset
448
     * @param        $orderBy
449
     * @param string $userName
450
     * @param string $email
451
     * @param string $host
452
     * @param string $role
453
     * @param bool   $apiRequests
454
     *
455
     * @return \Illuminate\Database\Eloquent\Collection
456
     * @throws \Throwable
457
     */
458
    public static function getRange($start, $offset, $orderBy, $userName = '', $email = '', $host = '', $role = '', $apiRequests = false)
459
    {
460
        if ($apiRequests) {
461
            UserRequest::clearApiRequests(false);
462
            $query = "
463
				SELECT users.*, roles.name AS rolename, COUNT(user_requests.id) AS apirequests
464
				FROM users
465
				INNER JOIN roles ON roles.id = users.roles_id
466
				LEFT JOIN user_requests ON user_requests.users_id = users.id
467
				WHERE users.id != 0 %s %s %s %s
468
				AND email != '[email protected]'
469
				GROUP BY users.id
470
				ORDER BY %s %s %s ";
471
        } else {
472
            $query = '
473
				SELECT users.*, roles.name AS rolename
474
				FROM users
475
				INNER JOIN roles ON roles.id = users.roles_id
476
				WHERE 1=1 %s %s %s %s
477
				ORDER BY %s %s %s';
478
        }
479
        $order = self::getBrowseOrder($orderBy);
480
481
        return self::fromQuery(
482
            sprintf(
483
                $query,
484
                ! empty($userName) ? 'AND users.username '.'LIKE '.escapeString('%'.$userName.'%') : '',
485
                ! empty($email) ? 'AND users.email '.'LIKE '.escapeString('%'.$email.'%') : '',
486
                ! empty($host) ? 'AND users.host '.'LIKE '.escapeString('%'.$host.'%') : '',
487
                (! empty($role) ? ('AND users.roles_id = '.$role) : ''),
488
                $order[0],
489
                $order[1],
490
                ($start === false ? '' : ('LIMIT '.$offset.' OFFSET '.$start))
491
            )
492
        );
493
    }
494
495
    /**
496
     * Get sort types for sorting users on the web page user list.
497
     *
498
     * @param $orderBy
499
     *
500
     * @return string[]
501
     */
502
    public static function getBrowseOrder($orderBy): array
503
    {
504
        $order = (empty($orderBy) ? 'username_desc' : $orderBy);
505
        $orderArr = explode('_', $order);
506
        switch ($orderArr[0]) {
507
            case 'email':
508
                $orderField = 'email';
509
                break;
510
            case 'host':
511
                $orderField = 'host';
512
                break;
513
            case 'createdat':
514
                $orderField = 'created_at';
515
                break;
516
            case 'lastlogin':
517
                $orderField = 'lastlogin';
518
                break;
519
            case 'apiaccess':
520
                $orderField = 'apiaccess';
521
                break;
522
            case 'grabs':
523
                $orderField = 'grabs';
524
                break;
525
            case 'role':
526
                $orderField = 'rolename';
527
                break;
528
            case 'rolechangedate':
529
                $orderField = 'rolechangedate';
530
                break;
531
            case 'verification':
532
                $orderField = 'verified';
533
                break;
534
            default:
535
                $orderField = 'username';
536
                break;
537
        }
538
        $orderSort = (isset($orderArr[1]) && preg_match('/^asc|desc$/i', $orderArr[1])) ? $orderArr[1] : 'desc';
539
540
        return [$orderField, $orderSort];
541
    }
542
543
    /**
544
     * Verify a password against a hash.
545
     *
546
     * Automatically update the hash if it needs to be.
547
     *
548
     * @param string $password Password to check against hash.
549
     * @param string|bool $hash     Hash to check against password.
550
     * @param int    $userID   ID of the user.
551
     *
552
     * @return bool
553
     */
554
    public static function checkPassword($password, $hash, $userID = -1): bool
555
    {
556
        if (Hash::check($password, $hash) === false) {
557
            return false;
558
        }
559
560
        // Update the hash if it needs to be.
561
        if (is_numeric($userID) && $userID > 0 && Hash::needsRehash($hash)) {
562
            $hash = self::hashPassword($password);
563
564
            if ($hash !== false) {
565
                self::find($userID)->update(['password' => $hash]);
566
            }
567
        }
568
569
        return true;
570
    }
571
572
    /**
573
     * @param $uid
574
     *
575
     * @return int
576
     */
577
    public static function updateRssKey($uid): int
578
    {
579
        self::find($uid)->update(['api_token' => md5(Password::getRepository()->createNewToken())]);
580
581
        return self::SUCCESS;
582
    }
583
584
    /**
585
     * @param $id
586
     * @param $guid
587
     *
588
     * @return int
589
     */
590
    public static function updatePassResetGuid($id, $guid): int
591
    {
592
        self::find($id)->update(['resetguid' => $guid]);
593
594
        return self::SUCCESS;
595
    }
596
597
    /**
598
     * @param int    $id
599
     * @param string $password
600
     *
601
     * @return int
602
     */
603
    public static function updatePassword(int $id, string $password): int
604
    {
605
        self::find($id)->update(['password' => self::hashPassword($password), 'userseed' => md5(Str::uuid()->toString())]);
606
607
        return self::SUCCESS;
608
    }
609
610
    /**
611
     * @param $password
612
     * @return mixed
613
     */
614
    public static function hashPassword($password)
615
    {
616
        return Hash::make($password);
617
    }
618
619
    /**
620
     * @param $guid
621
     *
622
     * @return \Illuminate\Database\Eloquent\Model|static
623
     * @throws \Illuminate\Database\Eloquent\ModelNotFoundException
624
     */
625
    public static function getByPassResetGuid(string $guid)
626
    {
627
        return self::whereResetguid($guid)->first();
628
    }
629
630
    /**
631
     * @param     $id
632
     * @param int $num
633
     */
634
    public static function incrementGrabs(int $id, $num = 1): void
635
    {
636
        self::find($id)->increment('grabs', $num);
637
    }
638
639
    /**
640
     * Check if the user is in the database, and if their API key is good, return user data if so.
641
     *
642
     *
643
     * @param $userID
644
     * @param $rssToken
645
     *
646
     * @return bool|\Illuminate\Database\Eloquent\Model|null|static
647
     */
648
    public static function getByIdAndRssToken($userID, $rssToken)
649
    {
650
        $user = self::query()->where(['id' => $userID, 'api_token' => $rssToken])->first();
651
        if ($user === null) {
652
            return false;
653
        }
654
655
        return $user;
656
    }
657
658
    /**
659
     * @param string $rssToken
660
     * @return \Illuminate\Database\Eloquent\Model|null|static
661
     */
662
    public static function getByRssToken(string $rssToken)
663
    {
664
        return self::whereApiToken($rssToken)->first();
665
    }
666
667
    /**
668
     * @param $url
669
     *
670
     * @return bool
671
     */
672
    public static function isValidUrl($url): bool
673
    {
674
        return (! preg_match('/^(http|https|ftp):\/\/([A-Z0-9][A-Z0-9_-]*(?:\.[A-Z0-9][A-Z0-9_-]*)+):?(\d+)?\/?/i', $url)) ? false : true;
675
    }
676
677
    /**
678
     * Generate a random username.
679
     *
680
     *
681
     * @return string
682
     */
683
    public static function generateUsername(): string
684
    {
685
        return Str::random();
686
    }
687
688
    /**
689
     * @param int $length
690
     *
691
     * @return string
692
     * @throws \Exception
693
     */
694
    public static function generatePassword($length = 15): string
695
    {
696
        return /Token::random($length, true);
0 ignored issues
show
Bug introduced by
A parse error occurred: Syntax error, unexpected '/', expecting ';' on line 696 at column 15
Loading history...
697
    }
698
699
    /**
700
     * Register a new user.
701
     *
702
     * @param        $userName
703
     * @param        $password
704
     * @param        $email
705
     * @param        $host
706
     * @param        $notes
707
     * @param int $invites
708
     * @param string $inviteCode
709
     * @param bool $forceInviteMode
710
     *
711
     * @param int $role
712
     * @param bool $validate
713
     * @return bool|int|string
714
     * @throws \Exception
715
     */
716
    public static function signUp($userName, $password, $email, $host, $notes, $invites = Invitation::DEFAULT_INVITES, $inviteCode = '', $forceInviteMode = false, $role = self::ROLE_USER, $validate = true)
717
    {
718
        $user = [
719
            'username' => trim($userName),
720
            'password' => trim($password),
721
            'email' => trim($email),
722
        ];
723
724
        if ($validate) {
725
            $validator = Validator::make($user, [
726
                'username' => ['required', 'string', 'min:5', 'max:255', 'unique:users'],
727
                'email' => ['required', 'string', 'email', 'max:255', 'unique:users', 'indisposable'],
728
                'password' => ['required', 'string', 'min:8', 'confirmed', 'regex:/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$/'],
729
            ]);
730
731
            if ($validator->fails()) {
732
                $error = implode('', Arr::collapse($validator->errors()->toArray()));
733
734
                return $error;
735
            }
736
        }
737
738
        // Make sure this is the last check, as if a further validation check failed, the invite would still have been used up.
739
        $invitedBy = 0;
740
        if (! $forceInviteMode && (int) Settings::settingValue('..registerstatus') === Settings::REGISTER_STATUS_INVITE) {
741
            if ($inviteCode === '') {
742
                return self::ERR_SIGNUP_BADINVITECODE;
743
            }
744
745
            $invitedBy = self::checkAndUseInvite($inviteCode);
746
            if ($invitedBy < 0) {
747
                return self::ERR_SIGNUP_BADINVITECODE;
748
            }
749
        }
750
751
        return self::add($user['username'], $user['password'], $user['email'], $role, $notes, $host, $invites, $invitedBy);
752
    }
753
754
    /**
755
     * If a invite is used, decrement the person who invited's invite count.
756
     *
757
     * @param string $inviteCode
758
     *
759
     * @return int
760
     */
761
    public static function checkAndUseInvite(string $inviteCode): int
762
    {
763
        $invite = Invitation::getInvite($inviteCode);
764
        if (! $invite) {
765
            return -1;
766
        }
767
768
        self::query()->where('id', $invite['users_id'])->decrement('invites');
769
        Invitation::deleteInvite($inviteCode);
770
771
        return $invite['users_id'];
772
    }
773
774
    /**
775
     * Add a new user.
776
     *
777
     * @param string    $userName
778
     * @param  string   $password
779
     * @param  string   $email
780
     * @param int    $role
781
     * @param string    $notes
782
     * @param string    $host
783
     * @param int $invites
784
     * @param int $invitedBy
785
     *
786
     * @return bool|int
787
     * @throws \Exception
788
     */
789
    public static function add($userName, $password, $email, $role, $notes = '', $host = '', $invites = Invitation::DEFAULT_INVITES, $invitedBy = 0)
790
    {
791
        $password = self::hashPassword($password);
792
        if (! $password) {
793
            return false;
794
        }
795
796
        $storeips = (int) Settings::settingValue('..storeuserips') === 1 ? $host : '';
797
798
        $user = self::create(
799
            [
800
                'username' => $userName,
801
                'password' => $password,
802
                'email' => $email,
803
                'host' => $storeips,
804
                'roles_id' => $role,
805
                'invites' => $invites,
806
                'invitedby' => (int) $invitedBy === 0 ? null : $invitedBy,
807
                'notes' => $notes,
808
            ]
809
        );
810
811
        return $user->id;
812
    }
813
814
    /**
815
     * Get the list of categories the user has excluded.
816
     *
817
     * @param int $userID ID of the user.
818
     *
819
     * @return array
820
     * @throws \Exception
821
     */
822
    public static function getCategoryExclusionById($userID): array
823
    {
824
        $ret = [];
825
826
        $user = self::find($userID);
827
828
        $userAllowed = $user->getDirectPermissions()->pluck('name')->toArray();
829
        $roleAllowed = $user->getAllPermissions()->pluck('name')->toArray();
830
831
        $allowed = array_intersect($roleAllowed, $userAllowed);
832
833
        $cats = ['view console', 'view movies', 'view audio', 'view tv', 'view pc', 'view adult', 'view books', 'view other'];
834
835
        if (! empty($allowed)) {
836
            foreach ($cats as $cat) {
837
                if (! \in_array($cat, $allowed, false)) {
838
                    switch ($cat) {
839
                        case 'view console':
840
                            $ret[] = 1000;
841
                            continue 2;
842
                        case 'view movies':
843
                            $ret[] = 2000;
844
                            continue 2;
845
                        case 'view audio':
846
                            $ret[] = 3000;
847
                            continue 2;
848
                        case 'view pc':
849
                            $ret[] = 4000;
850
                            continue 2;
851
                        case 'view tv':
852
                            $ret[] = 5000;
853
                            continue 2;
854
                        case 'view adult':
855
                            $ret[] = 6000;
856
                            continue 2;
857
                        case 'view books':
858
                            $ret[] = 7000;
859
                            continue 2;
860
                        case 'view other':
861
                            $ret[] = 1;
862
863
                    }
864
                }
865
            }
866
        }
867
868
        $exclusion = Category::query()->whereIn('root_categories_id', $ret)->pluck('id')->toArray();
869
870
        return $exclusion;
871
    }
872
873
    /**
874
     * @param \Illuminate\Http\Request $request
875
     * @return array
876
     * @throws \Exception
877
     */
878
    public static function getCategoryExclusionForApi(Request $request): array
879
    {
880
        $apiToken = $request->has('api_token') ? $request->input('api_token') : $request->input('apikey');
881
        $user = self::getByRssToken($apiToken);
882
883
        return self::getCategoryExclusionById($user->id);
884
    }
885
886
    /**
887
     * @return \Illuminate\Database\Eloquent\Collection|\Illuminate\Support\Collection|static[]
888
     */
889
    public static function getTopGrabbers()
890
    {
891
        return self::query()->selectRaw('id, username, SUM(grabs) as grabs')->groupBy('id', 'username')->having('grabs', '>', 0)->orderBy('grabs', 'desc')->limit(10)->get();
892
    }
893
894
    /**
895
     * @return \Illuminate\Database\Eloquent\Collection|\Illuminate\Support\Collection|static[]
896
     */
897
    public static function getUsersByMonth()
898
    {
899
        return self::query()->whereNotNull('created_at')->where('created_at', '<>', '0000-00-00 00:00:00')->selectRaw("DATE_FORMAT(created_at, '%M %Y') as mth, COUNT(id) as num")->groupBy(['mth'])->orderBy('created_at', 'desc')->get();
900
    }
901
902
    /**
903
     * @param $serverUrl
904
     * @param $uid
905
     * @param $emailTo
906
     *
907
     * @return string
908
     * @throws \Exception
909
     */
910
    public static function sendInvite($serverUrl, $uid, $emailTo): string
911
    {
912
        $user = self::find($uid);
913
        $token = Invite::invite($emailTo, $user->id);
914
        $url = $serverUrl.'/register?invitecode='.$token;
915
916
        Invitation::addInvite($uid, $token);
917
        SendInviteEmail::dispatch($emailTo, $user, $url)->onQueue('emails');
918
919
        return $url;
920
    }
921
922
    /**
923
     * Deletes old rows FROM the user_requests and user_downloads tables.
924
     * if site->userdownloadpurgedays SET to 0 then all release history is removed but
925
     * the download/request rows must remain for at least one day to allow the role based
926
     * limits to apply.
927
     *
928
     * @param int $days
929
     * @throws \Exception
930
     */
931
    public static function pruneRequestHistory($days = 0): void
932
    {
933
        if ($days === 0) {
934
            $days = 1;
935
            UserDownload::query()->update(['releases_id' => null]);
936
        }
937
938
        UserRequest::query()->where('timestamp', '<', now()->subDays($days))->delete();
939
        UserDownload::query()->where('timestamp', '<', now()->subDays($days))->delete();
940
    }
941
942
    /**
943
     * Deletes users that have not verified their accounts for 3 or more days.
944
     */
945
    public static function deleteUnVerified(): void
946
    {
947
        static::whereVerified(0)->where('created_at', '<', now()->subDays(3))->delete();
948
    }
949
}
950