UNPKG

@theguild/federation-composition

Version:
63 lines (62 loc) 3.06 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AuthOnContextRule = AuthOnContextRule; const graphql_1 = require("graphql"); const helpers_js_1 = require("../../../subgraph/helpers.js"); const state_js_1 = require("../../../subgraph/state.js"); const auth_on_requires_rule_js_1 = require("./auth-on-requires-rule.js"); function AuthOnContextRule(context, supergraph) { return { ObjectTypeField(objectTypeState, fieldState) { for (const { graphId, fromContext } of contextualArgs(fieldState)) { const subgraphState = context.subgraphStates.get(graphId); const selectionSet = (0, helpers_js_1.parseFields)(fromContext.selection); if (!subgraphState || !selectionSet) { continue; } const provisionedAccess = new auth_on_requires_rule_js_1.ProvisionedAccess(objectTypeState, fieldState); for (const providerName of findContextProviders(subgraphState, fromContext.context)) { const providerType = supergraph.objectTypes.get(providerName) ?? supergraph.interfaceTypes.get(providerName) ?? supergraph.unionTypes.get(providerName); if (!providerType || !(0, auth_on_requires_rule_js_1.ensureAccessToSelectionSet)(supergraph, providerType, selectionSet, provisionedAccess)) { continue; } context.reportError(createContextAccessRequirementError(context.graphIdToName(graphId), `${objectTypeState.name}.${fieldState.name}`, `${context.graphIdToName(graphId)}__${fromContext.context}`)); return; } } }, }; } function contextualArgs(fieldState) { const args = []; for (const arg of fieldState.args.values()) { for (const [graphId, argInGraph] of arg.byGraph) { if (argInGraph.fromContext) { args.push({ graphId, fromContext: argInGraph.fromContext }); } } } return args; } function findContextProviders(subgraphState, contextName) { const providers = []; for (const [typeName, typeState] of subgraphState.types) { if ((typeState.kind === state_js_1.TypeKind.OBJECT || typeState.kind === state_js_1.TypeKind.INTERFACE || typeState.kind === state_js_1.TypeKind.UNION) && typeState.contexts.has(contextName)) { providers.push(typeName); } } return providers; } function createContextAccessRequirementError(graphName, fieldCoordinate, contextName) { return new graphql_1.GraphQLError(`[${graphName}] Field "${fieldCoordinate}" does not specify necessary @authenticated, @requiresScopes and/or @policy auth requirements to access the transitive data in context ${contextName} from @fromContext selection set.`, { extensions: { code: "MISSING_TRANSITIVE_AUTH_REQUIREMENTS", }, }); }