-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Auth directive on Union type ignores the applyPolicy function #98
Comments
Good find, sounds like a bug in the way the type-level auth works - would you be up for contributing a PR? |
No, sorry, I don't have enough time to work on it |
Completely understand, no problem at all! |
Hi @Eomm. From your example I think the issue is your Grid resolveType function. You're checking for
Another option is to use the user role from the context like so:
Here are some unit tests which i've successfully tested locally: "use strict";
const { test } = require("tap");
const Fastify = require("fastify");
const mercurius = require("mercurius");
const mercuriusAuth = require("..");
const schema = `
directive @auth(role: String) on OBJECT
union Grid = AdminGrid | ModeratorGrid | UserGrid
type AdminGrid @auth(role: "admin") {
totalRevenue: Float
}
type ModeratorGrid @auth(role: "moderator") {
banHammer: Boolean
}
type UserGrid @auth(role: "user") {
basicColumn: String
}
type Query {
searchData: Grid
}
`;
const resolvers = {
Query: {
searchData: async function (root, args, context, info) {
return {
totalRevenue: 42,
banHammer: true,
basicColumn: "basic",
};
},
},
Grid: {
resolveType(obj, contextValue, info) {
const role = context.auth.identity;
if (role === "admin") return "AdminGrid";
if (role === "moderator") return "ModeratorGrid";
return "UserGrid";
},
},
};
test("A user with the `admin` role should only be able to retrieve the `totalRevenue` field", (t) => {
const app = Fastify();
t.teardown(app.close.bind(app));
app.register(mercurius, {
schema,
resolvers,
});
app.register(mercuriusAuth, {
authContext(context) {
return {
identity: context.reply.request.headers["x-user"],
};
},
async applyPolicy(policy, parent, args, context, info) {
const role = policy.arguments[0].value.value;
return context.auth.identity === role;
},
authDirective: "auth",
});
const request = (query) => {
return app.inject({
method: "POST",
headers: { "content-type": "application/json", "X-User": "admin" },
url: "/graphql",
body: JSON.stringify({ query }),
});
};
t.plan(3);
t.test("should be able to retrieve the `totalRevenue` field", async (t) => {
const query = `query {
searchData {
... on AdminGrid {
totalRevenue
}
}
}`;
const response = await request(query);
t.same(JSON.parse(response.body), {
data: {
searchData: {
totalRevenue: 42,
},
},
});
});
t.test("should not be able to retrieve the `banHammer` field", async (t) => {
const query = `query {
searchData {
... on ModeratorGrid {
banHammer
}
}
}`;
const response = await request(query);
t.same(JSON.parse(response.body), {
data: {
searchData: {},
},
});
});
t.test(
"should not be able to retrieve the `basicColumn` field",
async (t) => {
const query = `query {
searchData {
... on UserGrid {
basicColumn
}
}
}`;
const response = await request(query);
t.same(JSON.parse(response.body), {
data: {
searchData: {},
},
});
}
);
t.end();
}); |
Given this schema:
and this plugin setup:
The
applyPolicy
function is never executed.If I change the schema to:
The function is executed instead.
Here a complete code example + test (skipped) Eomm/blog-posts@7ec5f23
The text was updated successfully, but these errors were encountered: