feat: extended oauth2 user info and refactored authenticator
This commit is contained in:
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20251212162836 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('ALTER TABLE user ADD hotel_codes JSON NOT NULL COMMENT \'(DC2Type:json)\'');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('ALTER TABLE user DROP hotel_codes');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,10 +14,6 @@ class CrmAttributes
|
|||||||
{
|
{
|
||||||
public ?array $selectionGroups = null;
|
public ?array $selectionGroups = null;
|
||||||
public ?array $crmActions = null;
|
public ?array $crmActions = null;
|
||||||
public bool $admin = false;
|
public array $hotelCodes = [];
|
||||||
public bool $manager = false;
|
|
||||||
public bool $houseManager = false;
|
|
||||||
public bool $teamer = false;
|
|
||||||
public ?string $hotelCode = null;
|
|
||||||
public array $roles = [];
|
public array $roles = [];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ class PersonalData
|
|||||||
public Communication $communication;
|
public Communication $communication;
|
||||||
|
|
||||||
public array $roles = [];
|
public array $roles = [];
|
||||||
|
public array $hotelCodes = [];
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -135,12 +136,13 @@ class PersonalData
|
|||||||
'title' => $this->title,
|
'title' => $this->title,
|
||||||
'salutation' => $this->salutation,
|
'salutation' => $this->salutation,
|
||||||
'gender' => $this->gender,
|
'gender' => $this->gender,
|
||||||
|
'date_of_birth' => $this->dateOfBirth?->format('Y-m-d'),
|
||||||
'nationality' => $this->nationality,
|
'nationality' => $this->nationality,
|
||||||
'address' => [
|
'address' => [
|
||||||
'street' => $this->address->street,
|
'street' => $this->address->street,
|
||||||
'postcode' => $this->address->postCode,
|
'postcode' => $this->address->postCode,
|
||||||
'city' => $this->address->city,
|
'city' => $this->address->city,
|
||||||
'disctrict' => $this->address->district,
|
'district' => $this->address->district,
|
||||||
'country' => $this->address->country,
|
'country' => $this->address->country,
|
||||||
],
|
],
|
||||||
'communication' => [
|
'communication' => [
|
||||||
@@ -149,6 +151,7 @@ class PersonalData
|
|||||||
'phone' => $this->communication->phone,
|
'phone' => $this->communication->phone,
|
||||||
'newsletter' => $this->communication->newsletter,
|
'newsletter' => $this->communication->newsletter,
|
||||||
],
|
],
|
||||||
|
'hotel_codes' => $this->hotelCodes,
|
||||||
'height' => $this->height,
|
'height' => $this->height,
|
||||||
'weight' => $this->weight,
|
'weight' => $this->weight,
|
||||||
'shoe_size' => $this->shoeSize,
|
'shoe_size' => $this->shoeSize,
|
||||||
|
|||||||
@@ -16,13 +16,14 @@ class CrmAttributesResponseParser
|
|||||||
private const BPN_CRM_ID_ADMIN = 1292;
|
private const BPN_CRM_ID_ADMIN = 1292;
|
||||||
private const BPN_CRM_ID_MANAGER = 1293;
|
private const BPN_CRM_ID_MANAGER = 1293;
|
||||||
private const BPN_CRM_ID_TEAMER = 1070;
|
private const BPN_CRM_ID_TEAMER = 1070;
|
||||||
|
private const BPN_DEFAULT_HOTEL_CODE = 'SSL';
|
||||||
|
|
||||||
public function parse(Crawler $result): CrmAttributes
|
public function parse(Crawler $result): CrmAttributes
|
||||||
{
|
{
|
||||||
$groups = [];
|
$groups = [];
|
||||||
$actions = [];
|
$actions = [];
|
||||||
$roles = [];
|
$roles = [];
|
||||||
$hotelCode = null;
|
$hotelCodes = [];
|
||||||
|
|
||||||
$result
|
$result
|
||||||
->filterXPath('//selektionsmerkmale/selektionsgruppe')
|
->filterXPath('//selektionsmerkmale/selektionsgruppe')
|
||||||
@@ -35,7 +36,7 @@ class CrmAttributesResponseParser
|
|||||||
|
|
||||||
$node
|
$node
|
||||||
->filterXPath('//selektion')
|
->filterXPath('//selektion')
|
||||||
->each(function (Crawler $node) use (&$attributes, &$roles, &$hotelCode) {
|
->each(function (Crawler $node) use (&$attributes, &$roles, &$hotelCodes) {
|
||||||
$attribute = new CrmSelection();
|
$attribute = new CrmSelection();
|
||||||
$attribute->id = (int) $node->attr('id');
|
$attribute->id = (int) $node->attr('id');
|
||||||
$attribute->label = $node->attr('bezeichnung');
|
$attribute->label = $node->attr('bezeichnung');
|
||||||
@@ -44,10 +45,11 @@ class CrmAttributesResponseParser
|
|||||||
|
|
||||||
if (1 === preg_match('/^Hausleitung ([A-Z0-9]+)$/', $attribute->label, $matches) && true === $attribute->selected) {
|
if (1 === preg_match('/^Hausleitung ([A-Z0-9]+)$/', $attribute->label, $matches) && true === $attribute->selected) {
|
||||||
$roles[] = 'ROLE_HOUSE_MANAGER';
|
$roles[] = 'ROLE_HOUSE_MANAGER';
|
||||||
$hotelCode = $matches[1];
|
$hotelCodes[] = $matches[1];
|
||||||
}
|
}
|
||||||
if (static::BPN_CRM_ID_ADMIN === $attribute->id && true === $attribute->selected) {
|
if (static::BPN_CRM_ID_ADMIN === $attribute->id && true === $attribute->selected) {
|
||||||
$roles[] = 'ROLE_ADMIN';
|
$roles[] = 'ROLE_ADMIN';
|
||||||
|
$roles[] = 'ROLE_HOUSE_MANAGER';
|
||||||
}
|
}
|
||||||
if (static::BPN_CRM_ID_MANAGER === $attribute->id && true === $attribute->selected) {
|
if (static::BPN_CRM_ID_MANAGER === $attribute->id && true === $attribute->selected) {
|
||||||
$roles[] = 'ROLE_MANAGER';
|
$roles[] = 'ROLE_MANAGER';
|
||||||
@@ -65,6 +67,13 @@ class CrmAttributesResponseParser
|
|||||||
})
|
})
|
||||||
;
|
;
|
||||||
|
|
||||||
|
$roles = array_unique($roles);
|
||||||
|
|
||||||
|
// Assign default role if none could be resolved
|
||||||
|
if (0 === count($roles)) {
|
||||||
|
$roles = ['ROLE_CUSTOMER'];
|
||||||
|
}
|
||||||
|
|
||||||
$result
|
$result
|
||||||
->filterXPath('//crmaktionen/crmaktion')
|
->filterXPath('//crmaktionen/crmaktion')
|
||||||
->each(function (Crawler $node) use (&$actions) {
|
->each(function (Crawler $node) use (&$actions) {
|
||||||
@@ -80,15 +89,15 @@ class CrmAttributesResponseParser
|
|||||||
})
|
})
|
||||||
;
|
;
|
||||||
|
|
||||||
|
if (true === in_array('ROLE_ADMIN', $roles, true)) {
|
||||||
|
$hotelCodes[] = static::BPN_DEFAULT_HOTEL_CODE;
|
||||||
|
}
|
||||||
|
|
||||||
$response = new CrmAttributes();
|
$response = new CrmAttributes();
|
||||||
$response->selectionGroups = $groups;
|
$response->selectionGroups = $groups;
|
||||||
$response->crmActions = $actions;
|
$response->crmActions = $actions;
|
||||||
$response->roles = $roles;
|
$response->roles = $roles;
|
||||||
$response->admin = in_array('ROLE_ADMIN', $roles);
|
$response->hotelCodes = $hotelCodes;
|
||||||
$response->manager = in_array('ROLE_MANAGER', $roles);
|
|
||||||
$response->houseManager = in_array('ROLE_HOUSE_MANAGER', $roles);
|
|
||||||
$response->teamer = in_array('ROLE_TEAMER', $roles);
|
|
||||||
$response->hotelCode = $hotelCode;
|
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,9 @@ class UserinfoController extends AbstractController
|
|||||||
// Patch current user's roles
|
// Patch current user's roles
|
||||||
$data->roles = $user->getRoles();
|
$data->roles = $user->getRoles();
|
||||||
|
|
||||||
|
// Patch current user's hotel codes
|
||||||
|
$data->hotelCodes = $user->getHotelCodes();
|
||||||
|
|
||||||
// extract userdata for resulting claims
|
// extract userdata for resulting claims
|
||||||
$userData = $this->getClaims($data, $scopes);
|
$userData = $this->getClaims($data, $scopes);
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
|
|||||||
#[ORM\Column(type: 'json')]
|
#[ORM\Column(type: 'json')]
|
||||||
private array $roles = [];
|
private array $roles = [];
|
||||||
|
|
||||||
|
#[ORM\Column(type: 'json')]
|
||||||
|
private array $hotelCodes = [];
|
||||||
|
|
||||||
#[ORM\Column(type: 'datetime_immutable', nullable: true)]
|
#[ORM\Column(type: 'datetime_immutable', nullable: true)]
|
||||||
private ?\DateTimeImmutable $lastLoginAt = null;
|
private ?\DateTimeImmutable $lastLoginAt = null;
|
||||||
|
|
||||||
@@ -102,6 +105,18 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getHotelCodes(): array
|
||||||
|
{
|
||||||
|
return $this->hotelCodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setHotelCodes(array $hotelCodes): static
|
||||||
|
{
|
||||||
|
$this->hotelCodes = $hotelCodes;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function getLastLoginAt(): ?\DateTimeImmutable
|
public function getLastLoginAt(): ?\DateTimeImmutable
|
||||||
{
|
{
|
||||||
return $this->lastLoginAt;
|
return $this->lastLoginAt;
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ namespace App\Security;
|
|||||||
|
|
||||||
use App\BusProNet\ApiClient;
|
use App\BusProNet\ApiClient;
|
||||||
use App\BusProNet\Exception\ApiClientException;
|
use App\BusProNet\Exception\ApiClientException;
|
||||||
use App\BusProNet\Model\CrmAttributes;
|
|
||||||
use App\BusProNet\Model\PersonalData;
|
use App\BusProNet\Model\PersonalData;
|
||||||
use App\Entity\User;
|
use App\Entity\User;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
@@ -79,7 +78,9 @@ class BpnAuthenticator extends AbstractLoginFormAuthenticator implements Authent
|
|||||||
throw new CustomUserMessageAuthenticationException($e->getMessage());
|
throw new CustomUserMessageAuthenticationException($e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
$roles = $this->collectRoles($crmAttributes);
|
$roles = $crmAttributes->roles;
|
||||||
|
$hotelCodes = $crmAttributes->hotelCodes;
|
||||||
|
|
||||||
$encryptedPassword = $this->crypt->encrypt($password);
|
$encryptedPassword = $this->crypt->encrypt($password);
|
||||||
|
|
||||||
$userRepository = $this->entityManager->getRepository(User::class);
|
$userRepository = $this->entityManager->getRepository(User::class);
|
||||||
@@ -94,6 +95,7 @@ class BpnAuthenticator extends AbstractLoginFormAuthenticator implements Authent
|
|||||||
->setPersonId($personId)
|
->setPersonId($personId)
|
||||||
->setAddressId($addressId)
|
->setAddressId($addressId)
|
||||||
->setRoles($roles)
|
->setRoles($roles)
|
||||||
|
->setHotelCodes($hotelCodes)
|
||||||
->setLastLoginAt(new \DateTimeImmutable())
|
->setLastLoginAt(new \DateTimeImmutable())
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -114,28 +116,4 @@ class BpnAuthenticator extends AbstractLoginFormAuthenticator implements Authent
|
|||||||
|
|
||||||
return new RedirectResponse($this->urlGenerator->generate('app_account'));
|
return new RedirectResponse($this->urlGenerator->generate('app_account'));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function collectRoles(CrmAttributes $crmAttributes): array
|
|
||||||
{
|
|
||||||
// All users inherit the default role 'customer'
|
|
||||||
$roles = [
|
|
||||||
'ROLE_CUSTOMER',
|
|
||||||
];
|
|
||||||
|
|
||||||
// Get user's base role from CRM attributes
|
|
||||||
if ($crmAttributes->admin) {
|
|
||||||
$roles[] = 'ROLE_ADMIN';
|
|
||||||
} elseif ($crmAttributes->manager) {
|
|
||||||
$roles[] = 'ROLE_MANAGER';
|
|
||||||
} elseif ($crmAttributes->houseManager) {
|
|
||||||
$roles[] = 'ROLE_HOUSE_MANAGER';
|
|
||||||
}
|
|
||||||
|
|
||||||
// All users can have role 'teamer' additionally
|
|
||||||
if ($crmAttributes->teamer) {
|
|
||||||
$roles[] = 'ROLE_TEAMER';
|
|
||||||
}
|
|
||||||
|
|
||||||
return $roles;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user