Skip to content

Commit f8472e9

Browse files
committed
blacklist controller
1 parent 3ca5387 commit f8472e9

File tree

2 files changed

+344
-0
lines changed

2 files changed

+344
-0
lines changed
Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpList\RestBundle\Subscription\Controller;
6+
7+
use OpenApi\Attributes as OA;
8+
use PhpList\Core\Domain\Identity\Model\PrivilegeFlag;
9+
use PhpList\Core\Domain\Subscription\Service\Manager\SubscriberBlacklistManager;
10+
use PhpList\Core\Security\Authentication;
11+
use PhpList\RestBundle\Common\Controller\BaseController;
12+
use PhpList\RestBundle\Common\Validator\RequestValidator;
13+
use Symfony\Component\HttpFoundation\JsonResponse;
14+
use Symfony\Component\HttpFoundation\Request;
15+
use Symfony\Component\HttpFoundation\Response;
16+
use Symfony\Component\Routing\Attribute\Route;
17+
18+
/**
19+
* This controller provides REST API access to subscriber blacklist functionality.
20+
*/
21+
#[Route('/blacklist', name: 'blacklist_')]
22+
class BlacklistController extends BaseController
23+
{
24+
private SubscriberBlacklistManager $blacklistManager;
25+
26+
public function __construct(
27+
Authentication $authentication,
28+
RequestValidator $validator,
29+
SubscriberBlacklistManager $blacklistManager,
30+
) {
31+
parent::__construct($authentication, $validator);
32+
$this->authentication = $authentication;
33+
$this->blacklistManager = $blacklistManager;
34+
}
35+
36+
#[Route('/check/{email}', name: 'check', methods: ['GET'])]
37+
#[OA\Get(
38+
path: '/api/v2/blacklist/check/{email}',
39+
description: 'Checks if an email address is blacklisted.',
40+
summary: 'Check if email is blacklisted',
41+
tags: ['blacklist'],
42+
parameters: [
43+
new OA\Parameter(
44+
name: 'php-auth-pw',
45+
description: 'Session key obtained from login',
46+
in: 'header',
47+
required: true,
48+
schema: new OA\Schema(type: 'string')
49+
),
50+
new OA\Parameter(
51+
name: 'email',
52+
description: 'Email address to check',
53+
in: 'path',
54+
required: true,
55+
schema: new OA\Schema(type: 'string')
56+
)
57+
],
58+
responses: [
59+
new OA\Response(
60+
response: 200,
61+
description: 'Success',
62+
content: new OA\JsonContent(
63+
properties: [
64+
new OA\Property(property: 'blacklisted', type: 'boolean'),
65+
new OA\Property(property: 'reason', type: 'string', nullable: true)
66+
]
67+
),
68+
),
69+
new OA\Response(
70+
response: 403,
71+
description: 'Failure',
72+
content: new OA\JsonContent(ref: '#/components/schemas/UnauthorizedResponse')
73+
),
74+
]
75+
)]
76+
public function checkEmailBlacklisted(Request $request, string $email): JsonResponse
77+
{
78+
$admin = $this->requireAuthentication($request);
79+
if (!$admin->getPrivileges()->has(PrivilegeFlag::Subscribers)) {
80+
throw $this->createAccessDeniedException('You are not allowed to check blacklisted emails.');
81+
}
82+
83+
$isBlacklisted = $this->blacklistManager->isEmailBlacklisted($email);
84+
$reason = $isBlacklisted ? $this->blacklistManager->getBlacklistReason($email) : null;
85+
86+
return $this->json([
87+
'blacklisted' => $isBlacklisted,
88+
'reason' => $reason,
89+
]);
90+
}
91+
92+
#[Route('/add', name: 'add', methods: ['POST'])]
93+
#[OA\Post(
94+
path: '/api/v2/blacklist/add',
95+
description: 'Adds an email address to the blacklist.',
96+
summary: 'Add email to blacklist',
97+
requestBody: new OA\RequestBody(
98+
description: 'Email to blacklist',
99+
required: true,
100+
content: new OA\JsonContent(
101+
properties: [
102+
new OA\Property(property: 'email', type: 'string'),
103+
new OA\Property(property: 'reason', type: 'string', nullable: true)
104+
]
105+
)
106+
),
107+
tags: ['blacklist'],
108+
parameters: [
109+
new OA\Parameter(
110+
name: 'php-auth-pw',
111+
description: 'Session key obtained from login',
112+
in: 'header',
113+
required: true,
114+
schema: new OA\Schema(type: 'string')
115+
)
116+
],
117+
responses: [
118+
new OA\Response(
119+
response: 201,
120+
description: 'Success',
121+
content: new OA\JsonContent(
122+
properties: [
123+
new OA\Property(property: 'success', type: 'boolean'),
124+
new OA\Property(property: 'message', type: 'string')
125+
]
126+
),
127+
),
128+
new OA\Response(
129+
response: 403,
130+
description: 'Failure',
131+
content: new OA\JsonContent(ref: '#/components/schemas/UnauthorizedResponse')
132+
),
133+
new OA\Response(
134+
response: 422,
135+
description: 'Failure',
136+
content: new OA\JsonContent(ref: '#/components/schemas/ValidationErrorResponse')
137+
),
138+
]
139+
)]
140+
public function addEmailToBlacklist(Request $request): JsonResponse
141+
{
142+
$admin = $this->requireAuthentication($request);
143+
if (!$admin->getPrivileges()->has(PrivilegeFlag::Subscribers)) {
144+
throw $this->createAccessDeniedException('You are not allowed to add emails to blacklist.');
145+
}
146+
147+
$data = json_decode($request->getContent(), true);
148+
if (!isset($data['email']) || empty($data['email'])) {
149+
return $this->json(['error' => 'Email is required'], Response::HTTP_UNPROCESSABLE_ENTITY);
150+
}
151+
152+
$email = $data['email'];
153+
$reason = $data['reason'] ?? null;
154+
155+
$this->blacklistManager->addEmailToBlacklist($email, $reason);
156+
157+
return $this->json([
158+
'success' => true,
159+
'message' => sprintf('Email %s has been added to the blacklist', $email),
160+
], Response::HTTP_CREATED);
161+
}
162+
163+
#[Route('/remove/{email}', name: 'remove', methods: ['DELETE'])]
164+
#[OA\Delete(
165+
path: '/api/v2/blacklist/remove/{email}',
166+
description: 'Removes an email address from the blacklist.',
167+
summary: 'Remove email from blacklist',
168+
tags: ['blacklist'],
169+
parameters: [
170+
new OA\Parameter(
171+
name: 'php-auth-pw',
172+
description: 'Session key obtained from login',
173+
in: 'header',
174+
required: true,
175+
schema: new OA\Schema(type: 'string')
176+
),
177+
new OA\Parameter(
178+
name: 'email',
179+
description: 'Email address to remove from blacklist',
180+
in: 'path',
181+
required: true,
182+
schema: new OA\Schema(type: 'string')
183+
)
184+
],
185+
responses: [
186+
new OA\Response(
187+
response: 200,
188+
description: 'Success',
189+
content: new OA\JsonContent(
190+
properties: [
191+
new OA\Property(property: 'success', type: 'boolean'),
192+
new OA\Property(property: 'message', type: 'string')
193+
]
194+
),
195+
),
196+
new OA\Response(
197+
response: 403,
198+
description: 'Failure',
199+
content: new OA\JsonContent(ref: '#/components/schemas/UnauthorizedResponse')
200+
),
201+
]
202+
)]
203+
public function removeEmailFromBlacklist(Request $request, string $email): JsonResponse
204+
{
205+
$admin = $this->requireAuthentication($request);
206+
if (!$admin->getPrivileges()->has(PrivilegeFlag::Subscribers)) {
207+
throw $this->createAccessDeniedException('You are not allowed to remove emails from blacklist.');
208+
}
209+
210+
$this->blacklistManager->removeEmailFromBlacklist($email);
211+
212+
return $this->json([
213+
'success' => true,
214+
'message' => sprintf('Email %s has been removed from the blacklist', $email),
215+
]);
216+
}
217+
218+
#[Route('/info/{email}', name: 'info', methods: ['GET'])]
219+
#[OA\Get(
220+
path: '/api/v2/blacklist/info/{email}',
221+
description: 'Gets detailed information about a blacklisted email.',
222+
summary: 'Get blacklist information',
223+
tags: ['blacklist'],
224+
parameters: [
225+
new OA\Parameter(
226+
name: 'php-auth-pw',
227+
description: 'Session key obtained from login',
228+
in: 'header',
229+
required: true,
230+
schema: new OA\Schema(type: 'string')
231+
),
232+
new OA\Parameter(
233+
name: 'email',
234+
description: 'Email address to get information for',
235+
in: 'path',
236+
required: true,
237+
schema: new OA\Schema(type: 'string')
238+
)
239+
],
240+
responses: [
241+
new OA\Response(
242+
response: 200,
243+
description: 'Success',
244+
content: new OA\JsonContent(
245+
properties: [
246+
new OA\Property(property: 'email', type: 'string'),
247+
new OA\Property(property: 'added', type: 'string', format: 'date-time', nullable: true),
248+
new OA\Property(property: 'reason', type: 'string', nullable: true)
249+
]
250+
),
251+
),
252+
new OA\Response(
253+
response: 403,
254+
description: 'Failure',
255+
content: new OA\JsonContent(ref: '#/components/schemas/UnauthorizedResponse')
256+
),
257+
new OA\Response(
258+
response: 404,
259+
description: 'Failure',
260+
content: new OA\JsonContent(ref: '#/components/schemas/NotFoundResponse')
261+
),
262+
]
263+
)]
264+
public function getBlacklistInfo(Request $request, string $email): JsonResponse
265+
{
266+
$admin = $this->requireAuthentication($request);
267+
if (!$admin->getPrivileges()->has(PrivilegeFlag::Subscribers)) {
268+
throw $this->createAccessDeniedException('You are not allowed to view blacklist information.');
269+
}
270+
271+
$blacklistInfo = $this->blacklistManager->getBlacklistInfo($email);
272+
if (!$blacklistInfo) {
273+
return $this->json(['error' => sprintf('Email %s is not blacklisted', $email)], Response::HTTP_NOT_FOUND);
274+
}
275+
276+
$reason = $this->blacklistManager->getBlacklistReason($email);
277+
278+
return $this->json([
279+
'email' => $blacklistInfo->getEmail(),
280+
'added' => $blacklistInfo->getAdded() ? $blacklistInfo->getAdded()->format('c') : null,
281+
'reason' => $reason,
282+
]);
283+
}
284+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpList\RestBundle\Tests\Integration\Subscription\Controller;
6+
7+
use PhpList\RestBundle\Subscription\Controller\BlacklistController;
8+
use PhpList\RestBundle\Tests\Integration\Common\AbstractTestController;
9+
use Symfony\Component\HttpFoundation\Response;
10+
11+
/**
12+
* Integration tests for the BlacklistController.
13+
*/
14+
class BlacklistControllerTest extends AbstractTestController
15+
{
16+
public function testControllerIsAvailableViaContainer(): void
17+
{
18+
self::assertInstanceOf(
19+
BlacklistController::class,
20+
self::getContainer()->get(BlacklistController::class)
21+
);
22+
}
23+
24+
public function testCheckEmailBlacklistedWithoutSessionKeyReturnsForbiddenStatus(): void
25+
{
26+
$this->jsonRequest('get', '/api/v2/blacklist/check/[email protected]');
27+
28+
$this->assertHttpForbidden();
29+
}
30+
31+
public function testAddEmailToBlacklistWithoutSessionKeyReturnsForbiddenStatus(): void
32+
{
33+
$this->jsonRequest('post', '/api/v2/blacklist/add');
34+
35+
$this->assertHttpForbidden();
36+
}
37+
38+
public function testAddEmailToBlacklistWithMissingEmailReturnsUnprocessableEntityStatus(): void
39+
{
40+
$jsonData = [];
41+
42+
$this->authenticatedJsonRequest('post', '/api/v2/blacklist/add', [], [], [], json_encode($jsonData));
43+
44+
$this->assertHttpUnprocessableEntity();
45+
}
46+
47+
public function testRemoveEmailFromBlacklistWithoutSessionKeyReturnsForbiddenStatus(): void
48+
{
49+
$this->jsonRequest('delete', '/api/v2/blacklist/remove/[email protected]');
50+
51+
$this->assertHttpForbidden();
52+
}
53+
54+
public function testGetBlacklistInfoWithoutSessionKeyReturnsForbiddenStatus(): void
55+
{
56+
$this->jsonRequest('get', '/api/v2/blacklist/info/[email protected]');
57+
58+
$this->assertHttpForbidden();
59+
}
60+
}

0 commit comments

Comments
 (0)