Multi-tenant với Team Feature
Cách hoạt động
Spatie team feature cho phép phân quyền theo từng công ty (company). Mỗi role/permission được gắn với một company_id.
Khi bật 'teams' => true trong config, Spatie tự động:
- Thêm cột
company_idvào bảngroles,permissions, và các bảng pivot - Unique constraint:
(company_id, name, guard_name)cho roles và permissions - Tự động scope permissions theo team context
Cấu hình
// config/permission.php
'teams' => true,
'column_names' => [
'team_foreign_key' => 'company_id',
],
Sử dụng
Gán role trong ngữ cảnh company
// Gán role không có team (global)
$employee->assignRole('admin');
// Gán role trong company cụ thể
$employee->assignRole('manager', company_id: 1);
Kiểm tra permission (tự động scope theo team)
// Kiểm tra trong company hiện tại của employee
$employee->hasPermissionTo('department.create');
// Kiểm tra trong company cụ thể
$employee->hasPermissionTo('department.create', company_id: 1);
Set team context
use Spatie\Permission\PermissionRegistrar;
// Set company context
app(PermissionRegistrar::class)->setPermissionsTeamId($companyId);
// Kiểm tra permission sẽ tự động dùng company context này
$employee->hasPermissionTo('department.create');
// Reset về null (global)
app(PermissionRegistrar::class)->setPermissionsTeamId(null);
Company scope check trong Controller
Ngoài Spatie permission check, controller cũng kiểm tra company scope để đảm bảo employee chỉ truy cập dữ liệu của công ty mình:
$user = employee_account();
$companyId = $user->getCompanyAttribute()?->id;
// Kiểm tra department có thuộc company của employee không
if ($department->company_id != $companyId) {
return $this->error('Forbidden', 403);
}
Lưu ý
- Team feature hoạt động ở cấp độ permission checking, không tự động scope Eloquent queries
- Cần chủ động thêm
where('company_id', $companyId)trong repository/service khi query dữ liệu - Xem
DepartmentControllerđể tham khảo cách kiểm tra company scope