mercurius-js / auth

Mercurius Auth Plugin

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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

Mike-Van opened this issue · 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);

Does it work? Have you for any issues?

So when i tried to add filterSchema it crashed the app, seems like it doesnt work with external policy:

        mode: 'external',
	authContext(ctx): TAuthContext {
		const { device, location, role, staff, token, venue } = ctx;
		return { device, location, role, staff, token, venue };
	},
	filterSchema: true,

What error are you seeing? Are you seeing something like this? https://github.com/mercurius-js/auth/blob/main/lib/validation.js#L31

Atm, we don't support this, and to be fair this isn't called out in the docs - something we certainly add for sure!

Would you be interested in adding this caveat to the docs and/or potentially adding support for schema filtering with external policy mode?

@jonnydgreen Let me take this up. I did not think of externalPolicy. 👍