UNPKG

@pothos/plugin-scope-auth

Version:

A Pothos plugin for adding scope based authorization checks to your GraphQL Schema

162 lines (161 loc) 8.99 kB
import './global-types.js'; import './schema-builder.js'; import './field-builders.js'; import SchemaBuilder, { BasePlugin, PothosSchemaError, RootFieldBuilder } from '@pothos/core'; import { isTypeOfHelper } from './is-type-of-helper.js'; import RequestCache from './request-cache.js'; import { resolveHelper } from './resolve-helper.js'; import { createFieldAuthScopesStep, createFieldGrantScopesStep, createResolveStep, createTypeAuthScopesStep, createTypeGrantScopesStep } from './steps.js'; export * from './errors.js'; export * from './types.js'; export { RequestCache }; const pluginName = 'scopeAuth'; export default pluginName; let inResolveType = false; export class PothosScopeAuthPlugin extends BasePlugin { wrapResolve(resolver, fieldConfig) { var _ref, _typeConfig_pothosOptions_runScopesOnType; var _this_builder_options_scopeAuth, _this_builder_options_scopeAuth1; if (this.options.disableScopeAuth) { return resolver; } const typeConfig = this.buildCache.getTypeConfig(fieldConfig.parentType); if (typeConfig.graphqlKind !== 'Object' && typeConfig.graphqlKind !== 'Interface') { throw new PothosSchemaError(`Got fields for ${fieldConfig.parentType} which is a ${typeConfig.graphqlKind} which cannot have fields`); } const authorizedOnSubscribe = !!((_this_builder_options_scopeAuth = this.builder.options.scopeAuth) === null || _this_builder_options_scopeAuth === void 0 ? void 0 : _this_builder_options_scopeAuth.authorizeOnSubscribe) && typeConfig.kind === 'Subscription'; const nonRoot = (typeConfig.graphqlKind === 'Interface' || typeConfig.graphqlKind === 'Object') && typeConfig.kind !== 'Query' && typeConfig.kind !== 'Mutation' && typeConfig.kind !== 'Subscription'; const runTypeScopesOnField = !nonRoot || !((_ref = (_typeConfig_pothosOptions_runScopesOnType = typeConfig.pothosOptions.runScopesOnType) !== null && _typeConfig_pothosOptions_runScopesOnType !== void 0 ? _typeConfig_pothosOptions_runScopesOnType : (_this_builder_options_scopeAuth1 = this.builder.options.scopeAuth) === null || _this_builder_options_scopeAuth1 === void 0 ? void 0 : _this_builder_options_scopeAuth1.runScopesOnType) !== null && _ref !== void 0 ? _ref : false); const steps = this.createResolveSteps(fieldConfig, typeConfig, resolver, runTypeScopesOnField, authorizedOnSubscribe); if (steps.length > 1) { return resolveHelper(steps, this, fieldConfig); } return resolver; } wrapSubscribe(subscriber, fieldConfig) { var _this_builder_options_scopeAuth; if (this.options.disableScopeAuth) { return subscriber; } const typeConfig = this.buildCache.getTypeConfig(fieldConfig.parentType); if (typeConfig.graphqlKind !== 'Object' && typeConfig.graphqlKind !== 'Interface') { throw new PothosSchemaError(`Got fields for ${fieldConfig.parentType} which is a ${typeConfig.graphqlKind} which cannot have fields`); } if (!((_this_builder_options_scopeAuth = this.builder.options.scopeAuth) === null || _this_builder_options_scopeAuth === void 0 ? void 0 : _this_builder_options_scopeAuth.authorizeOnSubscribe) || typeConfig.kind !== 'Subscription') { return subscriber; } const steps = this.createSubscribeSteps(fieldConfig, typeConfig, subscriber); if (steps.length > 1) { return resolveHelper(steps, this, fieldConfig); } return subscriber; } wrapResolveType(resolveType) { return (...args)=>{ inResolveType = true; try { return resolveType(...args); } finally{ inResolveType = false; } }; } wrapIsTypeOf(isTypeOf, typeConfig) { var _ref, _typeConfig_pothosOptions_runScopesOnType; var _this_builder_options_scopeAuth; if (this.options.disableScopeAuth) { return isTypeOf; } const shouldRunTypeScopes = (_ref = (_typeConfig_pothosOptions_runScopesOnType = typeConfig.pothosOptions.runScopesOnType) !== null && _typeConfig_pothosOptions_runScopesOnType !== void 0 ? _typeConfig_pothosOptions_runScopesOnType : (_this_builder_options_scopeAuth = this.builder.options.scopeAuth) === null || _this_builder_options_scopeAuth === void 0 ? void 0 : _this_builder_options_scopeAuth.runScopesOnType) !== null && _ref !== void 0 ? _ref : false; if (!shouldRunTypeScopes) { return isTypeOf; } const steps = this.createStepsForType(typeConfig, { forField: false }); if (steps.length === 0) { return isTypeOf; } const runSteps = isTypeOfHelper(steps, this, isTypeOf); return (source, context, info)=>{ if (inResolveType) { var _ref; return (_ref = isTypeOf === null || isTypeOf === void 0 ? void 0 : isTypeOf(source, context, info)) !== null && _ref !== void 0 ? _ref : false; } return runSteps(source, context, info); }; } createStepsForType(typeConfig, { skipTypeScopes, skipInterfaceScopes, forField }) { const parentAuthScope = typeConfig.pothosOptions.authScopes; const parentGrantScopes = typeConfig.pothosOptions.grantScopes; const interfaceConfigs = typeConfig.kind === 'Object' || typeConfig.kind === 'Interface' ? typeConfig.interfaces.map((iface)=>this.buildCache.getTypeConfig(iface, 'Interface')) : []; const steps = []; if (parentAuthScope && !skipTypeScopes) { steps.push(createTypeAuthScopesStep(parentAuthScope, typeConfig.name)); } if (!skipInterfaceScopes && !(typeConfig.kind === 'Object' && typeConfig.pothosOptions.skipInterfaceScopes)) { for (const interfaceConfig of interfaceConfigs){ if (interfaceConfig.pothosOptions.authScopes) { steps.push(createTypeAuthScopesStep(interfaceConfig.pothosOptions.authScopes, interfaceConfig.name)); } } } if (parentGrantScopes) { steps.push(createTypeGrantScopesStep(parentGrantScopes, typeConfig.name, forField)); } return steps; } createResolveSteps(fieldConfig, typeConfig, resolver, shouldRunTypeScopes, authorizedOnSubscribe) { var _ref, _ref1; const stepsForType = shouldRunTypeScopes && !authorizedOnSubscribe ? this.createStepsForType(typeConfig, { skipTypeScopes: (_ref = (fieldConfig.graphqlKind === 'Interface' || fieldConfig.graphqlKind === 'Object') && fieldConfig.pothosOptions.skipTypeScopes) !== null && _ref !== void 0 ? _ref : false, skipInterfaceScopes: (_ref1 = (fieldConfig.graphqlKind === 'Interface' || fieldConfig.kind === 'Object') && fieldConfig.pothosOptions.skipInterfaceScopes) !== null && _ref1 !== void 0 ? _ref1 : false, forField: true }) : []; const fieldAuthScopes = fieldConfig.pothosOptions.authScopes; const fieldGrantScopes = fieldConfig.pothosOptions.grantScopes; const steps = [ ...stepsForType ]; if (fieldAuthScopes && !authorizedOnSubscribe) { steps.push(createFieldAuthScopesStep(fieldAuthScopes)); } steps.push(createResolveStep(resolver)); if (fieldGrantScopes) { steps.push(createFieldGrantScopesStep(fieldGrantScopes)); } return steps; } createSubscribeSteps(fieldConfig, typeConfig, subscriber) { var _ref, _ref1; const stepsForType = this.createStepsForType(typeConfig, { skipTypeScopes: (_ref = (fieldConfig.graphqlKind === 'Interface' || fieldConfig.graphqlKind === 'Object') && fieldConfig.pothosOptions.skipTypeScopes) !== null && _ref !== void 0 ? _ref : false, skipInterfaceScopes: (_ref1 = (fieldConfig.graphqlKind === 'Interface' || fieldConfig.kind === 'Object') && fieldConfig.pothosOptions.skipInterfaceScopes) !== null && _ref1 !== void 0 ? _ref1 : false, forField: true }); const fieldAuthScopes = fieldConfig.pothosOptions.authScopes; const steps = [ ...stepsForType ]; if (fieldAuthScopes) { steps.push(createFieldAuthScopesStep(fieldAuthScopes)); } steps.push(createResolveStep(subscriber)); return steps; } } const fieldBuilderProto = RootFieldBuilder.prototype; fieldBuilderProto.authField = function authField(options) { return this.field(options); }; SchemaBuilder.registerPlugin(pluginName, PothosScopeAuthPlugin, { v3: (options)=>({ scopeAuthOptions: undefined, authScopes: undefined, scopeAuth: { ...options.scopeAuthOptions, authScopes: options.authScopes } }) }); //# sourceMappingURL=index.js.map