feat: streamlined role-revocation logic

This commit is contained in:
Björn Fromme committed 2026-08-10 16:24:41 +02:00
1 parent b39a78da82
commit fd5d478a5c
14 files changed
+426 -22

No files matched your search

@@ -87,12 +87,13 @@ class CrmAttributesResponse
{
$crmSelections = [];
foreach ($this->getAttributeGroups() as $group) {
// a response the CRM sent no attributes in still has to flatten to an empty set
foreach ($this->getAttributeGroups() ?? [] as $group) {
/** @var CrmAttributeGroup $group */
if (false === isset($crmSelections[$group->getLabel()])) {
$crmSelections[$group->getLabel()] = [];
}
foreach ($group->getAttributes() as $attribute) {
foreach ($group->getAttributes() ?? [] as $attribute) {
/** @var CrmAttribute $attribute */
if (false === $attribute->isSelected()) {
continue;
+42 -8
View File
@@ -165,10 +165,11 @@ class UserDataHandler
/**
* 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.
* Administrative roles and hotel codes are imported once on user creation only and are
* managed manually afterwards, so they are intentionally left untouched here. The
* exceptions are the privilege-free pending markers, which keep tracking the
* administrative roles claimed in the CRM, and ROLE_TEAMER, which needs no approval
* and is granted to whoever the CRM reports as a teamer.
*
* @param string[] $claimedRoles pending markers as returned by collectPendingRoles()
*/
@@ -188,6 +189,8 @@ class UserDataHandler
$this->refreshPendingRoles($user, $claimedRoles);
if (true === $isTeamer) {
$this->grantTeamerRole($user);
$address = Address::fromApiResponse($profileResponse);
$communication = Communication::fromApiResponse($profileResponse);
if (null === $user->getTeamer()) {
@@ -221,15 +224,19 @@ class UserDataHandler
/**
* Blocks a user the CRM no longer grants anything in this application.
*
* The granted roles are deliberately kept: they stay visible for review and are what
* makes the user reappear in the administrative list, where a super admin can unblock
* them. Only the privilege-free markers are dropped, as they no longer reflect the CRM.
* The granted roles are deliberately kept: they stay visible for review. Only the
* privilege-free markers are dropped, as they no longer reflect the CRM. What keeps the
* user reachable is the block itself, not the roles: a teamer stays in the teamer list,
* everyone else is listed by getAdministrativeUsers() whatever roles are left.
* Regaining a CRM role does not unblock the account, that is a manual decision.
*/
public function disableForRevokedCrmRoles(User $user): void
{
// an existing block may be a disciplinary one and must never be overwritten
// an existing block may be a disciplinary one and must never be overwritten, but
// findLocalUser() may have refreshed the BusPro ids and nothing else flushes here
if (true === $user->isDisabled()) {
$this->entityManager->flush();
return;
}
@@ -249,6 +256,33 @@ class UserDataHandler
]);
}
/**
* Grants ROLE_TEAMER to a user the CRM reports as a teamer.
*
* Unlike the administrative roles this one needs no approval, so it may be granted on
* any login rather than on creation only: it carries no privileges beyond the teamer
* area, and a teamer without it would be left with a teamer record they cannot reach,
* or locked out entirely for holding no assignable role at all.
*
* It is never withdrawn here. Losing the CRM attribute while holding no other role
* blocks the account anyway, and a role handed out manually must survive a login.
*/
private function grantTeamerRole(User $user): void
{
$grantedRoles = $user->getAssignedRoles();
if (true === in_array('ROLE_TEAMER', $grantedRoles, true)) {
return;
}
$user->setRoles([...$grantedRoles, 'ROLE_TEAMER', ...$user->getPendingRoles()]);
$this->logger->info('Grant teamer role', [
'user_id' => $user->getId(),
'user_email' => $user->getEmail(),
]);
}
/**
* 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