UNPKG

@atproto/oauth-scopes

Version:

A library for manipulating and validating ATproto OAuth scopes in TypeScript.

97 lines • 3.17 kB
import { ScopeMissingError } from './scope-missing-error.js'; import { AccountPermission, } from './scopes/account-permission.js'; import { BlobPermission, } from './scopes/blob-permission.js'; import { IdentityPermission, } from './scopes/identity-permission.js'; import { RepoPermission, } from './scopes/repo-permission.js'; import { RpcPermission, } from './scopes/rpc-permission.js'; export { ScopeMissingError }; /** * Utility class to manage a set of scopes and check if they match specific * options for a given resource. */ export class ScopesSet extends Set { /** * Check if the container has a scope that matches the given options for a * specific resource. */ matches(resource, options) { for (const scope of this) { if (permissionScopeMatches(scope, resource, options)) return true; } return false; } assert(resource, options) { if (!this.matches(resource, options)) { const scope = scopeNeededFor(resource, options); throw new ScopeMissingError(scope); } } some(fn) { for (const scope of this) if (fn(scope)) return true; return false; } every(fn) { for (const scope of this) if (!fn(scope)) return false; return true; } *filter(fn) { for (const scope of this) if (fn(scope)) yield scope; } *map(fn) { for (const scope of this) yield fn(scope); } static fromString(string) { return new ScopesSet(string?.split(' ')); } } function scopeNeededFor(resource, options) { switch (resource) { case 'account': return AccountPermission.scopeNeededFor(options); case 'identity': return IdentityPermission.scopeNeededFor(options); case 'repo': return RepoPermission.scopeNeededFor(options); case 'rpc': return RpcPermission.scopeNeededFor(options); case 'blob': return BlobPermission.scopeNeededFor(options); } // @ts-expect-error throw new TypeError(`Unknown resource: ${resource}`); } function permissionScopeMatches(scope, resource, options) { // @NOTE we might want to cache the parsed scopes though, in practice, a // single scope is unlikely to be parsed multiple times during a single // request. const permission = parsePermissionScope(resource, scope); if (!permission) return false; // @ts-expect-error return permission.matches(options); } function parsePermissionScope(resource, scope) { switch (resource) { case 'account': return AccountPermission.fromString(scope); case 'identity': return IdentityPermission.fromString(scope); case 'repo': return RepoPermission.fromString(scope); case 'rpc': return RpcPermission.fromString(scope); case 'blob': return BlobPermission.fromString(scope); default: return null; } } //# sourceMappingURL=scopes-set.js.map