Implement RBAC (only built in roles) (#15212)

* Install bouncer

* Seeder and level migration

* Display and edit roles

* remove unused deluser page

* Update Radius and SSO to assign roles

* update AlertUtil direct level check to use roles instead

* rewrite ircbot auth handling

* Remove legacy auth getUserlist and getUserlevel methods, add getRoles
Set roles in LegacyUserProvider

* Small cleanups

* centralize role sync code
show roles on user preferences page

* VueSelect component WIP and a little docs

* WIP

* SelectControllers id and text fields.

* LibrenmsSelect component extracted from SettingSelectDynamic

* Handle multiple selections

* allow type coercion

* full width settings

* final style adjustments

* Final compiled assets update

* Style fixes

* Fix SSO tests

* Lint cleanups

* small style fix

* don't use json yet

* Update baseline for usptream package issues

* Change schema, not 100% sure it is correct
not sure why xor doesn't work
This commit is contained in:
Tony Murray
2023-08-28 00:13:40 -05:00
committed by GitHub
parent 4fc27d98e9
commit 2cd207028a
58 changed files with 1344 additions and 804 deletions

View File

@@ -13,16 +13,18 @@ use Illuminate\Support\Facades\Hash;
use LibreNMS\Authentication\LegacyAuth;
use NotificationChannels\WebPush\HasPushSubscriptions;
use Permissions;
use Silber\Bouncer\BouncerFacade as Bouncer;
use Silber\Bouncer\Database\HasRolesAndAbilities;
/**
* @method static \Database\Factories\UserFactory factory(...$parameters)
*/
class User extends Authenticatable
{
use Notifiable, HasFactory, HasPushSubscriptions;
use HasRolesAndAbilities, Notifiable, HasFactory, HasPushSubscriptions;
protected $primaryKey = 'user_id';
protected $fillable = ['realname', 'username', 'email', 'level', 'descr', 'can_modify_passwd', 'auth_type', 'auth_id', 'enabled'];
protected $fillable = ['realname', 'username', 'email', 'descr', 'can_modify_passwd', 'auth_type', 'auth_id', 'enabled'];
protected $hidden = ['password', 'remember_token', 'pivot'];
protected $attributes = [ // default values
'descr' => '',
@@ -42,31 +44,29 @@ class User extends Authenticatable
public function toFlare(): array
{
return $this->only(['level', 'auth_type', 'enabled']);
return $this->only(['auth_type', 'enabled']);
}
// ---- Helper Functions ----
/**
* Test if this user has global read access
* these users have a level of 5, 10 or 11 (demo).
*
* @return bool
*/
public function hasGlobalRead()
{
return $this->hasGlobalAdmin() || $this->level == 5;
return $this->isA('admin', 'global-read');
}
/**
* Test if this user has global admin access
* these users have a level of 10 or 11 (demo).
*
* @return bool
*/
public function hasGlobalAdmin()
{
return $this->level >= 10;
return $this->isA('admin', 'demo');
}
/**
@@ -76,7 +76,7 @@ class User extends Authenticatable
*/
public function isAdmin()
{
return $this->level == 10;
return $this->isA('admin');
}
/**
@@ -86,7 +86,7 @@ class User extends Authenticatable
*/
public function isDemo()
{
return $this->level == 11;
return $this->isA('demo');
}
/**
@@ -110,6 +110,20 @@ class User extends Authenticatable
$this->attributes['password'] = $password ? Hash::make($password) : null;
}
/**
* Set roles and remove extra roles, optionally creating non-existent roles, flush permissions cache for this user if roles changed
*/
public function setRoles(array $roles, bool $create = false): void
{
if ($roles != $this->getRoles()) {
if ($create) {
$this->assign($roles);
}
Bouncer::sync($this)->roles($roles);
Bouncer::refresh($this);
}
}
/**
* Check if the given user can set the password for this user
*
@@ -167,7 +181,7 @@ class User extends Authenticatable
public function scopeAdminOnly($query)
{
$query->where('level', 10);
$query->whereIs('admin');
}
// ---- Accessors/Mutators ----