ConfigControllerTest.php 3.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Tests\Integration\Admin;
  4. use App\Domain\Auth\Role;
  5. use App\Domain\Auth\TokenKind;
  6. use App\Tests\Integration\Support\AppTestCase;
  7. /**
  8. * `/api/v1/admin/config` — Admin-only effective config with secrets
  9. * masked.
  10. */
  11. final class ConfigControllerTest extends AppTestCase
  12. {
  13. public function testRequiresAdmin(): void
  14. {
  15. $token = $this->createToken(TokenKind::Admin, Role::Viewer);
  16. $resp = $this->request('GET', '/api/v1/admin/config', ['Authorization' => 'Bearer ' . $token]);
  17. self::assertSame(403, $resp->getStatusCode());
  18. }
  19. public function testReturnsSectionsAndMasksSecrets(): void
  20. {
  21. $token = $this->createToken(TokenKind::Admin, Role::Admin);
  22. $resp = $this->request('GET', '/api/v1/admin/config', ['Authorization' => 'Bearer ' . $token]);
  23. self::assertSame(200, $resp->getStatusCode());
  24. $body = $this->decode($resp);
  25. self::assertArrayHasKey('sections', $body);
  26. $sections = $body['sections'];
  27. // Required sections
  28. foreach (['app', 'database', 'auth', 'reputation', 'jobs', 'geoip'] as $section) {
  29. self::assertArrayHasKey($section, $sections, "missing section $section");
  30. }
  31. // INTERNAL_JOB_TOKEN / MAXMIND_LICENSE_KEY: empty in tests, so empty string.
  32. self::assertSame('', $sections['auth']['INTERNAL_JOB_TOKEN']);
  33. self::assertSame('', $sections['geoip']['MAXMIND_LICENSE_KEY']);
  34. // Plain values
  35. self::assertSame('sqlite', $sections['database']['DB_DRIVER']);
  36. self::assertSame('dbip', $sections['geoip']['GEOIP_PROVIDER']);
  37. }
  38. public function testMasksTokensWhenSet(): void
  39. {
  40. // Re-build the container with a configured ui_service_token / internal token / maxmind key
  41. $settings = $this->withSettings([
  42. 'ui_service_token' => 'irdb_svc_ABCDEFGHIJKLMNOPQRSTUVWXYZ234567',
  43. 'internal_job_token' => 'super-secret-internal-token-1234',
  44. 'geoip' => [
  45. 'enabled' => true,
  46. 'provider' => 'maxmind',
  47. 'country_db' => '/tmp/c.mmdb',
  48. 'asn_db' => '/tmp/a.mmdb',
  49. 'maxmind_license_key' => 'real-maxmind-key',
  50. 'ipinfo_token' => 'real-ipinfo-token',
  51. 'refresh_interval_days' => 7,
  52. ],
  53. ]);
  54. if (method_exists($this->container, 'set')) {
  55. /** @var \DI\Container $c */
  56. $c = $this->container;
  57. $c->set('settings', $settings);
  58. $c->set(
  59. \App\Application\Admin\ConfigController::class,
  60. new \App\Application\Admin\ConfigController($settings),
  61. );
  62. // Rebuild the app so the route picks up the patched controller.
  63. $this->app = \App\App\AppFactory::build($this->container);
  64. }
  65. $token = $this->createToken(TokenKind::Admin, Role::Admin);
  66. $resp = $this->request('GET', '/api/v1/admin/config', ['Authorization' => 'Bearer ' . $token]);
  67. $body = $this->decode($resp);
  68. $sections = $body['sections'];
  69. self::assertSame('irdb_svc...', $sections['auth']['UI_SERVICE_TOKEN']);
  70. self::assertSame('***', $sections['auth']['INTERNAL_JOB_TOKEN']);
  71. self::assertSame('***', $sections['geoip']['MAXMIND_LICENSE_KEY']);
  72. self::assertSame('***', $sections['geoip']['IPINFO_TOKEN']);
  73. }
  74. /**
  75. * @return array<string, mixed>
  76. */
  77. private function withSettings(array $overrides): array
  78. {
  79. // Read the live settings via container, layer the overrides on top.
  80. /** @var array<string, mixed> $settings */
  81. $settings = $this->container->get('settings');
  82. return array_replace($settings, $overrides);
  83. }
  84. }