feat: pending roles from crm to be confirmed by superadmins

This commit is contained in:
Björn Fromme
2026-08-10 12:26:21 +02:00
parent 681734533f
commit b01c2e84c7
26 changed files with 907 additions and 150 deletions
+128 -4
View File
@@ -6,6 +6,7 @@ namespace App\Tests\BusProNet;
use App\BusProNet\Model\Address as BusProAddress;
use App\BusProNet\Model\Communication as BusProCommunication;
use App\BusProNet\Model\CrmAttributesResponse;
use App\BusProNet\Model\ProfileResponse;
use App\BusProNet\UserDataHandler;
use App\Entity\Embeddable\Address;
@@ -29,6 +30,59 @@ class UserDataHandlerTest extends TestCase
$this->logger = $this->createMock(LoggerInterface::class);
}
/**
* @dataProvider collectRolesProvider
*/
public function testCollectRolesImportsAdministrativeRolesAsPendingOnly(CrmAttributesResponse $crmAttributes, array $expectedRoles): void
{
$handler = new UserDataHandler($this->entityManager, $this->logger);
$this->assertSame($expectedRoles, $handler->collectRoles($crmAttributes));
}
public static function collectRolesProvider(): iterable
{
yield 'admin only yields the pending marker' => [
(new CrmAttributesResponse())->setAdmin(true),
[User::PENDING_ROLES['ROLE_ADMIN']],
];
yield 'manager only yields the pending marker' => [
(new CrmAttributesResponse())->setManager(true),
[User::PENDING_ROLES['ROLE_MANAGER']],
];
yield 'house manager only yields the pending marker' => [
(new CrmAttributesResponse())->setHouseManager(true),
[User::PENDING_ROLES['ROLE_HOUSE_MANAGER']],
];
yield 'teamer is granted directly' => [
(new CrmAttributesResponse())->setTeamer(true),
['ROLE_TEAMER'],
];
yield 'admin and teamer' => [
(new CrmAttributesResponse())->setAdmin(true)->setTeamer(true),
[User::PENDING_ROLES['ROLE_ADMIN'], 'ROLE_TEAMER'],
];
yield 'admin and manager yield both markers' => [
(new CrmAttributesResponse())->setAdmin(true)->setManager(true),
[User::PENDING_ROLES['ROLE_ADMIN'], User::PENDING_ROLES['ROLE_MANAGER']],
];
yield 'manager takes precedence over house manager' => [
(new CrmAttributesResponse())->setManager(true)->setHouseManager(true),
[User::PENDING_ROLES['ROLE_MANAGER']],
];
yield 'house manager and teamer' => [
(new CrmAttributesResponse())->setHouseManager(true)->setTeamer(true),
[User::PENDING_ROLES['ROLE_HOUSE_MANAGER'], 'ROLE_TEAMER'],
];
}
public function testUpdateLocalUserSyncsUserAndTeamerDataFromBusPro(): void
{
$user = (new User())
@@ -37,6 +91,8 @@ class UserDataHandlerTest extends TestCase
->setEmail('[email protected]')
->setBusProAddressId(1)
->setBusProPersonId(2)
->setRoles(['ROLE_ADMIN'])
->setHotelCodes(['XYZ'])
;
$teamer = (new Teamer())
@@ -61,17 +117,17 @@ class UserDataHandlerTest extends TestCase
$handler->updateLocalUser(
$user,
$profileResponse,
['ROLE_TEAMER'],
true,
['team' => ['selected' => true]],
['ABC'],
);
$this->assertSame('New', $user->getFirstName());
$this->assertSame('Lastname', $user->getLastName());
$this->assertSame('[email protected]', $user->getEmail());
$this->assertSame(['ABC'], $user->getHotelCodes());
$this->assertTrue($user->hasRole('ROLE_TEAMER'));
// roles and hotel codes are imported on creation only and stay under manual control
$this->assertSame(['XYZ'], $user->getHotelCodes());
$this->assertTrue($user->hasRole('ROLE_ADMIN'));
$this->assertSame('New', $teamer->getFirstName());
$this->assertSame('Lastname', $teamer->getLastName());
@@ -89,6 +145,74 @@ class UserDataHandlerTest extends TestCase
$this->assertSame(['team' => ['selected' => true]], $teamer->getCrmSelections());
}
/**
* @dataProvider pendingRolesProvider
*/
public function testUpdateLocalUserRefreshesThePendingRoles(
array $roles,
array $claimedRoles,
array $expectedAssignedRoles,
array $expectedPendingRoles,
): void {
$user = (new User())
->setFirstName('Old')
->setLastName('Name')
->setEmail('[email protected]')
->setRoles($roles)
;
$handler = new UserDataHandler($this->entityManager, $this->logger);
$handler->updateLocalUser($user, $this->createProfileResponse(), false, [], $claimedRoles);
$this->assertSame($expectedAssignedRoles, $user->getAssignedRoles());
$this->assertSame($expectedPendingRoles, $user->getPendingRoles());
}
public static function pendingRolesProvider(): iterable
{
yield 'marker is added when the CRM claims a manager' => [
['ROLE_TEAMER'],
[User::PENDING_ROLES['ROLE_MANAGER']],
['ROLE_TEAMER'],
[User::PENDING_ROLES['ROLE_MANAGER']],
];
yield 'marker is dropped when the CRM attribute is gone' => [
[User::PENDING_ROLES['ROLE_HOUSE_MANAGER'], 'ROLE_TEAMER'],
[],
['ROLE_TEAMER'],
[],
];
yield 'an approved role is never marked again' => [
['ROLE_MANAGER'],
[User::PENDING_ROLES['ROLE_MANAGER']],
['ROLE_MANAGER'],
[],
];
yield 'a claim beyond the approved role stays pending' => [
['ROLE_MANAGER'],
[User::PENDING_ROLES['ROLE_ADMIN'], User::PENDING_ROLES['ROLE_MANAGER']],
['ROLE_MANAGER'],
[User::PENDING_ROLES['ROLE_ADMIN']],
];
yield 'the claimed role changes' => [
[User::PENDING_ROLES['ROLE_HOUSE_MANAGER']],
[User::PENDING_ROLES['ROLE_MANAGER']],
[],
[User::PENDING_ROLES['ROLE_MANAGER']],
];
yield 'granted roles are untouched without any claim' => [
['ROLE_ADMIN'],
[],
['ROLE_ADMIN'],
[],
];
}
public function testFindLocalUserFallsBackToUniqueEmailAndRefreshesBusProIds(): void
{
$user = (new User())