auth icon indicating copy to clipboard operation
auth copied to clipboard

Is there a way to make schema filtering work with external policy?

Open Mike-Van opened this issue 9 months ago • 4 comments

Hi i'm fairly new to Fastify and Mercurius, I'm trying to setup a graphql api project for 1 of my side project. I saw there's a documentation to filter schema for auth policy directive, n it works great, but for my use case i prefer to use the external auth policy, is there a way to make external policy work for schema filtering, as i might need to expose the graphql playground for potential authenticated users. Here's a minimal snippets of my setup:

const schema = await loadSchema('src/schemas/*.graphql', {
		loaders: [new GraphQLFileLoader()],
	});

const options: MercuriusAuthOptions<any, any, MercuriusContext, TPolicy> = {
	mode: 'external',
	authContext(ctx): TAuthContext {
		const { device, location, role, staff, token, venue } = ctx;
		return { device, location, role, staff, token, venue };
	},
	async applyPolicy(policy, _parent, _args, ctx, _info) {
		const isRolesPolicySatisfied = policy.roles?.length
			? !!(ctx.auth!.role && policy.roles.includes(ctx.auth!.role.type as USER_ROLE))
			: true;
		const isUserRequiredPolicySatisfied = policy.isUserRequired ? !!ctx.auth!.user : true;
		const isVenueRequiredPolicySatisfied = policy.isVenueRequired ? !!ctx.auth!.venue : true;
		const isRoleRequiredPolicySatisfied = policy.isRoleRequired ? !!ctx.auth!.role : true;
		const isLocationRequiredPolicySatisfied = policy.isLocationRequired ? !!ctx.auth!.location : true;
		const isDeviceRequiredPolicySatisfied = policy.isDeviceRequired ? !!ctx.auth!.device : true;

		const areAllConditionsSatisfied =
			isRolesPolicySatisfied &&
			isUserRequiredPolicySatisfied &&
			isVenueRequiredPolicySatisfied &&
			isRoleRequiredPolicySatisfied &&
			isLocationRequiredPolicySatisfied &&
			isDeviceRequiredPolicySatisfied;

		return areAllConditionsSatisfied;
	},
	policy: {
		// TODO: Add more policies
		Query: {
			getCurrentMenu: {
				isVenueRequired: true,
			},
		},
		Mutation: {},
		Subscription: {},
		Location: {
			current_orders: {
				roles: AUTHENTICATED_ROLES,
			},
			venue: {
				roles: AUTHENTICATED_ROLES,
			},
		},
		Menu: {
			posCategories: {
				roles: AUTHENTICATED_ROLES,
			},
		},
		Category: {
			posItems: {
				roles: AUTHENTICATED_ROLES,
			},
		},
		Item: {
			posOptions: {
				roles: AUTHENTICATED_ROLES,
			},
		},
	},
};

type TPolicy = {
	isRoleRequired?: boolean;
	isUserRequired?: boolean;
	isVenueRequired?: boolean;
	isLocationRequired?: boolean;
	isDeviceRequired?: boolean;
	roles?: USER_ROLE[];
};

	await fastify.register(mercurius, {
		schema,
		resolvers,
		loaders,
		ide: true,
		graphiql: true,
		path: '/graphql',
		allowBatchedQueries: true,
		queryDepth: 10,
		jit: 1,
		context: buildContext,
		subscription: {
			emitter,
			context: buildSubscriptionContext,
		},
		validationRules: isRelease ? [NoSchemaIntrospectionCustomRule] : [],
	});
	
	await fastify.register(mercuriusAuth, options);

Mike-Van avatar Nov 19 '23 04:11 Mike-Van