]> BookStack Code Mirror - bookstack/blob - app/Auth/User.php
6bf656be383614d8839d461aa72b427eed40ec29
[bookstack] / app / Auth / User.php
1 <?php namespace BookStack\Auth;
2
3 use BookStack\Api\ApiToken;
4 use BookStack\Interfaces\Loggable;
5 use BookStack\Model;
6 use BookStack\Notifications\ResetPassword;
7 use BookStack\Uploads\Image;
8 use Carbon\Carbon;
9 use Illuminate\Auth\Authenticatable;
10 use Illuminate\Auth\Passwords\CanResetPassword;
11 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
12 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
13 use Illuminate\Database\Eloquent\Relations\BelongsToMany;
14 use Illuminate\Database\Eloquent\Relations\HasMany;
15 use Illuminate\Notifications\Notifiable;
16
17 /**
18  * Class User
19  * @package BookStack\Auth
20  * @property string $id
21  * @property string $name
22  * @property string $email
23  * @property string $password
24  * @property Carbon $created_at
25  * @property Carbon $updated_at
26  * @property bool $email_confirmed
27  * @property int $image_id
28  * @property string $external_auth_id
29  * @property string $system_name
30  */
31 class User extends Model implements AuthenticatableContract, CanResetPasswordContract, Loggable
32 {
33     use Authenticatable, CanResetPassword, Notifiable;
34
35     /**
36      * The database table used by the model.
37      * @var string
38      */
39     protected $table = 'users';
40
41     /**
42      * The attributes that are mass assignable.
43      * @var array
44      */
45     protected $fillable = ['name', 'email'];
46
47     /**
48      * The attributes excluded from the model's JSON form.
49      * @var array
50      */
51     protected $hidden = [
52         'password', 'remember_token', 'system_name', 'email_confirmed', 'external_auth_id', 'email',
53         'created_at', 'updated_at', 'image_id',
54     ];
55
56     /**
57      * This holds the user's permissions when loaded.
58      * @var array
59      */
60     protected $permissions;
61
62     /**
63      * This holds the default user when loaded.
64      * @var null|User
65      */
66     protected static $defaultUser = null;
67
68     /**
69      * Returns the default public user.
70      * @return User
71      */
72     public static function getDefault()
73     {
74         if (!is_null(static::$defaultUser)) {
75             return static::$defaultUser;
76         }
77         
78         static::$defaultUser = static::where('system_name', '=', 'public')->first();
79         return static::$defaultUser;
80     }
81
82     /**
83      * Check if the user is the default public user.
84      * @return bool
85      */
86     public function isDefault()
87     {
88         return $this->system_name === 'public';
89     }
90
91     /**
92      * The roles that belong to the user.
93      * @return BelongsToMany
94      */
95     public function roles()
96     {
97         if ($this->id === 0) {
98             return ;
99         }
100         return $this->belongsToMany(Role::class);
101     }
102
103     /**
104      * Check if the user has a role.
105      */
106     public function hasRole($roleId): bool
107     {
108         return $this->roles->pluck('id')->contains($roleId);
109     }
110
111     /**
112      * Check if the user has a role.
113      * @param $role
114      * @return mixed
115      */
116     public function hasSystemRole($role)
117     {
118         return $this->roles->pluck('system_name')->contains($role);
119     }
120
121     /**
122      * Attach the default system role to this user.
123      */
124     public function attachDefaultRole(): void
125     {
126         $roleId = setting('registration-role');
127         if ($roleId && $this->roles()->where('id', '=', $roleId)->count() === 0) {
128             $this->roles()->attach($roleId);
129         }
130     }
131
132     /**
133      * Get all permissions belonging to a the current user.
134      * @param bool $cache
135      * @return \Illuminate\Database\Eloquent\Relations\HasManyThrough
136      */
137     public function permissions($cache = true)
138     {
139         if (isset($this->permissions) && $cache) {
140             return $this->permissions;
141         }
142         $this->load('roles.permissions');
143         $permissions = $this->roles->map(function ($role) {
144             return $role->permissions;
145         })->flatten()->unique();
146         $this->permissions = $permissions;
147         return $permissions;
148     }
149
150     /**
151      * Check if the user has a particular permission.
152      * @param $permissionName
153      * @return bool
154      */
155     public function can($permissionName)
156     {
157         if ($this->email === 'guest') {
158             return false;
159         }
160         return $this->permissions()->pluck('name')->contains($permissionName);
161     }
162
163     /**
164      * Attach a role to this user.
165      */
166     public function attachRole(Role $role)
167     {
168         $this->roles()->attach($role->id);
169     }
170
171     /**
172      * Get the social account associated with this user.
173      * @return \Illuminate\Database\Eloquent\Relations\HasMany
174      */
175     public function socialAccounts()
176     {
177         return $this->hasMany(SocialAccount::class);
178     }
179
180     /**
181      * Check if the user has a social account,
182      * If a driver is passed it checks for that single account type.
183      * @param bool|string $socialDriver
184      * @return bool
185      */
186     public function hasSocialAccount($socialDriver = false)
187     {
188         if ($socialDriver === false) {
189             return $this->socialAccounts()->count() > 0;
190         }
191
192         return $this->socialAccounts()->where('driver', '=', $socialDriver)->exists();
193     }
194
195     /**
196      * Returns the user's avatar,
197      * @param int $size
198      * @return string
199      */
200     public function getAvatar($size = 50)
201     {
202         $default = url('/user_avatar.png');
203         $imageId = $this->image_id;
204         if ($imageId === 0 || $imageId === '0' || $imageId === null) {
205             return $default;
206         }
207
208         try {
209             $avatar = $this->avatar ? url($this->avatar->getThumb($size, $size, false)) : $default;
210         } catch (\Exception $err) {
211             $avatar = $default;
212         }
213         return $avatar;
214     }
215
216     /**
217      * Get the avatar for the user.
218      * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
219      */
220     public function avatar()
221     {
222         return $this->belongsTo(Image::class, 'image_id');
223     }
224
225     /**
226      * Get the API tokens assigned to this user.
227      */
228     public function apiTokens(): HasMany
229     {
230         return $this->hasMany(ApiToken::class);
231     }
232
233     /**
234      * Get the url for editing this user.
235      */
236     public function getEditUrl(string $path = ''): string
237     {
238         $uri = '/settings/users/' . $this->id . '/' . trim($path, '/');
239         return url(rtrim($uri, '/'));
240     }
241
242     /**
243      * Get the url that links to this user's profile.
244      */
245     public function getProfileUrl(): string
246     {
247         return url('/user/' . $this->id);
248     }
249
250     /**
251      * Get a shortened version of the user's name.
252      * @param int $chars
253      * @return string
254      */
255     public function getShortName($chars = 8)
256     {
257         if (mb_strlen($this->name) <= $chars) {
258             return $this->name;
259         }
260
261         $splitName = explode(' ', $this->name);
262         if (mb_strlen($splitName[0]) <= $chars) {
263             return $splitName[0];
264         }
265
266         return '';
267     }
268
269     /**
270      * Send the password reset notification.
271      * @param  string  $token
272      * @return void
273      */
274     public function sendPasswordResetNotification($token)
275     {
276         $this->notify(new ResetPassword($token));
277     }
278
279     /**
280      * @inheritdoc
281      */
282     public function logDescriptor(): string
283     {
284         return "({$this->id}) {$this->name}";
285     }
286 }