typescript(lunargame/api): added eslint
Signed-off-by: prescientmoon <git@moonythm.dev>
This commit is contained in:
parent
013b17dc22
commit
02bf17d559
25
typescript/lunargame/api/.eslintrc.json
Normal file
25
typescript/lunargame/api/.eslintrc.json
Normal file
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"env": {
|
||||
"es6": true,
|
||||
"node": true,
|
||||
"jest": true
|
||||
},
|
||||
"extends": [
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"prettier/@typescript-eslint",
|
||||
"plugin:prettier/recommended"
|
||||
],
|
||||
"globals": {
|
||||
"Atomics": "readonly",
|
||||
"SharedArrayBuffer": "readonly"
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2018,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"rules": {
|
||||
"@typescript-eslint/explicit-function-return-type": 0,
|
||||
"@typescript-eslint/no-object-literal-type-assertion": 0
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"trailingComma": "none",
|
||||
"singleQuote": true,
|
||||
"printWidth": 80,
|
||||
"printWidth": 100,
|
||||
"tabWidth": 4,
|
||||
"semi": false
|
||||
}
|
||||
|
|
|
@ -2,5 +2,7 @@
|
|||
"eslint.enable": true,
|
||||
"editor.formatOnSave": true,
|
||||
"prettier.eslintIntegration": true,
|
||||
"explorer.autoReveal": false
|
||||
"explorer.autoReveal": false,
|
||||
"eslint.autoFixOnSave": true,
|
||||
"eslint.validate": ["javascript", { "language": "typescript", "autoFix": true }]
|
||||
}
|
||||
|
|
|
@ -16,8 +16,8 @@ exports.up = knex => {
|
|||
// the password of the user
|
||||
table.text('password').notNullable()
|
||||
|
||||
// the password encription
|
||||
table.text('password_encription').notNullable()
|
||||
// the password encryption
|
||||
table.text('passwordEncryption').notNullable()
|
||||
})
|
||||
}
|
||||
|
||||
|
|
821
typescript/lunargame/api/package-lock.json
generated
821
typescript/lunargame/api/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -12,6 +12,7 @@
|
|||
"devDependencies": {
|
||||
"@types/bcryptjs": "^2.4.2",
|
||||
"@types/dotenv": "^6.1.1",
|
||||
"@types/faker": "^4.1.5",
|
||||
"@types/jest": "^24.0.17",
|
||||
"@types/joi": "^14.3.3",
|
||||
"@types/koa": "^2.0.49",
|
||||
|
@ -20,12 +21,18 @@
|
|||
"@types/koa-session": "^5.10.1",
|
||||
"@types/koa__cors": "^2.2.3",
|
||||
"@types/node": "^12.0.10",
|
||||
"@types/nodemailer": "^6.2.0",
|
||||
"@types/supertest": "^2.0.8",
|
||||
"@types/uuid": "^3.4.5",
|
||||
"@typescript-eslint/eslint-plugin": "^1.13.0",
|
||||
"@typescript-eslint/parser": "^1.13.0",
|
||||
"cross-env": "^5.2.0",
|
||||
"eslint": "^6.1.0",
|
||||
"eslint-config-prettier": "^6.0.0",
|
||||
"eslint-plugin-prettier": "^3.1.0",
|
||||
"faker": "^4.1.0",
|
||||
"jest": "^24.8.0",
|
||||
"nodemon": "^1.19.1",
|
||||
"prettier": "^1.18.2",
|
||||
"sqlite3": "^4.0.9",
|
||||
"ts-jest": "^24.0.2",
|
||||
"ts-node": "^8.3.0",
|
||||
|
@ -37,13 +44,13 @@
|
|||
"bcryptjs": "^2.4.3",
|
||||
"dotenv": "^8.0.0",
|
||||
"joi": "^14.3.1",
|
||||
"joi-extract-type": "^15.0.0",
|
||||
"knex": "^0.18.1",
|
||||
"koa": "^2.7.0",
|
||||
"koa-bodyparser": "^4.2.1",
|
||||
"koa-router": "^7.4.0",
|
||||
"koa-session": "^5.12.0",
|
||||
"koa-session-knex-store": "^1.1.2",
|
||||
"nodemailer": "^6.2.1",
|
||||
"pg": "^7.11.0",
|
||||
"supertest": "^4.0.2",
|
||||
"uuid": "^3.3.2"
|
||||
|
|
|
@ -8,15 +8,8 @@ describe('The randomElement function', () => {
|
|||
})
|
||||
|
||||
test('should throw an error when passing an empty array', () => {
|
||||
let error: Error | undefined
|
||||
|
||||
try {
|
||||
expect(() => {
|
||||
randomElement([])
|
||||
} catch (catchedError) {
|
||||
//
|
||||
error = catchedError
|
||||
}
|
||||
|
||||
expect(error).toBeTruthy()
|
||||
}).toThrow()
|
||||
})
|
||||
})
|
||||
|
|
4
typescript/lunargame/api/src/modules/auth/constants.ts
Normal file
4
typescript/lunargame/api/src/modules/auth/constants.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
import { passwordEncryption } from './types/passwordEncryption'
|
||||
|
||||
// i made a separate constant to prevent duplication
|
||||
export const defaultEncryptionMethod: passwordEncryption = 'bcrypt'
|
|
@ -0,0 +1,20 @@
|
|||
import { checkPassword } from './checkPassword'
|
||||
import { passwordEncryption } from '../types/passwordEncryption'
|
||||
|
||||
describe('The checkPassword helper', () => {
|
||||
const pass = 'this is a test password'
|
||||
|
||||
test("should throw an error if the encryption method doesn't exist", () => {
|
||||
expect(() => {
|
||||
checkPassword(pass, pass, '12212' as passwordEncryption)
|
||||
}).toThrow()
|
||||
})
|
||||
|
||||
test('should return true if the password matches the hash and the encryption = plain', () => {
|
||||
expect(checkPassword(pass, pass, 'plain')).toBe(true)
|
||||
})
|
||||
|
||||
test('shoud return false if the password is wrong and the encryption = plain', () => {
|
||||
expect(checkPassword(pass, pass + 'something', 'plain')).toBe(false)
|
||||
})
|
||||
})
|
|
@ -0,0 +1,21 @@
|
|||
import { passwordEncryption } from '../types/passwordEncryption'
|
||||
import { HttpError } from '../../network/classes/HttpError'
|
||||
|
||||
/**
|
||||
* Comparesa apssword with it's hash
|
||||
*
|
||||
* @param hash The hash of the password
|
||||
* @param password The actual password
|
||||
* @param encryption The encription of the password
|
||||
*/
|
||||
export const checkPassword = (
|
||||
hash: string,
|
||||
password: string,
|
||||
encryption: passwordEncryption = 'plain'
|
||||
) => {
|
||||
if (encryption === 'plain') {
|
||||
return hash === password
|
||||
} else {
|
||||
throw new HttpError(400, `Encription ${encryption} doesn't exist`)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
import { internet } from 'faker'
|
||||
import { encryptPassword } from './encryptPassword'
|
||||
import { compare } from 'bcryptjs'
|
||||
|
||||
describe('The encryptPassword helper', () => {
|
||||
test("should return the same password if the method is 'plain'", async () => {
|
||||
const password = internet.password()
|
||||
const hash = await encryptPassword(password, 'plain')
|
||||
|
||||
expect(hash).toBe(password)
|
||||
})
|
||||
|
||||
test("should return a mactching hash if the method is 'bcrypt'", async () => {
|
||||
const password = internet.password()
|
||||
|
||||
// the amount of rounds is small because this is just a test
|
||||
const hash = await encryptPassword(password, 'bcrypt', 3)
|
||||
const match = await compare(password, hash)
|
||||
|
||||
expect(match).toBe(true)
|
||||
})
|
||||
})
|
|
@ -0,0 +1,24 @@
|
|||
import { passwordEncryption } from '../types/passwordEncryption'
|
||||
import { genSalt, hash } from 'bcryptjs'
|
||||
|
||||
/**
|
||||
* Encypts a string
|
||||
*
|
||||
* @param password The password to encrypt
|
||||
* @param method The method to encrypt the password with
|
||||
* @param rounds The salting rounds (for bcrypt only)
|
||||
*/
|
||||
export const encryptPassword = async (
|
||||
password: string,
|
||||
method: passwordEncryption,
|
||||
rounds = 10
|
||||
) => {
|
||||
if (method === 'bcrypt') {
|
||||
const salt = await genSalt(rounds)
|
||||
const result = await hash(password, salt)
|
||||
|
||||
return result
|
||||
} else {
|
||||
return password
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
import { Middleware } from 'koa'
|
||||
import { HttpError } from '../../network/classes/HttpError'
|
||||
|
||||
/**
|
||||
* Middlware wich throws an error if the user isn't logged in
|
||||
*/
|
||||
export const isAuthorized = (): Middleware => (context, next) => {
|
||||
if (context.session.uid !== undefined) {
|
||||
return next()
|
||||
} else {
|
||||
throw new HttpError(401)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
import { Context } from 'koa'
|
||||
import { isUnauthorized } from './isUnauthorized'
|
||||
|
||||
describe('The isUnauthorized middleware', () => {
|
||||
const fakeNext = () => async () => {}
|
||||
|
||||
test('should throw an error if the user is logged in', () => {
|
||||
const fakeContext = ({
|
||||
session: {
|
||||
uid: 7
|
||||
}
|
||||
} as unknown) as Context
|
||||
|
||||
expect(() => isUnauthorized()(fakeContext, fakeNext())).toThrow()
|
||||
})
|
||||
|
||||
test("should call next if the user isn't logged in", () => {
|
||||
const fakeContext = {
|
||||
session: {}
|
||||
} as Context
|
||||
|
||||
const next = jest.fn(fakeNext())
|
||||
|
||||
isUnauthorized()(fakeContext, next)
|
||||
|
||||
expect(next).toBeCalled()
|
||||
})
|
||||
})
|
|
@ -0,0 +1,13 @@
|
|||
import { Middleware } from 'koa'
|
||||
import { HttpError } from '../../network/classes/HttpError'
|
||||
|
||||
/**
|
||||
* Middleware wich throws an error if the user is logged in
|
||||
*/
|
||||
export const isUnauthorized = (): Middleware => (context, next) => {
|
||||
if (context.session.uid === undefined) {
|
||||
return next()
|
||||
} else {
|
||||
throw new HttpError(401)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
import { isAuthorized } from './isAuthorized'
|
||||
import { Context } from 'koa'
|
||||
|
||||
describe('The isAuthorized middleware', () => {
|
||||
const fakeNext = () => async () => {}
|
||||
|
||||
test("should throw an error if the user isn't logged in", () => {
|
||||
const fakeContext = {
|
||||
session: {}
|
||||
} as Context
|
||||
|
||||
expect(() => isAuthorized()(fakeContext, fakeNext())).toThrow()
|
||||
})
|
||||
|
||||
test('should call next if the user is logged in', () => {
|
||||
const fakeContext = ({
|
||||
session: {
|
||||
uid: Math.random()
|
||||
}
|
||||
} as unknown) as Context
|
||||
|
||||
const next = jest.fn(fakeNext())
|
||||
|
||||
isAuthorized()(fakeContext, next)
|
||||
|
||||
expect(next).toBeCalled()
|
||||
})
|
||||
})
|
|
@ -0,0 +1,32 @@
|
|||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
||||
import { name, random, internet } from 'faker'
|
||||
import { createAccount } from './createAccount'
|
||||
import { connection } from '../../db/connection'
|
||||
import { SignupBody } from '../schemas/SignupBody'
|
||||
|
||||
describe('The createAccount query', () => {
|
||||
test('should return the id of the account and add it to the db', async () => {
|
||||
const email = internet.email()
|
||||
const username = name.firstName()
|
||||
const password = random.alphaNumeric(10)
|
||||
|
||||
const result = await createAccount({
|
||||
email,
|
||||
name: username,
|
||||
password,
|
||||
passwordEncryption: 'plain'
|
||||
})
|
||||
|
||||
const account = await connection
|
||||
.from('account')
|
||||
.select<Required<SignupBody>>(['email', 'name', 'password'])
|
||||
.where({
|
||||
id: result
|
||||
})
|
||||
.first()
|
||||
|
||||
expect(account.name).toBe(username)
|
||||
expect(account.email).toBe(email)
|
||||
expect(account.password).toBe(password)
|
||||
})
|
||||
})
|
|
@ -0,0 +1,15 @@
|
|||
import { connection } from '../../db/connection'
|
||||
import { DbAccount } from '../types/Account'
|
||||
|
||||
/**
|
||||
* Saves a new user into the db
|
||||
*
|
||||
* @param user The user object to insert
|
||||
*/
|
||||
export const createAccount = async (user: DbAccount): Promise<number> => {
|
||||
const result = await connection.from('account').insert({
|
||||
...user
|
||||
})
|
||||
|
||||
return result[0]
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
import { getPasswordByEmail } from './getPasswordByEmail'
|
||||
import { mockAccounts } from '../../../../test/seeds/01_create-account'
|
||||
import { connection } from '../../db/connection'
|
||||
|
||||
describe('The getPasswordByName query', () => {
|
||||
test('should return the correct password & encryption for a mock account', async () => {
|
||||
await connection.seed.run()
|
||||
|
||||
for (const account of mockAccounts) {
|
||||
const result = await getPasswordByEmail(account.email)
|
||||
|
||||
expect(result.password).toBe(account.password)
|
||||
expect(result.passwordEncryption).toBe(account.passwordEncryption)
|
||||
}
|
||||
})
|
||||
})
|
|
@ -0,0 +1,26 @@
|
|||
import { connection } from '../../db/connection'
|
||||
import { passwordEncryption } from '../types/passwordEncryption'
|
||||
|
||||
/**
|
||||
* The result of the getPasswordByName query
|
||||
*/
|
||||
export interface PasswordByEmailResult {
|
||||
password: string
|
||||
passwordEncryption: passwordEncryption
|
||||
id: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the password, passwordEncryption and id of an account from it's email
|
||||
*
|
||||
* @param email The email of the account
|
||||
*/
|
||||
export const getPasswordByEmail = (email: string): Promise<PasswordByEmailResult> => {
|
||||
return connection
|
||||
.from('account')
|
||||
.select('password', 'passwordEncryption', 'id')
|
||||
.where({
|
||||
email
|
||||
})
|
||||
.first()
|
||||
}
|
|
@ -1,26 +1,95 @@
|
|||
import supertest from 'supertest'
|
||||
import { app } from '../../../server'
|
||||
import { loggedInAgent } from '../../../../test/utils/loggedInAgent'
|
||||
import { mockAccounts } from '../../../../test/seeds/01_create-account'
|
||||
import { random, internet } from 'faker'
|
||||
import { LoginReponseBody } from '../types/LoginReponseBody'
|
||||
import { defaultEncryptionMethod } from '../constants'
|
||||
|
||||
describe('The /auth route', () => {
|
||||
// used to make requests
|
||||
let request = supertest(app.callback())
|
||||
|
||||
test('should return undefined if the user was not logged in', async () => {
|
||||
const res = await request.get('/auth')
|
||||
describe(`The POST method on the /login subroute`, () => {
|
||||
test('should throw an error if the password field is empty', async () => {
|
||||
const response = await request.post('/auth/login').send({
|
||||
name: mockAccounts[0].name
|
||||
})
|
||||
|
||||
expect(res.body.uid).toBe(undefined)
|
||||
expect(response.status).not.toBe(200)
|
||||
})
|
||||
|
||||
test('should throw an error if the name field is empty', async () => {
|
||||
const response = await request.post('/auth/login').send({
|
||||
password: mockAccounts[0].password
|
||||
})
|
||||
|
||||
expect(response.status).not.toBe(200)
|
||||
})
|
||||
|
||||
test('should throw an error if the password is wrong', async () => {
|
||||
const response = await request.post('/auth/login').send({
|
||||
name: mockAccounts[0].name,
|
||||
password: mockAccounts[0].password + 'something'
|
||||
})
|
||||
|
||||
expect(response.status).not.toBe(200)
|
||||
})
|
||||
|
||||
test('should work just fine when the password is correct', async () => {
|
||||
for (const account of mockAccounts) {
|
||||
const response = await request.post('/auth/login').send({
|
||||
email: account.email,
|
||||
password: account.password
|
||||
})
|
||||
|
||||
// i'm making a separate constant for vsc to help me
|
||||
const body: LoginReponseBody = response.body
|
||||
|
||||
expect(response.status).toBe(200)
|
||||
expect(body.uid).not.toBe(undefined)
|
||||
expect(body.encryption).toBe(account.passwordEncryption)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
test.only('should return the uid form the session while logged in', async () => {
|
||||
const uid = 7
|
||||
describe(`The GET method on the / subroute`, () => {
|
||||
test('should return undefined if the user was not logged in', async () => {
|
||||
const res = await request.get('/auth')
|
||||
|
||||
const [agent, cookie] = await loggedInAgent(
|
||||
supertest.agent(app.callback()),
|
||||
uid
|
||||
)
|
||||
expect(res.body.uid).toBe(undefined)
|
||||
})
|
||||
|
||||
const res = await agent.get('/auth').set('cookie', cookie)
|
||||
test('should return the uid form the session while logged in', async () => {
|
||||
const [agent, cookie] = await loggedInAgent(supertest.agent(app.callback()), {
|
||||
email: mockAccounts[0].email,
|
||||
password: mockAccounts[0].password
|
||||
})
|
||||
|
||||
expect(res.body.uid).toBe(uid)
|
||||
const response = await agent.get('/auth').set('cookie', cookie)
|
||||
|
||||
expect(response.body.uid).not.toBe(undefined)
|
||||
})
|
||||
})
|
||||
|
||||
describe('The POST method on the /signup subroute', () => {
|
||||
test('should return the email name and the encrytion', async () => {
|
||||
const username = random.alphaNumeric(7)
|
||||
const password = random.alphaNumeric(5)
|
||||
const email = internet.email()
|
||||
|
||||
const response = await request.post('/auth/signup').send({
|
||||
name: username,
|
||||
email,
|
||||
password
|
||||
})
|
||||
|
||||
// i'm making a separate constant for vsc to help me
|
||||
const body: LoginReponseBody = response.body
|
||||
|
||||
expect(response.status).toBe(200)
|
||||
expect(body.uid).not.toBe(undefined)
|
||||
expect(body.encryption).toBe(defaultEncryptionMethod)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,4 +1,14 @@
|
|||
import Router from 'koa-router'
|
||||
import { validate } from '../../../common/validation/middleware/validate'
|
||||
import { getPasswordByEmail } from '../queries/getPasswordByEmail'
|
||||
import { HttpError } from '../../network/classes/HttpError'
|
||||
import { checkPassword } from '../helpers/checkPassword'
|
||||
import { SignupBodySchema } from '../schemas/SignupBody'
|
||||
import { encryptPassword } from '../helpers/encryptPassword'
|
||||
import { createAccount } from '../queries/createAccount'
|
||||
import { defaultEncryptionMethod } from '../constants'
|
||||
import { LoginBodySchema } from '../schemas/LoginBody'
|
||||
import { isUnauthorized } from '../middleware/isUnauthorized'
|
||||
|
||||
const router = new Router()
|
||||
|
||||
|
@ -10,11 +20,65 @@ router.get('/', (context, next) => {
|
|||
return next()
|
||||
})
|
||||
|
||||
router.post('/login', (context, next) => {
|
||||
context.session.uid = context.request.body.uid
|
||||
context.body = {}
|
||||
router.post(
|
||||
'/login',
|
||||
isUnauthorized(),
|
||||
validate(LoginBodySchema, 'body'),
|
||||
async (context, next) => {
|
||||
const { email, password } = context.request.body
|
||||
|
||||
return next()
|
||||
})
|
||||
const passwordData = await getPasswordByEmail(email)
|
||||
|
||||
// in case the user doesnt exist
|
||||
if (!passwordData) {
|
||||
throw new HttpError(400)
|
||||
}
|
||||
|
||||
const match = checkPassword(
|
||||
passwordData.password,
|
||||
password,
|
||||
passwordData.passwordEncryption
|
||||
)
|
||||
|
||||
if (!match) {
|
||||
throw new HttpError(400, 'wrong password')
|
||||
}
|
||||
|
||||
context.session.uid = passwordData.id
|
||||
|
||||
context.body = {
|
||||
encryption: passwordData.passwordEncryption,
|
||||
uid: passwordData.id
|
||||
}
|
||||
|
||||
return next()
|
||||
}
|
||||
)
|
||||
|
||||
router.post(
|
||||
'/signup',
|
||||
isUnauthorized(),
|
||||
validate(SignupBodySchema, 'body'),
|
||||
async (context, next) => {
|
||||
const { email, name, password } = context.request.body
|
||||
|
||||
// encript the password (bcrypt by default)
|
||||
const encryptedPassword = await encryptPassword(password, defaultEncryptionMethod, 10)
|
||||
|
||||
const uid = await createAccount({
|
||||
email,
|
||||
name,
|
||||
password: encryptedPassword,
|
||||
passwordEncryption: defaultEncryptionMethod
|
||||
})
|
||||
|
||||
context.body = {
|
||||
uid,
|
||||
encryption: defaultEncryptionMethod
|
||||
}
|
||||
|
||||
return next()
|
||||
}
|
||||
)
|
||||
|
||||
export default router
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import Joi from 'joi'
|
||||
import { name, password } from './authFields'
|
||||
import Joi from '@hapi/joi'
|
||||
import { email, password } from './authFields'
|
||||
|
||||
export const LoginBodySchema = Joi.object({
|
||||
name,
|
||||
email,
|
||||
password
|
||||
})
|
||||
}).required()
|
||||
|
||||
export type LoginBody = Joi.extractType<typeof LoginBodySchema>
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
import Joi from '@hapi/joi'
|
||||
import { email, name, password } from './authFields'
|
||||
|
||||
export const SignupBodySchema = Joi.object({
|
||||
name,
|
||||
password,
|
||||
email
|
||||
}).required()
|
||||
|
||||
export type SignupBody = Joi.extractType<typeof SignupBodySchema>
|
|
@ -1,10 +1,8 @@
|
|||
import Joi from 'joi'
|
||||
|
||||
export const name = Joi.string()
|
||||
.alphanum()
|
||||
.min(3)
|
||||
.max(30)
|
||||
.lowercase()
|
||||
.required()
|
||||
|
||||
export const email = Joi.string()
|
||||
|
@ -15,6 +13,6 @@ export const email = Joi.string()
|
|||
|
||||
export const password = Joi.string()
|
||||
.min(3)
|
||||
.max(50)
|
||||
.max(20)
|
||||
.alphanum()
|
||||
.required()
|
||||
|
|
32
typescript/lunargame/api/src/modules/auth/types/Account.ts
Normal file
32
typescript/lunargame/api/src/modules/auth/types/Account.ts
Normal file
|
@ -0,0 +1,32 @@
|
|||
import { passwordEncryption } from './passwordEncryption'
|
||||
|
||||
/**
|
||||
* The data about an account wich needs to be inserted into the db
|
||||
*/
|
||||
export interface DbAccount {
|
||||
name: string
|
||||
email: string
|
||||
password: string
|
||||
passwordEncryption: passwordEncryption
|
||||
}
|
||||
|
||||
/**
|
||||
* The data about an account wich actually gets stored into the db
|
||||
*/
|
||||
export interface FullDbAccount extends DbAccount {
|
||||
id: number
|
||||
}
|
||||
|
||||
/**
|
||||
* The data everyone can get about an account
|
||||
*/
|
||||
export interface AccountPublicData {
|
||||
name: string
|
||||
}
|
||||
|
||||
/**
|
||||
* The data only the owner of the account has acces to
|
||||
*/
|
||||
export interface AccountPrivateData extends AccountPublicData {
|
||||
email: string
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
import { passwordEncryption } from './passwordEncryption'
|
||||
|
||||
export interface LoginReponseBody {
|
||||
uid: number
|
||||
encryption: passwordEncryption
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* All modes a password can be encrypted in
|
||||
*/
|
||||
export type passwordEncryption = 'plain' | 'bcrypt'
|
21
typescript/lunargame/api/test/seeds/01_create-account.ts
Normal file
21
typescript/lunargame/api/test/seeds/01_create-account.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import * as Knex from 'knex'
|
||||
import { DbAccount } from '../../src/modules/auth/types/Account'
|
||||
|
||||
const tableName = 'account'
|
||||
|
||||
export const mockAccounts: DbAccount[] = [
|
||||
{
|
||||
name: 'Adriel',
|
||||
email: 'rafaeladriel11@gmail.com',
|
||||
password: '1234',
|
||||
passwordEncryption: 'plain'
|
||||
}
|
||||
]
|
||||
|
||||
export async function seed(knex: Knex): Promise<any> {
|
||||
return knex(tableName)
|
||||
.del()
|
||||
.then(() => {
|
||||
return knex(tableName).insert(mockAccounts)
|
||||
})
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
import supertest from 'supertest'
|
||||
import 'joi-extract-type'
|
||||
import { LoginBody } from '../../src/modules/auth/schemas/LoginBody'
|
||||
|
||||
/**
|
||||
* Helper to get a supertest agent wich is logged in
|
||||
|
@ -8,10 +10,11 @@ import supertest from 'supertest'
|
|||
*/
|
||||
export const loggedInAgent = async (
|
||||
agent: supertest.SuperTest<supertest.Test>,
|
||||
uid: number
|
||||
{ email, password }: LoginBody
|
||||
) => {
|
||||
const response = await agent.post('/auth/login').send({
|
||||
uid
|
||||
email,
|
||||
password
|
||||
})
|
||||
|
||||
// the cookie to send back
|
||||
|
|
Loading…
Reference in a new issue