first commit
This commit is contained in:
304
bundles/External/HannahBundle/SAP/Security/SAPAuthenticator.php
vendored
Normal file
304
bundles/External/HannahBundle/SAP/Security/SAPAuthenticator.php
vendored
Normal file
@@ -0,0 +1,304 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace External\HannahBundle\SAP\Security;
|
||||
|
||||
use External\HannahBundle\SAP\Exception\SAPManyException;
|
||||
use External\HannahBundle\SAP\MappingType;
|
||||
use External\HannahBundle\SAP\Util\SAPClient;
|
||||
use External\HannahBundle\SAP\Util\SAPUtil;
|
||||
use External\HannahBundle\Util\Configuration;
|
||||
use KupShop\KupShopBundle\Util\StringUtil;
|
||||
use KupShop\UserBundle\Security\CustomAuthenticator;
|
||||
use KupShop\UserBundle\Security\LegacyPasswordEncoder;
|
||||
use Query\Operator;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
|
||||
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\SecurityRequestAttributes;
|
||||
use Symfony\Component\Security\Http\Util\TargetPathTrait;
|
||||
use Symfony\Contracts\Service\Attribute\Required;
|
||||
|
||||
class SAPAuthenticator extends CustomAuthenticator
|
||||
{
|
||||
use TargetPathTrait;
|
||||
|
||||
#[Required]
|
||||
public Configuration $configuration;
|
||||
|
||||
private SAPClient $client;
|
||||
private SAPUtil $sapUtil;
|
||||
private LegacyPasswordEncoder $passwordEncoder;
|
||||
|
||||
#[Required]
|
||||
final public function setSAPClient(SAPClient $client): void
|
||||
{
|
||||
$this->client = $client;
|
||||
}
|
||||
|
||||
#[Required]
|
||||
final public function setSAPUtil(SAPUtil $sapUtil): void
|
||||
{
|
||||
$this->sapUtil = $sapUtil;
|
||||
}
|
||||
|
||||
#[Required]
|
||||
final public function setPasswordEncoder(LegacyPasswordEncoder $passwordEncoder): void
|
||||
{
|
||||
$this->passwordEncoder = $passwordEncoder;
|
||||
}
|
||||
|
||||
public function authenticate(Request $request): Passport
|
||||
{
|
||||
$email = $request->get('login');
|
||||
$password = $request->get('password');
|
||||
if (($url = $request->get('url')) && $request->getSession()) {
|
||||
$this->saveTargetPath($request->getSession(), 'main', $url);
|
||||
}
|
||||
|
||||
if (empty($email) || empty($password)) {
|
||||
throw new AuthenticationCredentialsNotFoundException();
|
||||
}
|
||||
|
||||
try {
|
||||
$email = mb_strtolower($email);
|
||||
|
||||
// nevalidni email ani nezkousim
|
||||
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
throw new AuthenticationCredentialsNotFoundException();
|
||||
}
|
||||
|
||||
$user = \User::createFromLogin($email);
|
||||
$process = $user ? $this->configuration->getProcessByUser($user) : null;
|
||||
|
||||
$result = $this->client->customerValidate(
|
||||
$email,
|
||||
$this->passwordEncoder->encodePassword($password, ''),
|
||||
$process
|
||||
);
|
||||
} catch (SAPManyException $e) {
|
||||
if ($e->hasExceptionWithCode(['005', '020', '095', '148', '318'])) {
|
||||
throw new AuthenticationCredentialsNotFoundException();
|
||||
}
|
||||
|
||||
$this->sapUtil->getLogger()->log(
|
||||
$e,
|
||||
sprintf('Při příhlašování uživatele "%s" vznikla chyba: %s', $email, $e->getMessage())
|
||||
);
|
||||
|
||||
// Nalezen více než jeden BP ... - chyba, kterou si musi OC opravit v SAPu
|
||||
if ($e->hasExceptionWithCode(['018'])) {
|
||||
throw new CustomUserMessageAuthenticationException(
|
||||
translate('error_login_generic', 'oc')
|
||||
);
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$customer = $result->CustomerData;
|
||||
if (empty($customer)) {
|
||||
throw new AuthenticationCredentialsNotFoundException();
|
||||
}
|
||||
|
||||
// check that user exists, or create new one
|
||||
/** @var \User $user */
|
||||
$user = sqlGetConnection()->transactional(function () use ($customer) {
|
||||
if (!($userId = $this->sapUtil->getMapping(MappingType::USERS, $customer->CustomerId))) {
|
||||
$userId = $this->createUser($customer);
|
||||
$this->sapUtil->createMapping(MappingType::USERS, $customer->CustomerId, $userId);
|
||||
}
|
||||
|
||||
return \User::createFromId($userId);
|
||||
});
|
||||
|
||||
$this->sapUtil->updateUser($user, $customer);
|
||||
|
||||
if (!$this->passwordEncoder->isPasswordValid(trim($customer->PaswdData->PaswdHash ?? ''), $password, '')) {
|
||||
throw new AuthenticationCredentialsNotFoundException();
|
||||
}
|
||||
|
||||
return new SelfValidatingPassport(
|
||||
new UserBadge($email),
|
||||
[new RememberMeBadge()]
|
||||
);
|
||||
}
|
||||
|
||||
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
|
||||
{
|
||||
if ($request->getSession() && ($url = $this->getTargetPath($request->getSession(), 'main'))) {
|
||||
$this->removeTargetPath($request->getSession(), 'main');
|
||||
|
||||
return new RedirectResponse($url);
|
||||
}
|
||||
|
||||
return new RedirectResponse(
|
||||
$request->headers->get('referer', '/')
|
||||
);
|
||||
}
|
||||
|
||||
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
|
||||
{
|
||||
// pass to next authenticator
|
||||
if ($exception instanceof AuthenticationCredentialsNotFoundException) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($request->hasSession()) {
|
||||
$request->getSession()->set(SecurityRequestAttributes::AUTHENTICATION_ERROR, $exception);
|
||||
}
|
||||
|
||||
$url = $this->getLoginUrl($request);
|
||||
|
||||
return new RedirectResponse($url);
|
||||
}
|
||||
|
||||
public function supports(Request $request): bool
|
||||
{
|
||||
return $request->isMethod('POST')
|
||||
&& StringUtil::startsWith($request->getPathInfo(), path('kupshop_user_login_login'));
|
||||
}
|
||||
|
||||
private function createUser(\stdClass $data): int
|
||||
{
|
||||
// check if user exists
|
||||
$userId = sqlQueryBuilder()
|
||||
->select('id')
|
||||
->from('users')
|
||||
->where(Operator::equals(
|
||||
[
|
||||
'email' => $data->PersonalData->Email,
|
||||
]
|
||||
))->execute()->fetchColumn();
|
||||
|
||||
if ($userId) {
|
||||
return (int) $userId;
|
||||
}
|
||||
|
||||
$addressData = [
|
||||
'name' => '',
|
||||
'surname' => '',
|
||||
'firm' => '',
|
||||
'ico' => '',
|
||||
'dic' => '',
|
||||
'street' => '',
|
||||
'city' => '',
|
||||
'zip' => '',
|
||||
'country' => '',
|
||||
|
||||
'delivery_name' => '',
|
||||
'delivery_surname' => '',
|
||||
'delivery_street' => '',
|
||||
'delivery_city' => '',
|
||||
'delivery_zip' => '',
|
||||
'delivery_country' => '',
|
||||
];
|
||||
|
||||
$addresses = $this->sapUtil->prepareSAPItems($data->AddressData);
|
||||
foreach ($addresses as $address) {
|
||||
foreach ($address as $key => $value) {
|
||||
if ($address->AddressType === 'COMPANY') {
|
||||
if (!in_array($key, ['Company', 'VatIdentNumber', 'CompRegNumber'])) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ($field = $this->getAddressField($key)) {
|
||||
$addressData[$this->getAddressPrefix($address->AddressType).$field] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sqlGetConnection()->transactional(function () use ($data, $addressData) {
|
||||
sqlQueryBuilder()
|
||||
->insert('users')
|
||||
->directValues(
|
||||
array_merge(
|
||||
[
|
||||
'email' => $data->PersonalData->Email,
|
||||
'phone' => $data->PersonalData->TelNo ?? '',
|
||||
'passw' => $data->PaswdData->PaswdHash ?? '',
|
||||
'date_reg' => (new \DateTime())->format('Y-m-d H:i:s'),
|
||||
'custom_data' => json_encode(
|
||||
[
|
||||
'passwordInSap' => $data->PaswdData->PaswdHash ?? '',
|
||||
'sap' => [
|
||||
'discountIndex' => $data->PersonalData->DiscountIndex,
|
||||
'cards' => [],
|
||||
],
|
||||
]
|
||||
),
|
||||
],
|
||||
$addressData
|
||||
)
|
||||
)->execute();
|
||||
|
||||
return (int) sqlInsertId();
|
||||
});
|
||||
}
|
||||
|
||||
private function updatePriceLevelByDiscountIndex(\User $user, string $discountIndex): void
|
||||
{
|
||||
$priceLevelId = sqlQueryBuilder()
|
||||
->select('id')
|
||||
->from('price_levels')
|
||||
->where(Operator::equals(['descr' => $discountIndex]))
|
||||
->execute()->fetchColumn();
|
||||
|
||||
sqlGetConnection()->transactional(function () use ($user, $priceLevelId) {
|
||||
sqlQueryBuilder()
|
||||
->delete('users_dealer_price_level')
|
||||
->where(Operator::equals(
|
||||
[
|
||||
'id_user' => $user->id,
|
||||
]
|
||||
))->execute();
|
||||
|
||||
if ($priceLevelId) {
|
||||
sqlQueryBuilder()
|
||||
->insert('users_dealer_price_level')
|
||||
->directValues(
|
||||
[
|
||||
'id_user' => $user->id,
|
||||
'id_price_level' => $priceLevelId,
|
||||
]
|
||||
)->execute();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private function getAddressPrefix(string $type): string
|
||||
{
|
||||
if ($type === 'SHIPPING') {
|
||||
return 'delivery_';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
private function getAddressField(string $key): ?string
|
||||
{
|
||||
$map = [
|
||||
'FirstName' => 'name',
|
||||
'LastName' => 'surname',
|
||||
'Street' => 'street',
|
||||
'City' => 'city',
|
||||
'PostlCod' => 'zip',
|
||||
'Country' => 'country',
|
||||
'Company' => 'firm',
|
||||
'VatIdentNumber' => 'ico',
|
||||
'CompRegNumber' => 'dic',
|
||||
];
|
||||
|
||||
return $map[$key] ?? null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user