api-keys.ts 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. /**
  2. * Both CLI and self-hosted inject the same env vars.
  3. */
  4. import { assertSelfHosted } from './util'
  5. export type NonPlatformApiKey = {
  6. name: string
  7. api_key: string
  8. id: string
  9. type: 'legacy' | 'publishable' | 'secret'
  10. hash: string
  11. prefix: string
  12. description: string
  13. }
  14. /**
  15. * Length of the identifying prefix shown for a secret key before it is
  16. * revealed. Mirrors the platform management API and the `ApiKeyPill` UI.
  17. */
  18. const SECRET_KEY_VISIBLE_PREFIX_LENGTH = 15
  19. export function parseRevealQuery(value: string | string[] | undefined): boolean {
  20. const raw = Array.isArray(value) ? value[0] : value
  21. return raw === 'true'
  22. }
  23. export function getNonPlatformApiKeys(): NonPlatformApiKey[] {
  24. assertSelfHosted()
  25. const keys: NonPlatformApiKey[] = [
  26. {
  27. name: 'anon',
  28. api_key: process.env.SUPABASE_ANON_KEY ?? '',
  29. id: 'anon',
  30. type: 'legacy',
  31. hash: '',
  32. prefix: '',
  33. description: 'Legacy anon API key',
  34. },
  35. {
  36. name: 'service_role',
  37. api_key: process.env.SUPABASE_SERVICE_KEY ?? '',
  38. id: 'service_role',
  39. type: 'legacy',
  40. hash: '',
  41. prefix: '',
  42. description: 'Legacy service_role API key',
  43. },
  44. ]
  45. const publishableKey = process.env.SUPABASE_PUBLISHABLE_KEY
  46. if (publishableKey) {
  47. keys.push({
  48. name: 'publishable',
  49. api_key: publishableKey,
  50. id: 'publishable',
  51. type: 'publishable',
  52. hash: '',
  53. prefix: '',
  54. description: 'Publishable API key (anon role)',
  55. })
  56. }
  57. const secretKey = process.env.SUPABASE_SECRET_KEY
  58. if (secretKey) {
  59. keys.push({
  60. name: 'secret',
  61. api_key: secretKey,
  62. id: 'secret',
  63. type: 'secret',
  64. hash: '',
  65. // Only expose the prefix when the key is genuinely longer than the prefix.
  66. prefix:
  67. secretKey.length > SECRET_KEY_VISIBLE_PREFIX_LENGTH
  68. ? secretKey.slice(0, SECRET_KEY_VISIBLE_PREFIX_LENGTH)
  69. : '',
  70. description: 'Secret API key (service_role)',
  71. })
  72. }
  73. return keys
  74. }
  75. export function applyRevealToApiKey(key: NonPlatformApiKey, reveal: boolean): NonPlatformApiKey {
  76. if (key.type !== 'secret' || reveal) return key
  77. return { ...key, api_key: key.prefix }
  78. }
  79. export function getNonPlatformApiKeyById(
  80. id: string,
  81. reveal: boolean
  82. ): NonPlatformApiKey | undefined {
  83. const key = getNonPlatformApiKeys().find((entry) => entry.id === id)
  84. if (!key) return undefined
  85. return applyRevealToApiKey(key, reveal)
  86. }