Skip to content

Commit a1bb87d

Browse files
authored
Merge pull request #265 from dotkernel/issue-241
Refactored handler
2 parents 8eafd9b + bab6f37 commit a1bb87d

File tree

18 files changed

+233
-98
lines changed

18 files changed

+233
-98
lines changed

.laminas-ci/pre-run.sh

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,4 @@ if [[ ${COMMAND} =~ phpunit ]];then
1212
cp config/autoload/mail.local.php.dist config/autoload/mail.local.php
1313
cp config/autoload/local.test.php.dist config/autoload/local.test.php
1414

15-
echo 'running if'
16-
1715
fi

psalm-baseline.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,14 @@
1111
<code>iterable</code>
1212
</LessSpecificImplementedReturnType>
1313
</file>
14+
<file src="src/Admin/src/Form/AdminForm.php">
15+
<UndefinedInterfaceMethod>
16+
<code>init</code>
17+
</UndefinedInterfaceMethod>
18+
</file>
19+
<file src="src/Admin/src/Form/AdminDeleteForm.php">
20+
<UndefinedInterfaceMethod>
21+
<code>init</code>
22+
</UndefinedInterfaceMethod>
23+
</file>
1424
</files>

public/js/app.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Admin/src/ConfigProvider.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use Frontend\Admin\Entity\Admin;
1414
use Frontend\Admin\Entity\AdminInterface;
1515
use Frontend\Admin\Factory\AuthenticationServiceFactory;
16+
use Frontend\Admin\Form\AdminDeleteForm;
1617
use Frontend\Admin\Form\AdminForm;
1718
use Frontend\Admin\Form\ChangePasswordForm;
1819
use Frontend\Admin\Form\LoginForm;
@@ -79,6 +80,7 @@ public function getForms(): array
7980
'factories' => [
8081
LoginForm::class => ElementFactory::class,
8182
ChangePasswordForm::class => ElementFactory::class,
83+
AdminDeleteForm::class => ElementFactory::class,
8284
],
8385
'aliases' => [],
8486
'delegators' => [],

src/Admin/src/Controller/AdminController.php

Lines changed: 33 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,26 @@
44

55
namespace Frontend\Admin\Controller;
66

7-
use Doctrine\ORM\Exception\ORMException;
87
use Doctrine\ORM\NonUniqueResultException;
98
use Dot\Controller\AbstractActionController;
109
use Dot\DependencyInjection\Attribute\Inject;
1110
use Dot\FlashMessenger\FlashMessengerInterface;
12-
use Exception;
11+
use Fig\Http\Message\RequestMethodInterface;
1312
use Fig\Http\Message\StatusCodeInterface;
1413
use Frontend\Admin\Adapter\AuthenticationAdapter;
1514
use Frontend\Admin\Entity\Admin;
1615
use Frontend\Admin\Entity\AdminIdentity;
1716
use Frontend\Admin\Entity\AdminLogin;
1817
use Frontend\Admin\Form\AccountForm;
18+
use Frontend\Admin\Form\AdminDeleteForm;
1919
use Frontend\Admin\Form\AdminForm;
2020
use Frontend\Admin\Form\ChangePasswordForm;
2121
use Frontend\Admin\Form\LoginForm;
2222
use Frontend\Admin\FormData\AdminFormData;
2323
use Frontend\Admin\InputFilter\EditAdminInputFilter;
2424
use Frontend\Admin\Service\AdminServiceInterface;
2525
use Frontend\App\Common\ServerRequestAwareTrait;
26+
use Frontend\App\Exception\IdentityException;
2627
use Frontend\App\Message;
2728
use Frontend\App\Plugin\FormsPlugin;
2829
use Laminas\Authentication\AuthenticationServiceInterface;
@@ -37,8 +38,6 @@
3738
use Psr\Http\Message\ResponseInterface;
3839
use Throwable;
3940

40-
use function password_verify;
41-
4241
class AdminController extends AbstractActionController
4342
{
4443
use ServerRequestAwareTrait;
@@ -75,11 +74,11 @@ public function addAction(): ResponseInterface
7574
try {
7675
$this->adminService->createAdmin($result);
7776
return new JsonResponse(['message' => Message::ADMIN_CREATED_SUCCESSFULLY]);
78-
} catch (ORMException $e) {
77+
} catch (IdentityException $e) {
7978
$this->logErrors($e, Message::CREATE_ADMIN);
8079
return new JsonResponse(
8180
['message' => $e->getMessage()],
82-
StatusCodeInterface::STATUS_INTERNAL_SERVER_ERROR
81+
StatusCodeInterface::STATUS_UNPROCESSABLE_ENTITY
8382
);
8483
} catch (Throwable $e) {
8584
$this->logErrors($e, Message::CREATE_ADMIN);
@@ -102,14 +101,12 @@ public function addAction(): ResponseInterface
102101
[
103102
'form' => $this->adminForm,
104103
'formAction' => '/admin/add',
104+
'method' => RequestMethodInterface::METHOD_POST,
105105
]
106106
),
107107
]);
108108
}
109109

110-
/**
111-
* @throws NonUniqueResultException
112-
*/
113110
public function editAction(): ResponseInterface
114111
{
115112
$uuid = $this->getAttribute('uuid');
@@ -121,18 +118,18 @@ public function editAction(): ResponseInterface
121118

122119
if ($this->isPost()) {
123120
$this->adminForm->setData($this->getPostParams());
124-
$this->adminForm->setDifferentInputFilter(new EditAdminInputFilter());
121+
$this->adminForm->setInputFilter(new EditAdminInputFilter());
125122
if ($this->adminForm->isValid()) {
126123
/** @var array $result */
127124
$result = $this->adminForm->getData();
128125
try {
129126
$this->adminService->updateAdmin($admin, $result);
130127
return new JsonResponse(['message' => Message::ADMIN_UPDATED_SUCCESSFULLY]);
131-
} catch (ORMException $e) {
128+
} catch (IdentityException $e) {
132129
$this->logErrors($e, Message::UPDATE_ADMIN);
133130
return new JsonResponse(
134131
['message' => $e->getMessage()],
135-
StatusCodeInterface::STATUS_INTERNAL_SERVER_ERROR
132+
StatusCodeInterface::STATUS_UNPROCESSABLE_ENTITY
136133
);
137134
} catch (Throwable $e) {
138135
$this->logErrors($e, Message::UPDATE_ADMIN);
@@ -157,24 +154,19 @@ public function editAction(): ResponseInterface
157154
[
158155
'form' => $this->adminForm,
159156
'formAction' => '/admin/edit/' . $uuid,
157+
'method' => RequestMethodInterface::METHOD_POST,
160158
]
161159
),
162160
]);
163161
}
164162

165-
/**
166-
* @throws NonUniqueResultException
167-
*/
168163
public function deleteAction(): ResponseInterface
169164
{
170-
if (! $this->isDelete()) {
171-
return new JsonResponse([
172-
'error' => [
173-
'messages' => [
174-
[Message::METHOD_NOT_ALLOWED],
175-
],
176-
],
177-
], StatusCodeInterface::STATUS_METHOD_NOT_ALLOWED);
165+
if (! $this->isPost()) {
166+
return new JsonResponse(
167+
['message' => Message::METHOD_NOT_ALLOWED],
168+
StatusCodeInterface::STATUS_METHOD_NOT_ALLOWED
169+
);
178170
}
179171

180172
$uuid = $this->getAttribute('uuid');
@@ -185,9 +177,17 @@ public function deleteAction(): ResponseInterface
185177
);
186178
}
187179

180+
$form = new AdminDeleteForm();
181+
$form->setData($this->getPostParams());
182+
if (! $form->isValid()) {
183+
return new JsonResponse(
184+
['message' => $this->forms->getMessages($form)],
185+
StatusCodeInterface::STATUS_BAD_REQUEST
186+
);
187+
}
188+
188189
/** @var Admin $admin */
189190
$admin = $this->adminService->getAdminRepository()->findOneBy(['uuid' => $uuid]);
190-
191191
try {
192192
$this->adminService->getAdminRepository()->deleteAdmin($admin);
193193
return new JsonResponse(['message' => Message::ADMIN_DELETED_SUCCESSFULLY]);
@@ -200,9 +200,6 @@ public function deleteAction(): ResponseInterface
200200
}
201201
}
202202

203-
/**
204-
* @throws NonUniqueResultException
205-
*/
206203
public function listAction(): ResponseInterface
207204
{
208205
$result = $this->adminService->getAdmins(
@@ -219,7 +216,9 @@ public function listAction(): ResponseInterface
219216
public function manageAction(): ResponseInterface
220217
{
221218
return new HtmlResponse(
222-
$this->template->render('admin::list')
219+
$this->template->render('admin::list', [
220+
'form' => new AdminDeleteForm(),
221+
])
223222
);
224223
}
225224

@@ -233,8 +232,7 @@ public function loginAction(): ResponseInterface
233232
return new RedirectResponse($this->router->generateUri("dashboard"));
234233
}
235234

236-
$form = new LoginForm();
237-
235+
$form = new LoginForm();
238236
$shouldRebind = $this->messenger->getData('shouldRebind') ?? true;
239237
if ($shouldRebind) {
240238
$this->forms->restoreState($form);
@@ -297,6 +295,7 @@ public function loginAction(): ResponseInterface
297295
public function logoutAction(): ResponseInterface
298296
{
299297
$this->authenticationService->clearIdentity();
298+
300299
return new RedirectResponse(
301300
$this->router->generateUri('admin', ['action' => 'login'])
302301
);
@@ -317,7 +316,7 @@ public function accountAction(): ResponseInterface
317316
try {
318317
$this->adminService->updateAdmin($admin, $result);
319318
$this->messenger->addSuccess(Message::ACCOUNT_UPDATE_SUCCESSFULLY);
320-
} catch (ORMException $e) {
319+
} catch (IdentityException $e) {
321320
$this->logErrors($e, Message::UPDATE_ADMIN);
322321
$this->messenger->addError($e->getMessage());
323322
} catch (Throwable $e) {
@@ -354,11 +353,11 @@ public function changePasswordAction(): ResponseInterface
354353
if ($changePasswordForm->isValid()) {
355354
/** @var array $result */
356355
$result = $changePasswordForm->getData();
357-
if (password_verify($result['currentPassword'], $admin->getPassword())) {
356+
if ($admin->verifyPassword($result['currentPassword'])) {
358357
try {
359358
$this->adminService->updateAdmin($admin, $result);
360359
$this->messenger->addSuccess(Message::ACCOUNT_UPDATE_SUCCESSFULLY);
361-
} catch (ORMException $e) {
360+
} catch (IdentityException $e) {
362361
$this->logErrors($e, Message::CHANGE_PASSWORD);
363362
$this->messenger->addError($e->getMessage());
364363
} catch (Throwable $e) {
@@ -398,7 +397,7 @@ public function listLoginsAction(): ResponseInterface
398397
return new JsonResponse($result);
399398
}
400399

401-
public function logErrors(Throwable|Exception $e, string $message): void
400+
private function logErrors(Throwable $e, string $message): void
402401
{
403402
$this->logger->err($message, [
404403
'error' => $e->getMessage(),

src/Admin/src/Entity/Admin.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use Frontend\Setting\Entity\Setting;
1414

1515
use function array_map;
16+
use function password_verify;
1617

1718
#[ORM\Entity(repositoryClass: AdminRepository::class)]
1819
#[ORM\Table(name: "admin")]
@@ -131,6 +132,11 @@ public function setPassword(string $password): self
131132
return $this;
132133
}
133134

135+
public function verifyPassword(string $password): bool
136+
{
137+
return password_verify($password, $this->getPassword());
138+
}
139+
134140
public function getStatus(): string
135141
{
136142
return $this->status;
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Frontend\Admin\Form;
6+
7+
use Frontend\Admin\InputFilter\AdminDeleteInputFilter;
8+
use Laminas\Form\Form;
9+
use Laminas\Form\FormInterface;
10+
use Laminas\InputFilter\InputFilterInterface;
11+
12+
/** @template-extends Form<FormInterface> */
13+
class AdminDeleteForm extends Form
14+
{
15+
protected InputFilterInterface $inputFilter;
16+
17+
public function __construct(?string $name = null, array $options = [])
18+
{
19+
parent::__construct($name, $options);
20+
21+
$this->init();
22+
23+
$this->inputFilter = new AdminDeleteInputFilter();
24+
$this->inputFilter->init();
25+
}
26+
27+
public function init(): void
28+
{
29+
$this->add([
30+
'name' => 'confirmation',
31+
'type' => 'checkbox',
32+
'options' => [
33+
'label' => 'Confirmation',
34+
'checked_value' => 'yes',
35+
'unchecked_value' => 'no',
36+
],
37+
'attributes' => [
38+
'value' => 'no',
39+
'id' => 'confirmation',
40+
'class' => 'form-check-input',
41+
],
42+
]);
43+
44+
$this->add([
45+
'name' => 'close',
46+
'type' => 'button',
47+
'options' => [
48+
'label' => 'Close',
49+
],
50+
'attributes' => [
51+
'class' => 'btn btn-default',
52+
'data-bs-dismiss' => 'modal',
53+
'role' => 'button',
54+
],
55+
]);
56+
57+
$this->add([
58+
'name' => 'submit',
59+
'type' => 'submit',
60+
'attributes' => [
61+
'class' => 'btn btn-danger',
62+
'id' => 'modalDeleteBtn',
63+
'value' => 'Delete',
64+
],
65+
]);
66+
}
67+
68+
public function getInputFilter(): InputFilterInterface
69+
{
70+
return $this->inputFilter;
71+
}
72+
73+
public function setInputFilter(InputFilterInterface $inputFilter): void
74+
{
75+
$this->inputFilter = $inputFilter;
76+
$this->inputFilter->init();
77+
}
78+
}

src/Admin/src/Form/AdminForm.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
use Frontend\Admin\InputFilter\AdminInputFilter;
99
use Laminas\Form\Form;
1010
use Laminas\Form\FormInterface;
11-
use Laminas\InputFilter\InputFilter;
1211
use Laminas\InputFilter\InputFilterInterface;
1312

1413
/** @template-extends Form<FormInterface> */
@@ -119,7 +118,7 @@ public function getInputFilter(): InputFilterInterface
119118
return $this->inputFilter;
120119
}
121120

122-
public function setDifferentInputFilter(InputFilter $inputFilter): void
121+
public function setInputFilter(InputFilterInterface $inputFilter): void
123122
{
124123
$this->inputFilter = $inputFilter;
125124
$this->inputFilter->init();
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Frontend\Admin\InputFilter;
6+
7+
use Laminas\InputFilter\Input;
8+
use Laminas\InputFilter\InputFilter;
9+
use Laminas\Validator\InArray;
10+
use Laminas\Validator\NotEmpty;
11+
12+
/** @extends InputFilter<object> */
13+
class AdminDeleteInputFilter extends InputFilter
14+
{
15+
public function init(): void
16+
{
17+
$confirmation = new Input('confirmation');
18+
$confirmation->setRequired(true);
19+
$confirmation->getValidatorChain()->attachByName(NotEmpty::class, [
20+
'break_chain_on_failure' => true,
21+
'message' => 'Please confirm admin deletion.',
22+
]);
23+
24+
$confirmation->getValidatorChain()->attachByName(InArray::class, [
25+
'haystack' => [
26+
'yes',
27+
],
28+
'break_chain_on_failure' => true,
29+
'message' => 'Please confirm the admin deletion.',
30+
]);
31+
32+
$this->add($confirmation);
33+
}
34+
}

0 commit comments

Comments
 (0)