AccessToken.constants.ts75 lines · main
1import { permissions } from '@supabase/shared-types'
2import { components } from 'api-types'
3
4export type ScopedAccessTokenPermission =
5 components['schemas']['CreateScopedAccessTokenBody']['permissions'][number]
6
7export const NON_EXPIRING_TOKEN_VALUE = 'never'
8export const CUSTOM_EXPIRY_VALUE = 'custom'
9
10export const EXPIRES_AT_OPTIONS = {
11 hour: { value: 'hour', label: '1 hour' },
12 day: { value: 'day', label: '1 day' },
13 week: { value: 'week', label: '7 days' },
14 month: { value: 'month', label: '30 days' },
15 never: { value: NON_EXPIRING_TOKEN_VALUE, label: 'Never' },
16 custom: { value: CUSTOM_EXPIRY_VALUE, label: 'Custom' },
17} as const
18
19const FGA = permissions.FgaPermissions
20
21const getAction = (key: string): string => {
22 if (key.endsWith('_READ')) return 'read'
23 if (key.endsWith('_WRITE')) return 'write'
24 if (key.endsWith('_CREATE')) return 'create'
25 if (key.endsWith('_DELETE')) return 'delete'
26 return 'read'
27}
28
29const getResource = (key: string): string => {
30 return key.replace(/_(READ|WRITE|CREATE|DELETE)$/, '').toLowerCase()
31}
32
33const buildPermissionList = () => {
34 const list: Array<{
35 scope: string
36 resource: string
37 action: string
38 id: string
39 title: string
40 }> = []
41
42 for (const [scope, scopePerms] of Object.entries(FGA)) {
43 for (const [key, perm] of Object.entries(scopePerms)) {
44 list.push({
45 scope: scope.toLowerCase(),
46 resource: getResource(key),
47 action: getAction(key),
48 id: perm.id,
49 title: perm.title,
50 })
51 }
52 }
53
54 return list
55}
56
57export const PERMISSION_LIST = buildPermissionList()
58
59export const ACCESS_TOKEN_RESOURCES = (() => {
60 const resourceMap = new Map<string, { resource: string; title: string; actions: string[] }>()
61
62 for (const p of PERMISSION_LIST) {
63 const key = `${p.scope}:${p.resource}`
64 if (!resourceMap.has(key)) {
65 const cleanTitle = p.title.replace(/^(Read|Manage|Create|Delete)\s+/i, '')
66 resourceMap.set(key, { resource: key, title: cleanTitle, actions: [] })
67 }
68 const entry = resourceMap.get(key)!
69 if (!entry.actions.includes(p.action)) {
70 entry.actions.push(p.action)
71 }
72 }
73
74 return Array.from(resourceMap.values())
75})()