Skip to content

Commit 9dd496e

Browse files
committed
refactored handler
Signed-off-by: MarioRadu <[email protected]>
1 parent 8eafd9b commit 9dd496e

File tree

13 files changed

+145
-66
lines changed

13 files changed

+145
-66
lines changed

psalm-baseline.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,9 @@
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>
1419
</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/Controller/AdminController.php

Lines changed: 78 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@
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;
@@ -23,6 +22,7 @@
2322
use Frontend\Admin\InputFilter\EditAdminInputFilter;
2423
use Frontend\Admin\Service\AdminServiceInterface;
2524
use Frontend\App\Common\ServerRequestAwareTrait;
25+
use Frontend\App\Exception\IdentityException;
2626
use Frontend\App\Message;
2727
use Frontend\App\Plugin\FormsPlugin;
2828
use Laminas\Authentication\AuthenticationServiceInterface;
@@ -37,8 +37,6 @@
3737
use Psr\Http\Message\ResponseInterface;
3838
use Throwable;
3939

40-
use function password_verify;
41-
4240
class AdminController extends AbstractActionController
4341
{
4442
use ServerRequestAwareTrait;
@@ -67,6 +65,12 @@ public function __construct(
6765

6866
public function addAction(): ResponseInterface
6967
{
68+
$this->denyRequest(
69+
! $this->isGet() || ! $this->isPost(),
70+
Message::METHOD_NOT_ALLOWED,
71+
StatusCodeInterface::STATUS_METHOD_NOT_ALLOWED
72+
);
73+
7074
if ($this->isPost()) {
7175
$this->adminForm->setData($this->getPostParams());
7276
if ($this->adminForm->isValid()) {
@@ -75,11 +79,11 @@ public function addAction(): ResponseInterface
7579
try {
7680
$this->adminService->createAdmin($result);
7781
return new JsonResponse(['message' => Message::ADMIN_CREATED_SUCCESSFULLY]);
78-
} catch (ORMException $e) {
82+
} catch (IdentityException $e) {
7983
$this->logErrors($e, Message::CREATE_ADMIN);
8084
return new JsonResponse(
8185
['message' => $e->getMessage()],
82-
StatusCodeInterface::STATUS_INTERNAL_SERVER_ERROR
86+
StatusCodeInterface::STATUS_UNPROCESSABLE_ENTITY
8387
);
8488
} catch (Throwable $e) {
8589
$this->logErrors($e, Message::CREATE_ADMIN);
@@ -102,16 +106,20 @@ public function addAction(): ResponseInterface
102106
[
103107
'form' => $this->adminForm,
104108
'formAction' => '/admin/add',
109+
'method' => RequestMethodInterface::METHOD_POST,
105110
]
106111
),
107112
]);
108113
}
109114

110-
/**
111-
* @throws NonUniqueResultException
112-
*/
113115
public function editAction(): ResponseInterface
114116
{
117+
$this->denyRequest(
118+
! $this->isGet() || ! $this->isPost(),
119+
Message::METHOD_NOT_ALLOWED,
120+
StatusCodeInterface::STATUS_METHOD_NOT_ALLOWED
121+
);
122+
115123
$uuid = $this->getAttribute('uuid');
116124

117125
/** @var Admin $admin */
@@ -121,18 +129,18 @@ public function editAction(): ResponseInterface
121129

122130
if ($this->isPost()) {
123131
$this->adminForm->setData($this->getPostParams());
124-
$this->adminForm->setDifferentInputFilter(new EditAdminInputFilter());
132+
$this->adminForm->setInputFilter(new EditAdminInputFilter());
125133
if ($this->adminForm->isValid()) {
126134
/** @var array $result */
127135
$result = $this->adminForm->getData();
128136
try {
129137
$this->adminService->updateAdmin($admin, $result);
130138
return new JsonResponse(['message' => Message::ADMIN_UPDATED_SUCCESSFULLY]);
131-
} catch (ORMException $e) {
139+
} catch (IdentityException $e) {
132140
$this->logErrors($e, Message::UPDATE_ADMIN);
133141
return new JsonResponse(
134142
['message' => $e->getMessage()],
135-
StatusCodeInterface::STATUS_INTERNAL_SERVER_ERROR
143+
StatusCodeInterface::STATUS_UNPROCESSABLE_ENTITY
136144
);
137145
} catch (Throwable $e) {
138146
$this->logErrors($e, Message::UPDATE_ADMIN);
@@ -157,25 +165,19 @@ public function editAction(): ResponseInterface
157165
[
158166
'form' => $this->adminForm,
159167
'formAction' => '/admin/edit/' . $uuid,
168+
'method' => RequestMethodInterface::METHOD_POST,
160169
]
161170
),
162171
]);
163172
}
164173

165-
/**
166-
* @throws NonUniqueResultException
167-
*/
168174
public function deleteAction(): ResponseInterface
169175
{
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);
178-
}
176+
$this->denyRequest(
177+
! $this->isDelete(),
178+
Message::METHOD_NOT_ALLOWED,
179+
StatusCodeInterface::STATUS_METHOD_NOT_ALLOWED
180+
);
179181

180182
$uuid = $this->getAttribute('uuid');
181183
if (empty($uuid)) {
@@ -200,11 +202,14 @@ public function deleteAction(): ResponseInterface
200202
}
201203
}
202204

203-
/**
204-
* @throws NonUniqueResultException
205-
*/
206205
public function listAction(): ResponseInterface
207206
{
207+
$this->denyRequest(
208+
! $this->isGet(),
209+
Message::METHOD_NOT_ALLOWED,
210+
StatusCodeInterface::STATUS_METHOD_NOT_ALLOWED
211+
);
212+
208213
$result = $this->adminService->getAdmins(
209214
$this->getQueryParam('offset', 0, 'int'),
210215
$this->getQueryParam('limit', 30, 'int'),
@@ -218,6 +223,12 @@ public function listAction(): ResponseInterface
218223

219224
public function manageAction(): ResponseInterface
220225
{
226+
$this->denyRequest(
227+
! $this->isGet(),
228+
Message::METHOD_NOT_ALLOWED,
229+
StatusCodeInterface::STATUS_METHOD_NOT_ALLOWED
230+
);
231+
221232
return new HtmlResponse(
222233
$this->template->render('admin::list')
223234
);
@@ -229,6 +240,12 @@ public function manageAction(): ResponseInterface
229240
*/
230241
public function loginAction(): ResponseInterface
231242
{
243+
$this->denyRequest(
244+
! $this->isGet() || ! $this->isPost(),
245+
Message::METHOD_NOT_ALLOWED,
246+
StatusCodeInterface::STATUS_METHOD_NOT_ALLOWED
247+
);
248+
232249
if ($this->authenticationService->hasIdentity()) {
233250
return new RedirectResponse($this->router->generateUri("dashboard"));
234251
}
@@ -296,6 +313,12 @@ public function loginAction(): ResponseInterface
296313

297314
public function logoutAction(): ResponseInterface
298315
{
316+
$this->denyRequest(
317+
! $this->isGet(),
318+
Message::METHOD_NOT_ALLOWED,
319+
StatusCodeInterface::STATUS_METHOD_NOT_ALLOWED
320+
);
321+
299322
$this->authenticationService->clearIdentity();
300323
return new RedirectResponse(
301324
$this->router->generateUri('admin', ['action' => 'login'])
@@ -304,6 +327,12 @@ public function logoutAction(): ResponseInterface
304327

305328
public function accountAction(): ResponseInterface
306329
{
330+
$this->denyRequest(
331+
! $this->isGet() || ! $this->isPost(),
332+
Message::METHOD_NOT_ALLOWED,
333+
StatusCodeInterface::STATUS_METHOD_NOT_ALLOWED
334+
);
335+
307336
$form = new AccountForm();
308337
$changePasswordForm = new ChangePasswordForm();
309338
$identity = $this->authenticationService->getIdentity();
@@ -317,7 +346,7 @@ public function accountAction(): ResponseInterface
317346
try {
318347
$this->adminService->updateAdmin($admin, $result);
319348
$this->messenger->addSuccess(Message::ACCOUNT_UPDATE_SUCCESSFULLY);
320-
} catch (ORMException $e) {
349+
} catch (IdentityException $e) {
321350
$this->logErrors($e, Message::UPDATE_ADMIN);
322351
$this->messenger->addError($e->getMessage());
323352
} catch (Throwable $e) {
@@ -342,6 +371,12 @@ public function accountAction(): ResponseInterface
342371

343372
public function changePasswordAction(): ResponseInterface
344373
{
374+
$this->denyRequest(
375+
! $this->isGet() || ! $this->isPost(),
376+
Message::METHOD_NOT_ALLOWED,
377+
StatusCodeInterface::STATUS_METHOD_NOT_ALLOWED
378+
);
379+
345380
$changePasswordForm = new ChangePasswordForm();
346381
/** @var AdminIdentity $adminIdentity */
347382
$adminIdentity = $this->authenticationService->getIdentity();
@@ -354,11 +389,11 @@ public function changePasswordAction(): ResponseInterface
354389
if ($changePasswordForm->isValid()) {
355390
/** @var array $result */
356391
$result = $changePasswordForm->getData();
357-
if (password_verify($result['currentPassword'], $admin->getPassword())) {
392+
if ($admin->verifyPassword($result['currentPassword'])) {
358393
try {
359394
$this->adminService->updateAdmin($admin, $result);
360395
$this->messenger->addSuccess(Message::ACCOUNT_UPDATE_SUCCESSFULLY);
361-
} catch (ORMException $e) {
396+
} catch (IdentityException $e) {
362397
$this->logErrors($e, Message::CHANGE_PASSWORD);
363398
$this->messenger->addError($e->getMessage());
364399
} catch (Throwable $e) {
@@ -378,6 +413,12 @@ public function changePasswordAction(): ResponseInterface
378413

379414
public function loginsAction(): ResponseInterface
380415
{
416+
$this->denyRequest(
417+
! $this->isGet(),
418+
Message::METHOD_NOT_ALLOWED,
419+
StatusCodeInterface::STATUS_METHOD_NOT_ALLOWED
420+
);
421+
381422
return new HtmlResponse(
382423
$this->template->render('admin::list-logins')
383424
);
@@ -388,6 +429,12 @@ public function loginsAction(): ResponseInterface
388429
*/
389430
public function listLoginsAction(): ResponseInterface
390431
{
432+
$this->denyRequest(
433+
! $this->isGet(),
434+
Message::METHOD_NOT_ALLOWED,
435+
StatusCodeInterface::STATUS_METHOD_NOT_ALLOWED
436+
);
437+
391438
$result = $this->adminService->getAdminLogins(
392439
$this->getQueryParam('offset', 0, 'int'),
393440
$this->getQueryParam('limit', 30, 'int'),
@@ -398,7 +445,7 @@ public function listLoginsAction(): ResponseInterface
398445
return new JsonResponse($result);
399446
}
400447

401-
public function logErrors(Throwable|Exception $e, string $message): void
448+
private function logErrors(Throwable $e, string $message): void
402449
{
403450
$this->logger->err($message, [
404451
'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;

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();

src/Admin/src/Service/AdminService.php

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
use Doctrine\Common\Collections\ArrayCollection;
88
use Doctrine\ORM\EntityRepository;
9-
use Doctrine\ORM\Exception\ORMException;
109
use Doctrine\ORM\NonUniqueResultException;
1110
use Dot\DependencyInjection\Attribute\Inject;
1211
use Dot\GeoIP\Service\LocationServiceInterface;
@@ -15,6 +14,7 @@
1514
use Frontend\Admin\Entity\AdminRole;
1615
use Frontend\Admin\Repository\AdminRepository;
1716
use Frontend\Admin\Repository\AdminRoleRepository;
17+
use Frontend\App\Exception\IdentityException;
1818
use Frontend\App\Service\IpService;
1919

2020
use function implode;
@@ -127,14 +127,10 @@ public function getAdminLogins(
127127
return $result;
128128
}
129129

130-
/**
131-
* @throws NonUniqueResultException
132-
* @throws ORMException
133-
*/
134130
public function createAdmin(array $data): Admin
135131
{
136132
if ($this->exists($data['identity'])) {
137-
throw new \Frontend\App\Exception\ORMException('An account with this identity already exists.');
133+
throw IdentityException::duplicate();
138134
}
139135

140136
$admin = (new Admin())
@@ -152,17 +148,13 @@ public function createAdmin(array $data): Admin
152148
return $this->getAdminRepository()->saveAdmin($admin);
153149
}
154150

155-
/**
156-
* @throws NonUniqueResultException
157-
* @throws ORMException
158-
*/
159151
public function updateAdmin(Admin $admin, array $data): Admin
160152
{
161153
if (! empty($data['identity'])) {
162154
if (! $this->exists($data['identity'])) {
163155
$admin->setIdentity($data['identity']);
164156
} elseif ($admin->getIdentity() !== $data['identity']) {
165-
throw new \Frontend\App\Exception\ORMException('An account with this identity already exists');
157+
throw IdentityException::duplicate();
166158
}
167159
}
168160
if (! empty($data['password'])) {

src/App/assets/js/components/_admin.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ $(document).ready(() => {
2626
return;
2727
}
2828

29-
request('POST', form.attr('action'), new FormData(form.get(0)))
29+
request(form.attr('method'), form.attr('action'), new FormData(form.get(0)))
3030
.then(data => {
3131
messages.html('');
3232
messages.append(

0 commit comments

Comments
 (0)