Skip to content

Commit bbc22d7

Browse files
committed
Add 403UserCentricPreparator to handle random parameters that generates a 403 error because the user is not allowed to browse them
1 parent 8d2b024 commit bbc22d7

File tree

4 files changed

+110
-3
lines changed

4 files changed

+110
-3
lines changed

src/Definition/Loader/OpenApiDefinitionLoader.php

+11
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
use cebe\openapi\spec\MediaType;
3737
use cebe\openapi\spec\OAuthFlow;
3838
use cebe\openapi\spec\OpenApi;
39+
use cebe\openapi\spec\Operation as OpenApiOperation;
3940
use cebe\openapi\spec\PathItem;
4041
use cebe\openapi\spec\RequestBody;
4142
use cebe\openapi\spec\Schema;
@@ -115,13 +116,23 @@ private function getOperations(array $paths, array $securitySchemes): Operations
115116
->setTags($this->getTags($operation->tags))
116117
->setSecurities($this->getSecurities($securitySchemes, $requirements))
117118
->setExamples($this->getExamples($operation, $parameters))
119+
->setCustomParameters($this->getCustomParameters($operation))
118120
);
119121
}
120122
}
121123

122124
return $operations;
123125
}
124126

127+
private function getCustomParameters(OpenApiOperation $operation): array
128+
{
129+
return array_filter(
130+
(array) $operation->getSerializableData(),
131+
fn ($v, $k) => str_starts_with($k, 'x-'),
132+
ARRAY_FILTER_USE_BOTH
133+
);
134+
}
135+
125136
/**
126137
* @param \cebe\openapi\spec\Server[] $servers
127138
*/

src/Definition/Operation.php

+20
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ final class Operation implements Filterable
4343

4444
private OperationExamples $examples;
4545

46+
private array $customParameters;
47+
4648
public function __construct(
4749
private readonly string $id,
4850
private readonly string $path,
@@ -56,6 +58,7 @@ public function __construct(
5658
$this->tags = new Tags();
5759
$this->securities = new Securities();
5860
$this->examples = new OperationExamples();
61+
$this->customParameters = [];
5962
}
6063

6164
public function addHeader(Parameter $header): self
@@ -277,6 +280,23 @@ public function setExamples(OperationExamples $examples): self
277280
return $this;
278281
}
279282

283+
public function getCustomParameters(): array
284+
{
285+
return $this->customParameters;
286+
}
287+
288+
public function setCustomParameters(array $customParameters): self
289+
{
290+
$this->customParameters = $customParameters;
291+
292+
return $this;
293+
}
294+
295+
public function isUserCentric(): bool
296+
{
297+
return isset($this->customParameters['x-apitester-user-centric-parameter']) && $this->customParameters['x-apitester-user-centric-parameter'] === true;
298+
}
299+
280300
/**
281301
* @param array<int|string, string|int> $params
282302
*
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace APITester\Preparator;
6+
7+
use APITester\Definition\Collection\Operations;
8+
use APITester\Definition\Example\OperationExample;
9+
use APITester\Definition\Example\ResponseExample;
10+
use APITester\Definition\Operation;
11+
use APITester\Definition\Response as DefinitionResponse;
12+
use APITester\Test\TestCase;
13+
14+
final class Error403UserCentricPreparator extends TestCasesPreparator
15+
{
16+
public function getStatusCode(): string
17+
{
18+
return '403';
19+
}
20+
/**
21+
* @inheritDoc
22+
*/
23+
protected function prepare(Operations $operations): iterable
24+
{
25+
/** @var iterable<array-key, TestCase> */
26+
return $operations
27+
->filter(fn ($operation) => $operation->isUserCentric())
28+
->values()
29+
->map(function ($operation) {
30+
return $this->prepareTestCase($operation);
31+
})
32+
->flatten()
33+
;
34+
}
35+
36+
/**
37+
* @return array<TestCase>
38+
*/
39+
private function prepareTestCase(Operation $operation): array
40+
{
41+
$testcases = [];
42+
43+
if ($operation->getRequestBodies()->count() === 0) {
44+
$testcases[] = $this->buildTestCase(
45+
OperationExample::create('RandomPath', $operation)
46+
->setForceRandom()
47+
->setResponse(
48+
ResponseExample::create()
49+
->setStatusCode($this->config->response->getStatusCode() ?? '403')
50+
->setHeaders($this->config->response->headers ?? [])
51+
->setContent($this->config->response->body ?? null)
52+
)
53+
);
54+
}
55+
56+
foreach ($operation->getRequestBodies() as $ignored) {
57+
$testcases[] = $this->buildTestCase(
58+
OperationExample::create('RandomPath', $operation)
59+
->setForceRandom()
60+
->setResponse(
61+
ResponseExample::create()
62+
->setStatusCode($this->config->response->getStatusCode() ?? '403')
63+
->setHeaders($this->config->response->headers ?? [])
64+
->setContent($this->config->response->body ?? null)
65+
)
66+
);
67+
}
68+
69+
return $testcases;
70+
}
71+
}

src/Preparator/Error404Preparator.php

+8-3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212

1313
final class Error404Preparator extends TestCasesPreparator
1414
{
15+
protected function getStatusCode(): string
16+
{
17+
return '404';
18+
}
1519
/**
1620
* @inheritDoc
1721
*/
@@ -21,7 +25,8 @@ protected function prepare(Operations $operations): iterable
2125
return $operations
2226
->select('responses.*')
2327
->flatten()
24-
->where('statusCode', 404)
28+
->where('statusCode', $this->getgetStatusCode())
29+
->filter(fn ($response) => !$response->getParent()->isUserCentric())
2530
->values()
2631
->map(function ($response) {
2732
/** @var DefinitionResponse $response */
@@ -46,7 +51,7 @@ private function prepareTestCase(DefinitionResponse $response): array
4651
->setForceRandom()
4752
->setResponse(
4853
ResponseExample::create()
49-
->setStatusCode($this->config->response->getStatusCode() ?? '404')
54+
->setStatusCode($this->config->response->getStatusCode() ?? $this->getgetStatusCode())
5055
->setHeaders($this->config->response->headers ?? [])
5156
->setContent($this->config->response->body ?? $response->getDescription())
5257
)
@@ -59,7 +64,7 @@ private function prepareTestCase(DefinitionResponse $response): array
5964
->setForceRandom()
6065
->setResponse(
6166
ResponseExample::create()
62-
->setStatusCode($this->config->response->getStatusCode() ?? '404')
67+
->setStatusCode($this->config->response->getStatusCode() ?? $this->getgetStatusCode())
6368
->setHeaders($this->config->response->headers ?? [])
6469
->setContent($this->config->response->body ?? $response->getDescription())
6570
)

0 commit comments

Comments
 (0)