2020-09-02 23:00:16 -07:00
|
|
|
const util = require("util");
|
|
|
|
|
2020-09-19 21:31:09 -07:00
|
|
|
const { beelinePlugin } = require("./lib/beeline-graphql");
|
2020-09-02 23:00:16 -07:00
|
|
|
const { gql, makeExecutableSchema } = require("apollo-server");
|
|
|
|
const jwtVerify = util.promisify(require("jsonwebtoken").verify);
|
|
|
|
const jwksClient = require("jwks-rsa");
|
2020-04-22 11:51:36 -07:00
|
|
|
|
|
|
|
const connectToDb = require("./db");
|
2020-04-23 14:23:46 -07:00
|
|
|
const buildLoaders = require("./loaders");
|
2020-09-06 01:51:58 -07:00
|
|
|
const { svgLoggingPlugin } = require("./types/AppearanceLayer");
|
2020-04-22 11:51:36 -07:00
|
|
|
|
2020-09-06 01:51:58 -07:00
|
|
|
const rootTypeDefs = gql`
|
2020-08-16 23:28:41 -07:00
|
|
|
directive @cacheControl(maxAge: Int!) on FIELD_DEFINITION | OBJECT
|
|
|
|
|
2020-09-06 01:51:58 -07:00
|
|
|
type Mutation
|
|
|
|
type Query
|
2020-04-22 11:51:36 -07:00
|
|
|
`;
|
|
|
|
|
2020-09-06 01:51:58 -07:00
|
|
|
function mergeTypeDefsAndResolvers(modules) {
|
|
|
|
const allTypeDefs = [];
|
|
|
|
const allResolvers = {};
|
2020-08-01 15:30:26 -07:00
|
|
|
|
2020-09-06 01:51:58 -07:00
|
|
|
for (const { typeDefs, resolvers } of modules) {
|
|
|
|
allTypeDefs.push(typeDefs);
|
|
|
|
for (const typeName of Object.keys(resolvers)) {
|
|
|
|
allResolvers[typeName] = {
|
|
|
|
...allResolvers[typeName],
|
|
|
|
...resolvers[typeName],
|
2020-04-25 06:50:34 -07:00
|
|
|
};
|
2020-09-06 01:51:58 -07:00
|
|
|
}
|
|
|
|
}
|
2020-05-23 11:32:05 -07:00
|
|
|
|
2020-09-06 01:51:58 -07:00
|
|
|
return { typeDefs: allTypeDefs, resolvers: allResolvers };
|
|
|
|
}
|
2020-05-23 11:32:05 -07:00
|
|
|
|
2020-09-06 01:51:58 -07:00
|
|
|
const schema = makeExecutableSchema(
|
|
|
|
mergeTypeDefsAndResolvers([
|
|
|
|
{ typeDefs: rootTypeDefs, resolvers: {} },
|
|
|
|
require("./types/AppearanceLayer"),
|
|
|
|
require("./types/Item"),
|
|
|
|
require("./types/MutationsForSupport"),
|
|
|
|
require("./types/Outfit"),
|
|
|
|
require("./types/PetAppearance"),
|
|
|
|
require("./types/User"),
|
|
|
|
require("./types/Zone"),
|
|
|
|
])
|
|
|
|
);
|
|
|
|
|
|
|
|
const plugins = [svgLoggingPlugin];
|
2020-08-17 01:27:05 -07:00
|
|
|
|
|
|
|
if (process.env["NODE_ENV"] !== "test") {
|
|
|
|
plugins.push(beelinePlugin);
|
|
|
|
}
|
2020-08-16 23:28:41 -07:00
|
|
|
|
2020-09-02 23:00:16 -07:00
|
|
|
const jwks = jwksClient({
|
|
|
|
jwksUri: "https://openneo.us.auth0.com/.well-known/jwks.json",
|
|
|
|
});
|
|
|
|
|
|
|
|
async function getJwtKey(header, callback) {
|
|
|
|
jwks.getSigningKey(header.kid, (err, key) => {
|
|
|
|
if (err) {
|
|
|
|
return callback(null, signingKey);
|
|
|
|
}
|
|
|
|
const signingKey = key.publicKey || key.rsaPublicKey;
|
|
|
|
callback(null, signingKey);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
async function getUserIdFromToken(token) {
|
|
|
|
if (!token) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
let payload;
|
|
|
|
try {
|
|
|
|
payload = await jwtVerify(token, getJwtKey, {
|
|
|
|
audience: "https://impress-2020.openneo.net/api",
|
|
|
|
issuer: "https://openneo.us.auth0.com/",
|
|
|
|
algorithms: ["RS256"],
|
|
|
|
});
|
|
|
|
} catch (e) {
|
|
|
|
console.error(`Invalid auth token: ${token}\n${e}`);
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2020-09-02 23:07:44 -07:00
|
|
|
const subMatch = payload.sub.match(/auth0\|impress-([0-9]+)/);
|
|
|
|
if (!subMatch) {
|
2020-09-02 23:00:16 -07:00
|
|
|
console.log("Unexpected auth token sub format", payload.sub);
|
|
|
|
return null;
|
|
|
|
}
|
2020-09-02 23:07:44 -07:00
|
|
|
const userId = subMatch[1];
|
2020-09-02 23:00:16 -07:00
|
|
|
return userId;
|
|
|
|
}
|
|
|
|
|
2020-04-22 13:03:32 -07:00
|
|
|
const config = {
|
2020-08-16 23:28:41 -07:00
|
|
|
schema,
|
2020-09-02 23:00:16 -07:00
|
|
|
context: async ({ req }) => {
|
2020-04-22 11:51:36 -07:00
|
|
|
const db = await connectToDb();
|
2020-05-23 11:32:05 -07:00
|
|
|
|
2020-09-06 01:51:58 -07:00
|
|
|
const svgLogger = svgLoggingPlugin.buildSvgLogger();
|
2020-05-23 11:32:05 -07:00
|
|
|
|
2020-09-02 23:19:50 -07:00
|
|
|
const auth = (req && req.headers && req.headers.authorization) || "";
|
|
|
|
const authMatch = auth.match(/^Bearer (.+)$/);
|
|
|
|
const token = authMatch && authMatch[1];
|
2020-09-02 23:00:16 -07:00
|
|
|
const currentUserId = await getUserIdFromToken(token);
|
|
|
|
|
2020-04-22 12:00:52 -07:00
|
|
|
return {
|
2020-08-01 00:04:11 -07:00
|
|
|
db,
|
2020-09-06 01:51:58 -07:00
|
|
|
svgLogger,
|
2020-09-02 23:00:16 -07:00
|
|
|
currentUserId,
|
2020-04-23 14:23:46 -07:00
|
|
|
...buildLoaders(db),
|
2020-04-22 12:00:52 -07:00
|
|
|
};
|
2020-04-22 11:51:36 -07:00
|
|
|
},
|
2020-04-23 01:09:17 -07:00
|
|
|
|
2020-08-17 01:27:05 -07:00
|
|
|
plugins,
|
2020-05-23 11:32:05 -07:00
|
|
|
|
2020-04-23 01:09:17 -07:00
|
|
|
// Enable Playground in production :)
|
|
|
|
introspection: true,
|
2020-04-23 01:12:52 -07:00
|
|
|
playground: {
|
|
|
|
endpoint: "/api/graphql",
|
|
|
|
},
|
2020-04-22 13:03:32 -07:00
|
|
|
};
|
2020-04-22 11:51:36 -07:00
|
|
|
|
|
|
|
if (require.main === module) {
|
2020-04-22 13:03:32 -07:00
|
|
|
const { ApolloServer } = require("apollo-server");
|
|
|
|
const server = new ApolloServer(config);
|
2020-04-22 11:51:36 -07:00
|
|
|
server.listen().then(({ url }) => {
|
|
|
|
console.log(`🚀 Server ready at ${url}`);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-04-22 13:03:32 -07:00
|
|
|
module.exports = { config };
|