feat: email the administrators when a role nomination appears

This commit is contained in:
2026-09-13 12:50:01 +02:00
parent fab89dead6
commit b41820c39d
12 changed files with 458 additions and 36 deletions
+70
View File
@@ -9,6 +9,7 @@ use App\BusProNet\Model\CrmAttributes;
use App\BusProNet\Model\CrmSelectionGroup;
use App\BusProNet\Model\PersonalData;
use App\Entity\User;
use App\Message\RoleNominationMessage;
use App\Security\BpnAuthenticator;
use App\Security\Crypt;
use App\Security\EmployeeDomainMatcher;
@@ -19,6 +20,8 @@ use Doctrine\ORM\EntityRepository;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
@@ -28,6 +31,14 @@ use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
*/
class BpnAuthenticatorTest extends TestCase
{
/** @var object[] messages the authenticator dispatched during the login under test */
private array $dispatched = [];
protected function setUp(): void
{
$this->dispatched = [];
}
public function testNewAccountIsSeededFromTheCrm(): void
{
$persisted = null;
@@ -229,6 +240,54 @@ class BpnAuthenticatorTest extends TestCase
self::assertSame(['ROLE_USER', Role::CUSTOMER], $user->getRoles());
}
public function testANewNominationIsAnnouncedOnce(): void
{
$persisted = null;
$authenticator = $this->authenticator($this->crmAttributes([Role::ADMIN], []), null, $persisted);
$user = $this->loadUser($authenticator);
self::assertCount(1, $this->dispatched);
$message = $this->dispatched[0];
self::assertInstanceOf(RoleNominationMessage::class, $message);
// The role itself, not its marker: the marker is an internal bookkeeping detail.
self::assertSame([Role::ADMIN], $message->roles);
self::assertContains(Role::pending(Role::ADMIN), $user->getRoles());
}
public function testAStandingNominationIsNotAnnouncedAgain(): void
{
$existing = (new User('[email protected]'))->setRoles([Role::pending(Role::ADMIN)]);
$persisted = null;
$authenticator = $this->authenticator($this->crmAttributes([Role::ADMIN], []), $existing, $persisted);
$this->loadUser($authenticator);
// The nomination has not changed, so there is nothing new to tell an administrator about.
self::assertSame([], $this->dispatched);
}
public function testAnApprovedRoleIsNotAnnouncedAsANomination(): void
{
$existing = (new User('[email protected]'))->setRoles([Role::ADMIN]);
$persisted = null;
$authenticator = $this->authenticator($this->crmAttributes([Role::ADMIN], []), $existing, $persisted);
$this->loadUser($authenticator);
self::assertSame([], $this->dispatched);
}
public function testALoginWithoutANominationAnnouncesNothing(): void
{
$persisted = null;
$authenticator = $this->authenticator($this->crmAttributes([Role::TEAMER], []), null, $persisted);
$this->loadUser($authenticator);
self::assertSame([], $this->dispatched);
}
private function authenticator(
CrmAttributes $crmAttributes,
?User $existing,
@@ -264,6 +323,16 @@ class BpnAuthenticatorTest extends TestCase
$completenessChecker = $this->createStub(ProfileCompletenessChecker::class);
$completenessChecker->method('isComplete')->willReturn(true);
$messageBus = $this->createStub(MessageBusInterface::class);
$messageBus
->method('dispatch')
->willReturnCallback(function (object $message): Envelope {
$this->dispatched[] = $message;
return new Envelope($message);
})
;
return new BpnAuthenticator(
$this->createStub(UrlGeneratorInterface::class),
$apiClient,
@@ -272,6 +341,7 @@ class BpnAuthenticatorTest extends TestCase
$completenessChecker,
$this->createStub(LoggerInterface::class),
new EmployeeDomainMatcher(['ep-reisen.de']),
$messageBus,
);
}