1. 主帳號不變量:storeAccount 的 is_admin 改補位(每家公司恰一主帳號)、destroyAccount 禁刪最後主帳號、roles 新增 is_company_admin 旗標保護公司管理員角色不被刪除 2. 帳號樹狀層級:users 新增 parent_id/level(主帳號 level 0、子帳號最多兩層),新增 visibleTo/canManageAccount,帳號清單與管理端點(accounts/update/destroy/toggle、機台授權選帳號、補貨指派)一律套層級可見範圍與越權防護 3. 角色指派子集:storeAccount/updateAccount 指派角色與帳號 Modal 下拉一律限制為「權限為操作者子集」,杜絕權限提升 4. 機台授權子集:MachinePermissionController 僅允許在操作者本身可授權機台範圍內增刪,保留範圍外既有授權,並修正 machine_access 全域 scope 對讀寫的干擾 5. 角色層級隔離:roles 新增 created_by,子帳號只看/只管/只能指派自己建立的角色(主帳號看全公司),edit/update/destroy 加 canBeManagedBy 守衛 6. 補強:MachineSetting 機台權限人員清單補租戶隔離、修正角色下拉 N+1、三語系新增提示字串 7. 測試:新增 AccountHierarchyTest/AccountSubsetGuardTest/RoleHierarchyTest,Admin 套件 55 測試 0 回歸 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
89 lines
2.2 KiB
PHP
89 lines
2.2 KiB
PHP
<?php
|
||
|
||
namespace App\Models\System;
|
||
|
||
use Spatie\Permission\Models\Role as SpatieRole;
|
||
|
||
class Role extends SpatieRole
|
||
{
|
||
protected $fillable = [
|
||
'name',
|
||
'guard_name',
|
||
'company_id',
|
||
'created_by',
|
||
'is_system',
|
||
'is_company_admin',
|
||
];
|
||
|
||
protected $casts = [
|
||
'is_system' => 'boolean',
|
||
'is_company_admin' => 'boolean',
|
||
];
|
||
|
||
/**
|
||
* Get the company that owns the role.
|
||
*/
|
||
public function company()
|
||
{
|
||
return $this->belongsTo(Company::class);
|
||
}
|
||
|
||
/**
|
||
* 建立者帳號。
|
||
*/
|
||
public function creator()
|
||
{
|
||
return $this->belongsTo(User::class, 'created_by');
|
||
}
|
||
|
||
/**
|
||
* Scope a query to only include roles for a specific company or system roles.
|
||
*/
|
||
public function scopeForCompany($query, $company_id)
|
||
{
|
||
return $query->where(function($q) use ($company_id) {
|
||
$q->where('company_id', $company_id)
|
||
->orWhereNull('company_id');
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 查詢範圍:限制為指定使用者「可見」的角色(鏡像 User::scopeVisibleTo)。
|
||
* - 系統管理員:全部
|
||
* - 主帳號:同公司全部
|
||
* - 子帳號:僅自己建立的角色
|
||
*/
|
||
public function scopeVisibleTo($query, User $viewer)
|
||
{
|
||
if ($viewer->isSystemAdmin()) {
|
||
return $query;
|
||
}
|
||
$query->where($this->getTable() . '.company_id', $viewer->company_id);
|
||
if (!$viewer->is_admin) {
|
||
$query->where($this->getTable() . '.created_by', $viewer->id);
|
||
}
|
||
return $query;
|
||
}
|
||
|
||
/**
|
||
* 操作者是否有權管理(編輯/刪除)此角色。
|
||
* - 系統管理員:全部
|
||
* - 跨公司:禁止
|
||
* - 主帳號:同公司全部
|
||
* - 子帳號:僅自己建立的角色
|
||
*/
|
||
public function canBeManagedBy(User $user): bool
|
||
{
|
||
if ($user->isSystemAdmin()) {
|
||
return true;
|
||
}
|
||
if ($this->company_id !== $user->company_id) {
|
||
return false;
|
||
}
|
||
if ($user->is_admin) {
|
||
return true;
|
||
}
|
||
return $this->created_by === $user->id;
|
||
}
|
||
}
|