Skip to content
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
24 changes: 12 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,30 @@ Your assignment page on Canvas should contain instructions for submitting this p

Write the following user access functions inside `api/users/users-model.js`:

- [ ] `find`
- [ ] `findBy`
- [ ] `findById`
- [ ] `add`
- [x] `find`
- [x] `findBy`
- [x] `findById`
- [x] `add`

#### 2B - Middleware Functions

Write the following auth middlewares inside `api/auth/auth-middleware.js`:

- [ ] `restricted`
- [ ] `checkUsernameFree`
- [ ] `checkPasswordLength`
- [ ] `checkUsernameExists`
- [x] `restricted`
- [x] `checkUsernameFree`
- [x] `checkPasswordLength`
- [x] `checkUsernameExists`

#### 2C - Endpoints

Authentication will be tracked using sessions and cookies. See `api/server.js` for more instructions.

Write the following endpoints. The first one belongs inside `api/users/users-router.js` and the rest inside `api/auth/auth-router.js`:

- [ ] `[GET] /api/users`
- [ ] `[POST] /api/auth/register`
- [ ] `[POST] /api/auth/login`
- [ ] `[GET] /api/auth/logout`
- [x] `[GET] /api/users`
- [x] `[POST] /api/auth/register`
- [x] `[POST] /api/auth/login`
- [x] `[GET] /api/auth/logout`

#### Users Schema

Expand Down
56 changes: 50 additions & 6 deletions api/auth/auth-middleware.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
const User = require('../users/users-model')
const db = require('../../data/db-config')
/*
If the user does not have a session saved in the server

Expand All @@ -6,8 +8,12 @@
"message": "You shall not pass!"
}
*/
function restricted() {

const restricted = (req, res, next) => {
if(req.session && req.session.user) {
next()
} else {
res.status(401).json("You shall not pass!")
}
}

/*
Expand All @@ -18,8 +24,18 @@ function restricted() {
"message": "Username taken"
}
*/
function checkUsernameFree() {
const checkUsernameFree = async (req, res, next) => {
try {
const user = await User.findBy({user: req.body.username})

if(!user.length) {
next()
} else {
res.status(401).json("Username taken")
}
} catch(err) {
res.status(500).json(`Server error: ${err}`)
}
}

/*
Expand All @@ -30,8 +46,21 @@ function checkUsernameFree() {
"message": "Invalid credentials"
}
*/
function checkUsernameExists() {
const checkUsernameExists = async (req, res, next) => {
try {

const user = await User.findBy({username: req.body.username})

if (user.length) {
req.userData = user[0]
next()
} else {
res.status(401).json("Invalid credentials")
}

} catch(err) {
res.status(500).json(`Server error: ${err}`)
}
}

/*
Expand All @@ -42,8 +71,23 @@ function checkUsernameExists() {
"message": "Password must be longer than 3 chars"
}
*/
function checkPasswordLength() {

const checkPasswordLength = async (req, res, next) => {
try {
if (!req.body.password || req.body.password.length <= 3) {
res.status(401).json("Password must be longer than 3 chars")
} else {
next()
}
} catch(err) {
res.status(500).json(`Server error: ${err}`)
}
}


// Don't forget to add these to the `exports` object so they can be required in other modules
module.exports = {
restricted,
checkUsernameFree,
checkPasswordLength,
checkUsernameExists,
}
48 changes: 45 additions & 3 deletions api/auth/auth-router.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
// Require `checkUsernameFree`, `checkUsernameExists` and `checkPasswordLength`
// middleware functions from `auth-middleware.js`. You will need them here!

const router = require('express').Router()
const bcrypt = require('bcryptjs')
const User = require('../users/users-model')
const {
checkPasswordLength,
checkUsernameExists,
checkUsernameFree
} = require('./auth-middleware')

/**
1 [POST] /api/auth/register { "username": "sue", "password": "1234" }
Expand All @@ -24,7 +31,16 @@
"message": "Password must be longer than 3 chars"
}
*/
router.post('/register', checkUsernameFree, checkPasswordLength, async (req, res, next) => {
try {
const hash = bcrypt.hashSync(req.body.password, 10)
const newUser = await User.add({username: req.body.username, password: hash})
res.status(201).json(newUser)

} catch(err) {
res.status(500).json(`Server error: ${err}`)
}
})

/**
2 [POST] /api/auth/login { "username": "sue", "password": "1234" }
Expand All @@ -41,7 +57,20 @@
"message": "Invalid credentials"
}
*/

router.post('/login', checkUsernameExists, (req, res, next) => {
const { password } = req.body
if(bcrypt.compareSync(password, req.user.password)){
req.session.user = req.user
res.json({
message: `Welcome ${req.user.username}`
})
}else{
next({
status: 401,
message: 'Invalid credentials'
})
}
})

/**
3 [GET] /api/auth/logout
Expand All @@ -58,6 +87,19 @@
"message": "no session"
}
*/

router.post('/logout', (req, res, next) => {
if (req.session) {
req.session.destroy(err => {
if (err) {
res.json('cannot log out')
} else {
res.json('logged out')
}
})
} else {
res.json("no session exists")
}
})

// Don't forget to add the router to the `exports` object so it can be required in other modules
module.exports = router
31 changes: 29 additions & 2 deletions api/server.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
const express = require("express");
const helmet = require("helmet");
const cors = require("cors");
const usersRouter = require('./users/users-router')
const authRouter = require('./auth/auth-router')
// const session = require('express-session')
// const Store = require('connect-session-knex')(session)
// const knex = require('../data/db-config')

/**
Do what needs to be done to support sessions with the `express-session` package!
Expand All @@ -13,13 +18,35 @@ const cors = require("cors");

The session can be persisted in memory (would not be adecuate for production)
or you can use a session store like `connect-session-knex`.
*/

*/
const server = express();

// server.use(session({
// name: 'chocolatechip',
// secret: 'shh',
// saveUninitialized: false,
// resave: false,
// store: new Store({
// knex,
// createTable: true,
// clearInterval: 1000 * 60 * 10,
// tableName: 'sessions',
// sidfieldname: 'sid'
// }),
// cookie: {
// maxAge: 100 * 60 * 10,
// secure: false,
// httpOnly: true,
// // sameSite: 'none'
// }
// })
// )

server.use(helmet());
server.use(express.json());
server.use(cors());
server.use('/api/users', usersRouter)
server.use('/api/auth', authRouter)

server.get("/", (req, res) => {
res.json({ api: "up" });
Expand Down
25 changes: 20 additions & 5 deletions api/users/users-model.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,44 @@
const db = require('../../data/db-config')

/**
resolves to an ARRAY with all users, each user having { user_id, username }
*/
function find() {

return db('users')
.select('user_id', 'username')
}

/**
resolves to an ARRAY with all users that match the filter condition
*/
function findBy(filter) {

return db('users')
.where(filter)
// .orderBy('user_id')
// .first()
}

/**
resolves to the user { user_id, username } with the given user_id
*/
function findById(user_id) {

async function findById(user_id) {
return db('users')
.where({ user_id })
.first()
}

/**
resolves to the newly inserted user { user_id, username }
*/
function add(user) {

const [id] = db('users').insert(user)
return findById(id)
}

// Don't forget to add these to the `exports` object so they can be required in other modules
module.exports = {
find,
findBy,
findById,
add,
}
13 changes: 12 additions & 1 deletion api/users/users-router.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// Require the `restricted` middleware from `auth-middleware.js`. You will need it here!

const router = require('express').Router()
const { restricted } = require('../auth/auth-middleware')
const User = require('./users-model')

/**
[GET] /api/users
Expand All @@ -23,6 +25,15 @@
"message": "You shall not pass!"
}
*/
router.get('/', restricted, async (req, res, next) => {
try {
const users = await Users.find()
res.status(200).send(users);
} catch(err) {
res.status(401).json('You shall not pass!')
}
})


// Don't forget to add the router to the `exports` object so it can be required in other modules
module.exports = router
Binary file modified data/auth.db3
Binary file not shown.
Loading