app.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. "use strict";
  2. require("dotenv").config();
  3. const cors = require("cors");
  4. const express = require("express");
  5. const helmet = require("helmet");
  6. const http = require("http");
  7. const jwksClient = require("jwks-rsa");
  8. const jwt = require("jsonwebtoken");
  9. const { MongoClient } = require("mongodb");
  10. const { ApolloServer, AuthenticationError, gql } = require("apollo-server-express");
  11. const { ApolloServerPluginDrainHttpServer } = require("apollo-server-core");
  12. const corsOrigins = process.env.APP_CORS_ORIGINS.split(",");
  13. const app = express();
  14. app.enable("trust proxy");
  15. app.use(cors({ origin: corsOrigins }));
  16. if (app.get("env") === "production") {
  17. app.use(helmet());
  18. app.use(helmet.contentSecurityPolicy());
  19. }
  20. const httpServer = http.createServer(app);
  21. const typeDefs = gql`
  22. "Party definition."
  23. type Party {
  24. "Unique party identifier"
  25. _id: ID!
  26. "Full name, concatenation of first, last, and middle."
  27. name: String!
  28. """
  29. Auth0 user identifier.
  30. Application access granted when set.
  31. """
  32. user_id: String
  33. "On-boarded in the application?."
  34. onboarded: Boolean!
  35. }
  36. "Query definitions."
  37. type Query {
  38. "Get party by identifier."
  39. getParty(_id: ID!): Party!
  40. }
  41. `;
  42. const resolvers = {
  43. Query: {
  44. getParty: async (parent, args, { user, dataSources }) => {
  45. const parties = dataSources.mongodb.collection("parties");
  46. const party = await parties.findOne({ _id: args._id });
  47. return party;
  48. }
  49. }
  50. };
  51. let client = jwksClient({ jwksUri: `https://${process.env.AUTH0_DOMAIN}/.well-known/jwks.json` });
  52. const authentication = async context => {
  53. const token = context.req.headers.authorization || "";
  54. if (!token) throw new AuthenticationError("Authentication required");
  55. const keys = await client.getSigningKeys();
  56. const user = await jwt.verify(token, keys[0].getPublicKey(), { algorithms: [ "RS256" ] });
  57. if (!user.email) throw new AuthenticationError("Wrong token presented");
  58. return { user };
  59. }
  60. const mongodb = new MongoClient(process.env.MONGODB_STRING, { useNewUrlParser: true, useUnifiedTopology: true });
  61. mongodb.connect();
  62. const apollo = new ApolloServer({
  63. typeDefs,
  64. resolvers,
  65. dataSources: _ => ({
  66. mongodb: mongodb.db(process.env.MONGODB_DB)
  67. }),
  68. plugin: [ApolloServerPluginDrainHttpServer({ httpServer })],
  69. context: authentication
  70. });
  71. apollo.start().then(_ => {
  72. apollo.applyMiddleware({ app });
  73. app.all("*", (request, response) => response.send(""));
  74. httpServer.listen(process.env.APP_PORT);
  75. let apolloData = httpServer.address();
  76. console.log(`GraphQL service listening on ${apolloData.address}:${apolloData.port}${apollo.graphqlPath}`);
  77. }).catch(error => console.log(error.message));