diff --git a/WebFiori/Framework/AccessManager.php b/WebFiori/Framework/AccessManager.php index 5d23d515d..78d46d954 100644 --- a/WebFiori/Framework/AccessManager.php +++ b/WebFiori/Framework/AccessManager.php @@ -153,6 +153,10 @@ public function can($user, string $permission, ?object $resource = null): bool { $userId = is_object($user) && method_exists($user, 'getId') ? $user->getId() : $user; $roles = $this->getUserRoles($userId); + if (empty($roles) && is_object($user) && method_exists($user, 'getRoles')) { + $roles = $user->getRoles(); + } + $hasPermission = false; foreach ($roles as $roleName) { diff --git a/tests/WebFiori/Framework/Tests/AccessTest.php b/tests/WebFiori/Framework/Tests/AccessTest.php index 2c335cbd1..392bf3bad 100644 --- a/tests/WebFiori/Framework/Tests/AccessTest.php +++ b/tests/WebFiori/Framework/Tests/AccessTest.php @@ -648,4 +648,36 @@ public function testPermissionDbId() { $perm->setDescription('Updated'); $this->assertEquals('Updated', $perm->getDescription()); } + + /** @test */ + public function testCanFallsBackToUserGetRoles() { + $manager = new AccessManager(); + $manager->role('customer', ['VIEW_ORDERS']); + + $user = new class { + public function getId() { return 55; } + public function getRoles(): array { return ['customer']; } + }; + + // No assignRoleToUser() — should fallback to $user->getRoles() + $this->assertTrue($manager->can($user, 'VIEW_ORDERS')); + $this->assertFalse($manager->can($user, 'DELETE_ORDERS')); + } + + /** @test */ + public function testCanPrefersInternalMapOverGetRoles() { + $manager = new AccessManager(); + $manager->role('admin', ['MANAGE']); + $manager->role('viewer', ['VIEW']); + + $user = new class { + public function getId() { return 56; } + public function getRoles(): array { return ['viewer']; } + }; + + // Internal map assigned — getRoles() should NOT be used + $manager->assignRoleToUser(56, 'admin'); + $this->assertTrue($manager->can($user, 'MANAGE')); + $this->assertFalse($manager->can($user, 'VIEW')); + } }