UNPKG

@pothos/plugin-scope-auth

Version:

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

163 lines (162 loc) 9.01 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 { RequestCache }; export * from './errors.js'; export * from './types.js'; const pluginName = "scopeAuth"; export default pluginName; let inResolveType = false; export class PothosScopeAuthPlugin extends BasePlugin { wrapResolve(resolver, fieldConfig) { 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"; var _typeConfig_pothosOptions_runScopesOnType, _ref; 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 _this_builder_options_scopeAuth; if (this.options.disableScopeAuth) { return isTypeOf; } var _typeConfig_pothosOptions_runScopesOnType, _ref; 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 _isTypeOf; return (_isTypeOf = isTypeOf === null || isTypeOf === void 0 ? void 0 : isTypeOf(source, context, info)) !== null && _isTypeOf !== void 0 ? _isTypeOf : 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