1
Fork 0

typescript(lunargame/api): got supertest sessions to work

Signed-off-by: prescientmoon <git@moonythm.dev>
This commit is contained in:
Mateiadrielrafael 2019-08-11 19:08:55 +03:00 committed by prescientmoon
parent dfab3750f9
commit 013b17dc22
Signed by: prescientmoon
SSH key fingerprint: SHA256:UUF9JT2s8Xfyv76b8ZuVL7XrmimH4o49p4b+iexbVH4
16 changed files with 245 additions and 64 deletions

View file

@ -0,0 +1,26 @@
// in case i want to change it
// it's alwys a pain to change it everywhere
const tableName = 'account'
exports.up = knex => {
return knex.schema.createTable(tableName, table => {
// this is the id of the simulation
table.increments()
// the name of the user
table.text('name').notNullable()
// the email of the user
table.text('email').notNullable()
// the password of the user
table.text('password').notNullable()
// the password encription
table.text('password_encription').notNullable()
})
}
exports.down = knex => {
return knex.schema.dropTable(tableName)
}

View file

@ -1,17 +0,0 @@
// in case i want to change it
// it's alwys a pain to change it everywhere
const tableName = 'simulation'
exports.up = function up(knex) {
return knex.schema.createTable(tableName, table => {
// this is the id of the simulation
table.increments()
// this is the actual name of the simulation
table.text('name').notNull()
})
}
exports.down = function down(knex) {
return knex.schema.dropTable(tableName)
}

View file

@ -10,9 +10,12 @@ const dbFolder = resolve(__dirname, 'db')
const testFolder = resolve(__dirname, 'test') const testFolder = resolve(__dirname, 'test')
// This is used in all configs // This is used in all configs
const migrations: Config['migrations'] = { const commonConfig: Partial<Config> = {
directory: resolve(dbFolder, 'migrations'), migrations: {
tableName: 'migrations' directory: resolve(dbFolder, 'migrations'),
tableName: 'migrations'
},
useNullAsDefault: true
} }
// This is the confg we are going to esport // This is the confg we are going to esport
@ -25,7 +28,7 @@ const config: Partial<Record<iNode_env, Config>> = {
connection: { connection: {
filename: resolve(dbFolder, dbName) filename: resolve(dbFolder, dbName)
}, },
migrations, ...commonConfig,
seeds: { seeds: {
directory: resolve(dbFolder, 'seeds') directory: resolve(dbFolder, 'seeds')
} }
@ -35,7 +38,7 @@ const config: Partial<Record<iNode_env, Config>> = {
connection: { connection: {
filename: resolve(testFolder, dbName) filename: resolve(testFolder, dbName)
}, },
migrations, ...commonConfig,
seeds: { seeds: {
directory: resolve(testFolder, 'seeds') directory: resolve(testFolder, 'seeds')
} }

View file

@ -231,10 +231,6 @@
"minimist": "^1.2.0" "minimist": "^1.2.0"
} }
}, },
"@eix/utils": {
"version": "github:eix-js/utils#a21d3b755e965e3c1b6022d0ccc8db457e5a706c",
"from": "github:eix-js/utils"
},
"@jest/console": { "@jest/console": {
"version": "24.7.1", "version": "24.7.1",
"resolved": "https://registry.npmjs.org/@jest/console/-/console-24.7.1.tgz", "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.7.1.tgz",
@ -569,6 +565,12 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"@types/cookiejar": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.1.tgz",
"integrity": "sha512-aRnpPa7ysx3aNW60hTiCtLHlQaIFsXFCgQlpakNgDNVFzbtusSY8PwjAQgRWfSk0ekNoBjO51eQRB6upA9uuyw==",
"dev": true
},
"@types/cookies": { "@types/cookies": {
"version": "0.7.2", "version": "0.7.2",
"resolved": "https://registry.npmjs.org/@types/cookies/-/cookies-0.7.2.tgz", "resolved": "https://registry.npmjs.org/@types/cookies/-/cookies-0.7.2.tgz",
@ -790,6 +792,25 @@
"integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==", "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==",
"dev": true "dev": true
}, },
"@types/superagent": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.3.tgz",
"integrity": "sha512-vy2licJQwOXrTAe+yz9SCyUVXAkMgCeDq9VHzS5CWJyDU1g6CI4xKb4d5sCEmyucjw5sG0y4k2/afS0iv/1D0Q==",
"dev": true,
"requires": {
"@types/cookiejar": "*",
"@types/node": "*"
}
},
"@types/supertest": {
"version": "2.0.8",
"resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.8.tgz",
"integrity": "sha512-wcax7/ip4XSSJRLbNzEIUVy2xjcBIZZAuSd2vtltQfRK7kxhx5WMHbLHkYdxN3wuQCrwpYrg86/9byDjPXoGMA==",
"dev": true,
"requires": {
"@types/superagent": "*"
}
},
"@types/tough-cookie": { "@types/tough-cookie": {
"version": "2.3.5", "version": "2.3.5",
"resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-2.3.5.tgz", "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-2.3.5.tgz",
@ -1542,6 +1563,11 @@
"safe-buffer": "~5.1.1" "safe-buffer": "~5.1.1"
} }
}, },
"cookiejar": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz",
"integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA=="
},
"cookies": { "cookies": {
"version": "0.7.3", "version": "0.7.3",
"resolved": "https://registry.npmjs.org/cookies/-/cookies-0.7.3.tgz", "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.7.3.tgz",
@ -2244,6 +2270,11 @@
"mime-types": "^2.1.12" "mime-types": "^2.1.12"
} }
}, },
"formidable": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz",
"integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg=="
},
"fragment-cache": { "fragment-cache": {
"version": "0.2.1", "version": "0.2.1",
"resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
@ -4707,6 +4738,11 @@
"to-regex": "^3.0.2" "to-regex": "^3.0.2"
} }
}, },
"mime": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
},
"mime-db": { "mime-db": {
"version": "1.40.0", "version": "1.40.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
@ -5590,8 +5626,7 @@
"process-nextick-args": { "process-nextick-args": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
"dev": true
}, },
"prompts": { "prompts": {
"version": "2.2.1", "version": "2.2.1",
@ -5708,7 +5743,6 @@
"version": "2.3.6", "version": "2.3.6",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
"dev": true,
"requires": { "requires": {
"core-util-is": "~1.0.0", "core-util-is": "~1.0.0",
"inherits": "~2.0.3", "inherits": "~2.0.3",
@ -6360,7 +6394,6 @@
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"dev": true,
"requires": { "requires": {
"safe-buffer": "~5.1.0" "safe-buffer": "~5.1.0"
} }
@ -6392,6 +6425,32 @@
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
"dev": true "dev": true
}, },
"superagent": {
"version": "3.8.3",
"resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz",
"integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==",
"requires": {
"component-emitter": "^1.2.0",
"cookiejar": "^2.1.0",
"debug": "^3.1.0",
"extend": "^3.0.0",
"form-data": "^2.3.1",
"formidable": "^1.2.0",
"methods": "^1.1.1",
"mime": "^1.4.1",
"qs": "^6.5.1",
"readable-stream": "^2.3.5"
}
},
"supertest": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/supertest/-/supertest-4.0.2.tgz",
"integrity": "sha512-1BAbvrOZsGA3YTCWqbmh14L0YEq0EGICX/nBnfkfVJn7SrxQV1I3pMYjSzG9y/7ZU2V9dWqyqk2POwxlb09duQ==",
"requires": {
"methods": "^1.1.2",
"superagent": "^3.8.3"
}
},
"supports-color": { "supports-color": {
"version": "5.5.0", "version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
@ -6829,8 +6888,7 @@
"util-deprecate": { "util-deprecate": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
"dev": true
}, },
"util.promisify": { "util.promisify": {
"version": "1.0.0", "version": "1.0.0",

View file

@ -3,8 +3,9 @@
"version": "1.0.0", "version": "1.0.0",
"scripts": { "scripts": {
"start": "nodemon", "start": "nodemon",
"reset:db": "knex migrate:rollback && knex migrate:latest && knex seed:run", "reset-db": "knex migrate:rollback && knex migrate:latest && knex seed:run",
"test": "cross-env NODE_ENV=test && jest --runInBand" "reset-db:test": "(knex migrate:rollback --env test) && (knex migrate:latest --env test) && (knex seed:run --env test)",
"test": "cross-env NODE_ENV=test && jest"
}, },
"main": "index.js", "main": "index.js",
"private": true, "private": true,
@ -20,6 +21,7 @@
"@types/koa__cors": "^2.2.3", "@types/koa__cors": "^2.2.3",
"@types/node": "^12.0.10", "@types/node": "^12.0.10",
"@types/nodemailer": "^6.2.0", "@types/nodemailer": "^6.2.0",
"@types/supertest": "^2.0.8",
"@types/uuid": "^3.4.5", "@types/uuid": "^3.4.5",
"cross-env": "^5.2.0", "cross-env": "^5.2.0",
"jest": "^24.8.0", "jest": "^24.8.0",
@ -30,7 +32,6 @@
"typescript": "^3.5.2" "typescript": "^3.5.2"
}, },
"dependencies": { "dependencies": {
"@eix/utils": "github:eix-js/utils",
"@koa/cors": "^3.0.0", "@koa/cors": "^3.0.0",
"@sendgrid/mail": "^6.4.0", "@sendgrid/mail": "^6.4.0",
"bcryptjs": "^2.4.3", "bcryptjs": "^2.4.3",
@ -44,6 +45,7 @@
"koa-session-knex-store": "^1.1.2", "koa-session-knex-store": "^1.1.2",
"nodemailer": "^6.2.1", "nodemailer": "^6.2.1",
"pg": "^7.11.0", "pg": "^7.11.0",
"supertest": "^4.0.2",
"uuid": "^3.3.2" "uuid": "^3.3.2"
} }
} }

View file

@ -2,6 +2,14 @@ import { ObjectSchema } from 'joi'
import { Middleware } from 'koa' import { Middleware } from 'koa'
import { HttpError } from '../../../modules/network/classes/HttpError' import { HttpError } from '../../../modules/network/classes/HttpError'
/**
* Middlware to validate a joi schema against a request
*
* @param schema The joi shcema to use for the validation
* @param field The field to validate the schema against
*
* @throws HttpError if the validation fails
*/
export const validate = ( export const validate = (
schema: ObjectSchema, schema: ObjectSchema,
field: 'params' | 'body' | 'query' field: 'params' | 'body' | 'query'

View file

@ -1,29 +1,7 @@
import Koa from 'koa' import { app } from './server'
import cors from '@koa/cors'
import parser from 'koa-bodyparser'
import { config } from 'dotenv'
import { handleError } from './modules/network/middleware/errorHandler'
import { handleSessions } from './modules/network/middleware/handleSessions'
import { router } from './modules/core/router'
config()
const port = process.env.PORT const port = process.env.PORT
const app = new Koa()
app.keys = [process.env.secret || 'secret'] export const server = app.listen(Number(port), () => {
app.use(
cors({
credentials: true
})
)
.use(handleError())
.use(handleSessions(app))
.use(parser())
.use(router.middleware())
app.listen(Number(port), () => {
console.log(`Listening on port ${port}`) console.log(`Listening on port ${port}`)
}) })

View file

@ -0,0 +1,26 @@
import supertest from 'supertest'
import { app } from '../../../server'
import { loggedInAgent } from '../../../../test/utils/loggedInAgent'
describe('The /auth route', () => {
let request = supertest(app.callback())
test('should return undefined if the user was not logged in', async () => {
const res = await request.get('/auth')
expect(res.body.uid).toBe(undefined)
})
test.only('should return the uid form the session while logged in', async () => {
const uid = 7
const [agent, cookie] = await loggedInAgent(
supertest.agent(app.callback()),
uid
)
const res = await agent.get('/auth').set('cookie', cookie)
expect(res.body.uid).toBe(uid)
})
})

View file

@ -0,0 +1,20 @@
import Router from 'koa-router'
const router = new Router()
router.get('/', (context, next) => {
context.body = {
uid: context.session.uid
}
return next()
})
router.post('/login', (context, next) => {
context.session.uid = context.request.body.uid
context.body = {}
return next()
})
export default router

View file

@ -0,0 +1,7 @@
import Joi from 'joi'
import { name, password } from './authFields'
export const LoginBodySchema = Joi.object({
name,
password
})

View file

@ -0,0 +1,20 @@
import Joi from 'joi'
export const name = Joi.string()
.alphanum()
.min(3)
.max(30)
.lowercase()
.required()
export const email = Joi.string()
.email()
.min(3)
.max(30)
.required()
export const password = Joi.string()
.min(3)
.max(50)
.alphanum()
.required()

View file

@ -1,7 +1,8 @@
import Router from 'koa-router' import Router from 'koa-router'
import AuthRouter from '../auth/routes/authRoute'
const router = new Router() const router = new Router()
router.use('/game') router.use('/auth', AuthRouter.middleware())
export { router } export { router }

View file

@ -4,7 +4,7 @@ import knexSessionStore from 'koa-session-knex-store'
import { connection } from '../../db/connection' import { connection } from '../../db/connection'
// The store sessions are saved to // The store sessions are saved to
const store = knexSessionStore(connection, { export const sessionStore = knexSessionStore(connection, {
createtable: true createtable: true
}) })
@ -16,13 +16,12 @@ const store = knexSessionStore(connection, {
export const handleSessions = (app: Koa): Middleware => export const handleSessions = (app: Koa): Middleware =>
session( session(
{ {
key: 'something',
maxAge: 1000 * 60 * 60 * (24 * 7), maxAge: 1000 * 60 * 60 * (24 * 7),
overwrite: true, overwrite: true,
signed: true, signed: true,
rolling: true, rolling: true,
renew: false, renew: false,
store, store: sessionStore,
domain: 'localhost' domain: 'localhost'
}, },
app app

View file

@ -0,0 +1,26 @@
import Koa from 'koa'
import cors from '@koa/cors'
import parser from 'koa-bodyparser'
import { config } from 'dotenv'
import { handleError } from './modules/network/middleware/errorHandler'
import { handleSessions } from './modules/network/middleware/handleSessions'
import { router } from './modules/core/router'
config()
const app = new Koa()
app.keys = [process.env.secret || 'secret']
app.use(
cors({
credentials: true
})
)
.use(handleError())
.use(parser())
.use(handleSessions(app))
.use(router.middleware())
export { app }

View file

@ -0,0 +1,24 @@
import supertest from 'supertest'
/**
* Helper to get a supertest agent wich is logged in
*
* @param agent The agent to make the request with
* @param uid The uid to use to login
*/
export const loggedInAgent = async (
agent: supertest.SuperTest<supertest.Test>,
uid: number
) => {
const response = await agent.post('/auth/login').send({
uid
})
// the cookie to send back
// needs to be set manually due to a bug with jest
const cookie = response.header['set-cookie']
expect(response.status).toBe(200)
return [agent, cookie]
}

View file

@ -8,6 +8,6 @@
"lib": ["es2015", "dom", "dom.iterable", "esnext"], "lib": ["es2015", "dom", "dom.iterable", "esnext"],
"target": "esnext" "target": "esnext"
}, },
"include": ["src"], "include": ["src", "test"],
"exclude": ["node_modules"] "exclude": ["node_modules"]
} }