Skip to content

Commit

Permalink
populate data model and testing of register/authenticate user b00tc4m…
Browse files Browse the repository at this point in the history
  • Loading branch information
Rafa0297 committed Nov 27, 2024
1 parent 375f6fa commit b902c36
Show file tree
Hide file tree
Showing 32 changed files with 345 additions and 130 deletions.
41 changes: 27 additions & 14 deletions staff/rafael-infante/lovingHands/api/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import 'dotenv/config'
import db from '../dat/index.js'
import express, {json} from 'express'
import express, { json } from 'express'
import cors from 'cors'
import jwt from 'jsonwebtoken'
import { errors } from 'com'

import logic from './logic/index.js'
import { createFunctionalHandler, authorizationHandler, errorHandler } from './helpers/index.js'
Expand All @@ -18,21 +19,33 @@ db.connect(process.env.MONGO_URL_TEST).then(() => {

server.get('/', (_, res) => res.send('Hello, API!'))

server.post('/users', jsonBodyParser, (req, res) => {
const { name, email, username, password, passwordRepeat } = req.body

try {
logic.registerUser(name, email, username, password, passwordRepeat)

server.post(
'/users/auth',
jsonBodyParser,
createFunctionalHandler(async (req, res) => {
const { email, password } = req.body

const { id, role } = await logic.authenticateUser(email, password)

const token = await jwt.sign({ sub: id, role }, process.env.JWT_SECRET, { expiresIn: '2h' })

res.json(token)
})
)

server.post(
'/users',
jsonBodyParser,
createFunctionalHandler(async (req, res) => {
const { name, email, password, passwordRepeat } = req.body

await logic.registerUser(name, email, password, passwordRepeat)

res.status(201).send()
} catch (error) {
res.status(400).json({ error: error.constructor.name, message: error.message })

console.error(error)
}
})
})
)

server.use(errorHandler)

server.listen(process.env.PORT, () => console.log(`API listening on port ${process.env.PORT}`))
})
})
37 changes: 37 additions & 0 deletions staff/rafael-infante/lovingHands/api/logic/authenticateUser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import bcrypt from 'bcryptjs'

import { User } from 'dat'
import { validate, errors } from 'com'
const { CredentialsError, SystemError } = errors

export default (email, password) => {
validate.email(email)
validate.password(password)

return (async () => {
let user

try {
user = await User.findOne({ email })
} catch (error) {
throw new SystemError(error.message)
}

if (!user) throw new CredentialsError('wrong credentials')

let match

try {
match = await bcrypt.compare(password, user.password)
} catch (error) {
throw new SystemError(error.message)
}

if (!match) throw new CredentialsError('wrong credentials')

return {
id: user._id.toString(),
role: user.role,
}
})()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import 'dotenv/config'
import * as chai from 'chai'
import chaiAsPromised from 'chai-as-promised'
import bcrypt from 'bcryptjs'

chai.use(chaiAsPromised)
const { expect } = chai
import db, { User } from 'dat'
import { errors } from 'com'

const { CredentialsError } = errors

import authenticateUser from './authenticateUser.js'

describe('authenticateUser', () => {
before(() => db.connect(process.env.MONGO_URL_TEST))

beforeEach(() => User.deleteMany())

it('succeeds on existing user', async () => {
await User.create({
name: 'Alba Cete',
email: '[email protected]',
password: bcrypt.hashSync('123123123', 10),
})

const user = await authenticateUser('[email protected]', '123123123')
expect(user).to.exist
expect(user.id).to.be.a.string
expect(user.role).to.equal('caregiver')
expect(user.id).to.have.lengthOf(24)
})

it('fails on non-existing user', () =>
expect(
(async () => {
await authenticateUser('[email protected]', '123123123')
})()
).to.be.rejectedWith(CredentialsError, /^wrong credentials$/))

after(() => db.disconnect())
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import 'dotenv/config'
import db from 'dat'

import authenticateUser from './authenticateUser.js'

await db.connect(process.env.MONGO_URL_TEST)

try {
const result = await authenticateUser('[email protected]', '123123123')
console.log(result)
} catch (error) {
console.error(error)
} finally {
await db.disconnect()
}
8 changes: 5 additions & 3 deletions staff/rafael-infante/lovingHands/api/logic/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import registerUser from "./registerUser.js";
import authenticateUser from './authenticateUser.js'
import registerUser from './registerUser.js'

const logic = {
registerUser
registerUser,
authenticateUser,
}

export default logic
export default logic
26 changes: 14 additions & 12 deletions staff/rafael-infante/lovingHands/api/logic/registerUser.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
import bcrypt from 'bcryptjs'

import {User} from "../../dat/index.js"
import { User } from '../../dat/index.js'
import { validate, errors } from 'com'

const {DuplicityError, SystemError} = errors
const { DuplicityError, SystemError } = errors

export default (name, email, username, password, passwordRepeat) => {
export default (name, email, password, passwordRepeat) => {
validate.name(name)
validate.email(email)
validate.username(username)
validate.password(password)
validate.passwordsMatch(password, passwordRepeat)

return bcrypt.hash(password, 10)
.catch(error => {throw new SystemError(error.message)})
.then(hash =>
User.create({name, email, username, password: hash})
.then(_ => {})
.catch(error => {
return bcrypt
.hash(password, 10)
.catch((error) => {
throw new SystemError(error.message)
})
.then((hash) =>
User.create({ name, email, password: hash })
.then((_) => {})
.catch((error) => {
if (error.code === 11000) throw new DuplicityError('user already exists')

throw new SystemError(error.message)
})
)
}
}
64 changes: 64 additions & 0 deletions staff/rafael-infante/lovingHands/api/logic/registerUser.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import 'dotenv/config'
import * as chai from 'chai'
import chaiAsPromised from 'chai-as-promised'
import bcrypt from 'bcryptjs'

chai.use(chaiAsPromised)
const { expect } = chai

import db, { User } from 'dat'
import { errors } from 'com'

const { DuplicityError, ValidationError } = errors

import registerUser from './registerUser.js'

describe('registerUser', () => {
before(() => db.connect(process.env.MONGO_URL_TEST))

beforeEach(() => User.deleteMany())
afterEach(() => User.deleteMany())

it('succeds on new user', async () => {
await registerUser('Rive Lino', '[email protected]', '123123123', '123123123')

const user = await User.findOne({ email: '[email protected]' })

expect(user).to.exist //.not.to.be.null
expect(user.name).to.equal('Rive Lino')
expect(user.email).to.equal('[email protected]')
expect(bcrypt.compareSync('123123123', user.password)).to.be.true
})

it('fails on existing user', () =>
expect(
(async () => {
await User.create({ name: 'Casi Miro', email: '[email protected]', password: bcrypt.hashSync('123123123', 10) })

await registerUser('Casi Miro', '[email protected]', '123123123', '123123123')
})()
).to.be.rejectedWith(DuplicityError, 'user already exists'))

it('fails on existing user', () =>
expect(
(async () => {
await registerUser(undefined, '[email protected]', '123123123', '123123123')
})()
).to.be.rejectedWith(ValidationError, 'Invalid name'))

it('fails on existing email', () =>
expect(
(async () => {
await registerUser('Seño Rito', undefined, '123123123', '123123123')
})()
).to.be.rejectedWith(ValidationError, 'Invalid email'))

it('fails when passwords do not match', () =>
expect(
(async () => {
await registerUser('Seño Rito', 'señ[email protected]', '123123124', '123123123')
})()
).to.be.rejectedWith(ValidationError, 'passwords do not match'))

after(() => db.disconnect())
})
35 changes: 22 additions & 13 deletions staff/rafael-infante/lovingHands/api/logic/registerUser.test.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
import 'dotenv/config'
import db from '../../dat/index.js'
import db from 'dat'

import registerUser from './registerUser.js'

db.connect(process.env.MONGO_URL_TEST)
.then(() => {
try {
return registerUser('Rive Lino', '[email protected]', 'rivelino', '123123123', '123123123')
.then(console.log)
.catch(console.error)
} catch (error) {
console.error()
}
})
.catch(console.error)
.finally(() => db.disconnect())
await db.connect(process.env.MONGO_URL_TEST)

try {
const result = await registerUser('Marga Rita', '[email protected]', '123123123', '123123123')
console.log(result)
} catch (error) {
console.error(error)
} finally {
await db.disconnect()
}

// db.connect(process.env.MONGO_URL_TEST)
// .then(() => {
// try {
// return registerUser('Rive Lino', '[email protected]', '123123123', '123123123').then(console.log).catch(console.error)
// } catch (error) {
// console.error()
// }
// })
// .catch(console.error)
// .finally(() => db.disconnect())
6 changes: 5 additions & 1 deletion staff/rafael-infante/lovingHands/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
"scripts": {
"start": "node .",
"inspect": "node --inspect-brk .",
"test": "echo \"Error: no test specified\" && exit 1"
"test": "mocha logic/*.spec.js",
"test-one": "mocha",
"test-inspect": "mocha --inspect-brk logic/*.spec.js",
"test-inspect-one": "mocha --inspect-brk",
"coverage": "c8 --experimental-monocart --reporter=html --reporter=text mocha logic/*.spec.js --timeout 20000"
},
"keywords": [],
"author": "",
Expand Down
35 changes: 35 additions & 0 deletions staff/rafael-infante/lovingHands/api/test/authenticate-user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { errors } from 'com'

const { SystemError } = errors

fetch('http://localhost:8080/users/auth', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: '[email protected]',
password: '123123123',
}),
})
.catch((error) => {
throw new SystemError(error.message)
})
.then((res) => {
if (res.ok)
return res
.json()
.catch((error) => {
throw new SystemError(error.message)
})
.then((token) => {
console.log(token)
})

return res
.json()
.catch((error) => {
throw new SystemError(error.message)
})
.then(({ error, message }) => {
throw new errors[error](message)
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
curl -H 'Content-Type: application/json' -d '{"email":"[email protected]", "password":"123123123"}' http://localhost:8080/users/auth -v
Loading

0 comments on commit b902c36

Please sign in to comment.