diff --git a/src/Controller/Admin/AdministratorController.php b/src/Controller/Admin/AdministratorController.php
index 87400124b6..8bcfb84eed 100644
--- a/src/Controller/Admin/AdministratorController.php
+++ b/src/Controller/Admin/AdministratorController.php
@@ -18,7 +18,6 @@
use Shopsys\FrameworkBundle\Model\Administrator\Exception\AdministratorNotFoundException;
use Shopsys\FrameworkBundle\Model\Administrator\Exception\DeletingLastAdministratorException;
use Shopsys\FrameworkBundle\Model\Administrator\Exception\DeletingSelfException;
-use Shopsys\FrameworkBundle\Model\Administrator\Exception\DuplicateUserNameException;
use Shopsys\FrameworkBundle\Model\Administrator\Security\AdministratorRolesChangedFacade;
use Shopsys\FrameworkBundle\Model\AdminNavigation\BreadcrumbOverrider;
use Shopsys\FrameworkBundle\Model\Security\Authenticator;
@@ -121,30 +120,23 @@ public function editAction(Request $request, int $id)
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
- try {
- $this->administratorFacade->edit($id, $administratorData);
-
- if ($loggedUser->getId() === $id) {
- $this->administratorRolesChangedFacade->refreshAdministratorToken($administrator);
- }
-
- $this->addSuccessFlashTwig(
- t('Administrator {{ name }} modified'),
- [
- 'name' => $administratorData->realName,
- 'url' => $this->generateUrl('admin_administrator_edit', ['id' => $administrator->getId()]),
- ],
- );
-
- return $this->redirectToRoute('admin_administrator_list');
- } catch (DuplicateUserNameException $ex) {
- $this->addErrorFlashTwig(
- t('Login name {{ name }} is already used'),
- [
- 'name' => $administratorData->username,
- ],
- );
+ $this->administratorFacade->edit($id, $administratorData);
+
+ if ($loggedUser->getId() === $id) {
+ $this->administratorRolesChangedFacade->refreshAdministratorToken($administrator);
}
+
+ $this->addSuccessFlashTwig(
+ t('Administrator {{ name }} modified'),
+ [
+ 'name' => $administratorData->realName,
+ 'url' => $this->generateUrl('admin_administrator_edit', ['id' => $administrator->getId()]),
+ ],
+ );
+
+ $redirectRouteName = $this->isGranted(Roles::ROLE_ADMINISTRATOR_VIEW) ? 'admin_administrator_list' : 'admin_default_dashboard';
+
+ return $this->redirectToRoute($redirectRouteName);
}
if ($form->isSubmitted() && !$form->isValid()) {
@@ -193,27 +185,18 @@ public function newAction(Request $request)
if ($form->isSubmitted() && $form->isValid()) {
$administratorData = $form->getData();
- try {
- $administrator = $this->administratorFacade->create($administratorData);
- $this->administratorPasswordFacade->resetPassword($administrator->getUsername());
-
- $this->addSuccessFlashTwig(
- t('Administrator {{ name }} created. A link to set a password has been sent to his email.'),
- [
- 'name' => $administrator->getRealName(),
- 'url' => $this->generateUrl('admin_administrator_edit', ['id' => $administrator->getId()]),
- ],
- );
-
- return $this->redirectToRoute('admin_administrator_list');
- } catch (DuplicateUserNameException $ex) {
- $this->addErrorFlashTwig(
- t('Login name {{ name }} is already used'),
- [
- 'name' => $administratorData->username,
- ],
- );
- }
+ $administrator = $this->administratorFacade->create($administratorData);
+ $this->administratorPasswordFacade->resetPassword($administrator->getUsername());
+
+ $this->addSuccessFlashTwig(
+ t('Administrator {{ name }} created. A link to set a password has been sent to his email.'),
+ [
+ 'name' => $administrator->getRealName(),
+ 'url' => $this->generateUrl('admin_administrator_edit', ['id' => $administrator->getId()]),
+ ],
+ );
+
+ return $this->redirectToRoute('admin_administrator_list');
}
if ($form->isSubmitted() && !$form->isValid()) {
@@ -551,7 +534,9 @@ public function setNewPasswordAction(Request $request): Response
$this->authenticator->loginAdministrator($administrator);
}
- return $this->redirectToRoute('admin_administrator_list');
+ $this->addSuccessFlash(t('Password has been successfully set.'));
+
+ return $this->redirectToRoute('admin_default_dashboard');
}
if ($form->isSubmitted() && !$form->isValid()) {
diff --git a/src/Form/Admin/Administrator/AdministratorFormType.php b/src/Form/Admin/Administrator/AdministratorFormType.php
index 43b7ddedb8..6f0c350ecf 100644
--- a/src/Form/Admin/Administrator/AdministratorFormType.php
+++ b/src/Form/Admin/Administrator/AdministratorFormType.php
@@ -6,6 +6,7 @@
use Shopsys\FrameworkBundle\Component\Router\Security\RouteCsrfProtector;
use Shopsys\FrameworkBundle\Form\Constraints\Email;
+use Shopsys\FrameworkBundle\Form\Constraints\UniqueEntityField;
use Shopsys\FrameworkBundle\Form\DisplayOnlyType;
use Shopsys\FrameworkBundle\Form\DisplayOnlyUrlType;
use Shopsys\FrameworkBundle\Form\GroupType;
@@ -68,6 +69,12 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
new Constraints\Length(
['max' => 100, 'maxMessage' => 'Username cannot be longer than {{ limit }} characters'],
),
+ new UniqueEntityField([
+ 'entityInstance' => $options['administrator'],
+ 'message' => 'Administrator with user name "{{ value }}" is already registered',
+ 'fieldName' => 'username',
+ 'entityName' => Administrator::class,
+ ]),
],
'label' => t('Login name'),
])
@@ -88,6 +95,12 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
new Constraints\Length(
['max' => 255, 'maxMessage' => 'Email cannot be longer than {{ limit }} characters'],
),
+ new UniqueEntityField([
+ 'entityInstance' => $options['administrator'],
+ 'message' => 'Administrator with email "{{ value }}" is already registered',
+ 'fieldName' => 'email',
+ 'entityName' => Administrator::class,
+ ]),
],
'label' => t('Email'),
]);
diff --git a/src/Form/Constraints/UniqueEntityField.php b/src/Form/Constraints/UniqueEntityField.php
new file mode 100644
index 0000000000..86ccfb094b
--- /dev/null
+++ b/src/Form/Constraints/UniqueEntityField.php
@@ -0,0 +1,18 @@
+em->getRepository($constraint->entityName)->findOneBy([$constraint->fieldName => $value]);
+
+ if ($entity !== null && $entity !== $constraint->entityInstance) {
+ $this->context->buildViolation($constraint->message)
+ ->setParameter('{{ value }}', $value)
+ ->setParameter('{{ fieldName }}', $constraint->fieldName)
+ ->addViolation();
+ }
+ }
+}
diff --git a/src/Migrations/Version20180702111015.php b/src/Migrations/Version20180702111015.php
index 5da823acec..f828f7b57a 100644
--- a/src/Migrations/Version20180702111015.php
+++ b/src/Migrations/Version20180702111015.php
@@ -25,7 +25,7 @@ public function up(Schema $schema): void
$this->sql(
'INSERT INTO administrators (id, username, real_name, password, login_token, email, superadmin) VALUES '
- . '(1, \'superadmin\', \'superadmin\', \'$2y$12$ppwYj/By0pDkiLlE.ssf6uuwCvtfdDfsJJNr84fU59HmxSfj0luSC\', \'\', \'no-reply@shopsys.com\', true),'
+ . '(1, \'superadmin\', \'superadmin\', \'$2y$12$ppwYj/By0pDkiLlE.ssf6uuwCvtfdDfsJJNr84fU59HmxSfj0luSC\', \'\', \'no-reply.1@shopsys.com\', true),'
. '(2, \'admin\', \'admin\', \'$2y$12$tRU86hi0UxWEMQzP08nl..hKiClF.Pj3D1oIcKDL.aA7ph2Vomwh2\', \'\', \'no-reply@shopsys.com\', false)',
);
diff --git a/src/Migrations/Version20241220094923.php b/src/Migrations/Version20241220094923.php
new file mode 100644
index 0000000000..74951eb712
--- /dev/null
+++ b/src/Migrations/Version20241220094923.php
@@ -0,0 +1,26 @@
+sql('CREATE UNIQUE INDEX UNIQ_73A716FE7927C74 ON administrators (email)');
+ }
+
+ /**
+ * @param \Doctrine\DBAL\Schema\Schema $schema
+ */
+ public function down(Schema $schema): void
+ {
+ }
+}
diff --git a/src/Model/Administrator/Administrator.php b/src/Model/Administrator/Administrator.php
index 723ce994c0..97e885208c 100644
--- a/src/Model/Administrator/Administrator.php
+++ b/src/Model/Administrator/Administrator.php
@@ -80,7 +80,7 @@ class Administrator implements UserInterface, UniqueLoginInterface, TimelimitLog
/**
* @var string
- * @ORM\Column(type="string", length=255)
+ * @ORM\Column(type="string", length=255, unique=true)
*/
protected $email;
diff --git a/src/Model/Administrator/AdministratorFacade.php b/src/Model/Administrator/AdministratorFacade.php
index 454396cf26..ce54c2f4b6 100644
--- a/src/Model/Administrator/AdministratorFacade.php
+++ b/src/Model/Administrator/AdministratorFacade.php
@@ -10,7 +10,6 @@
use Shopsys\FrameworkBundle\Model\Administrator\Exception\DeletingLastAdministratorException;
use Shopsys\FrameworkBundle\Model\Administrator\Exception\DeletingSelfException;
use Shopsys\FrameworkBundle\Model\Administrator\Exception\DeletingSuperadminException;
-use Shopsys\FrameworkBundle\Model\Administrator\Exception\DuplicateUserNameException;
use Shopsys\FrameworkBundle\Model\Administrator\Role\AdministratorRoleFacade;
use Shopsys\FrameworkBundle\Model\Administrator\Security\Exception\AdministratorIsNotLoggedException;
use Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface;
@@ -42,11 +41,6 @@ public function __construct(
*/
public function create(AdministratorData $administratorData): Administrator
{
- $administratorByUserName = $this->administratorRepository->findByUserName($administratorData->username);
-
- if ($administratorByUserName !== null) {
- throw new DuplicateUserNameException($administratorByUserName->getUsername());
- }
$administrator = $this->administratorFactory->create($administratorData);
$this->em->persist($administrator);
@@ -65,7 +59,6 @@ public function create(AdministratorData $administratorData): Administrator
public function edit($administratorId, AdministratorData $administratorData): Administrator
{
$administrator = $this->administratorRepository->getById($administratorId);
- $this->checkUsername($administrator, $administratorData->username);
$administrator->edit($administratorData);
$this->em->flush();
@@ -75,22 +68,6 @@ public function edit($administratorId, AdministratorData $administratorData): Ad
return $administrator;
}
- /**
- * @param \Shopsys\FrameworkBundle\Model\Administrator\Administrator $administrator
- * @param string $username
- */
- protected function checkUsername(Administrator $administrator, string $username): void
- {
- $administratorByUserName = $this->administratorRepository->findByUserName($username);
-
- if ($administratorByUserName !== null
- && $administratorByUserName !== $administrator
- && $administratorByUserName->getUsername() === $username
- ) {
- throw new DuplicateUserNameException($administrator->getUsername());
- }
- }
-
/**
* @param int $administratorId
*/
diff --git a/src/Model/Administrator/Exception/DuplicateUserNameException.php b/src/Model/Administrator/Exception/DuplicateUserNameException.php
deleted file mode 100644
index 4bddc183d3..0000000000
--- a/src/Model/Administrator/Exception/DuplicateUserNameException.php
+++ /dev/null
@@ -1,19 +0,0 @@
-{{ name }} is already used"
-msgstr "Přihlašovací jméno {{ name }} je již použito"
-
msgid "Login time"
msgstr "Čas přihlášení"
@@ -3013,6 +3010,9 @@ msgstr "Heslo"
msgid "Password again"
msgstr "Heslo znovu"
+msgid "Password has been successfully set."
+msgstr "Heslo bylo úspěšně nastaveno."
+
msgid "Password has to include uppercase letters, lowercase letters, numbers and must be longer than 10 characters."
msgstr "Heslo musí obsahovat velká písmena, malá písmena, číslice a musí být delší než 10 znaků."
diff --git a/src/Resources/translations/messages.en.po b/src/Resources/translations/messages.en.po
index 8a50dcb2f5..e29a260eec 100644
--- a/src/Resources/translations/messages.en.po
+++ b/src/Resources/translations/messages.en.po
@@ -2356,9 +2356,6 @@ msgstr ""
msgid "Login name"
msgstr ""
-msgid "Login name {{ name }} is already used"
-msgstr ""
-
msgid "Login time"
msgstr ""
@@ -3013,6 +3010,9 @@ msgstr ""
msgid "Password again"
msgstr ""
+msgid "Password has been successfully set."
+msgstr ""
+
msgid "Password has to include uppercase letters, lowercase letters, numbers and must be longer than 10 characters."
msgstr ""
diff --git a/src/Resources/translations/validators.cs.po b/src/Resources/translations/validators.cs.po
index 7392740973..e839c485ff 100644
--- a/src/Resources/translations/validators.cs.po
+++ b/src/Resources/translations/validators.cs.po
@@ -7,6 +7,12 @@ msgstr ""
msgid "Address {{ url }} already exists."
msgstr "Adresa {{ url }} již existuje."
+msgid "Administrator with email \"{{ value }}\" is already registered"
+msgstr "Aministrátor s e-mailem \"{{ value }}\" je již registrován"
+
+msgid "Administrator with user name \"{{ value }}\" is already registered"
+msgstr "Aministrátor s uživatelským jménem \"{{ value }}\" je již registrován"
+
msgid "Amount of money should be greater than or equal to zero."
msgstr "Tato částka musí být větší nebo rovna nule."
@@ -547,6 +553,9 @@ msgstr "DIČ nesmí být delší než {{ limit }} znaků"
msgid "Telephone number cannot be longer than {{ limit }} characters"
msgstr "Telefon nesmí být delší než {{ limit }} znaků"
+msgid "The \"{{ value }}\" value of \"{{ fieldName }}\" field must be unique"
+msgstr "Hodnota \"{{ value }}\" pole \"{{ fieldName }}\" musí být unikátní"
+
msgid "The amount of money should be {{ limit }} or less."
msgstr "Tato částka musí být {{ limit }} nebo méně."
diff --git a/src/Resources/translations/validators.en.po b/src/Resources/translations/validators.en.po
index 627a23a084..3c0138118f 100644
--- a/src/Resources/translations/validators.en.po
+++ b/src/Resources/translations/validators.en.po
@@ -7,6 +7,12 @@ msgstr ""
msgid "Address {{ url }} already exists."
msgstr ""
+msgid "Administrator with email \"{{ value }}\" is already registered"
+msgstr ""
+
+msgid "Administrator with user name \"{{ value }}\" is already registered"
+msgstr ""
+
msgid "Amount of money should be greater than or equal to zero."
msgstr ""
@@ -547,6 +553,9 @@ msgstr ""
msgid "Telephone number cannot be longer than {{ limit }} characters"
msgstr ""
+msgid "The \"{{ value }}\" value of \"{{ fieldName }}\" field must be unique"
+msgstr ""
+
msgid "The amount of money should be {{ limit }} or less."
msgstr ""