feat: 增强管理员权限管理,添加 RBAC 支持,更新 AdminUser 模型以处理角色和权限,更新登录接口返回权限信息,扩展数据库填充器以同步角色权限

This commit is contained in:
2026-05-11 16:21:13 +08:00
parent 19003f5041
commit fc023242ce
39 changed files with 1587 additions and 123 deletions

View File

@@ -0,0 +1,27 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class AdminPermission extends Model
{
protected $table = 'admin_permissions';
protected $fillable = [
'slug',
'name',
];
/** @return BelongsToMany<AdminRole, AdminPermission> */
public function roles(): BelongsToMany
{
return $this->belongsToMany(
AdminRole::class,
'admin_role_permissions',
'permission_id',
'role_id',
);
}
}

38
app/Models/AdminRole.php Normal file
View File

@@ -0,0 +1,38 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class AdminRole extends Model
{
protected $table = 'admin_roles';
protected $fillable = [
'slug',
'name',
];
/** @return BelongsToMany<AdminPermission, AdminRole> */
public function permissions(): BelongsToMany
{
return $this->belongsToMany(
AdminPermission::class,
'admin_role_permissions',
'role_id',
'permission_id',
);
}
/** @return BelongsToMany<AdminUser, AdminRole> */
public function users(): BelongsToMany
{
return $this->belongsToMany(
AdminUser::class,
'admin_user_roles',
'role_id',
'admin_user_id',
);
}
}

View File

@@ -2,6 +2,7 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
@@ -11,6 +12,8 @@ class AdminUser extends Authenticatable
use HasApiTokens;
use Notifiable;
public const ROLE_SUPER_ADMIN = 'super_admin';
protected $table = 'admin_users';
protected $fillable = [
@@ -34,4 +37,54 @@ class AdminUser extends Authenticatable
'password' => 'hashed',
];
}
/** @return BelongsToMany<AdminRole, AdminUser> */
public function roles(): BelongsToMany
{
return $this->belongsToMany(
AdminRole::class,
'admin_user_roles',
'admin_user_id',
'role_id',
);
}
/** 是否具备指定权限(含 `super_admin` 角色全放行)。 */
public function hasAdminPermission(string $slug): bool
{
$this->loadMissing(['roles.permissions']);
foreach ($this->roles as $role) {
if ($role->slug === self::ROLE_SUPER_ADMIN) {
return true;
}
foreach ($role->permissions as $permission) {
if ($permission->slug === $slug) {
return true;
}
}
}
return false;
}
/**
* @return list<string>
*/
public function adminPermissionSlugs(): array
{
$this->loadMissing(['roles.permissions']);
if ($this->roles->contains('slug', self::ROLE_SUPER_ADMIN)) {
return AdminPermission::query()->orderBy('slug')->pluck('slug')->all();
}
$out = [];
foreach ($this->roles as $role) {
foreach ($role->permissions as $permission) {
$out[$permission->slug] = true;
}
}
return array_keys($out);
}
}

View File

@@ -0,0 +1,34 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class ReconcileItem extends Model
{
protected $table = 'reconcile_items';
protected $fillable = [
'reconcile_job_id',
'side_a_ref',
'side_b_ref',
'difference_amount',
'status',
'resolved_at',
];
protected function casts(): array
{
return [
'difference_amount' => 'integer',
'resolved_at' => 'datetime',
];
}
/** @return BelongsTo<ReconcileJob, ReconcileItem> */
public function reconcileJob(): BelongsTo
{
return $this->belongsTo(ReconcileJob::class, 'reconcile_job_id');
}
}

View File

@@ -0,0 +1,45 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
class ReconcileJob extends Model
{
protected $table = 'reconcile_jobs';
protected $fillable = [
'job_no',
'admin_user_id',
'reconcile_type',
'status',
'period_start',
'period_end',
'summary_json',
'finished_at',
];
protected function casts(): array
{
return [
'period_start' => 'datetime',
'period_end' => 'datetime',
'summary_json' => 'array',
'finished_at' => 'datetime',
];
}
/** @return BelongsTo<AdminUser, ReconcileJob> */
public function adminUser(): BelongsTo
{
return $this->belongsTo(AdminUser::class, 'admin_user_id');
}
/** @return HasMany<ReconcileItem, ReconcileJob> */
public function items(): HasMany
{
return $this->hasMany(ReconcileItem::class, 'reconcile_job_id');
}
}

37
app/Models/ReportJob.php Normal file
View File

@@ -0,0 +1,37 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class ReportJob extends Model
{
protected $table = 'report_jobs';
protected $fillable = [
'job_no',
'admin_user_id',
'report_type',
'export_format',
'filter_json',
'status',
'output_path',
'error_message',
'finished_at',
];
protected function casts(): array
{
return [
'filter_json' => 'array',
'finished_at' => 'datetime',
];
}
/** @return BelongsTo<AdminUser, ReportJob> */
public function adminUser(): BelongsTo
{
return $this->belongsTo(AdminUser::class, 'admin_user_id');
}
}