Files
hqland-app/app/Models/User.php

114 lines
3.2 KiB
PHP

<?php
namespace App\Models;
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Database\Factories\UserFactory;
use Illuminate\Database\Eloquent\Attributes\Fillable;
use Illuminate\Database\Eloquent\Attributes\Hidden;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Filament\Models\Contracts\FilamentUser;
use Filament\Panel;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
#[Fillable(['name', 'email', 'password'])]
#[Hidden(['password', 'remember_token'])]
class User extends Authenticatable implements FilamentUser
{
/** @use HasFactory<UserFactory> */
use HasFactory, Notifiable;
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'email_verified_at' => 'datetime',
'password' => 'hashed',
'extra_permissions' => 'array',
'excluded_permissions' => 'array',
];
}
public function roleTemplate()
{
return $this->belongsTo(RoleTemplate::class);
}
/**
* Tính toán effective permissions từ role template + extra - excluded.
* Cache trong session (1 lần/login).
*/
public function getEffectivePermissions(): array
{
$cacheKey = "user.{$this->id}.permissions";
if (session()->has($cacheKey)) {
return session()->get($cacheKey);
}
$permissions = $this->calculateEffectivePermissions();
session()->put($cacheKey, $permissions);
return $permissions;
}
public function hasEffectivePermission(string $permission): bool
{
return in_array($permission, $this->getEffectivePermissions());
}
public function clearPermissionCache(): void
{
session()->forget("user.{$this->id}.permissions");
}
protected function calculateEffectivePermissions(): array
{
$templatePerms = [];
if ($this->roleTemplate) {
$templatePerms = $this->roleTemplate->permissions ?? [];
}
// Flatten template permissions từ {"contracts":["view","create"]} thành ["contracts.view","contracts.create"]
$templateFlat = [];
foreach ($templatePerms as $module => $actions) {
foreach ($actions as $action) {
$templateFlat[] = "{$module}.{$action}";
}
}
$extra = $this->extra_permissions ?? [];
$excluded = $this->excluded_permissions ?? [];
return array_values(array_diff(
array_unique(array_merge($templateFlat, $extra)),
$excluded
));
}
/**
* Override can() để tích hợp với Laravel Authorization.
* Nếu ability là dạng "contracts.view" → dùng effective permissions.
* Ngược lại fallback về parent.
*/
public function can($abilities, $arguments = []): bool
{
if (is_string($abilities) && str_contains($abilities, '.')) {
return $this->hasEffectivePermission($abilities);
}
return parent::can($abilities, $arguments);
}
public function canAccessPanel(Panel $panel): bool
{
return true;
}
}