Php Spatial用户权限-属于许多公司,解决方案反馈
我遇到的情况是,一个用户可以属于多个团队/公司,并且在该团队/公司中,他们可以拥有不同的角色和权限,具体取决于他们登录到哪个团队/公司。我已经想出了以下解决方案,并希望得到一些反馈 注意:目前我仅使用具有空间权限的Php Spatial用户权限-属于许多公司,解决方案反馈,php,laravel,permissions,spatie,Php,Laravel,Permissions,Spatie,我遇到的情况是,一个用户可以属于多个团队/公司,并且在该团队/公司中,他们可以拥有不同的角色和权限,具体取决于他们登录到哪个团队/公司。我已经想出了以下解决方案,并希望得到一些反馈 注意:目前我仅使用具有空间权限的model\u has\u roles表,并始终使用$user->can('Permission')检查权限 我们的公司模式具有以下关系和方法 我们修改了pivot模型,使其具有SpatieHasRoles特性。这允许我们将角色分配给公司用户,而不是身份验证用户。您还需要指定默认的保护
model\u has\u roles
表,并始终使用$user->can('Permission')
检查权限
HasRoles
特性。这允许我们将角色分配给公司用户
,而不是身份验证用户。您还需要指定默认的保护或空间权限can()
方法当前公司id
列定义它
同样重要的是确保透视表ID被拉过(它将不是标准的),因为这是我们现在在Spatiale模型中使用的
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();
}
private function companyWithPivot(Company $company)
{
return $this->teams()->where('companies.id', $company->id)->first();
}
public function assignRolesForCompany(Company $company, ...$roles)
{
if($company = $this->companyWithPivot($company)){
/** @var CompanyUser $companyUser */
$companyUser = $company->pivot;
$companyUser->assignRole($roles);
return;
}
throw new Exception('Roles could not be assigned to company user');
}
public function hasRoleForCurrentCompany(string $roles, Company $company = null, string $guard = null): bool
{
if(! $company){
if(! $company = $this->currentCompany){
throw new Exception('Cannot check role for current company because it has not been set');
}
}
if($company = $this->companyWithPivot($company)){
/** @var CompanyUser $companyUser */
$companyUser = $company->pivot;
return $companyUser->hasRole($roles, $guard);
}
return false;
}
public function can($ability, $arguments = []): bool
{
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;
}
// Still run through the gate as this will check for gate bypass
return app(Gate::class)->forUser($this)->check('N/A', []);
}
return app(Gate::class)->forUser($this)->check($ability, $arguments);
}
}
现在我们可以这样做:
创建角色和权限
创建一个拥有用户的新公司,然后将此公司切换到该所有者的活动公司
这一切都是可行的,我主要关心的是:
我们正在覆盖can方法。可能还有其他未捕获的授权方法/门函数
我们有两套model_权限。身份验证用户和公司用户。我认为我需要进行一些检查,以确保只能将正确类型的用户分配给角色。在此阶段,所有管理员用户都将拥有分配给其身份验证用户的权限,而拥有公司的任何用户都只应拥有公司用户模型的权限
class CompanyUser extends Pivot
{
use HasRoles;
protected $guard_name = 'web';
}
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();
}
private function companyWithPivot(Company $company)
{
return $this->teams()->where('companies.id', $company->id)->first();
}
public function assignRolesForCompany(Company $company, ...$roles)
{
if($company = $this->companyWithPivot($company)){
/** @var CompanyUser $companyUser */
$companyUser = $company->pivot;
$companyUser->assignRole($roles);
return;
}
throw new Exception('Roles could not be assigned to company user');
}
public function hasRoleForCurrentCompany(string $roles, Company $company = null, string $guard = null): bool
{
if(! $company){
if(! $company = $this->currentCompany){
throw new Exception('Cannot check role for current company because it has not been set');
}
}
if($company = $this->companyWithPivot($company)){
/** @var CompanyUser $companyUser */
$companyUser = $company->pivot;
return $companyUser->hasRole($roles, $guard);
}
return false;
}
public function can($ability, $arguments = []): bool
{
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;
}
// Still run through the gate as this will check for gate bypass
return app(Gate::class)->forUser($this)->check('N/A', []);
}
return app(Gate::class)->forUser($this)->check($ability, $arguments);
}
}
/** @var Role $ownerRoll */
$ownerRoll = Role::create(['name' => 'Owner']);
/** @var Permission $permission */
$permission = Permission::create([
'name' => 'Create Company',
'guard_name' => 'web',
]);
$ownerRoll->givePermissionTo($permission);
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();
}