Best Practice to Get Roles of Active Users = Auth::user() - laravel

I have 3 table
users
roles
role_users
this table created by Orchid Platform, i want to get role name of Auth::user() in Dashboard Laravel 8 (/home) from role_users table, i have tried to add role_id to users table, thats realy work.
But i want use role_users, because Orchid Platform use role_users.
Please help me, thank you.

I don't know about "Orchid Platform" but that User<->Role (ManyToMany) relationship is a pretty common database structure.
users
id - integer
name - string
roles
id - integer
name - string
role_user
user_id - integer
role_id - integer
User Model:
class User extends Model
{
/**
* The roles that belong to the user.
*/
public function roles()
{
return $this->belongsToMany(Role::class);
}
}
Role Model:
class Role extends Model
{
/**
* The users that belong to the role.
*/
public function users()
{
return $this->belongsToMany(User::class);
}
}
To get roles of the authenticated User
$user = User::find(1);
foreach ($user->roles as $role) {
//
}
If your users will only have 1 role, you can just use a method in your User model to get first role of the User.
public function getRole(){
return $this->roles()->first();
}
Now, you can used this way:
Auth::user()->getRole()->name

Related

How to override laravel model query?

I have a main model called User that returns all the users of the application.
There is a table called invites which manages the users invited to access the invitee panel. The invites table is thus linked to users:
So we have a general User model which handle all the users, and other two types of users:
Patient: user who invited the tenant
Tenant: user who has access to a list of associated patients
What I am trying to do is to fetch a patient list of a certain tenant (logged in user) using the eloquent relationship system, so I don't have to write a query for the join every time. Is it possible to do this?
At the moment, I tried this:
class Patient extends User
{
use HasFactory;
//protected $table = 'users';
public function getList()
{
return $this->belongsToMany(User::class, 'invites', 'id', 'user_id');
}
}
but of course this relationship not works because the query that should execute must be this:
SELECT u.*
FROM users u
INNER JOIN invites i ON i.user_id = u.id
WHERE i.tenant_id = 1
where id is the reference of the current user logged in which I retrieve using laratrust auth: auth()->user()->id.
Would be possible to return all the patients associated to the logged in user automatically? So simply calling:
Patient::query();
How can I achieve this?
To achieve that you should define relation and reverse many to many relation:
in your user model:
class Tenant extends User
{
use HasFactory;
protected $table = 'users';
public function patients()
{
return $this->belongsToMany(User::class, 'invites', 'tenant_id', 'user_id');
}
}
And in Patient model define reverse many to many relation by reverse belongToMany params :
class Patient extends User
{
use HasFactory;
protected $table = 'users';
public function tenants()
{
return $this->belongsToMany(User::class, 'invites', 'user_id', 'tenant_id');
}
}
To use the auth id for each model you have 2 option:
Option 1:
add column in users table that named user_type wich have type enum('tenant','patient') and depend user type use the appropriate model
Option 2:
by using custom auth guards , take look to this article
https://www.codecheef.org/article/laravel-8-login-with-custom-guard-example

Laravel relationship for user with multiple scenarios

So, i need to make relationship between users table, roles and sections table, the table structure as follows :
users
id - integer
name - string
role_id - foreignId
section_id - foreignId
sections
id - integer
section - string
department - string
roles
id - integer
title - string
User model :
<?php
namespace App\Models;
class User extends Authenticatable
{
use HasFactory, Notifiable;
public function section()
{
return $this->belongsTo(Section::class);
}
public function role()
{
return $this->belongsTo(Role::class);
}
}
The model above is OK if the user only belongsTo one section.
The problem is user can belongs to more than one section depending on their role.
The role itself determine this matrix below
How can i achive this ?

Laravel - User > Roles > Permissions within a Company

I am trying to describe a relationship between a User and a Company. More specific I want the following:
A User has one or Many Roles within a Company.
A Role has one or Many Permissions.
- users (id, name, surname, email, ...)
- permissions (id, name, label, ...)
- roles (id, name, label,...)
- companies (id, name, address, ...)
- permission_role (permission_id, role_id)
- user_role (user_id, role_id)
- company_user (company_id, user_id)
Anyone could help me out?
ER Diagram: https://prnt.sc/q4l614
The pivot_table name will be like user_role_company. Pivot table structure will be like
role_user Table
+---------+-----------+----------+-------------+
| id |user_id | role_id | company_id |
+---------+-----------+----------+-------------+
| 1 | 1 | 2 | 3 |
+---------+-----------+----------+-------------+
One User has one or many company id,
One User has also one or many role id,
One Role has belongs to many user
One Role has belongs to many company.
One Company has belongs to many user.
One Company has belongs to many role.
All of this scenario. you can implements scenario by this -
In User Model
class User extends Authenticatable
{
public function roles()
{
return $this->belongsToMany(Role::class);
}
public function companyies()
{
return $this->belongsToMany(Company::class);
}
}
In Role Model -
class Role extends Model
{
public function users()
{
return $this->belongsToMany(User::class);
}
public function companies()
{
return $this->belongsToMany(Company::class);
}
}
In Company Model -
class Company extends Model
{
public function users()
{
return $this->belongsToMany(User::class);
}
public function roles()
{
return $this->belongsToMany(Role::class);
}
}
Same as for Role and Permission.
You can check the relationship using Laravel tinker.
I Hope it will work for you.
you can read more details from this link : https://laravel.com/docs/6.x/eloquent-relationships#many-to-many

Separate roles/permissions if user belongs to many organizations

I have an application where a user can belong to multiple organizations. I want to set it up in a way that a user can have different roles/permissions for each organization. I am using Laravel and plan on implementing Spatie/laravel-permission. What is the best way to implement this?
I have tried setting up two guards, one for the main user account and another for the pivot model between the user and the organization they log into. So basically when they log into the app using the main user model, I ask them which organization they would like to log into, when they choose the organization I will then also set up an auth session on the pivot model that links the user to the organization and access the roles off that model. This works, but having to manage the auth sessions is kind of a pain.
// User Model
class User extends Authenticatable
{
public function organizationUsers()
{
return $this->hasMany(OrganizationUser::class);
}
}
// OrganizationUser Model
class Organziationuser extends Authenticatable
{
use HasRoles;
public $guard_name = 'organization_user';
public function organization()
{
return $this->belongsTo(Organization::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
}
I would expect a user to be able to log into the application using a single login, but also be able to have different permissions for different organizations.
I have got around this issue by doing the following. I would welcome feedback on peoples views of this method!
Note: Currently I am only using the model_has_roles table with Spatie permissions and always use $user->can('Permission') to check permissions.
Our company model has the following relationships and method
class Company extends Model
{
public function owner(): HasOne
{
return $this->hasOne(User::class, 'id', 'user_id');
}
public function users(): BelongsToMany
{
return $this->belongsToMany(
User::class, 'company_users', 'company_id', 'user_id'
)->using(CompanyUser::class);
}
public function addTeamMember(User $user)
{
$this->users()->detach($user);
$this->users()->attach($user);
}
}
We modify the pivot model to have the Spatie HasRoles trait. This allows us to assign a role to the CompanyUser as opposed to the Auth User. You also need to specify the default guard or Spatie permissions squarks.
class CompanyUser extends Pivot
{
use HasRoles;
protected $guard_name = 'web';
}
On the user model, I have created the HasCompanies Trait. This provides the relationships and provides a method for assigning the roles to the new company user. Additionally, it overwrites the gate can() method.
A user can belong to many companies, but can only have one active company at a time (i.e. the one they are viewing). We define this with the current_company_id column.
It is also important to ensure the pivot table ID is pulled across (which it will not be as standard) as this is now what we are using in the Spatie model_has_roles table.
trait HasCompanies
{
public function companies(): HasMany
{
return $this->hasMany(Company::class);
}
public function currentCompany(): HasOne
{
return $this->hasOne(Company::class, 'id', 'current_company_id');
}
public function teams(): BelongsToMany
{
return $this->belongsToMany(
Company::class, 'company_users', 'user_id', 'company_id'
)->using(CompanyUser::class)->withPivot('id');
}
public function switchCompanies(Company $company): void
{
$this->current_company_id = $company->id;
$this->save();
}
public function assignRolesForCompany(Company $company, ...$roles)
{
if($company = $this->teams()->where('companies.id', $company->id)->first()){
/** #var CompanyUser $companyUser */
$companyUser = $company->pivot;
$companyUser->assignRole($roles);
return;
}
throw new Exception('Roles could not be assigned to company user');
}
public function can($ability, $arguments = [])
{
if(isset($this->current_company_id)){
/** #var CompanyUser $companyUser */
$companyUser = $this->teams()->where('companies.id', $this->current_company_id)->first()->pivot;
if($companyUser->hasPermissionTo($ability)){
return true;
}
// We still run through the gate on fail, as this will check for gate bypass. i.e. Super User
return app(Gate::class)->forUser($this)->check('InvalidPermission');
}
return app(Gate::class)->forUser($this)->check($ability, $arguments);
}
}
Now we can do something like this:
Create the role & permission
/** #var Role $ownerRoll */
$ownerRoll = Role::create(['name' => 'Owner']);
/** #var Permission $permission */
$permission = Permission::create([
'name' => 'Create Company',
'guard_name' => 'web',
]);
$ownerRoll->givePermissionTo($permission);
Create a new company with an owning user and then switch this company to that owner's active company.
public function store(CompanyStoreRequest $request)
{
DB::transaction(function () use($request) {
/** #var User $owner */
$owner = User::findOrFail($request->user_id);
/** #var Company $company */
$company = $owner->companies()->create($request->validated());
$company->addTeamMember($owner);
$owner->assignRolesForCompany($company, 'Owner');
$owner->switchCompanies($company);
});
return redirect()->back();
}
So this all works, my main concerns are that:
We are overwriting the can method. There may be other authorization methods/gate functions that are not caught.
We have 2 sets of model_permissions. The Auth user and the company user. I think I need to build in some checks to ensure that only the correct kinds of users can be assigned to the roles. At this stage, all administrator users would have permissions assigned to their auth user, while any users who own a company should only have permissions on the company user model

Polymorphic relations in Laravel

Please, Help me!
I have User model and migration: id, login, password.
3 roles and models (Admin, Teacher, Student) and here more information about user. And user can get several roles (he can be admin and teacher)
And one polymorphic model Role with columns:
user_id
roleable_id
roleable_type
For example, User::find(1)->roles;
And i'd like that result shows two model (admin and teacher).
Pleasee, help me))
You could try to eager load the models by using this in your User model https://gist.github.com/thisdotvoid/3022fee8afa53e45a6b89da3f16b3815. Add the required morph functions and then add three functions to the user model similar to this one (change the name and the model name accordingly):
public function admin()
{
return BelongsToMorph::build($this, 'App\Admin', 'rolable');
}
Then create a mutator function like
function getRolesAttribute()
{
$roles = new Collection();
$roleNames = ['admin', 'teacher', 'student'];
foreach ($roleNames as $role) {
$hasRole = $this->{$role};
if ($hasRole) {
$roles->push($role);
}
}
return $roles;
}

Resources