AccessToken.constants.ts75 lines · main
| 1 | import { permissions } from '@supabase/shared-types' |
| 2 | import { components } from 'api-types' |
| 3 | |
| 4 | export type ScopedAccessTokenPermission = |
| 5 | components['schemas']['CreateScopedAccessTokenBody']['permissions'][number] |
| 6 | |
| 7 | export const NON_EXPIRING_TOKEN_VALUE = 'never' |
| 8 | export const CUSTOM_EXPIRY_VALUE = 'custom' |
| 9 | |
| 10 | export 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 | |
| 19 | const FGA = permissions.FgaPermissions |
| 20 | |
| 21 | const 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 | |
| 29 | const getResource = (key: string): string => { |
| 30 | return key.replace(/_(READ|WRITE|CREATE|DELETE)$/, '').toLowerCase() |
| 31 | } |
| 32 | |
| 33 | const 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 | |
| 57 | export const PERMISSION_LIST = buildPermissionList() |
| 58 | |
| 59 | export 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 | })() |