configRepo = static::getContainer()->get(SiteConfigRepository::class); $this->maintenance = static::getContainer()->get(MaintenanceService::class); } protected function tearDown(): void { $this->setMaintenance('0'); parent::tearDown(); } private function setMaintenance(string $enabled, string $allowedIps = ''): void { $this->configRepo->set('maintenance_enabled', $enabled); $this->configRepo->set('maintenance_allowed_ips', $allowedIps); static::getContainer()->get(EntityManagerInterface::class)->flush(); $this->maintenance->invalidate(); } public function testAnonymousApiRequestIsBlockedWithMaintenanceEnvelope(): void { $this->setMaintenance('1'); $this->client->request('GET', '/api/v1/doctors'); $response = $this->client->getResponse(); $body = json_decode($response->getContent(), true); self::assertSame(503, $response->getStatusCode()); self::assertSame('MAINTENANCE_MODE', $body['errors'][0]['code']); self::assertFalse($body['success']); self::assertNull($body['data']); self::assertNotEmpty($response->headers->get('Retry-After')); } public function testRoutingErrorsAlsoReturnMaintenance(): void { $this->setMaintenance('1'); // 404 is thrown by the router at a higher priority than the request // listener, so it is only covered by the kernel.exception path. $this->client->request('GET', '/api/v1/definitely-not-a-route'); self::assertSame(503, $this->responseCode()); self::assertSame( 'MAINTENANCE_MODE', json_decode($this->client->getResponse()->getContent(), true)['errors'][0]['code'], ); } public function testAdminBypassesMaintenance(): void { $this->setMaintenance('1'); $admin = $this->createUser(['ROLE_USER', 'ROLE_ADMIN']); $this->authJson('GET', '/api/v1/admin/pre-registrations', $admin); self::assertNotSame(503, $this->responseCode()); } public function testNonAdminRoleIsBlocked(): void { $this->setMaintenance('1'); $doctor = $this->createUser(['ROLE_USER', 'ROLE_DOCTOR']); $body = $this->authJson('GET', '/api/v1/admin/pre-registrations', $doctor); self::assertSame(503, $this->responseCode()); self::assertSame('MAINTENANCE_MODE', $body['errors'][0]['code']); } public function testSettingsEndpointStaysReachableSoMaintenanceCanBeTurnedOff(): void { $this->setMaintenance('1'); $admin = $this->createUser(['ROLE_USER', 'ROLE_ADMIN']); $this->authJson('GET', '/api/v1/admin/settings', $admin); self::assertSame(200, $this->responseCode()); } public function testAllowedIpBypassesWithoutAuthentication(): void { $this->setMaintenance('1', '127.0.0.1, 10.0.0.1'); $this->client->request('GET', '/api/v1/doctors', server: ['REMOTE_ADDR' => '10.0.0.1']); self::assertNotSame(503, $this->responseCode()); } public function testDisabledMaintenanceLetsEveryoneThrough(): void { $this->setMaintenance('0'); $this->client->request('GET', '/api/v1/doctors'); self::assertNotSame(503, $this->responseCode()); } }