X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/1b8a1644123e00ae9b8785886c63f20e1ee134da..refs/pull/2515/head:/app/Auth/User.php diff --git a/app/Auth/User.php b/app/Auth/User.php index e5a8a3931..9d7eaa72e 100644 --- a/app/Auth/User.php +++ b/app/Auth/User.php @@ -1,16 +1,37 @@ 'datetime']; + /** * The attributes excluded from the model's JSON form. * @var array */ - protected $hidden = ['password', 'remember_token']; + protected $hidden = [ + 'password', 'remember_token', 'system_name', 'email_confirmed', 'external_auth_id', 'email', + 'created_at', 'updated_at', 'image_id', + ]; /** * This holds the user's permissions when loaded. - * @var array + * @var ?Collection */ protected $permissions; + /** + * This holds the default user when loaded. + * @var null|User + */ + protected static $defaultUser = null; + /** * Returns the default public user. * @return User */ public static function getDefault() { - return static::where('system_name', '=', 'public')->first(); + if (!is_null(static::$defaultUser)) { + return static::$defaultUser; + } + + static::$defaultUser = static::where('system_name', '=', 'public')->first(); + return static::$defaultUser; } /** @@ -70,12 +107,10 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon /** * Check if the user has a role. - * @param $role - * @return mixed */ - public function hasRole($role) + public function hasRole($roleId): bool { - return $this->roles->pluck('name')->contains($role); + return $this->roles->pluck('id')->contains($roleId); } /** @@ -89,57 +124,67 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon } /** - * Get all permissions belonging to a the current user. - * @param bool $cache - * @return \Illuminate\Database\Eloquent\Relations\HasManyThrough + * Attach the default system role to this user. */ - public function permissions($cache = true) + public function attachDefaultRole(): void { - if (isset($this->permissions) && $cache) { - return $this->permissions; + $roleId = setting('registration-role'); + if ($roleId && $this->roles()->where('id', '=', $roleId)->count() === 0) { + $this->roles()->attach($roleId); } - $this->load('roles.permissions'); - $permissions = $this->roles->map(function ($role) { - return $role->permissions; - })->flatten()->unique(); - $this->permissions = $permissions; - return $permissions; } /** * Check if the user has a particular permission. - * @param $permissionName - * @return bool */ - public function can($permissionName) + public function can(string $permissionName): bool { if ($this->email === 'guest') { return false; } - return $this->permissions()->pluck('name')->contains($permissionName); + + return $this->permissions()->contains($permissionName); } /** - * Attach a role to this user. - * @param Role $role + * Get all permissions belonging to a the current user. */ - public function attachRole(Role $role) + protected function permissions(): Collection { - $this->attachRoleId($role->id); + if (isset($this->permissions)) { + return $this->permissions; + } + + $this->permissions = $this->newQuery()->getConnection()->table('role_user', 'ru') + ->select('role_permissions.name as name')->distinct() + ->leftJoin('permission_role', 'ru.role_id', '=', 'permission_role.role_id') + ->leftJoin('role_permissions', 'permission_role.permission_id', '=', 'role_permissions.id') + ->where('ru.user_id', '=', $this->id) + ->get() + ->pluck('name'); + + return $this->permissions; } /** - * Attach a role id to this user. - * @param $id + * Clear any cached permissions on this instance. */ - public function attachRoleId($id) + public function clearPermissionCache() { - $this->roles()->attach($id); + $this->permissions = null; + } + + /** + * Attach a role to this user. + */ + public function attachRole(Role $role) + { + $this->roles()->attach($role->id); } /** * Get the social account associated with this user. - * @return \Illuminate\Database\Eloquent\Relations\HasMany + * @return HasMany */ public function socialAccounts() { @@ -176,7 +221,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon try { $avatar = $this->avatar ? url($this->avatar->getThumb($size, $size, false)) : $default; - } catch (\Exception $err) { + } catch (Exception $err) { $avatar = $default; } return $avatar; @@ -184,27 +229,47 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon /** * Get the avatar for the user. - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + * @return BelongsTo */ public function avatar() { return $this->belongsTo(Image::class, 'image_id'); } + /** + * Get the API tokens assigned to this user. + */ + public function apiTokens(): HasMany + { + return $this->hasMany(ApiToken::class); + } + + /** + * Get the last activity time for this user. + */ + public function scopeWithLastActivityAt(Builder $query) + { + $query->addSelect(['activities.created_at as last_activity_at']) + ->leftJoinSub(function (\Illuminate\Database\Query\Builder $query) { + $query->from('activities')->select('user_id') + ->selectRaw('max(created_at) as created_at') + ->groupBy('user_id'); + }, 'activities', 'users.id', '=', 'activities.user_id'); + } + /** * Get the url for editing this user. - * @return string */ - public function getEditUrl() + public function getEditUrl(string $path = ''): string { - return url('/http/source.bookstackapp.com/settings/users/' . $this->id); + $uri = '/settings/users/' . $this->id . '/' . trim($path, '/'); + return url(rtrim($uri, '/')); } /** * Get the url that links to this user's profile. - * @return mixed */ - public function getProfileUrl() + public function getProfileUrl(): string { return url('/http/source.bookstackapp.com/user/' . $this->id); } @@ -237,4 +302,12 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon { $this->notify(new ResetPassword($token)); } + + /** + * @inheritdoc + */ + public function logDescriptor(): string + { + return "({$this->id}) {$this->name}"; + } }