feat: pending roles from crm to be confirmed by superadmins
This commit is contained in:
1 parent
681734533f
commit
b01c2e84c7
26 files changed
+907
-150
No files matched your search
@@ -19,18 +19,19 @@ class UserDataHandler
|
||||
) {
|
||||
}
|
||||
|
||||
public function collectRoles(CrmAttributesResponse $crmAttributes, ?string $preferredRole): array
|
||||
/**
|
||||
* Collects the roles to grant on initial user creation.
|
||||
*
|
||||
* Administrative roles are deliberately not importable: they may only be granted
|
||||
* manually by a super admin, so that nobody can escalate their own privileges via
|
||||
* the BusPro CRM. They are imported as pending markers instead, which grant nothing
|
||||
* but mark the user for approval. ROLE_TEAMER carries no privileges of its own and
|
||||
* is granted directly.
|
||||
*/
|
||||
public function collectRoles(CrmAttributesResponse $crmAttributes): array
|
||||
{
|
||||
// Collect user's roles from CRM attributes
|
||||
$roles = [];
|
||||
|
||||
if ($crmAttributes->isAdmin() && (null === $preferredRole || 'admin' === $preferredRole)) {
|
||||
$roles[] = 'ROLE_ADMIN';
|
||||
} elseif ($crmAttributes->isManager() && (null === $preferredRole || 'manager' === $preferredRole)) {
|
||||
$roles[] = 'ROLE_MANAGER';
|
||||
} elseif ($crmAttributes->isHouseManager() && (null === $preferredRole || 'house_manager' === $preferredRole)) {
|
||||
$roles[] = 'ROLE_HOUSE_MANAGER';
|
||||
}
|
||||
$roles = $this->collectPendingRoles($crmAttributes);
|
||||
|
||||
if ($crmAttributes->isTeamer()) {
|
||||
$roles[] = 'ROLE_TEAMER';
|
||||
@@ -39,6 +40,26 @@ class UserDataHandler
|
||||
return $roles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects the pending markers for the administrative roles claimed in the CRM.
|
||||
*/
|
||||
public function collectPendingRoles(CrmAttributesResponse $crmAttributes): array
|
||||
{
|
||||
$roles = [];
|
||||
|
||||
if ($crmAttributes->isAdmin()) {
|
||||
$roles[] = User::PENDING_ROLES['ROLE_ADMIN'];
|
||||
}
|
||||
|
||||
if ($crmAttributes->isManager()) {
|
||||
$roles[] = User::PENDING_ROLES['ROLE_MANAGER'];
|
||||
} elseif ($crmAttributes->isHouseManager()) {
|
||||
$roles[] = User::PENDING_ROLES['ROLE_HOUSE_MANAGER'];
|
||||
}
|
||||
|
||||
return $roles;
|
||||
}
|
||||
|
||||
public function findLocalUser(ProfileResponse $profileResponse): ?User
|
||||
{
|
||||
// Check if user is already present in local database
|
||||
@@ -141,22 +162,31 @@ class UserDataHandler
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an existing user from BusPro data.
|
||||
*
|
||||
* Roles and hotel codes are imported once on user creation only and are managed
|
||||
* manually afterwards, so they are intentionally left untouched here. The only
|
||||
* exception are the privilege-free pending markers, which keep tracking the
|
||||
* administrative roles claimed in the CRM.
|
||||
*
|
||||
* @param string[] $claimedRoles pending markers as returned by collectPendingRoles()
|
||||
*/
|
||||
public function updateLocalUser(
|
||||
User $user,
|
||||
ProfileResponse $profileResponse,
|
||||
array $roles,
|
||||
bool $isTeamer = false,
|
||||
array $crmSelections = [],
|
||||
array $hotelCodes = [],
|
||||
array $claimedRoles = [],
|
||||
): void {
|
||||
$user
|
||||
->setFirstName($profileResponse->getFirstName())
|
||||
->setLastName($profileResponse->getName())
|
||||
->setEmail($profileResponse->getCommunication()->getEmail())
|
||||
->setRoles($roles)
|
||||
->setHotelCodes($hotelCodes)
|
||||
;
|
||||
|
||||
$this->refreshPendingRoles($user, $claimedRoles);
|
||||
|
||||
if (true === $isTeamer) {
|
||||
$address = Address::fromApiResponse($profileResponse);
|
||||
$communication = Communication::fromApiResponse($profileResponse);
|
||||
@@ -187,4 +217,39 @@ class UserDataHandler
|
||||
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Keeps the pending markers in sync with the administrative roles claimed in the CRM.
|
||||
* The markers grant no privileges, so tracking them on every login is safe: only a
|
||||
* super admin can turn one into an actual role, and an already granted role is never
|
||||
* marked as pending again.
|
||||
*
|
||||
* @param string[] $claimedRoles
|
||||
*/
|
||||
private function refreshPendingRoles(User $user, array $claimedRoles): void
|
||||
{
|
||||
// an approved role needs no marker anymore
|
||||
$grantedRoles = $user->getAssignedRoles();
|
||||
$pendingRoles = array_values(array_filter(
|
||||
$claimedRoles,
|
||||
static fn (string $pendingRole): bool => false === in_array(
|
||||
array_search($pendingRole, User::PENDING_ROLES, true),
|
||||
$grantedRoles,
|
||||
true,
|
||||
),
|
||||
));
|
||||
|
||||
if ($pendingRoles === $user->getPendingRoles()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// getAssignedRoles() returns the manually assignable roles without the markers
|
||||
$user->setRoles([...$grantedRoles, ...$pendingRoles]);
|
||||
|
||||
$this->logger->info('Refresh pending roles', [
|
||||
'user_id' => $user->getId(),
|
||||
'user_email' => $user->getEmail(),
|
||||
'pending_roles' => $pendingRoles,
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user