Authorization with GraphQL Shield

16 Aug 2021

const { applyMiddleware } = require("graphql-middleware");

const schemaWithPermissions = applyMiddleware(schema, permissions);
const { shield, rule, and, inputRule, deny } = require("graphql-shield");

const permissions = shield({
  Query: {
    "*": deny,
    users: and(isAuthenticated, isAdmin),
    me: isAuthenticated,
  },
  Mutation: {
    createUser: isNotAlreadyRegistered,
  },
});
const isAuthenticated = rule()(async (parent, args, ctx, info) => {
  return !!ctx.headers["user-id"];
});

const isAdmin = rule()(async (parent, args, ctx, info) => {
  const user = users.find(({ id }) => id === ctx.headers["user-id"]);

  return user && user.role === "ADMIN";
});

const isNotAlreadyRegistered = inputRule()((yup) =>
  yup.object({
    input: yup.object({
      name: yup.string().required(),
      email: yup
        .string()
        .email()
        .required()
        .notOneOf(
          users.map(({ email }) => email),
          "A user exists with this email. Choose another."
        ),
    }),
  })
);