feat: reserve administrative roles for staff email addresses
This commit is contained in:
@@ -33,11 +33,11 @@ class ApproveRoleControllerTest extends TestCase
|
||||
|
||||
$controller = new TestableApproveRoleController($entityManager, $this->createStub(LoggerInterface::class));
|
||||
|
||||
$response = $controller->index($user, Role::GROUPS_ADMIN, Request::create('/admin/user/1/approve/ROLE_GROUPS_ADMIN'));
|
||||
$response = $controller->index($user, Role::HOUSE_MANAGER, Request::create('/admin/user/1/approve/ROLE_HOUSE_MANAGER'));
|
||||
|
||||
self::assertSame(Response::HTTP_OK, $response->getStatusCode());
|
||||
self::assertSame('admin/user/modal_approve_role.html.twig', $controller->renderedView);
|
||||
self::assertSame([Role::TEAMER, Role::pending(Role::GROUPS_ADMIN)], Role::assignedOnly($user->getRoles()));
|
||||
self::assertSame([Role::TEAMER, Role::pending(Role::HOUSE_MANAGER)], Role::assignedOnly($user->getRoles()));
|
||||
}
|
||||
|
||||
public function testPostGrantsTheRoleAndRedirectsTheBrowser(): void
|
||||
@@ -49,9 +49,9 @@ class ApproveRoleControllerTest extends TestCase
|
||||
|
||||
$controller = new TestableApproveRoleController($entityManager, $this->createStub(LoggerInterface::class));
|
||||
|
||||
$response = $controller->index($user, Role::GROUPS_ADMIN, Request::create('/admin/user/1/approve/ROLE_GROUPS_ADMIN', 'POST'));
|
||||
$response = $controller->index($user, Role::HOUSE_MANAGER, Request::create('/admin/user/1/approve/ROLE_HOUSE_MANAGER', 'POST'));
|
||||
|
||||
self::assertSame([Role::TEAMER, Role::GROUPS_ADMIN], Role::assignedOnly($user->getRoles()));
|
||||
self::assertSame([Role::TEAMER, Role::HOUSE_MANAGER], Role::assignedOnly($user->getRoles()));
|
||||
self::assertTrue($response->headers->has('HX-Redirect'));
|
||||
self::assertSame(['success'], array_column($controller->flashes, 'type'));
|
||||
}
|
||||
@@ -94,9 +94,9 @@ class ApproveRoleControllerTest extends TestCase
|
||||
|
||||
// Only ROLE_ADMIN needs a second pair of eyes — an approver already holds it, so the
|
||||
// rest grant less than they could grant themselves anyway.
|
||||
$controller->index($user, Role::GROUPS_ADMIN, Request::create('/admin/user/1/approve/ROLE_GROUPS_ADMIN', 'POST'));
|
||||
$controller->index($user, Role::HOUSE_MANAGER, Request::create('/admin/user/1/approve/ROLE_HOUSE_MANAGER', 'POST'));
|
||||
|
||||
self::assertSame([Role::TEAMER, Role::GROUPS_ADMIN], Role::assignedOnly($user->getRoles()));
|
||||
self::assertSame([Role::TEAMER, Role::HOUSE_MANAGER], Role::assignedOnly($user->getRoles()));
|
||||
}
|
||||
|
||||
public function testPostWithAnInvalidTokenIsDenied(): void
|
||||
@@ -108,7 +108,7 @@ class ApproveRoleControllerTest extends TestCase
|
||||
|
||||
$this->expectException(AccessDeniedException::class);
|
||||
|
||||
$controller->index($this->nominatedUser(), Role::GROUPS_ADMIN, Request::create('/admin/user/1/approve/ROLE_GROUPS_ADMIN', 'POST'));
|
||||
$controller->index($this->nominatedUser(), Role::HOUSE_MANAGER, Request::create('/admin/user/1/approve/ROLE_HOUSE_MANAGER', 'POST'));
|
||||
}
|
||||
|
||||
public function testApprovingForYourselfReissuesTheSecurityToken(): void
|
||||
@@ -125,12 +125,12 @@ class ApproveRoleControllerTest extends TestCase
|
||||
tokenStorage: $tokenStorage,
|
||||
);
|
||||
|
||||
$controller->index($user, Role::GROUPS_ADMIN, Request::create('/admin/user/1/approve/ROLE_GROUPS_ADMIN', 'POST'));
|
||||
$controller->index($user, Role::HOUSE_MANAGER, Request::create('/admin/user/1/approve/ROLE_HOUSE_MANAGER', 'POST'));
|
||||
|
||||
// Without this the next request would find the stored roles out of step with the token
|
||||
// and end the session, logging the approver out mid-action.
|
||||
self::assertContains(Role::GROUPS_ADMIN, $tokenStorage->getToken()?->getRoleNames() ?? []);
|
||||
self::assertNotContains(Role::pending(Role::GROUPS_ADMIN), $tokenStorage->getToken()?->getRoleNames() ?? []);
|
||||
self::assertContains(Role::HOUSE_MANAGER, $tokenStorage->getToken()?->getRoleNames() ?? []);
|
||||
self::assertNotContains(Role::pending(Role::HOUSE_MANAGER), $tokenStorage->getToken()?->getRoleNames() ?? []);
|
||||
}
|
||||
|
||||
public function testApprovingForSomebodyElseLeavesYourOwnTokenAlone(): void
|
||||
@@ -148,14 +148,14 @@ class ApproveRoleControllerTest extends TestCase
|
||||
tokenStorage: $tokenStorage,
|
||||
);
|
||||
|
||||
$controller->index($other, Role::GROUPS_ADMIN, Request::create('/admin/user/1/approve/ROLE_GROUPS_ADMIN', 'POST'));
|
||||
$controller->index($other, Role::HOUSE_MANAGER, Request::create('/admin/user/1/approve/ROLE_HOUSE_MANAGER', 'POST'));
|
||||
|
||||
self::assertSame($originalToken, $tokenStorage->getToken());
|
||||
}
|
||||
|
||||
private function nominatedUser(): User
|
||||
{
|
||||
return (new User('[email protected]'))->setRoles([Role::TEAMER, Role::pending(Role::GROUPS_ADMIN)]);
|
||||
return (new User('[email protected]'))->setRoles([Role::TEAMER, Role::pending(Role::HOUSE_MANAGER)]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ class ShowControllerTest extends TestCase
|
||||
$controller->index($this->nominatedUser(), $this->permissionsRequest());
|
||||
|
||||
self::assertSame(
|
||||
[Role::MANAGER => 'Manager:in', Role::GROUPS_ADMIN => 'Preisrechner Admin'],
|
||||
[Role::HOUSE_MANAGER => 'Hausleitung', Role::GROUPS_ADMIN => 'Preisrechner Admin'],
|
||||
$controller->parameters['approvableRoles'],
|
||||
);
|
||||
self::assertSame([], $controller->parameters['selfRefusedRoles']);
|
||||
@@ -29,7 +29,7 @@ class ShowControllerTest extends TestCase
|
||||
|
||||
public function testWhatCannotBeSelfApprovedIsNotOffered(): void
|
||||
{
|
||||
$user = (new User('admin@example.org'))->setRoles([Role::ADMIN, Role::pending(Role::ADMIN), Role::pending(Role::MANAGER)]);
|
||||
$user = (new User('admin@ep-reisen.de'))->setRoles([Role::EMPLOYEE, Role::ADMIN, Role::pending(Role::ADMIN), Role::pending(Role::MANAGER)]);
|
||||
|
||||
$controller = new TestableShowController(currentUser: $user);
|
||||
|
||||
@@ -62,8 +62,8 @@ class ShowControllerTest extends TestCase
|
||||
|
||||
private function nominatedUser(): User
|
||||
{
|
||||
return (new User('teamer@example.org'))
|
||||
->setRoles([Role::TEAMER, Role::pending(Role::MANAGER), Role::pending(Role::GROUPS_ADMIN)]);
|
||||
return (new User('teamer@ep-reisen.de'))
|
||||
->setRoles([Role::TEAMER, Role::EMPLOYEE, Role::pending(Role::HOUSE_MANAGER), Role::pending(Role::GROUPS_ADMIN)]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,7 +19,7 @@ class PendingRoleApprovalsWidgetProviderTest extends TestCase
|
||||
$user = (new User('[email protected]'))
|
||||
->setFirstName('Rita')
|
||||
->setLastName('Vorschlag')
|
||||
->setRoles([Role::TEAMER, Role::pending(Role::GROUPS_ADMIN)])
|
||||
->setRoles([Role::TEAMER, Role::pending(Role::HOUSE_MANAGER)])
|
||||
;
|
||||
|
||||
$widget = $this->provider([$user])->build();
|
||||
@@ -27,7 +27,7 @@ class PendingRoleApprovalsWidgetProviderTest extends TestCase
|
||||
$this->assertNotNull($widget);
|
||||
$this->assertCount(1, $widget->entries);
|
||||
$this->assertStringContainsString('Rita Vorschlag', $widget->entries[0]->label);
|
||||
$this->assertStringContainsString(Role::labels()[Role::GROUPS_ADMIN], $widget->entries[0]->label);
|
||||
$this->assertStringContainsString(Role::labels()[Role::HOUSE_MANAGER], $widget->entries[0]->label);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -43,7 +43,7 @@ class BpnAuthenticatorTest extends TestCase
|
||||
{
|
||||
$persisted = null;
|
||||
$authenticator = $this->authenticator(
|
||||
$this->crmAttributes([Role::ADMIN, Role::TEAMER], ['SSL', 'SSL']),
|
||||
$this->crmAttributes([Role::HOUSE_MANAGER, Role::TEAMER], ['SSL', 'SSL']),
|
||||
null,
|
||||
$persisted,
|
||||
);
|
||||
@@ -51,7 +51,7 @@ class BpnAuthenticatorTest extends TestCase
|
||||
$user = $this->loadUser($authenticator);
|
||||
|
||||
self::assertSame($persisted, $user);
|
||||
self::assertSame(['ROLE_USER', Role::TEAMER, Role::pending(Role::ADMIN)], $user->getRoles());
|
||||
self::assertSame(['ROLE_USER', Role::TEAMER, Role::pending(Role::HOUSE_MANAGER)], $user->getRoles());
|
||||
self::assertSame(['SSL'], $user->getHotelCodes());
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ class BpnAuthenticatorTest extends TestCase
|
||||
|
||||
$persisted = null;
|
||||
$authenticator = $this->authenticator(
|
||||
$this->crmAttributes([Role::TEAMER, Role::GROUPS_ADMIN], []),
|
||||
$this->crmAttributes([Role::TEAMER, Role::HOUSE_MANAGER], []),
|
||||
$existing,
|
||||
$persisted,
|
||||
);
|
||||
@@ -70,7 +70,7 @@ class BpnAuthenticatorTest extends TestCase
|
||||
|
||||
self::assertSame($existing, $persisted, 'a login must not create a second account');
|
||||
self::assertSame(
|
||||
['ROLE_USER', Role::TEAMER, Role::pending(Role::GROUPS_ADMIN)],
|
||||
['ROLE_USER', Role::TEAMER, Role::pending(Role::HOUSE_MANAGER)],
|
||||
$user->getRoles(),
|
||||
);
|
||||
self::assertNotNull($user->getLastLoginAt(), 'the rest of the profile is still synced');
|
||||
@@ -78,24 +78,24 @@ class BpnAuthenticatorTest extends TestCase
|
||||
|
||||
public function testApprovedRoleSurvivesTheNextLogin(): void
|
||||
{
|
||||
$existing = (new User('[email protected]'))->setRoles([Role::TEAMER, Role::GROUPS_MANAGER]);
|
||||
$existing = (new User('[email protected]'))->setRoles([Role::TEAMER, Role::HOUSE_MANAGER]);
|
||||
|
||||
$persisted = null;
|
||||
$authenticator = $this->authenticator(
|
||||
$this->crmAttributes([Role::TEAMER, Role::GROUPS_MANAGER], []),
|
||||
$this->crmAttributes([Role::TEAMER, Role::HOUSE_MANAGER], []),
|
||||
$existing,
|
||||
$persisted,
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
['ROLE_USER', Role::TEAMER, Role::GROUPS_MANAGER],
|
||||
['ROLE_USER', Role::TEAMER, Role::HOUSE_MANAGER],
|
||||
$this->loadUser($authenticator)->getRoles(),
|
||||
);
|
||||
}
|
||||
|
||||
public function testRoleRevokedInBusProIsWithdrawnOnLogin(): void
|
||||
{
|
||||
$existing = (new User('[email protected]'))->setRoles([Role::TEAMER, Role::GROUPS_MANAGER]);
|
||||
$existing = (new User('[email protected]'))->setRoles([Role::TEAMER, Role::HOUSE_MANAGER]);
|
||||
|
||||
$persisted = null;
|
||||
$authenticator = $this->authenticator($this->crmAttributes([], []), $existing, $persisted);
|
||||
@@ -140,7 +140,7 @@ class BpnAuthenticatorTest extends TestCase
|
||||
public function testDegradedCrmResponseLeavesAnExistingAccountUntouched(): void
|
||||
{
|
||||
$existing = (new User('[email protected]'))
|
||||
->setRoles([Role::TEAMER, Role::GROUPS_MANAGER])
|
||||
->setRoles([Role::TEAMER, Role::HOUSE_MANAGER])
|
||||
->setHotelCodes(['DKS'])
|
||||
;
|
||||
|
||||
@@ -155,7 +155,7 @@ class BpnAuthenticatorTest extends TestCase
|
||||
|
||||
$user = $this->loadUser($authenticator);
|
||||
|
||||
self::assertSame(['ROLE_USER', Role::TEAMER, Role::GROUPS_MANAGER], $user->getRoles());
|
||||
self::assertSame(['ROLE_USER', Role::TEAMER, Role::HOUSE_MANAGER], $user->getRoles());
|
||||
self::assertSame(['DKS'], $user->getHotelCodes());
|
||||
}
|
||||
|
||||
@@ -240,12 +240,40 @@ class BpnAuthenticatorTest extends TestCase
|
||||
self::assertSame(['ROLE_USER', Role::CUSTOMER], $user->getRoles());
|
||||
}
|
||||
|
||||
public function testEmployeeOnlyClaimFromAnotherDomainIsIgnored(): void
|
||||
{
|
||||
$persisted = null;
|
||||
$authenticator = $this->authenticator($this->crmAttributes([Role::ADMIN, Role::TEAMER], []), null, $persisted);
|
||||
|
||||
$user = $this->loadUser($authenticator, '[email protected]');
|
||||
|
||||
// Not even a nomination, so there is nothing for an administrator to be told about.
|
||||
self::assertSame(['ROLE_USER', Role::TEAMER], $user->getRoles());
|
||||
self::assertSame([], $this->dispatched);
|
||||
}
|
||||
|
||||
public function testEmployeeOnlyRoleIsRevokedWhenTheAddressIsNotStaff(): void
|
||||
{
|
||||
$existing = (new User('[email protected]'))->setRoles([Role::TEAMER, Role::ADMIN, Role::HOUSE_MANAGER]);
|
||||
$persisted = null;
|
||||
$authenticator = $this->authenticator(
|
||||
$this->crmAttributes([Role::TEAMER, Role::ADMIN, Role::HOUSE_MANAGER], []),
|
||||
$existing,
|
||||
$persisted,
|
||||
);
|
||||
|
||||
$user = $this->loadUser($authenticator, '[email protected]');
|
||||
|
||||
// Only the EMPLOYEE_ONLY role goes; a Hausleitung does not need a staff address.
|
||||
self::assertSame(['ROLE_USER', Role::TEAMER, Role::HOUSE_MANAGER], $user->getRoles());
|
||||
}
|
||||
|
||||
public function testANewNominationIsAnnouncedOnce(): void
|
||||
{
|
||||
$persisted = null;
|
||||
$authenticator = $this->authenticator($this->crmAttributes([Role::ADMIN], []), null, $persisted);
|
||||
|
||||
$user = $this->loadUser($authenticator);
|
||||
$user = $this->loadUser($authenticator, '[email protected]');
|
||||
|
||||
self::assertCount(1, $this->dispatched);
|
||||
$message = $this->dispatched[0];
|
||||
@@ -257,11 +285,11 @@ class BpnAuthenticatorTest extends TestCase
|
||||
|
||||
public function testAStandingNominationIsNotAnnouncedAgain(): void
|
||||
{
|
||||
$existing = (new User('[email protected]'))->setRoles([Role::pending(Role::ADMIN)]);
|
||||
$existing = (new User('[email protected]'))->setRoles([Role::EMPLOYEE, Role::pending(Role::ADMIN)]);
|
||||
$persisted = null;
|
||||
$authenticator = $this->authenticator($this->crmAttributes([Role::ADMIN], []), $existing, $persisted);
|
||||
|
||||
$this->loadUser($authenticator);
|
||||
$this->loadUser($authenticator, '[email protected]');
|
||||
|
||||
// The nomination has not changed, so there is nothing new to tell an administrator about.
|
||||
self::assertSame([], $this->dispatched);
|
||||
@@ -269,11 +297,11 @@ class BpnAuthenticatorTest extends TestCase
|
||||
|
||||
public function testAnApprovedRoleIsNotAnnouncedAsANomination(): void
|
||||
{
|
||||
$existing = (new User('[email protected]'))->setRoles([Role::ADMIN]);
|
||||
$existing = (new User('[email protected]'))->setRoles([Role::EMPLOYEE, Role::ADMIN]);
|
||||
$persisted = null;
|
||||
$authenticator = $this->authenticator($this->crmAttributes([Role::ADMIN], []), $existing, $persisted);
|
||||
|
||||
$this->loadUser($authenticator);
|
||||
$this->loadUser($authenticator, '[email protected]');
|
||||
|
||||
self::assertSame([], $this->dispatched);
|
||||
}
|
||||
|
||||
+76
-20
@@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace App\Tests\Security;
|
||||
|
||||
use App\Security\Role;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
@@ -15,46 +16,46 @@ class RoleTest extends TestCase
|
||||
{
|
||||
public function testAdministrativeClaimOnlyProducesANomination(): void
|
||||
{
|
||||
$roles = Role::sync([], [Role::ADMIN, Role::GROUPS_ADMIN, Role::TEAMER]);
|
||||
$roles = Role::sync([], [Role::HOUSE_MANAGER, Role::GROUPS_ADMIN, Role::TEAMER, Role::EMPLOYEE]);
|
||||
|
||||
self::assertSame(
|
||||
[Role::TEAMER, Role::pending(Role::ADMIN), Role::pending(Role::GROUPS_ADMIN)],
|
||||
[Role::TEAMER, Role::EMPLOYEE, Role::pending(Role::HOUSE_MANAGER), Role::pending(Role::GROUPS_ADMIN)],
|
||||
$roles,
|
||||
);
|
||||
self::assertSame([Role::TEAMER], Role::effectiveOnly($roles));
|
||||
self::assertSame([Role::TEAMER, Role::EMPLOYEE], Role::effectiveOnly($roles));
|
||||
}
|
||||
|
||||
public function testCustomerExpertClaimOnlyProducesANomination(): void
|
||||
{
|
||||
$roles = Role::sync([], [Role::CUSTOMER_EXPERT]);
|
||||
$roles = Role::sync([], [Role::EMPLOYEE, Role::CUSTOMER_EXPERT]);
|
||||
|
||||
self::assertSame([Role::pending(Role::CUSTOMER_EXPERT), Role::CUSTOMER], $roles);
|
||||
self::assertSame([Role::CUSTOMER], Role::effectiveOnly($roles));
|
||||
self::assertSame([Role::EMPLOYEE, Role::pending(Role::CUSTOMER_EXPERT)], $roles);
|
||||
self::assertSame([Role::EMPLOYEE], Role::effectiveOnly($roles));
|
||||
self::assertSame(
|
||||
[Role::CUSTOMER_EXPERT => 'KO-Experte'],
|
||||
[Role::CUSTOMER_EXPERT => 'KO-Expert:in'],
|
||||
Role::nominatedFrom($roles),
|
||||
);
|
||||
}
|
||||
|
||||
public function testApprovedCustomerExpertDisplacesTheCustomerFallback(): void
|
||||
public function testCustomerExpertCanBeApprovedForStaff(): void
|
||||
{
|
||||
$roles = Role::approve([Role::pending(Role::CUSTOMER_EXPERT), Role::CUSTOMER], Role::CUSTOMER_EXPERT);
|
||||
$roles = Role::approve([Role::EMPLOYEE, Role::pending(Role::CUSTOMER_EXPERT)], Role::CUSTOMER_EXPERT);
|
||||
|
||||
self::assertSame([Role::CUSTOMER_EXPERT], $roles);
|
||||
self::assertSame([Role::EMPLOYEE, Role::CUSTOMER_EXPERT], $roles);
|
||||
}
|
||||
|
||||
public function testApprovedRoleSurvivesTheNextSyncAndIsNotMarkedAgain(): void
|
||||
{
|
||||
$roles = Role::sync([Role::TEAMER, Role::GROUPS_ADMIN], [Role::GROUPS_ADMIN, Role::TEAMER]);
|
||||
$roles = Role::sync([Role::TEAMER, Role::HOUSE_MANAGER], [Role::HOUSE_MANAGER, Role::TEAMER]);
|
||||
|
||||
self::assertSame([Role::TEAMER, Role::GROUPS_ADMIN], $roles);
|
||||
self::assertSame([Role::TEAMER, Role::HOUSE_MANAGER], $roles);
|
||||
}
|
||||
|
||||
public function testRoleTheCrmNoLongerClaimsIsRevoked(): void
|
||||
{
|
||||
// Both halves go: BusPro is the source of truth for the granted role as much as for
|
||||
// the nomination.
|
||||
$roles = Role::sync([Role::TEAMER, Role::ADMIN, Role::pending(Role::MANAGER)], [Role::TEAMER]);
|
||||
$roles = Role::sync([Role::TEAMER, Role::GROUPS_ADMIN, Role::pending(Role::HOUSE_MANAGER)], [Role::TEAMER]);
|
||||
|
||||
self::assertSame([Role::TEAMER], $roles);
|
||||
}
|
||||
@@ -69,8 +70,8 @@ class RoleTest extends TestCase
|
||||
// The nomination stays visible — it is what an approver acts on — but grants nothing,
|
||||
// so the account is a customer in the meantime.
|
||||
self::assertSame(
|
||||
[Role::pending(Role::ADMIN), Role::CUSTOMER],
|
||||
Role::sync([], [Role::ADMIN]),
|
||||
[Role::pending(Role::HOUSE_MANAGER), Role::CUSTOMER],
|
||||
Role::sync([], [Role::HOUSE_MANAGER]),
|
||||
);
|
||||
self::assertSame([Role::CUSTOMER], Role::sync([], []));
|
||||
}
|
||||
@@ -90,10 +91,10 @@ class RoleTest extends TestCase
|
||||
|
||||
public function testApprovalTurnsTheNominationIntoTheRole(): void
|
||||
{
|
||||
$roles = Role::approve([Role::pending(Role::ADMIN), Role::CUSTOMER], Role::ADMIN);
|
||||
$roles = Role::approve([Role::pending(Role::HOUSE_MANAGER), Role::CUSTOMER], Role::HOUSE_MANAGER);
|
||||
|
||||
// The customer fallback goes with it: the account now holds an effective role.
|
||||
self::assertSame([Role::ADMIN], $roles);
|
||||
self::assertSame([Role::HOUSE_MANAGER], $roles);
|
||||
}
|
||||
|
||||
public function testApprovingARoleWithoutANominationIsRefused(): void
|
||||
@@ -105,11 +106,11 @@ class RoleTest extends TestCase
|
||||
|
||||
public function testEffectiveRolesExcludeNominationsAndTheImplicitRoleUser(): void
|
||||
{
|
||||
$roles = [Role::USER, Role::TEAMER, Role::pending(Role::ADMIN)];
|
||||
$roles = [Role::USER, Role::TEAMER, Role::pending(Role::HOUSE_MANAGER)];
|
||||
|
||||
self::assertSame([Role::TEAMER], Role::effectiveOnly($roles));
|
||||
self::assertSame([Role::pending(Role::ADMIN)], Role::pendingOnly($roles));
|
||||
self::assertSame([Role::ADMIN => 'Administration'], Role::nominatedFrom($roles));
|
||||
self::assertSame([Role::pending(Role::HOUSE_MANAGER)], Role::pendingOnly($roles));
|
||||
self::assertSame([Role::HOUSE_MANAGER => 'Hausleitung'], Role::nominatedFrom($roles));
|
||||
}
|
||||
|
||||
public function testEmployeeIsGrantedOutrightAndDisplacesTheCustomerFallback(): void
|
||||
@@ -133,6 +134,61 @@ class RoleTest extends TestCase
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return iterable<string, array{string}>
|
||||
*/
|
||||
public static function employeeOnlyRoles(): iterable
|
||||
{
|
||||
foreach (Role::EMPLOYEE_ONLY as $role) {
|
||||
yield $role => [$role];
|
||||
}
|
||||
}
|
||||
|
||||
#[DataProvider('employeeOnlyRoles')]
|
||||
public function testEmployeeOnlyClaimWithoutEmployeeIsNotNominated(string $role): void
|
||||
{
|
||||
self::assertSame([Role::TEAMER], Role::sync([], [Role::TEAMER, $role]));
|
||||
}
|
||||
|
||||
#[DataProvider('employeeOnlyRoles')]
|
||||
public function testEmployeeOnlyRoleIsRevokedWithoutEmployee(string $role): void
|
||||
{
|
||||
// The CRM still claims it, but the account is no longer staff: the claim counts as not
|
||||
// made, and a role approved back when it was staff goes with it.
|
||||
self::assertSame(
|
||||
[Role::TEAMER],
|
||||
Role::sync([Role::TEAMER, Role::EMPLOYEE, $role], [Role::TEAMER, $role]),
|
||||
);
|
||||
}
|
||||
|
||||
#[DataProvider('employeeOnlyRoles')]
|
||||
public function testEmployeeOnlyRoleSurvivesTheNextSyncForStaff(string $role): void
|
||||
{
|
||||
self::assertSame(
|
||||
[Role::EMPLOYEE, $role],
|
||||
Role::sync([Role::EMPLOYEE, $role], [Role::EMPLOYEE, $role]),
|
||||
);
|
||||
}
|
||||
|
||||
public function testHouseManagerDoesNotNeedEmployee(): void
|
||||
{
|
||||
// A Hausleitung signs in with the hotel's own address.
|
||||
self::assertSame([Role::pending(Role::HOUSE_MANAGER), Role::CUSTOMER], Role::sync([], [Role::HOUSE_MANAGER]));
|
||||
self::assertSame([Role::HOUSE_MANAGER], Role::sync([Role::HOUSE_MANAGER], [Role::HOUSE_MANAGER]));
|
||||
}
|
||||
|
||||
public function testStaleEmployeeOnlyNominationWithoutEmployeeCannotBeApproved(): void
|
||||
{
|
||||
// A marker from before the rule, still stored until the account's next login.
|
||||
$roles = [Role::TEAMER, Role::pending(Role::ADMIN)];
|
||||
|
||||
self::assertSame([], Role::nominatedFrom($roles));
|
||||
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
|
||||
Role::approve($roles, Role::ADMIN);
|
||||
}
|
||||
|
||||
public function testEmployeeAndTeamerCoexist(): void
|
||||
{
|
||||
self::assertSame(
|
||||
|
||||
@@ -26,10 +26,10 @@ class AppRuntimeRoleLabelsTest extends TestCase
|
||||
|
||||
public function testNominationsAreListedApartFromTheEffectiveRoles(): void
|
||||
{
|
||||
$roles = [Role::TEAMER, Role::pending(Role::ADMIN)];
|
||||
$roles = [Role::TEAMER, Role::pending(Role::HOUSE_MANAGER)];
|
||||
|
||||
self::assertSame(['Teamer:in'], $this->runtime()->effectiveRoles($roles));
|
||||
self::assertSame(['Administration'], $this->runtime()->nominatedRoles($roles));
|
||||
self::assertSame(['Hausleitung'], $this->runtime()->nominatedRoles($roles));
|
||||
}
|
||||
|
||||
public function testUnknownRoleStaysVisible(): void
|
||||
|
||||
Reference in New Issue
Block a user