question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Question: wrap all top-level queries / mutations only

See original GitHub issue

Hey all, trying to figure out if I’m approaching this wrong or just not understanding. So, what I’d like to do is put a simple tracing middleware around any “top level” query. I.e. the request comes in and they ask for PersonA and PersonB query.

I’ve got one that runs, and I can filter out decently well by only measuring if parent is null, which seems to work. But the downside is that it’s making my introspection query SUPER slow – proabbly because it’s hitting every prop and we have a huuuge schema which is split into multiple files and stitched together. Also, we’re on lambda, so we recompile this on every invocation (at least locally) so our dev cycles are suffering.

I’m wondering: is there some easy way to say wrap Query.* and Mutation.* but not anything deeper? I saw #13 and looked at the applyMiddlewareToDeclaredResolvers but it doesn’t seem to have much impact.

Thoughts? Am I missing something simple?

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:8

github_iconTop GitHub Comments

2reactions
maticzavcommented, Mar 1, 2019

@Abhijeetjaiswalit

const executableSchema = makeExecutableSchema({
  typeDefs: schema,
  resolvers: { ...resolvers, JSON: GraphQLJSON },
  schemaDirectives: { auth: AuthDirective },
})

const schemaWithMiddleware = applyMiddleware(
  executableSchema,
  {
    Query: logInputMiddleware,
    Mutation: logInputMiddleware,
  },
  {
    Query: {
       user: logResultMiddleware,
    },
  },
)
2reactions
ghirlekarcommented, Dec 10, 2018

@maticzav, I elected to use graphql-shield instead of rolling my own middleware. The fallbackRule option works perfectly for this kinda task.

I apologize that this comment is extremely off-topic in this issue, but in case anyone is interested, this is the way I’ve setup my authorization rules.

const { shield, rule, and, or, not, allow } = require('graphql-shield');

// Authorization rules
const deny401 = rule()(() => new Error('401 Unauthorized'));
const deny403 = rule()(() => new Error('403 Forbidden'));
const isAuthenticated = or(rule()((parent, args, { req }) => {
  return req.session.id != null;
}), deny401);
const isAdmin = and(isAuthenticated, rule()((parent, args, { req }) => {
  return req.session.roles.includes('admin'); 
}));
const isSales = and(isAuthenticated, rule()((parent, args, { req }) => {
  return req.session.roles.includes('admin') || req.session.roles.includes('sales');
}));
const isInvoiceLocked = and(isAuthenticated, rule()((parent, args, ctx) => {
  return ctx.is_invoice_locked;
}));

module.exports = shield({
  RootQuery: {
    schema_version: allow,
  },
  RootMutation: {
    login: allow,
    invoice_create: or(isSales, deny403),
    invoice_update: or(and(isSales, or(not(isInvoiceLocked), isAdmin)), deny403),
    invoice_delete: or(isSales, deny403),
    sales_order_create: or(isSales, deny403),
    sales_order_update: or(and(isSales, or(not(isInvoiceLocked), isAdmin)), deny403),
    sales_order_delete: or(isSales, deny403),
  }
}, { fallbackRule: isAuthenticated, graphiql: true });

@maticzav, thanks for your wonderful graphql-shield module. It’s very well structured and has saved me so much time. I am very grateful for your efforts.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Question: wrap all top-level queries / mutations only #78
I'm wondering: is there some easy way to say wrap Query.* and Mutation.* but not anything deeper? I saw #13 and looked at...
Read more >
Designing response types - Apollo GraphQL Docs
To answer questions like these, it's helpful for top-level fields of Query and Mutation to return "wrapper" objects that can include both the...
Read more >
graphql - Are mutation methods required to be on the top level?
GraphQL specification defines mutations as top level operations exclusively. All levels below are regular queries. The fact that they're ...
Read more >
Schema Wrapping – GraphQL Tools
Schema wrapping works by creating a new "gateway" schema that simply delegates all operations to the original subschema.
Read more >
Mutations - Hot Chocolate - ChilliCream GraphQL Platform
GraphQL defines mutations as top-level fields on the mutation type. Meaning only the fields on the mutation root type itself are mutations.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found