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