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