|
|
@@ -12,11 +12,18 @@ use App\Tests\Integration\Support\AppTestCase;
|
|
|
* `crossorigin="anonymous"` so the browser refuses to execute the JS
|
|
|
* if a CDN compromise or in-flight content modification serves
|
|
|
* different bytes.
|
|
|
+ *
|
|
|
+ * Also covers SEC_REVIEW F68 — the docs routes are gated behind
|
|
|
+ * `API_DOCS_PUBLIC` (default off). Tests that reach the routes
|
|
|
+ * enable the flag and rebuild the app; the dedicated F68 cases
|
|
|
+ * leave it off and assert 404.
|
|
|
*/
|
|
|
final class DocsControllerTest extends AppTestCase
|
|
|
{
|
|
|
public function testDocsPageEmbedsRapiDocWithSriIntegrity(): void
|
|
|
{
|
|
|
+ $this->enableDocs();
|
|
|
+
|
|
|
$resp = $this->request('GET', '/api/docs');
|
|
|
self::assertSame(200, $resp->getStatusCode());
|
|
|
self::assertStringContainsString('text/html', $resp->getHeaderLine('Content-Type'));
|
|
|
@@ -41,6 +48,7 @@ final class DocsControllerTest extends AppTestCase
|
|
|
{
|
|
|
// Sanity check that we didn't break the spec endpoint while
|
|
|
// editing the controller.
|
|
|
+ $this->enableDocs();
|
|
|
$resp = $this->request('GET', '/api/v1/openapi.yaml');
|
|
|
// The spec file isn't shipped in tests; either 200 with content
|
|
|
// or 500 with `spec_unavailable`. Both are acceptable here —
|
|
|
@@ -48,4 +56,36 @@ final class DocsControllerTest extends AppTestCase
|
|
|
// edited controller.
|
|
|
self::assertContains($resp->getStatusCode(), [200, 500]);
|
|
|
}
|
|
|
+
|
|
|
+ public function testDocsPageIs404ByDefault(): void
|
|
|
+ {
|
|
|
+ // SEC_REVIEW F68: `/api/docs` is gated behind
|
|
|
+ // `API_DOCS_PUBLIC`. AppTestCase builds the container with
|
|
|
+ // the env var unset, so the default (false) applies and the
|
|
|
+ // route is never registered → Slim returns 404.
|
|
|
+ $resp = $this->request('GET', '/api/docs');
|
|
|
+ self::assertSame(404, $resp->getStatusCode());
|
|
|
+ }
|
|
|
+
|
|
|
+ public function testOpenapiSpecIs404ByDefault(): void
|
|
|
+ {
|
|
|
+ $resp = $this->request('GET', '/api/v1/openapi.yaml');
|
|
|
+ self::assertSame(404, $resp->getStatusCode());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Re-bind `settings.api_docs_public` to `true` and rebuild the app
|
|
|
+ * so the docs routes are registered. Same pattern
|
|
|
+ * `JobsAdminControllerTest::testRefreshGeoip412UnderMaxmindWithoutKey`
|
|
|
+ * uses to swap a binding mid-test.
|
|
|
+ */
|
|
|
+ private function enableDocs(): void
|
|
|
+ {
|
|
|
+ if (method_exists($this->container, 'set')) {
|
|
|
+ /** @var \DI\Container $c */
|
|
|
+ $c = $this->container;
|
|
|
+ $c->set('settings.api_docs_public', true);
|
|
|
+ $this->app = \App\App\AppFactory::build($this->container);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|