feat: minimal locally stored user entity
This commit is contained in:
@@ -1,106 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\Security;
|
||||
|
||||
use App\BusProNet\ApiClient;
|
||||
use App\BusProNet\Exception\ApiClientException;
|
||||
use App\BusProNet\Model\CrmAttributes;
|
||||
use App\BusProNet\Model\PersonalData;
|
||||
use App\Security\Crypt;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
|
||||
use Symfony\Component\Security\Http\Authenticator\AbstractLoginFormAuthenticator;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\CsrfTokenBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\RememberMeBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
|
||||
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
|
||||
|
||||
class Authenticator extends AbstractLoginFormAuthenticator implements AuthenticationEntryPointInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly UrlGeneratorInterface $urlGenerator,
|
||||
private readonly ApiClient $apiClient,
|
||||
private readonly Crypt $crypt,
|
||||
private readonly LoggerInterface $logger,
|
||||
) {
|
||||
}
|
||||
|
||||
protected function getLoginUrl(Request $request): string
|
||||
{
|
||||
return $this->urlGenerator->generate('app_login');
|
||||
}
|
||||
|
||||
public function authenticate(Request $request): Passport
|
||||
{
|
||||
$email = trim($request->request->getString('_username'));
|
||||
$passwordPlain = trim($request->request->getString('_password'));
|
||||
|
||||
// Very lame hashing applied here as required by BPN
|
||||
$password = md5($passwordPlain);
|
||||
|
||||
try {
|
||||
$response = $this->apiClient->getPersonalData($email, $password);
|
||||
} catch (ApiClientException $e) {
|
||||
throw new CustomUserMessageAuthenticationException($e->getMessage());
|
||||
}
|
||||
|
||||
if (false === $response instanceof PersonalData) {
|
||||
throw new CustomUserMessageAuthenticationException('Der Login ist fehlgeschlagen :(');
|
||||
}
|
||||
|
||||
$csrfToken = $request->request->getString('_csrf_token');
|
||||
|
||||
return new SelfValidatingPassport(
|
||||
new UserBadge($email, function () use ($email, $password, $response, $request) {
|
||||
$crmAttributes = $this->apiClient->getCrmAttributes($email, $password);
|
||||
$roles = $this->collectRoles($crmAttributes);
|
||||
$encryptedPassword = $this->crypt->encrypt($password);
|
||||
$user = new User($email, $response->personId, $response->addressId, $encryptedPassword, $roles);
|
||||
|
||||
$request->getSession()->set('bpn_user', $user);
|
||||
|
||||
return $user;
|
||||
}),
|
||||
[
|
||||
new CsrfTokenBadge('authenticate', $csrfToken),
|
||||
new RememberMeBadge(),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
|
||||
{
|
||||
$this->logger->info('Login', [
|
||||
'email' => $token->getUserIdentifier(),
|
||||
]);
|
||||
|
||||
return new RedirectResponse($this->urlGenerator->generate('app_personal_data'));
|
||||
}
|
||||
|
||||
private function collectRoles(CrmAttributes $crmAttributes): array
|
||||
{
|
||||
// Collect user's roles from CRM attributes
|
||||
$roles = [];
|
||||
|
||||
if ($crmAttributes->admin) {
|
||||
$roles[] = 'ROLE_ADMIN';
|
||||
} elseif ($crmAttributes->manager) {
|
||||
$roles[] = 'ROLE_MANAGER';
|
||||
} elseif ($crmAttributes->houseManager) {
|
||||
$roles[] = 'ROLE_HOUSE_MANAGER';
|
||||
}
|
||||
|
||||
if ($crmAttributes->teamer) {
|
||||
$roles[] = 'ROLE_TEAMER';
|
||||
}
|
||||
|
||||
return $roles;
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\Security;
|
||||
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
|
||||
class User implements UserInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly string $email,
|
||||
private readonly int $personId,
|
||||
private readonly int $addressId,
|
||||
private readonly ?string $password = null,
|
||||
private readonly array $roles = [],
|
||||
) {
|
||||
}
|
||||
|
||||
public function getEmail(): ?string
|
||||
{
|
||||
return $this->email;
|
||||
}
|
||||
|
||||
public function getPassword(): ?string
|
||||
{
|
||||
return $this->password;
|
||||
}
|
||||
|
||||
public function getPersonId(): ?int
|
||||
{
|
||||
return $this->personId;
|
||||
}
|
||||
|
||||
public function getAddressId(): int
|
||||
{
|
||||
return $this->addressId;
|
||||
}
|
||||
|
||||
public function getRoles(): array
|
||||
{
|
||||
return ['ROLE_USER', ...$this->roles];
|
||||
}
|
||||
|
||||
public function eraseCredentials(): void
|
||||
{
|
||||
}
|
||||
|
||||
public function getUserIdentifier(): string
|
||||
{
|
||||
return $this->email;
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\Security;
|
||||
|
||||
use App\BusProNet\ApiClient;
|
||||
use App\BusProNet\Exception\ApiClientException;
|
||||
use App\BusProNet\Model\PersonalData;
|
||||
use App\Controller\Traits\CredentialsTrait;
|
||||
use App\Security\Crypt;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Symfony\Component\Security\Core\User\UserProviderInterface;
|
||||
|
||||
class UserProvider implements UserProviderInterface
|
||||
{
|
||||
use CredentialsTrait;
|
||||
|
||||
public function __construct(
|
||||
private readonly ApiClient $apiClient,
|
||||
private readonly RequestStack $requestStack,
|
||||
private readonly Crypt $crypt,
|
||||
) {
|
||||
}
|
||||
|
||||
public function refreshUser(UserInterface $user): UserInterface
|
||||
{
|
||||
if (null !== $activeUser = $this->requestStack->getSession()->get('bpn_user')) {
|
||||
return $activeUser;
|
||||
}
|
||||
|
||||
return $this->loadUserByIdentifier($user->getUserIdentifier());
|
||||
}
|
||||
|
||||
public function supportsClass(string $class): bool
|
||||
{
|
||||
return User::class === $class;
|
||||
}
|
||||
|
||||
public function loadUserByIdentifier(string $identifier): UserInterface
|
||||
{
|
||||
if (null === $activeUser = $this->requestStack->getSession()->get('bpn_user')) {
|
||||
throw new UserNotFoundException();
|
||||
}
|
||||
|
||||
try {
|
||||
$email = $activeUser->getEmail();
|
||||
$password = $this->crypt->decrypt($activeUser->getPassword());
|
||||
$response = $this->apiClient->getPersonalData($email, $password);
|
||||
} catch (ApiClientException $e) {
|
||||
throw new UserNotFoundException();
|
||||
}
|
||||
|
||||
if (false === $response instanceof PersonalData) {
|
||||
throw new UserNotFoundException();
|
||||
}
|
||||
|
||||
return $activeUser;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user