refactor(auth): unify route authorization around scopes (#544)

This commit is contained in:
Jasper Van
2026-07-29 23:26:07 -04:00
committed by GitHub
parent e50c19051a
commit a890e7bba2
45 changed files with 680 additions and 731 deletions
+2 -3
View File
@@ -1,7 +1,6 @@
import { describe, expect, it } from 'vitest'
import { WEBDAV_API_KEY_PERMISSIONS } from './api-key-templates'
import { AGENT_GRANTABLE_API_KEY_SCOPES, WEBDAV_API_KEY_PERMISSIONS } from './api-key-templates'
import {
AGENT_GRANTABLE_AUTHORIZATION_SCOPES,
AuthorizationScope,
authorizationScope,
CANONICAL_AUTHORIZATION_SCOPES,
@@ -22,7 +21,7 @@ describe('authorization scope registry', () => {
it('keeps permanent object purge out of agent-grantable scopes', () => {
expect(CANONICAL_AUTHORIZATION_SCOPES).toContain(AuthorizationScope.OBJECTS_PURGE)
expect(AGENT_GRANTABLE_AUTHORIZATION_SCOPES).not.toContain(AuthorizationScope.OBJECTS_PURGE)
expect(AGENT_GRANTABLE_API_KEY_SCOPES).not.toContain(AuthorizationScope.OBJECTS_PURGE)
expect(scopePermissions([AuthorizationScope.OBJECTS_DELETE])).toEqual({ objects: ['delete'] })
})
+73 -4
View File
@@ -13,16 +13,85 @@ export const AuthorizationScope = {
DOWNLOAD_TASKS_READ: 'download-tasks:read',
DOWNLOAD_TASKS_CREATE: 'download-tasks:create',
DOWNLOAD_TASKS_CANCEL: 'download-tasks:cancel',
SITE_ANALYTICS_READ: 'site-analytics:read',
AGENT_API_KEYS_READ: 'agent-api-keys:read',
AGENT_API_KEYS_CREATE: 'agent-api-keys:create',
AGENT_API_KEYS_UPDATE: 'agent-api-keys:update',
AGENT_API_KEYS_DELETE: 'agent-api-keys:delete',
AGENT_OAUTH_GRANTS_READ: 'agent-oauth-grants:read',
AGENT_OAUTH_GRANTS_CREATE: 'agent-oauth-grants:create',
AGENT_OAUTH_GRANTS_DELETE: 'agent-oauth-grants:delete',
BACKGROUND_JOBS_READ: 'background-jobs:read',
BACKGROUND_JOBS_CREATE: 'background-jobs:create',
BACKGROUND_JOBS_UPDATE: 'background-jobs:update',
DOWNLOADERS_READ: 'downloaders:read',
DOWNLOADERS_CREATE: 'downloaders:create',
DOWNLOADERS_UPDATE: 'downloaders:update',
DOWNLOADERS_DELETE: 'downloaders:delete',
IMAGE_HOSTING_CONFIG_READ: 'image-hosting-config:read',
IMAGE_HOSTING_CONFIG_UPDATE: 'image-hosting-config:update',
IMAGE_HOSTING_CONFIG_DELETE: 'image-hosting-config:delete',
IMAGES_READ: 'images:read',
IMAGES_CREATE: 'images:create',
IMAGES_UPDATE: 'images:update',
IMAGES_DELETE: 'images:delete',
NOTIFICATIONS_READ: 'notifications:read',
NOTIFICATIONS_UPDATE: 'notifications:update',
ANNOUNCEMENTS_READ: 'announcements:read',
ANNOUNCEMENTS_CREATE: 'announcements:create',
ANNOUNCEMENTS_UPDATE: 'announcements:update',
ANNOUNCEMENTS_DELETE: 'announcements:delete',
AUDIT_EVENTS_READ: 'audit-events:read',
AUTH_PROVIDERS_READ: 'auth-providers:read',
AUTH_PROVIDERS_UPDATE: 'auth-providers:update',
AUTH_PROVIDERS_DELETE: 'auth-providers:delete',
BRANDING_UPDATE: 'branding:update',
EMAIL_CONFIG_READ: 'email-config:read',
EMAIL_CONFIG_UPDATE: 'email-config:update',
EMAIL_CONFIG_TEST: 'email-config:test',
IMAGE_DOMAIN_PROVIDER_READ: 'image-domain-provider:read',
IMAGE_DOMAIN_PROVIDER_UPDATE: 'image-domain-provider:update',
IMAGE_DOMAIN_PROVIDER_TEST: 'image-domain-provider:test',
SITE_INVITATIONS_READ: 'site-invitations:read',
SITE_INVITATIONS_CREATE: 'site-invitations:create',
SITE_INVITATIONS_DELETE: 'site-invitations:delete',
INVITE_CODES_READ: 'invite-codes:read',
INVITE_CODES_CREATE: 'invite-codes:create',
INVITE_CODES_DELETE: 'invite-codes:delete',
LICENSING_READ: 'licensing:read',
LICENSING_UPDATE: 'licensing:update',
SITE_SETTINGS_READ: 'site-settings:read',
SITE_SETTINGS_UPDATE: 'site-settings:update',
STORAGES_READ: 'storages:read',
STORAGES_CREATE: 'storages:create',
STORAGES_UPDATE: 'storages:update',
STORAGES_DELETE: 'storages:delete',
SYSTEM_READ: 'system:read',
STORE_READ: 'store:read',
STORE_CREATE: 'store:create',
STORE_UPDATE: 'store:update',
TEAMS_READ: 'teams:read',
TEAMS_CREATE: 'teams:create',
TEAMS_UPDATE: 'teams:update',
TEAM_INVITATIONS_READ: 'team-invitations:read',
TEAM_INVITATIONS_CREATE: 'team-invitations:create',
TEAM_MEMBERS_CREATE: 'team-members:create',
TEAM_ENTITLEMENTS_READ: 'team-entitlements:read',
TEAM_ENTITLEMENTS_CREATE: 'team-entitlements:create',
TEAM_ENTITLEMENTS_UPDATE: 'team-entitlements:update',
TEAM_ENTITLEMENTS_DELETE: 'team-entitlements:delete',
USERS_READ: 'users:read',
USERS_UPDATE: 'users:update',
USER_ENTITLEMENTS_READ: 'user-entitlements:read',
USER_ENTITLEMENTS_CREATE: 'user-entitlements:create',
USER_ENTITLEMENTS_UPDATE: 'user-entitlements:update',
USER_ENTITLEMENTS_DELETE: 'user-entitlements:delete',
} as const
export type AuthorizationScope = (typeof AuthorizationScope)[keyof typeof AuthorizationScope]
export const CANONICAL_AUTHORIZATION_SCOPES = Object.values(AuthorizationScope)
export const AGENT_GRANTABLE_AUTHORIZATION_SCOPES = CANONICAL_AUTHORIZATION_SCOPES.filter(
(scope) => scope !== AuthorizationScope.OBJECTS_PURGE,
)
const AUTHORIZATION_SCOPE_SET = new Set<string>(CANONICAL_AUTHORIZATION_SCOPES)
export type ApiKeyPermissions = Record<string, string[]>