diff --git a/package-lock.json b/package-lock.json index 276c9a3..74e90e8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -652,12 +652,6 @@ "integrity": "sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA==", "dev": true }, - "@types/js-cookie": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.2.tgz", - "integrity": "sha512-vkuGzldF9mNsWS9cmmMFfW1rufa7IdPUorS150gKoU/2fzLJ/0LXiMMtRqIBWz0sZ/VF2VxwB25WXEOo6akU6w==", - "dev": true - }, "@types/jsonwebtoken": { "version": "8.3.3", "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.3.3.tgz", @@ -713,15 +707,6 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.5.tgz", "integrity": "sha512-9fq4jZVhPNW8r+UYKnxF1e2HkDWOWKM5bC2/7c9wPV835I0aOrVbS/Hw/pWPk2uKrNXQqg9Z959Kz+IYDd5p3w==" }, - "@types/node-fetch": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.2.tgz", - "integrity": "sha512-djYYKmdNRSBtL1x4CiE9UJb9yZhwtI1VC+UxZD0psNznrUj80ywsxKlEGAE+QL1qvLjPbfb24VosjkYM6W4RSQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, "@types/range-parser": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", diff --git a/package.json b/package.json index f4139c3..d5e82f3 100644 --- a/package.json +++ b/package.json @@ -4,11 +4,12 @@ "description": "", "main": "src/app.js", "scripts": { - "dev": "ts-node-dev --respawn src/app.ts", + "dev": "ts-node-dev --respawn src/bootstrap.ts", "test": "jest --coverage", "test:debug": "jest -i --verbose --detectOpenHandles", "test:watch": "jest -i --watch", - "gen:key": "ssh-keygen -t rsa -b 2048 -f src/app/userResolver/auth/jwtRS256.key && openssl rsa -in src/app/userResolver/auth/wtRS256.key -pubout -outform PEM -out src/app/userResolver/auth/wtRS256.key.pub" + "gen:key": "ssh-keygen -t rsa -b 2048 -f src/app/userResolver/auth/jwtRS256.key && openssl rsa -in src/app/userResolver/auth/wtRS256.key -pubout -outform PEM -out src/app/userResolver/auth/wtRS256.key.pub", + "debug": "ts-node-dev --inspect --respawn --transpileOnly src/bootstrap.ts" }, "keywords": [], "author": "", @@ -33,6 +34,7 @@ "@types/jsonwebtoken": "^8.3.3", "@types/node": "^12.7.5", "class-transformer": "^0.2.3", + "isomorphic-fetch": "^2.2.1", "jest": "^24.9.0", "ts-jest": "^24.1.0", "ts-node-dev": "^1.0.0-pre.42", diff --git a/src/app.spec.ts b/src/app.spec.ts new file mode 100644 index 0000000..82c1d20 --- /dev/null +++ b/src/app.spec.ts @@ -0,0 +1,49 @@ +require("isomorphic-fetch") +import { ApolloServer } from "apollo-server-express" +import { getConnection } from "typeorm" +import { bootstrap } from "./app" +import { connectionOptionsforTesting } from "./app/schema" +import { signToken } from "./app/userResolver/auth" +import { User } from "./app/userResolver/User" + +let server: ApolloServer +let port: number + +beforeAll(async () => { + port = 4001 + server = await bootstrap(connectionOptionsforTesting(), port) +}) + +describe("app should", () => { + it("accept auth header correctly", async () => { + const user = await User.create({ + email: "email@email.com", + }).save() + + let token = signToken({ userId: user.id }) + + const url = `http://localhost:${port}/graphql` + + const rawResponse = await fetch(url, { + method: "post", + headers: { + "content-Type": "application/json", + authorization: "Bearer " + token, + }, + body: JSON.stringify({ + query: "{me{email}}", + }), + }) + + const response = await rawResponse.json() + + expect(response.errors).toBeUndefined() + expect(response.data).toMatchObject({ + me: { email: user.email }, + }) + + await getConnection().synchronize(true) + await getConnection().close() + await server.stop() + }) +}) diff --git a/src/app.ts b/src/app.ts index f9b6f5b..fcf6456 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,25 +1,23 @@ -require("dotenv").config() -import { ApolloServer } from "apollo-server-express" -import { createConnection } from "typeorm" -import { connectionOptionsforDB, createSchema } from "./app/schema" import express = require("express") -;(async () => { - await createConnection(connectionOptionsforDB()) +import { ApolloServer } from "apollo-server-express" +import { ConnectionOptions, createConnection } from "typeorm" +import { createSchema } from "./app/schema" +import { contextFunction } from "./app/userResolver/auth" + +export const bootstrap = async (connectionOptions: ConnectionOptions, port: number) => { + await createConnection(connectionOptions) const server = new ApolloServer({ schema: await createSchema(), playground: true, introspection: true, debug: true, - context: ({ req, res }) => ({ req, res }), + context: contextFunction, }) const app = express() server.applyMiddleware({ app }) + app.listen({ port }) - app.listen({ port: process.env.APP_PORT }, () => - console.log( - `Server ready at http://localhost:${process.env.APP_PORT}${server.graphqlPath}` - ) - ) -})() + return server +} diff --git a/src/app/UserResolver.spec.ts b/src/app/UserResolver.spec.ts index a4c276b..ad17c81 100644 --- a/src/app/UserResolver.spec.ts +++ b/src/app/UserResolver.spec.ts @@ -1,12 +1,12 @@ import { gql } from "apollo-server" import { createConnection, getConnection } from "typeorm" -import { callSchema, connectionOptionsforDB } from "./schema" +import { callSchema, connectionOptionsforTesting } from "./schema" import { signToken, verifyToken } from "./userResolver/auth" import { LoginTokens } from "./userResolver/LoginTokens" import { User } from "./userResolver/User" beforeAll(async () => { - return await createConnection(connectionOptionsforDB("testing")) + return await createConnection(connectionOptionsforTesting()) }) afterAll(async () => { diff --git a/src/app/schema.ts b/src/app/schema.ts index dd3d633..2f28e84 100644 --- a/src/app/schema.ts +++ b/src/app/schema.ts @@ -26,12 +26,12 @@ export const createSchema = () => authChecker: customAuthChecker, }) -export const connectionOptionsforDB = (dbName?: string) => { +export const connectionOptionsforTesting = () => { let connectionOptions: ConnectionOptions = { type: "postgres", host: process.env.DB_HOST, port: 5432, - database: dbName || process.env.DB_NAME, + database: "testing", username: process.env.DB_USER, password: process.env.DB_PASS, entities: [User], diff --git a/src/app/userResolver/auth.ts b/src/app/userResolver/auth.ts index a200ffc..4be1e50 100644 --- a/src/app/userResolver/auth.ts +++ b/src/app/userResolver/auth.ts @@ -49,8 +49,10 @@ export const customAuthChecker: AuthChecker = ({ context }) => { return true } catch (error) { - throw new Error("the valid authorization header is required: ") + throw new Error("the valid authorization header is required: " + error) } } +export const contextFunction = ({ req, res }: MyContext) => ({ req, res }) + const readKeyFile = (fileName: string) => readFileSync(join(__dirname, "auth", fileName)) diff --git a/src/bootstrap.ts b/src/bootstrap.ts new file mode 100644 index 0000000..a7b159a --- /dev/null +++ b/src/bootstrap.ts @@ -0,0 +1,18 @@ +require("dotenv").config() +import { ConnectionOptions } from "typeorm" +import { bootstrap } from "./app" +import { User } from "./app/userResolver/User" + +let connectionOptions: ConnectionOptions = { + type: "postgres", + host: process.env.DB_HOST, + port: 5432, + database: process.env.DB_NAME, + username: process.env.DB_USER, + password: process.env.DB_PASS, + entities: [User], + synchronize: true, + logging: false, +} + +bootstrap(connectionOptions, 4000)