1<?php 2 3namespace App\Models; 4 5use App\Events\UserCreated; 6use Illuminate\Database\Eloquent\Builder; 7use Illuminate\Database\Eloquent\Factories\HasFactory; 8use Illuminate\Database\Eloquent\Relations\BelongsToMany; 9use Illuminate\Database\Eloquent\Relations\HasMany; 10use Illuminate\Database\Eloquent\Relations\HasOne; 11use Illuminate\Foundation\Auth\User as Authenticatable; 12use Illuminate\Notifications\Notifiable; 13use Illuminate\Support\Facades\Hash; 14use LibreNMS\Authentication\LegacyAuth; 15use Permissions; 16 17/** 18 * @method static \Database\Factories\UserFactory factory(...$parameters) 19 */ 20class User extends Authenticatable 21{ 22 use Notifiable, HasFactory; 23 24 protected $primaryKey = 'user_id'; 25 protected $fillable = ['realname', 'username', 'email', 'level', 'descr', 'can_modify_passwd', 'auth_type', 'auth_id', 'enabled']; 26 protected $hidden = ['password', 'remember_token', 'pivot']; 27 protected $attributes = [ // default values 28 'descr' => '', 29 'realname' => '', 30 'email' => '', 31 ]; 32 protected $dispatchesEvents = [ 33 'created' => UserCreated::class, 34 ]; 35 36 protected $casts = [ 37 'realname' => 'string', 38 'descr' => 'string', 39 'email' => 'string', 40 'can_modify_passwd' => 'integer', 41 ]; 42 43 // ---- Helper Functions ---- 44 45 /** 46 * Test if this user has global read access 47 * these users have a level of 5, 10 or 11 (demo). 48 * 49 * @return bool 50 */ 51 public function hasGlobalRead() 52 { 53 return $this->hasGlobalAdmin() || $this->level == 5; 54 } 55 56 /** 57 * Test if this user has global admin access 58 * these users have a level of 10 or 11 (demo). 59 * 60 * @return bool 61 */ 62 public function hasGlobalAdmin() 63 { 64 return $this->level >= 10; 65 } 66 67 /** 68 * Test if the User is an admin. 69 * 70 * @return bool 71 */ 72 public function isAdmin() 73 { 74 return $this->level == 10; 75 } 76 77 /** 78 * Test if this user is the demo user 79 * 80 * @return bool 81 */ 82 public function isDemo() 83 { 84 return $this->level == 11; 85 } 86 87 /** 88 * Check if this user has access to a device 89 * 90 * @param Device|int $device can be a device Model or device id 91 * @return bool 92 */ 93 public function canAccessDevice($device) 94 { 95 return $this->hasGlobalRead() || Permissions::canAccessDevice($device, $this->user_id); 96 } 97 98 /** 99 * Helper function to hash passwords before setting 100 * 101 * @param string $password 102 */ 103 public function setPassword($password) 104 { 105 $this->attributes['password'] = $password ? Hash::make($password) : null; 106 } 107 108 /** 109 * Check if the given user can set the password for this user 110 * 111 * @param User $user 112 * @return bool 113 */ 114 public function canSetPassword($user) 115 { 116 if ($user && LegacyAuth::get()->canUpdatePasswords()) { 117 if ($user->isAdmin()) { 118 return true; 119 } 120 121 return $user->is($this) && $this->can_modify_passwd; 122 } 123 124 return false; 125 } 126 127 // ---- Query scopes ---- 128 129 /** 130 * This restricts the query to only users that match the current auth method 131 * It is not needed when using user_id, but should be used for username and auth_id 132 * 133 * @param Builder $query 134 * @return Builder 135 */ 136 public function scopeThisAuth($query) 137 { 138 // find user including ones where we might not know the auth type 139 $type = LegacyAuth::getType(); 140 141 return $query->where(function ($query) use ($type) { 142 $query->where('auth_type', $type) 143 ->orWhereNull('auth_type') 144 ->orWhere('auth_type', ''); 145 }); 146 } 147 148 public function scopeAdminOnly($query) 149 { 150 $query->where('level', 10); 151 } 152 153 // ---- Accessors/Mutators ---- 154 155 public function setRealnameAttribute($realname) 156 { 157 $this->attributes['realname'] = (string) $realname; 158 } 159 160 public function setDescrAttribute($descr) 161 { 162 $this->attributes['descr'] = (string) $descr; 163 } 164 165 public function setEmailAttribute($email) 166 { 167 $this->attributes['email'] = (string) $email; 168 } 169 170 public function setCanModifyPasswdAttribute($modify) 171 { 172 $this->attributes['can_modify_passwd'] = $modify ? 1 : 0; 173 } 174 175 public function setEnabledAttribute($enable) 176 { 177 $this->attributes['enabled'] = $enable ? 1 : 0; 178 } 179 180 public function getDevicesAttribute() 181 { 182 // pseudo relation 183 if (! array_key_exists('devices', $this->relations)) { 184 $this->setRelation('devices', $this->devices()->get()); 185 } 186 187 return $this->getRelation('devices'); 188 } 189 190 // ---- Define Relationships ---- 191 192 public function apiToken(): HasOne 193 { 194 return $this->hasOne(\App\Models\ApiToken::class, 'user_id', 'user_id'); 195 } 196 197 public function devices() 198 { 199 // pseudo relation 200 return Device::query()->when(! $this->hasGlobalRead(), function ($query) { 201 return $query->whereIn('device_id', Permissions::devicesForUser($this)); 202 }); 203 } 204 205 public function deviceGroups(): BelongsToMany 206 { 207 return $this->belongsToMany(\App\Models\DeviceGroup::class, 'devices_group_perms', 'user_id', 'device_group_id'); 208 } 209 210 public function ports() 211 { 212 if ($this->hasGlobalRead()) { 213 return Port::query(); 214 } else { 215 //FIXME we should return all ports for a device if the user has been given access to the whole device. 216 return $this->belongsToMany(\App\Models\Port::class, 'ports_perms', 'user_id', 'port_id'); 217 } 218 } 219 220 public function dashboards(): HasMany 221 { 222 return $this->hasMany(\App\Models\Dashboard::class, 'user_id'); 223 } 224 225 public function preferences(): HasMany 226 { 227 return $this->hasMany(\App\Models\UserPref::class, 'user_id'); 228 } 229 230 public function widgets(): HasMany 231 { 232 return $this->hasMany(\App\Models\UserWidget::class, 'user_id'); 233 } 234} 235