export const scopeMessages = defineMessages({ userReadEmailLabel: { id: 'scopes.userReadEmail.label', defaultMessage: 'Read user email', }, userReadEmailDescription: { id: 'scopes.userReadEmail.description', defaultMessage: 'Read your email', }, userReadLabel: { id: 'scopes.userRead.label', defaultMessage: 'Read user data', }, userReadDescription: { id: 'scopes.userRead.description', defaultMessage: 'Access your public profile information', }, userWriteLabel: { id: 'scopes.userWrite.label', defaultMessage: 'Write user data', }, userWriteDescription: { id: 'scopes.userWrite.description', defaultMessage: 'Write to your profile', }, userDeleteLabel: { id: 'scopes.userDelete.label', defaultMessage: 'Delete your account', }, userDeleteDescription: { id: 'scopes.userDelete.description', defaultMessage: 'Delete your account', }, userAuthWriteLabel: { id: 'scopes.userAuthWrite.label', defaultMessage: 'Write auth data', }, userAuthWriteDescription: { id: 'scopes.userAuthWrite.description', defaultMessage: 'Modify your authentication data', }, notificationReadLabel: { id: 'scopes.notificationRead.label', defaultMessage: 'Read notifications', }, notificationReadDescription: { id: 'scopes.notificationRead.description', defaultMessage: 'Read your notifications', }, notificationWriteLabel: { id: 'scopes.notificationWrite.label', defaultMessage: 'Write notifications', }, notificationWriteDescription: { id: 'scopes.notificationWrite.description', defaultMessage: 'Delete/View your notifications', }, payoutsReadLabel: { id: 'scopes.payoutsRead.label', defaultMessage: 'Read payouts', }, payoutsReadDescription: { id: 'scopes.payoutsRead.description', defaultMessage: 'Read your payouts data', }, payoutsWriteLabel: { id: 'scopes.payoutsWrite.label', defaultMessage: 'Write payouts', }, payoutsWriteDescription: { id: 'scopes.payoutsWrite.description', defaultMessage: 'Withdraw money', }, analyticsLabel: { id: 'scopes.analytics.label', defaultMessage: 'Read analytics', }, analyticsDescription: { id: 'scopes.analytics.description', defaultMessage: 'Access your analytics data', }, projectCreateLabel: { id: 'scopes.projectCreate.label', defaultMessage: 'Create projects', }, projectCreateDescription: { id: 'scopes.projectCreate.description', defaultMessage: 'Create new projects', }, projectReadLabel: { id: 'scopes.projectRead.label', defaultMessage: 'Read projects', }, projectReadDescription: { id: 'scopes.projectRead.description', defaultMessage: 'Read all your projects', }, projectWriteLabel: { id: 'scopes.projectWrite.label', defaultMessage: 'Write projects', }, projectWriteDescription: { id: 'scopes.projectWrite.description', defaultMessage: 'Write to project data', }, projectDeleteLabel: { id: 'scopes.projectDelete.label', defaultMessage: 'Delete projects', }, projectDeleteDescription: { id: 'scopes.projectDelete.description', defaultMessage: 'Delete your projects', }, versionCreateLabel: { id: 'scopes.versionCreate.label', defaultMessage: 'Create versions', }, versionCreateDescription: { id: 'scopes.versionCreate.description', defaultMessage: 'Create new versions', }, versionReadLabel: { id: 'scopes.versionRead.label', defaultMessage: 'Read versions', }, versionReadDescription: { id: 'scopes.versionRead.description', defaultMessage: 'Read all versions', }, versionWriteLabel: { id: 'scopes.versionWrite.label', defaultMessage: 'Write versions', }, versionWriteDescription: { id: 'scopes.versionWrite.description', defaultMessage: 'Write to version data', }, versionDeleteLabel: { id: 'scopes.versionDelete.label', defaultMessage: 'Delete versions', }, versionDeleteDescription: { id: 'scopes.versionDelete.description', defaultMessage: 'Delete a version', }, reportCreateLabel: { id: 'scopes.reportCreate.label', defaultMessage: 'Create reports', }, reportCreateDescription: { id: 'scopes.reportCreate.description', defaultMessage: 'Create reports', }, reportReadLabel: { id: 'scopes.reportRead.label', defaultMessage: 'Read reports', }, reportReadDescription: { id: 'scopes.reportRead.description', defaultMessage: 'Read reports', }, reportWriteLabel: { id: 'scopes.reportWrite.label', defaultMessage: 'Write reports', }, reportWriteDescription: { id: 'scopes.reportWrite.description', defaultMessage: 'Edit reports', }, reportDeleteLabel: { id: 'scopes.reportDelete.label', defaultMessage: 'Delete reports', }, reportDeleteDescription: { id: 'scopes.reportDelete.description', defaultMessage: 'Delete reports', }, threadReadLabel: { id: 'scopes.threadRead.label', defaultMessage: 'Read threads', }, threadReadDescription: { id: 'scopes.threadRead.description', defaultMessage: 'Read threads', }, threadWriteLabel: { id: 'scopes.threadWrite.label', defaultMessage: 'Write threads', }, threadWriteDescription: { id: 'scopes.threadWrite.description', defaultMessage: 'Write to threads', }, patCreateLabel: { id: 'scopes.patCreate.label', defaultMessage: 'Create PATs', }, patCreateDescription: { id: 'scopes.patCreate.description', defaultMessage: 'Create personal API tokens', }, patReadLabel: { id: 'scopes.patRead.label', defaultMessage: 'Read PATs', }, patReadDescription: { id: 'scopes.patRead.description', defaultMessage: 'View created API tokens', }, patWriteLabel: { id: 'scopes.patWrite.label', defaultMessage: 'Write PATs', }, patWriteDescription: { id: 'scopes.patWrite.description', defaultMessage: 'Edit personal API tokens', }, patDeleteLabel: { id: 'scopes.patDelete.label', defaultMessage: 'Delete PATs', }, patDeleteDescription: { id: 'scopes.patDelete.description', defaultMessage: 'Delete your personal API tokens', }, sessionReadLabel: { id: 'scopes.sessionRead.label', defaultMessage: 'Read sessions', }, sessionReadDescription: { id: 'scopes.sessionRead.description', defaultMessage: 'Read active sessions', }, sessionDeleteLabel: { id: 'scopes.sessionDelete.label', defaultMessage: 'Delete sessions', }, sessionDeleteDescription: { id: 'scopes.sessionDelete.description', defaultMessage: 'Delete sessions', }, performAnalyticsLabel: { id: 'scopes.performAnalytics.label', defaultMessage: 'Perform analytics', }, performAnalyticsDescription: { id: 'scopes.performAnalytics.description', defaultMessage: 'Perform analytics actions', }, collectionCreateLabel: { id: 'scopes.collectionCreate.label', defaultMessage: 'Create collections', }, collectionCreateDescription: { id: 'scopes.collectionCreate.description', defaultMessage: 'Create collections', }, collectionReadLabel: { id: 'scopes.collectionRead.label', defaultMessage: 'Read collections', }, collectionReadDescription: { id: 'scopes.collectionRead.description', defaultMessage: 'Read collections', }, collectionWriteLabel: { id: 'scopes.collectionWrite.label', defaultMessage: 'Write collections', }, collectionWriteDescription: { id: 'scopes.collectionWrite.description', defaultMessage: 'Write to collections', }, collectionDeleteLabel: { id: 'scopes.collectionDelete.label', defaultMessage: 'Delete collections', }, collectionDeleteDescription: { id: 'scopes.collectionDelete.description', defaultMessage: 'Delete collections', }, organizationCreateLabel: { id: 'scopes.organizationCreate.label', defaultMessage: 'Create organizations', }, organizationCreateDescription: { id: 'scopes.organizationCreate.description', defaultMessage: 'Create organizations', }, organizationReadLabel: { id: 'scopes.organizationRead.label', defaultMessage: 'Read organizations', }, organizationReadDescription: { id: 'scopes.organizationRead.description', defaultMessage: 'Read organizations', }, organizationWriteLabel: { id: 'scopes.organizationWrite.label', defaultMessage: 'Write organizations', }, organizationWriteDescription: { id: 'scopes.organizationWrite.description', defaultMessage: 'Write to organizations', }, organizationDeleteLabel: { id: 'scopes.organizationDelete.label', defaultMessage: 'Delete organizations', }, organizationDeleteDescription: { id: 'scopes.organizationDelete.description', defaultMessage: 'Delete organizations', }, sessionAccessLabel: { id: 'scopes.sessionAccess.label', defaultMessage: 'Access sessions', }, sessionAccessDescription: { id: 'scopes.sessionAccess.description', defaultMessage: 'Access modrinth-issued sessions', }, }) const scopeDefinitions = [ { id: 'USER_READ_EMAIL', value: BigInt(1) << BigInt(0), label: scopeMessages.userReadEmailLabel, desc: scopeMessages.userReadEmailDescription, }, { id: 'USER_READ', value: BigInt(1) << BigInt(1), label: scopeMessages.userReadLabel, desc: scopeMessages.userReadDescription, }, { id: 'USER_WRITE', value: BigInt(1) << BigInt(2), label: scopeMessages.userWriteLabel, desc: scopeMessages.userWriteDescription, }, { id: 'USER_DELETE', value: BigInt(1) << BigInt(3), label: scopeMessages.userDeleteLabel, desc: scopeMessages.userDeleteDescription, }, { id: 'USER_AUTH_WRITE', value: BigInt(1) << BigInt(4), label: scopeMessages.userAuthWriteLabel, desc: scopeMessages.userAuthWriteDescription, }, { id: 'NOTIFICATION_READ', value: BigInt(1) << BigInt(5), label: scopeMessages.notificationReadLabel, desc: scopeMessages.notificationReadDescription, }, { id: 'NOTIFICATION_WRITE', value: BigInt(1) << BigInt(6), label: scopeMessages.notificationWriteLabel, desc: scopeMessages.notificationWriteDescription, }, { id: 'PAYOUTS_READ', value: BigInt(1) << BigInt(7), label: scopeMessages.payoutsReadLabel, desc: scopeMessages.payoutsReadDescription, }, { id: 'PAYOUTS_WRITE', value: BigInt(1) << BigInt(8), label: scopeMessages.payoutsWriteLabel, desc: scopeMessages.payoutsWriteDescription, }, { id: 'ANALYTICS', value: BigInt(1) << BigInt(9), label: scopeMessages.analyticsLabel, desc: scopeMessages.analyticsDescription, }, { id: 'PROJECT_CREATE', value: BigInt(1) << BigInt(10), label: scopeMessages.projectCreateLabel, desc: scopeMessages.projectCreateDescription, }, { id: 'PROJECT_READ', value: BigInt(1) << BigInt(11), label: scopeMessages.projectReadLabel, desc: scopeMessages.projectReadDescription, }, { id: 'PROJECT_WRITE', value: BigInt(1) << BigInt(12), label: scopeMessages.projectWriteLabel, desc: scopeMessages.projectWriteDescription, }, { id: 'PROJECT_DELETE', value: BigInt(1) << BigInt(13), label: scopeMessages.projectDeleteLabel, desc: scopeMessages.projectDeleteDescription, }, { id: 'VERSION_CREATE', value: BigInt(1) << BigInt(14), label: scopeMessages.versionCreateLabel, desc: scopeMessages.versionCreateDescription, }, { id: 'VERSION_READ', value: BigInt(1) << BigInt(15), label: scopeMessages.versionReadLabel, desc: scopeMessages.versionReadDescription, }, { id: 'VERSION_WRITE', value: BigInt(1) << BigInt(16), label: scopeMessages.versionWriteLabel, desc: scopeMessages.versionWriteDescription, }, { id: 'VERSION_DELETE', value: BigInt(1) << BigInt(17), label: scopeMessages.versionDeleteLabel, desc: scopeMessages.versionDeleteDescription, }, { id: 'REPORT_CREATE', value: BigInt(1) << BigInt(18), label: scopeMessages.reportCreateLabel, desc: scopeMessages.reportCreateDescription, }, { id: 'REPORT_READ', value: BigInt(1) << BigInt(19), label: scopeMessages.reportReadLabel, desc: scopeMessages.reportReadDescription, }, { id: 'REPORT_WRITE', value: BigInt(1) << BigInt(20), label: scopeMessages.reportWriteLabel, desc: scopeMessages.reportWriteDescription, }, { id: 'REPORT_DELETE', value: BigInt(1) << BigInt(21), label: scopeMessages.reportDeleteLabel, desc: scopeMessages.reportDeleteDescription, }, { id: 'THREAD_READ', value: BigInt(1) << BigInt(22), label: scopeMessages.threadReadLabel, desc: scopeMessages.threadReadDescription, }, { id: 'THREAD_WRITE', value: BigInt(1) << BigInt(23), label: scopeMessages.threadWriteLabel, desc: scopeMessages.threadWriteDescription, }, { id: 'PAT_CREATE', value: BigInt(1) << BigInt(24), label: scopeMessages.patCreateLabel, desc: scopeMessages.patCreateDescription, }, { id: 'PAT_READ', value: BigInt(1) << BigInt(25), label: scopeMessages.patReadLabel, desc: scopeMessages.patReadDescription, }, { id: 'PAT_WRITE', value: BigInt(1) << BigInt(26), label: scopeMessages.patWriteLabel, desc: scopeMessages.patWriteDescription, }, { id: 'PAT_DELETE', value: BigInt(1) << BigInt(27), label: scopeMessages.patDeleteLabel, desc: scopeMessages.patDeleteDescription, }, { id: 'SESSION_READ', value: BigInt(1) << BigInt(28), label: scopeMessages.sessionReadLabel, desc: scopeMessages.sessionReadDescription, }, { id: 'SESSION_DELETE', value: BigInt(1) << BigInt(29), label: scopeMessages.sessionDeleteLabel, desc: scopeMessages.sessionDeleteDescription, }, { id: 'PERFORM_ANALYTICS', value: BigInt(1) << BigInt(30), label: scopeMessages.performAnalyticsLabel, desc: scopeMessages.performAnalyticsDescription, }, { id: 'COLLECTION_CREATE', value: BigInt(1) << BigInt(31), label: scopeMessages.collectionCreateLabel, desc: scopeMessages.collectionCreateDescription, }, { id: 'COLLECTION_READ', value: BigInt(1) << BigInt(32), label: scopeMessages.collectionReadLabel, desc: scopeMessages.collectionReadDescription, }, { id: 'COLLECTION_WRITE', value: BigInt(1) << BigInt(33), label: scopeMessages.collectionWriteLabel, desc: scopeMessages.collectionWriteDescription, }, { id: 'COLLECTION_DELETE', value: BigInt(1) << BigInt(34), label: scopeMessages.collectionDeleteLabel, desc: scopeMessages.collectionDeleteDescription, }, { id: 'ORGANIZATION_CREATE', value: BigInt(1) << BigInt(35), label: scopeMessages.organizationCreateLabel, desc: scopeMessages.organizationCreateDescription, }, { id: 'ORGANIZATION_READ', value: BigInt(1) << BigInt(36), label: scopeMessages.organizationReadLabel, desc: scopeMessages.organizationReadDescription, }, { id: 'ORGANIZATION_WRITE', value: BigInt(1) << BigInt(37), label: scopeMessages.organizationWriteLabel, desc: scopeMessages.organizationWriteDescription, }, { id: 'ORGANIZATION_DELETE', value: BigInt(1) << BigInt(38), label: scopeMessages.organizationDeleteLabel, desc: scopeMessages.organizationDeleteDescription, }, { id: 'SESSION_ACCESS', value: BigInt(1) << BigInt(39), label: scopeMessages.sessionAccessLabel, desc: scopeMessages.sessionAccessDescription, }, ] const Scopes = scopeDefinitions.reduce((acc, scope) => { acc[scope.id] = scope.value return acc }, {} as Record) export const restrictedScopes = [ Scopes.PAT_READ, Scopes.PAT_CREATE, Scopes.PAT_WRITE, Scopes.PAT_DELETE, Scopes.SESSION_READ, Scopes.SESSION_DELETE, Scopes.SESSION_ACCESS, Scopes.USER_AUTH_WRITE, Scopes.USER_DELETE, Scopes.PERFORM_ANALYTICS, ] export const scopeList = Object.entries(Scopes) .filter(([_, value]) => !restrictedScopes.includes(value)) .map(([key, _]) => key) export const getScopeValue = (scope: string) => { return Scopes[scope] } export const encodeScopes = (scopes: string[]) => { let scopeFlag = BigInt(0) // We iterate over the provided scopes for (const scope of scopes) { // We iterate over the entries of the Scopes object for (const [scopeName, scopeFlagValue] of Object.entries(Scopes)) { // If the scope name is the same as the provided scope, add the scope flag to the scopeFlag variable if (scopeName === scope) { scopeFlag = scopeFlag | scopeFlagValue } } } return scopeFlag } export const decodeScopes = (scopes: bigint | number) => { if (typeof scopes === 'number') { scopes = BigInt(scopes) } const authorizedScopes = [] // We iterate over the entries of the Scopes object for (const [scopeName, scopeFlag] of Object.entries(Scopes)) { // If the scope flag is present in the provided number, add the scope name to the list if ((scopes & scopeFlag) === scopeFlag) { authorizedScopes.push(scopeName) } } return authorizedScopes } export const hasScope = (scopes: bigint, scope: string) => { const authorizedScopes = decodeScopes(scopes) return authorizedScopes.includes(scope) } export const toggleScope = (scopes: bigint, scope: string) => { const authorizedScopes = decodeScopes(scopes) if (authorizedScopes.includes(scope)) { return encodeScopes(authorizedScopes.filter((authorizedScope) => authorizedScope !== scope)) } else { return encodeScopes([...authorizedScopes, scope]) } } export const useScopes = () => { const { formatMessage } = useVIntl() const scopesToDefinitions = (scopes: bigint) => { const authorizedScopes = decodeScopes(scopes) return authorizedScopes.map((scope) => { const scopeDefinition = scopeDefinitions.find( (scopeDefinition) => scopeDefinition.id === scope ) if (!scopeDefinition) { throw new Error(`Scope ${scope} not found`) } return formatMessage(scopeDefinition.desc) }) } const scopesToLabels = (scopes: bigint) => { const authorizedScopes = decodeScopes(scopes) return authorizedScopes.map((scope) => { const scopeDefinition = scopeDefinitions.find( (scopeDefinition) => scopeDefinition.id === scope ) if (!scopeDefinition) { throw new Error(`Scope ${scope} not found`) } return formatMessage(scopeDefinition.label) }) } return { scopesToDefinitions, scopesToLabels, } }