1<?php
2
3// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0.
4// See the LICENCE file in the repository root for full licence text.
5
6namespace App\Models;
7
8use Carbon\Carbon;
9
10/**
11 * @property User $actor
12 * @property int $ban_id
13 * @property int|null $ban_status
14 * @property int|null $banner_id
15 * @property int $period
16 * @property bool $permanent
17 * @property string|null $reason
18 * @property string|null $supporting_url
19 * @property \Carbon\Carbon|null $timestamp
20 * @property mixed $type
21 * @property User $user
22 * @property int|null $user_id
23 */
24class UserAccountHistory extends Model
25{
26 const TYPES = [
27 'note' => 0,
28 'restriction' => 1,
29 'silence' => 2,
30 'tournament_ban' => 3,
31 ];
32
33 public $timestamps = false;
34
35 protected $casts = [
36 'permanent' => 'boolean',
37 'timestamp' => 'datetime',
38 ];
39 protected $primaryKey = 'ban_id';
40 protected $table = 'osu_user_banhistory';
41
42 public static function addNote($user, $message, $actor = null)
43 {
44 $actor = $actor ?? $user;
45
46 return static::create([
47 'user_id' => $user->getKey(),
48 'banner_id' => $actor->getKey(),
49
50 'ban_status' => static::TYPES['note'],
51
52 'reason' => $message,
53 ]);
54 }
55
56 public static function logUserPageModerated($user, $actor)
57 {
58 return static::addNote($user, 'User page moderated', $actor);
59 }
60
61 public static function logUserResetPassword($user)
62 {
63 return static::addNote($user, 'User forgot and recovered their password.');
64 }
65
66 public static function logUserUpdateEmail($user, $previousEmail)
67 {
68 $previousEmail = $previousEmail ?? 'null';
69 $message = "User changed email from {$previousEmail} to {$user->user_email}";
70
71 return static::addNote($user, $message);
72 }
73
74 public function scopeBans($query)
75 {
76 return $query->whereIn('ban_status', [static::TYPES['restriction'], static::TYPES['silence']])->orderBy('timestamp', 'desc');
77 }
78
79 public function scopeDefault($query)
80 {
81 return $query->whereIn('ban_status', [static::TYPES['silence'], static::TYPES['tournament_ban']]);
82 }
83
84 public function scopeRecent($query)
85 {
86 return $query
87 ->whereRaw('(UNIX_TIMESTAMP(`timestamp`) + `period`) > ?', time())
88 ->orWhere('timestamp', '>', Carbon::now()->subDays($GLOBALS['cfg']['osu']['user']['ban_persist_days']))
89 ->orWhere('permanent', true)
90 ->orderBy('timestamp', 'desc');
91 }
92
93 public function scopeRecentForChat($query)
94 {
95 return $query->where('timestamp', '>', Carbon::now()->subHours(1));
96 }
97
98 public function actor()
99 {
100 return $this->belongsTo(User::class, 'banner_id', 'user_id');
101 }
102
103 public function user()
104 {
105 return $this->belongsTo(User::class, 'user_id', 'user_id');
106 }
107
108 public function getTypeAttribute()
109 {
110 return array_search_null($this->ban_status, static::TYPES);
111 }
112
113 public function endTime()
114 {
115 return $this->timestamp->addSeconds($this->period);
116 }
117}