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
59 changes: 48 additions & 11 deletions api/auth/auth-middleware.js
Original file line number Diff line number Diff line change
@@ -1,49 +1,86 @@
const User = require('../users/users-model.js')
/*
If the user does not have a session saved in the server

status 401
{
"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!')
}

}

/*
If the username in req.body already exists in the database

status 422
{
"message": "Username taken"
}
*/
function checkUsernameFree() {

const checkUsernameFree = async (req, res, next) => {
try {
const rows = await User.findBy({ username: req.body.username })
if(!rows.length){
next()
} else {
res.status(422).json("Username taken")
}
} catch (error) {
res.status(500).json(`Server error: ${error.message}`)
}
}

/*
If the username in req.body does NOT exist in the database

status 401
{
"message": "Invalid credentials"
}
*/
function checkUsernameExists() {

const checkUsernameExists = async (req, res, next) => {
try {
const rows = await User.findBy({ username: req.body.username})
if(rows.length){
req.userData = rows[0]
next()
} else {
res.status(401).json("Invalid credentials")
}
} catch (error) {
res.status(500).json(`Server error: ${error.message}`)
}
}

/*
If password is missing from req.body, or if it's 3 chars or shorter

status 422
{
"message": "Password must be longer than 3 chars"
}
*/
function checkPasswordLength() {

const checkPasswordLength = async (req, res, next) => {
try {
const rows = await User.findBy({ username: req.body.password })
if(rows.length < 3 || !req.body.password){
res.status(422).json(`Password must be longer than 3 chars`)
} else {
next()
}
} catch (error) {
res.status(500).json(`Server error: ${error.message}`)
}
}

// Don't forget to add these to the `exports` object so they can be required in other modules

module.exports = {
restricted,
checkUsernameExists,
checkUsernameFree,
checkPasswordLength
}
55 changes: 47 additions & 8 deletions api/auth/auth-router.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,66 @@
// Require `checkUsernameFree`, `checkUsernameExists` and `checkPasswordLength`
// middleware functions from `auth-middleware.js`. You will need them here!
const express = require("express");
const router = express.Router();
const User = require("../users/users-model.js");
const session = require("express-session");
const bcrypt = require("bcryptjs");
const { restricted, checkUsernameExists } = require("./auth-middleware.js");

router.post("/register", async (req, res ) => {
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 (error) {
res.status(500).json(`Server error: ${error.message}`)
}
})

router.post("/login", checkUsernameExists, (req, res) => {
try {
const verified = bcrypt.compareSync(req.body.password, req.userData.username)
if(verified){
req.session.user = req.userData
req.json(`Welcome back ${req.userData.username}`)
} else {
res.status(401).json("Incorrect username or password")
}
} catch (error) {
res.status(500).json(`Server error: ${error.message}`)
}
})

router.get("/logout", (req, res) => {
if(req.session){
req.session.destroy(e => {
if(e){
res.json(`Can't log out: ${e.message}`)
} else {
res.json(`Logged out successfully.`)
}
})
} else {
res.json("Session doesn't exist")
}
})

module.exports = router


/**
1 [POST] /api/auth/register { "username": "sue", "password": "1234" }

response:
status 200
{
"user_id": 2,
"username": "sue"
}

response on username taken:
status 422
{
"message": "Username taken"
}

response on password three chars or less:
status 422
{
Expand All @@ -28,13 +71,11 @@

/**
2 [POST] /api/auth/login { "username": "sue", "password": "1234" }

response:
status 200
{
"message": "Welcome sue!"
}

response on invalid credentials:
status 401
{
Expand All @@ -45,13 +86,11 @@

/**
3 [GET] /api/auth/logout

response for logged-in users:
status 200
{
"message": "logged out"
}

response for not-logged-in users:
status 200
{
Expand All @@ -60,4 +99,4 @@
*/


// Don't forget to add the router to the `exports` object so it can be required in other modules
// Don't forget to add the router to the `exports` object so it can be required in other modules
9 changes: 6 additions & 3 deletions api/server.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
const express = require("express");
cconst express = require("express");
const helmet = require("helmet");
const cors = require("cors");

const userRouter = require("./users/users-router");
const authRouter = require("./auth/auth-router");

/**
Do what needs to be done to support sessions with the `express-session` package!
To respect users' privacy, do NOT send them a cookie unless they log in.
This is achieved by setting 'saveUninitialized' to false, and by not
changing the `req.session` object unless the user authenticates.

Users that do authenticate should have a session persisted on the server,
and a cookie set on the client. The name of the cookie should be "chocolatechip".

The session can be persisted in memory (would not be adecuate for production)
or you can use a session store like `connect-session-knex`.
*/
Expand All @@ -20,6 +21,8 @@ const server = express();
server.use(helmet());
server.use(express.json());
server.use(cors());
server.use("/api/users", userRouter)
server.use("/api/auth", authRouter )

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

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

return db("users").select("user_id", "username").orderBy("user_id")
}

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

return db("users").where(filter).orderBy("user_id")
}

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

return db("users").where({ user_id }).first()
}

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

async function add(user) {
const [id] = await db("users").insert(user, "user_id")
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
}
15 changes: 12 additions & 3 deletions api/users/users-router.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
// Require the `restricted` middleware from `auth-middleware.js`. You will need it here!
const express = require('express');
const { restricted } = require('../auth/auth-middleware.js');
const router = express.Router();
const User = require("./users-model.js");

router.get("/", restricted, (req, res) => {
User.find()
.then(users => {
res.status(200).json(users)
})
})


module.exports = router
/**
[GET] /api/users

This endpoint is RESTRICTED: only authenticated clients
should have access.

response:
status 200
[
Expand All @@ -16,7 +26,6 @@
},
// etc
]

response on non-authenticated:
status 401
{
Expand Down
Binary file modified data/auth.db3
Binary file not shown.
Loading