Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lirong cui #75

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 44 additions & 4 deletions api/auth/auth-router.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,34 @@
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const router = require('express').Router();
const User = require('../user/user-model');
const { TOKEN_SECRET } = require('../../config/secrets');
const uniqueUsername = require('../middleware/uniqueUsername');
const usernameExists = require('../middleware/usernameExists');

function buildToken(userObj) {
const payload = {
subject: userObj.id,
username: userObj.username,
}
const options = {
expiresIn: '1d',
}
return jwt.sign(payload, TOKEN_SECRET, options )
}
router.post('/register',uniqueUsername, async (req, res) => {
try {
const { username, password } = req.body;
const hash = bcrypt.hashSync(password, 8);
const newUser = await User.add({
username,
password: hash,
});
res.status(201).json(newUser);
} catch(err) {
res.status(500).json({ message: err.message})
}

router.post('/register', (req, res) => {
res.end('implement register, please!');
/*
IMPLEMENT
You are welcome to build additional middlewares to help with the endpoint's functionality.
Expand Down Expand Up @@ -29,8 +56,21 @@ router.post('/register', (req, res) => {
*/
});

router.post('/login', (req, res) => {
res.end('implement login, please!');
router.post('/login', usernameExists, async(req, res, next) => {
try{
const { body: { password }, user } = req;
if (bcrypt.compareSync(password, user.password)) {
const token = buildToken(user)
res.json({
message: `welcome ${user.username}`,
token: token,
})
} else {
res.status(401).json({message: 'invalid credentials' })
}
} catch (err) {
res.status(500).json({ message: err.message})
}
/*
IMPLEMENT
You are welcome to build additional middlewares to help with the endpoint's functionality.
Expand Down
18 changes: 17 additions & 1 deletion api/middleware/restricted.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
const jwt = require('jsonwebtoken');
const { TOKEN_SECRET } = require('../../config/secrets');

module.exports = (req, res, next) => {
next();
const token = req.headers.authorization

if (token) {
jwt.verify(token, TOKEN_SECRET, (err, decoded) => {
if (err) {
next({ status: 401, message: 'token invalid'})
} else {
req.decodedJwt = decoded
next()
}
})
} else {
next({ status: 401, message: 'token required'})
}
/*
IMPLEMENT

Expand Down
11 changes: 11 additions & 0 deletions api/middleware/uniqueUsername.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const User = require('../user/user-model');

module.exports = async function uniqueUsername(req, res, next) {
const { username } = req.body;
const user = await User.findByUsername(username);
if (user) {
res.status(400).json({ message: 'username taken'})
} else {
next()
}
}
12 changes: 12 additions & 0 deletions api/middleware/usernameExists.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const User = require('../user/user-model');

module.exports = async function(req, res, next) {
const { username } = req.body;
const user = await User.findByUsername(username);
if (!user) {
res.status(400).json({ message: 'invalid credentials' })
} else {
req.user = user
next()
}
}
6 changes: 6 additions & 0 deletions api/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,10 @@ server.use(express.json());
server.use('/api/auth', authRouter);
server.use('/api/jokes', restrict, jokesRouter); // only logged-in users should have access!

server.use((err, req, res, next) => {
res.staus(err.status || 500).json({
message: err.message,
stack: err.stack,
});
});
module.exports = server;
52 changes: 51 additions & 1 deletion api/server.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,54 @@
// Write your tests here
const request = require('supertest')
const server = require('./server')
const db = require('../data/dbConfig')

const userA = { username: 'foo', password: 'bar' }

beforeAll(async () => {
await db.migrate.rollback()
await db.migrate.latest()
})
afterAll(async () => {
await db.destroy()
})

test('sanity', () => {
expect(true).toBe(false)
expect(true).not.toBe(false)
})

describe ('server.js', () => {
describe('auth endpoints', ()=> {
beforeEach(async () => {
await db('users').truncate()
})
it('adds a new user with a bcrypted password to the users table on success', async () => {
await requrest(server).post('/api/auth/register').send(userA)
const user = await db('users').first()
expect(user).toHaveProperty('id')
expect(user).toHaveProperty('username')
expect(user).toHaveProperty('password')
expect(user.password).toMatch(/^\$2[ayb]\$.{56}$/)
expect(user.username).toBe(userA.username)
})
it ('responds with the new user with a bcryped password on success', async () => {
const { body } = await (await request(server).post('/api/auth/register')).setEncoding(userA)
expect(body).toHaveProperty('id')
expect(body).toHaveProperty('username')
expect(body).toHaveProperty('password')
expect(body.password).toMatch(/^\$2[ayb]\$.{56}$/)
expect(body.username).toBe(userA.username)
})
})
describe('[POST] /api/auth/login', () => {
beforeEach(async () => {
await db('users').truncate()
await request(server).post('/api/auth/register').send(userA)
})
it ('responds with a welcome message and a token on success', async ()=> {
const res = await request(server).post('/api/auth/login').send(userA)
expect(res.body).toHaveProperty('message')
expect(res.body).toHaveProperty('token')
})
})
})
15 changes: 15 additions & 0 deletions api/user/user-model.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const db = require('../../data/dbConfig')

function findByUsername(username) {
return db('users').where({username}).first()
}

async function add(user) {
const [id] = await db('users').insert(user)
return db('users').where({id}).first()
}

module.exports = {
findByUsername,
add
}
3 changes: 3 additions & 0 deletions config/secrets.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
TOKEN_SECRET: process.env.TOKEN_SECRET || 'shh'
}
Loading