Skip to content

Commit a2e98fd

Browse files
committed
ISSUE-345: refactor validation logic
1 parent 3d12deb commit a2e98fd

25 files changed

+441
-238
lines changed

config/services/providers.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,7 @@ services:
77
PhpList\RestBundle\Service\Provider\SubscriberListProvider:
88
autowire: true
99
autoconfigure: true
10+
11+
PhpList\RestBundle\Service\Provider\AdministratorProvider:
12+
autowire: true
13+
autoconfigure: true

config/services/validators.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,8 @@ services:
2929

3030
PhpList\RestBundle\Validator\Constraint\ContainsPlaceholderValidator:
3131
tags: ['validator.constraint_validator']
32+
33+
PhpList\RestBundle\Validator\Constraint\UniqueLoginNameValidator:
34+
autowire: true
35+
autoconfigure: true
36+
tags: [ 'validator.constraint_validator' ]

src/Controller/AdministratorController.php

Lines changed: 96 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,32 +6,104 @@
66

77
use OpenApi\Attributes as OA;
88
use PhpList\Core\Domain\Model\Identity\Administrator;
9-
use PhpList\RestBundle\Controller\Traits\AuthenticationTrait;
9+
use PhpList\Core\Security\Authentication;
1010
use PhpList\RestBundle\Entity\Request\CreateAdministratorRequest;
1111
use PhpList\RestBundle\Entity\Request\UpdateAdministratorRequest;
1212
use PhpList\RestBundle\Serializer\AdministratorNormalizer;
1313
use PhpList\RestBundle\Service\Manager\AdministratorManager;
14+
use PhpList\RestBundle\Service\Provider\AdministratorProvider;
1415
use PhpList\RestBundle\Validator\RequestValidator;
1516
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
16-
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
1717
use Symfony\Component\HttpFoundation\JsonResponse;
1818
use Symfony\Component\HttpFoundation\Request;
1919
use Symfony\Component\HttpFoundation\Response;
20+
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
2021
use Symfony\Component\Routing\Attribute\Route;
2122

2223
/**
2324
* This controller provides CRUD operations for Administrator entities.
2425
*/
2526
#[Route('/administrators')]
26-
class AdministratorController extends AbstractController
27+
class AdministratorController extends BaseController
2728
{
28-
use AuthenticationTrait;
29-
3029
private AdministratorManager $administratorManager;
30+
private AdministratorNormalizer $normalizer;
31+
private AdministratorProvider $administratorProvider;
3132

32-
public function __construct(AdministratorManager $administratorManager)
33-
{
33+
public function __construct(
34+
Authentication $authentication,
35+
AdministratorManager $administratorManager,
36+
AdministratorNormalizer $normalizer,
37+
RequestValidator $validator,
38+
AdministratorProvider $administratorProvider
39+
) {
40+
parent::__construct($authentication, $validator);
3441
$this->administratorManager = $administratorManager;
42+
$this->normalizer = $normalizer;
43+
$this->administratorProvider = $administratorProvider;
44+
}
45+
46+
#[Route('', name: 'get_administrators', methods: ['GET'])]
47+
#[OA\Post(
48+
path: '/administrators',
49+
description: 'Get list of administrators.',
50+
summary: 'Get Administrators',
51+
tags: ['administrators'],
52+
parameters: [
53+
new OA\Parameter(
54+
name: 'session',
55+
description: 'Session ID obtained from authentication',
56+
in: 'header',
57+
required: true,
58+
schema: new OA\Schema(
59+
type: 'string'
60+
)
61+
),
62+
new OA\Parameter(
63+
name: 'after_id',
64+
description: 'Last id (starting from 0)',
65+
in: 'query',
66+
required: false,
67+
schema: new OA\Schema(type: 'integer', default: 1, minimum: 1)
68+
),
69+
new OA\Parameter(
70+
name: 'limit',
71+
description: 'Number of results per page',
72+
in: 'query',
73+
required: false,
74+
schema: new OA\Schema(type: 'integer', default: 25, maximum: 100, minimum: 1)
75+
)
76+
],
77+
responses: [
78+
new OA\Response(
79+
response: 200,
80+
description: 'Success',
81+
content: new OA\JsonContent(
82+
properties: [
83+
new OA\Property(
84+
property: 'items',
85+
type: 'array',
86+
items: new OA\Items(ref: '#/components/schemas/Administrator')
87+
),
88+
new OA\Property(property: 'pagination', ref: '#/components/schemas/CursorPagination')
89+
],
90+
type: 'object'
91+
)
92+
),
93+
new OA\Response(
94+
response: 400,
95+
description: 'Invalid input'
96+
)
97+
]
98+
)]
99+
public function getAdministrators(Request $request): JsonResponse
100+
{
101+
$this->requireAuthentication($request);
102+
103+
return new JsonResponse(
104+
$this->administratorProvider->getPaginatedList($request),
105+
Response::HTTP_OK
106+
);
35107
}
36108

37109
#[Route('', name: 'create_administrator', methods: ['POST'])]
@@ -49,7 +121,7 @@ public function __construct(AdministratorManager $administratorManager)
49121
new OA\Response(
50122
response: 201,
51123
description: 'Administrator created successfully',
52-
content: new OA\JsonContent(ref: '#/components/schemas/CreateAdministratorRequest')
124+
content: new OA\JsonContent(ref: '#/components/schemas/Administrator')
53125
),
54126
new OA\Response(
55127
response: 400,
@@ -62,11 +134,11 @@ public function createAdministrator(
62134
RequestValidator $validator,
63135
AdministratorNormalizer $normalizer
64136
): JsonResponse {
137+
$this->requireAuthentication($request);
138+
65139
/** @var CreateAdministratorRequest $dto */
66140
$dto = $validator->validate($request, CreateAdministratorRequest::class);
67-
68141
$administrator = $this->administratorManager->createAdministrator($dto);
69-
70142
$json = $normalizer->normalize($administrator, 'json');
71143

72144
return new JsonResponse($json, Response::HTTP_CREATED);
@@ -100,16 +172,17 @@ public function createAdministrator(
100172
]
101173
)]
102174
public function getAdministrator(
175+
Request $request,
103176
#[MapEntity(mapping: ['administratorId' => 'id'])] ?Administrator $administrator,
104-
AdministratorNormalizer $normalizer
105177
): JsonResponse {
178+
$this->requireAuthentication($request);
179+
106180
if (!$administrator) {
107-
return new JsonResponse(['message' => 'Administrator not found.'], Response::HTTP_NOT_FOUND);
181+
throw new NotFoundHttpException('Administrator not found.');
108182
}
183+
$json = $this->normalizer->normalize($administrator, 'json');
109184

110-
$json = $normalizer->normalize($administrator, 'json');
111-
112-
return new JsonResponse($json);
185+
return new JsonResponse($json, Response::HTTP_OK);
113186
}
114187

115188
#[Route('/{administratorId}', name: 'update_administrator', methods: ['PUT'])]
@@ -146,15 +219,14 @@ public function getAdministrator(
146219
public function updateAdministrator(
147220
Request $request,
148221
#[MapEntity(mapping: ['administratorId' => 'id'])] ?Administrator $administrator,
149-
RequestValidator $validator
150222
): JsonResponse {
223+
$this->requireAuthentication($request);
224+
151225
if (!$administrator) {
152-
return new JsonResponse(['message' => 'Administrator not found.'], Response::HTTP_NOT_FOUND);
226+
throw new NotFoundHttpException('Administrator not found.');
153227
}
154-
155228
/** @var UpdateAdministratorRequest $dto */
156-
$dto = $validator->validate($request, UpdateAdministratorRequest::class);
157-
229+
$dto = $this->validator->validate($request, UpdateAdministratorRequest::class);
158230
$this->administratorManager->updateAdministrator($administrator, $dto);
159231

160232
return new JsonResponse(null, Response::HTTP_OK);
@@ -187,12 +259,14 @@ public function updateAdministrator(
187259
]
188260
)]
189261
public function deleteAdministrator(
262+
Request $request,
190263
#[MapEntity(mapping: ['administratorId' => 'id'])] ?Administrator $administrator
191264
): JsonResponse {
265+
$this->requireAuthentication($request);
266+
192267
if (!$administrator) {
193-
return new JsonResponse(['message' => 'Administrator not found.'], Response::HTTP_NOT_FOUND);
268+
throw new NotFoundHttpException('Administrator not found.');
194269
}
195-
196270
$this->administratorManager->deleteAdministrator($administrator);
197271

198272
return new JsonResponse(null, Response::HTTP_NO_CONTENT);

src/Controller/BaseController.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpList\RestBundle\Controller;
6+
7+
use PhpList\Core\Domain\Model\Identity\Administrator;
8+
use PhpList\Core\Security\Authentication;
9+
use PhpList\RestBundle\Validator\RequestValidator;
10+
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
11+
use Symfony\Component\HttpFoundation\Request;
12+
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
13+
14+
abstract class BaseController extends AbstractController
15+
{
16+
protected Authentication $authentication;
17+
protected RequestValidator $validator;
18+
19+
public function __construct(
20+
Authentication $authentication,
21+
RequestValidator $validator,
22+
) {
23+
$this->authentication = $authentication;
24+
$this->validator = $validator;
25+
}
26+
27+
protected function requireAuthentication(Request $request): Administrator
28+
{
29+
$administrator = $this->authentication->authenticateByApiKey($request);
30+
if ($administrator === null) {
31+
throw new AccessDeniedHttpException(
32+
'No valid session key was provided as basic auth password.',
33+
null,
34+
1512749701
35+
);
36+
}
37+
38+
return $administrator;
39+
}
40+
}

src/Controller/CampaignController.php

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,33 +7,26 @@
77
use OpenApi\Attributes as OA;
88
use PhpList\Core\Domain\Model\Messaging\Message;
99
use PhpList\Core\Security\Authentication;
10-
use PhpList\RestBundle\Controller\Traits\AuthenticationTrait;
1110
use PhpList\RestBundle\Entity\Request\CreateMessageRequest;
1211
use PhpList\RestBundle\Entity\Request\UpdateMessageRequest;
1312
use PhpList\RestBundle\Serializer\MessageNormalizer;
1413
use PhpList\RestBundle\Service\Manager\MessageManager;
15-
use PhpList\RestBundle\Service\Provider\MessageProvider;
1614
use PhpList\RestBundle\Validator\RequestValidator;
1715
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
18-
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
1916
use Symfony\Component\HttpFoundation\JsonResponse;
2017
use Symfony\Component\HttpFoundation\Request;
2118
use Symfony\Component\HttpFoundation\Response;
2219
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
2320
use Symfony\Component\Routing\Attribute\Route;
24-
use Symfony\Component\Serializer\SerializerInterface;
2521

2622
/**
2723
* This controller provides REST API to manage campaigns.
2824
*
2925
* @author Tatevik Grigoryan <[email protected]>
3026
*/
3127
#[Route('/campaigns')]
32-
class CampaignController extends AbstractController
28+
class CampaignController extends BaseController
3329
{
34-
use AuthenticationTrait;
35-
36-
private RequestValidator $validator;
3730
private MessageNormalizer $normalizer;
3831
private MessageManager $messageManager;
3932

@@ -43,8 +36,7 @@ public function __construct(
4336
MessageNormalizer $normalizer,
4437
MessageManager $messageManager
4538
) {
46-
$this->authentication = $authentication;
47-
$this->validator = $validator;
39+
parent::__construct($authentication, $validator);
4840
$this->normalizer = $normalizer;
4941
$this->messageManager = $messageManager;
5042
}
@@ -265,26 +257,18 @@ public function createMessage(Request $request, MessageNormalizer $normalizer):
265257
)]
266258
public function updateMessage(
267259
Request $request,
268-
SerializerInterface $serializer,
269260
#[MapEntity(mapping: ['messageId' => 'id'])] ?Message $message = null,
270261
): JsonResponse {
271262
$authUser = $this->requireAuthentication($request);
272263

273264
if (!$message) {
274265
throw new NotFoundHttpException('Campaign not found.');
275266
}
267+
/** @var UpdateMessageRequest $updateMessageRequest */
268+
$updateMessageRequest = $this->validator->validate($request, UpdateMessageRequest::class);
269+
$data = $this->messageManager->updateMessage($updateMessageRequest, $message, $authUser);
276270

277-
/** @return UpdateMessageRequest $updateMessageRequest */
278-
$updateMessageRequest = $serializer->deserialize($request->getContent(), UpdateMessageRequest::class, 'json');
279-
$updateMessageRequest->messageId = $message->getId();
280-
$this->validator->validateDto($updateMessageRequest);
281-
282-
return new JsonResponse(
283-
$this->normalizer->normalize(
284-
$this->messageManager->updateMessage($updateMessageRequest, $message, $authUser)
285-
),
286-
Response::HTTP_OK
287-
);
271+
return new JsonResponse($this->normalizer->normalize($data), Response::HTTP_OK);
288272
}
289273

290274
#[Route('/{messageId}', name: 'delete_campaign', methods: ['DELETE'])]

src/Controller/ListController.php

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,13 @@
77
use OpenApi\Attributes as OA;
88
use PhpList\Core\Domain\Model\Subscription\SubscriberList;
99
use PhpList\Core\Security\Authentication;
10-
use PhpList\RestBundle\Controller\Traits\AuthenticationTrait;
1110
use PhpList\RestBundle\Entity\Request\CreateSubscriberListRequest;
1211
use PhpList\RestBundle\Serializer\SubscriberListNormalizer;
1312
use PhpList\RestBundle\Service\Factory\PaginationCursorRequestFactory;
1413
use PhpList\RestBundle\Service\Manager\SubscriberListManager;
1514
use PhpList\RestBundle\Service\Provider\SubscriberListProvider;
1615
use PhpList\RestBundle\Validator\RequestValidator;
1716
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
18-
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
1917
use Symfony\Component\HttpFoundation\JsonResponse;
2018
use Symfony\Component\HttpFoundation\Request;
2119
use Symfony\Component\HttpFoundation\Response;
@@ -30,13 +28,10 @@
3028
* @author Tatevik Grigoryan <[email protected]>
3129
*/
3230
#[Route('/lists')]
33-
class ListController extends AbstractController
31+
class ListController extends BaseController
3432
{
35-
use AuthenticationTrait;
36-
3733
private SubscriberListNormalizer $normalizer;
3834
private SubscriberListManager $subscriberListManager;
39-
private RequestValidator $validator;
4035
private PaginationCursorRequestFactory $paginationFactory;
4136
private SubscriberListProvider $subscriberListProvider;
4237

@@ -48,9 +43,8 @@ public function __construct(
4843
PaginationCursorRequestFactory $paginationFactory,
4944
SubscriberListProvider $subscriberListProvider
5045
) {
51-
$this->authentication = $authentication;
46+
parent::__construct($authentication, $validator);
5247
$this->normalizer = $normalizer;
53-
$this->validator = $validator;
5448
$this->subscriberListManager = $subscriberListManager;
5549
$this->paginationFactory = $paginationFactory;
5650
$this->subscriberListProvider = $subscriberListProvider;

0 commit comments

Comments
 (0)