star-cloud/app/Models/System/Role.php
sky121113 201663741d [FEAT] 帳號與角色多層級隔離(主/子帳號樹狀 + 角色權限/機台授權子集把關)
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>
2026-06-25 17:03:43 +08:00

89 lines
2.2 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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;
}
}