create([ 'username' => 'finance_report_tester', 'name' => 'Tester', 'email' => null, 'password' => Hash::make('secret-strong'), 'status' => 0, ]); $role = AdminRole::query()->where('slug', 'finance')->firstOrFail(); $siteId = AdminUser::defaultAdminSiteId(); $admin->roles()->sync([ (int) $role->id => [ 'site_id' => $siteId, 'granted_at' => now(), ], ]); return $admin->createToken('test', ['*'], now()->addDay())->plainTextToken; } test('finance role with report legacy can access report jobs after rbac seed', function (): void { $this->seed(AdminRbacAndUserSeeder::class); $finance = AdminRole::query()->where('slug', 'finance')->firstOrFail(); expect($finance->legacyPermissionSlugs())->toContain('prd.report.view'); $hasReportAction = DB::table('admin_role_menu_actions as rma') ->join('admin_menu_actions as ma', 'ma.id', '=', 'rma.menu_action_id') ->where('rma.role_id', $finance->id) ->where('ma.permission_code', 'service.report.view') ->exists(); expect($hasReportAction)->toBeTrue(); $token = makeFinanceReportAdminToken(); $this->withHeader('Authorization', 'Bearer '.$token) ->getJson('/api/v1/admin/report-jobs') ->assertOk(); }); test('report api resources only bind service.report.view', function (): void { $this->seed(AdminRbacAndUserSeeder::class); $this->artisan('lottery:admin-auth-sync')->assertExitCode(0); $codes = [ 'admin.reports.daily-profit', 'admin.report-jobs.index', ]; foreach ($codes as $code) { $bindings = DB::table('admin_api_resources as ar') ->join('admin_api_resource_bindings as arb', 'arb.api_resource_id', '=', 'ar.id') ->join('admin_menu_actions as ma', 'ma.id', '=', 'arb.menu_action_id') ->where('ar.code', $code) ->pluck('ma.permission_code') ->all(); expect($bindings)->toBe(['service.report.view']); } });