feat: derive ROLE_EMPLOYEE from the account's email domain

This commit is contained in:
2026-09-13 12:49:51 +02:00
parent 443a3ed248
commit fab89dead6
7 changed files with 221 additions and 8 deletions
+15 -3
View File
@@ -34,8 +34,10 @@ use Symfony\Component\Security\Http\Util\TargetPathTrait;
*
* The password is kept, RSA-encrypted, because every later BPN call needs it again.
*
* BusPro owns the whole role set and the hotel codes: both are synced on every login, in both
* directions, so anything the CRM no longer reports is withdrawn here. What the CRM claims is
* BusPro owns the whole role set bar one, and the hotel codes: both are synced on every login, in
* both directions, so anything the CRM no longer reports is withdrawn here. The exception is
* ROLE_EMPLOYEE, which BusPro has no selection for and which is derived from the account's email
* domain — passed to Role::sync() as a claim, so it is granted and revoked by the same machinery. What the CRM claims is
* not automatically granted, though — Role::sync() turns an administrative claim into a
* nomination that an administrator has to approve in /admin/user, because BusPro backend users
* can edit their own CRM selections and would otherwise make themselves administrators.
@@ -51,6 +53,7 @@ class BpnAuthenticator extends AbstractLoginFormAuthenticator implements Authent
private readonly Crypt $crypt,
private readonly ProfileCompletenessChecker $completenessChecker,
private readonly LoggerInterface $authLogger,
private readonly EmployeeDomainMatcher $employeeDomainMatcher,
) {
}
@@ -152,8 +155,17 @@ class BpnAuthenticator extends AbstractLoginFormAuthenticator implements Authent
}
}
$claimedRoles = $crmAttributes->roles;
// Not a CRM claim: BusPro has no selection for it, so the account's own address decides.
// Passing it in as a claim rather than setting it afterwards is what makes it revocable —
// Role::sync() strips every stored role the claim set does not contain.
if ($this->employeeDomainMatcher->isEmployee($user->getEmail())) {
$claimedRoles[] = Role::EMPLOYEE;
}
$user
->setRoles(Role::sync($previousRoles, $crmAttributes->roles))
->setRoles(Role::sync($previousRoles, $claimedRoles))
->setHotelCodes(array_values(array_unique($crmAttributes->hotelCodes)))
;