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

Fernando.quizhpi #1

Open
wants to merge 6 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
30 changes: 20 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,34 +25,44 @@ Commit your code regularly and meaningfully. This helps both you (in case you ev
Be prepared to demonstrate your understanding of this week's concepts by answering questions on the following topics. You might prepare by writing down your own answers before hand.

1. Differences between using _sessions_ or _JSON Web Tokens_ for authentication.
Sessions use cookies to create instances('sessions') which stores user information
that remains peristed until deleted. JWT store user information on generated token
that is a string of data holding user information.

2. What does `bcrypt` do to help us store passwords in a secure manner.
bcrypt secures passwords by hashing them, essentially scrambling the password
and breaking it down into layers of strings, this can be increased depending on the
amount of time the hash is set to happen. For dev. puposes, its around 8 and for
any production hashes, it is increased, varying on servers, and how much it can handle as it slows down the process a lot.

3. How are unit tests different from integration and end-to-end testing.
- unit testing focuses on individual parts and tests those parts alone,
- integration and end to end focuses on 2 or more working together

4. How _Test Driven Development_ changes the way we write applications and tests.
rigorous testing of application as it develops

You are expected to be able to answer questions in these areas. Your responses contribute to your Sprint Challenge grade.

## Instructions

### Task 1: Project Set Up

- [ ] Create a forked copy of this project
- [ ] Add your team lead as collaborator on Github
- [ ] Clone your OWN version of the repository (Not Lambda's by mistake!)
- [ ] Create a new branch: git checkout -b `<firstName-lastName>`.
- [ ] Implement the project on your newly created `<firstName-lastName>` branch, committing changes regularly
- [ ] Push commits: git push origin `<firstName-lastName>`
- [+] Create a forked copy of this project
- [+] Add your team lead as collaborator on Github
- [+] Clone your OWN version of the repository (Not Lambda's by mistake!)
- [+] Create a new branch: git checkout -b `<firstName-lastName>`.
- [+] Implement the project on your newly created `<firstName-lastName>` branch, committing changes regularly
- [+] Push commits: git push origin `<firstName-lastName>`

### Task 2: Project Requirements

Your finished project must include all of the following requirements:

- [ ] An authentication workflow with functionality for account creation and login implemented inside `/auth/auth-router.js`. A `user` has `username` and `password`. Both properties are required.
- [ ] Middleware used to restrict access to resources for non authenticated requests. Use the file: `./auth/authenticate-middleware.js` as a starting point.
- [ ] Configuration for running tests using `Jest`.
- [ ] A **minimum o 2 tests** per API endpoint.
- [+] An authentication workflow with functionality for account creation and login implemented inside `/auth/auth-router.js`. A `user` has `username` and `password`. Both properties are required.
- [+] Middleware used to restrict access to resources for non authenticated requests. Use the file: `./auth/authenticate-middleware.js` as a starting point.
- [+] Configuration for running tests using `Jest`.
- [+] A **minimum o 2 tests** per API endpoint.

**Note**: the database already has the users table, but if you run into issues, the migrations are available.

Expand Down
7 changes: 7 additions & 0 deletions api/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const helmet = require('helmet');
const authenticate = require('../auth/authenticate-middleware.js');
const authRouter = require('../auth/auth-router.js');
const jokesRouter = require('../jokes/jokes-router.js');
let userRouter = require('../users/users-router');

const server = express();

Expand All @@ -14,5 +15,11 @@ server.use(express.json());

server.use('/api/auth', authRouter);
server.use('/api/jokes', authenticate, jokesRouter);
server.use('/api/user', authenticate, userRouter);
// server.use('/api/user', userRouter);
server.get('/', (req, res) => {
res.status(200).json({ api: "up" })
})


module.exports = server;
15 changes: 15 additions & 0 deletions api/server.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
let supertest = require('supertest');

let server = require('./server');

describe("read server.js", () => {
describe("GET /", () => {
it("should return 200 OK status", () => {
return supertest(server)
.get("/")
.then(res => {
expect(res.status).toBe(200);
})
})
})
})
48 changes: 48 additions & 0 deletions auth/auth-router.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,59 @@
const router = require('express').Router();

let Users = require('../users/users-model');

let encrypt = require('bcryptjs');
// let jwt = require('jsonwebtoken');
let isValid = require('../utils/validate');
const { createToken } = require('../utils/methods');

router.post('/register', (req, res) => {
// implement registration
let creds = req.body;

if(isValid.isValid (creds)) {
let rounds = process.env.BCRYPT_ROUNDS || 8; // defaults to 8 on dev env

let hash = encrypt.hashSync(creds.password, rounds) //takes pw from body and hashes it 8 times(dev)

creds.password = hash; // sets original pw from body to newly hashed pw

Users.create(creds)
.then(user => {
res.status(201).json({ data: user })
})
.catch(err => {
res.status(500).json({ error: "Could not create user"})
})
} else {
res.status(400).json({ message: "Provide a username and password" });
}

});

router.post('/login', (req, res) => {
// implement login

let { username, password } = req.body; // extracting from body

if(isValid.isValid(req.body)) {
Users.findBy({ username })
.then(([ user ]) => {
if(user && encrypt.compareSync(password, user.password)) {
let token = createToken(user); // creates a token with payload
res.status(200).json({ token, message: "Login success" })
} else {
res.status(401).json({ error: "Either username or password do not match in our records" });
}
})
.catch(err => {
res.status(500).json("Could not process request")
})
} else {
res.status(400).json({ message: "Please provide a valid username and password"})
}


});

module.exports = router;
131 changes: 131 additions & 0 deletions auth/auth-router.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
let server = require('../api/server');

let supertest = require('supertest');

let authRouter = require('./auth-router');
let db = require('../database/dbConfig');


describe("POST /login flow", () => {
it('should return status 200 OK', async () => {
let user = {
username: "legacy",
password: "mypw"
}
return await supertest(server)
.post('/api/auth/register')
.send(user)
.then(res => {
// console.log(res.body, 'asdfasdf')
// console.log(res.status)
expect(res.status).toBe(201);
// expect(res.body.data.username).toBe(user.username)
})
})

it("Should succesfully give 200 status, succesful message", async() => {
let user = {
username: "legacy",
password: "mypw"
}

return await supertest(server)
.post('/api/auth/login')
.send(user)
.then(res => {
console.log(res.status, "from login")
console.log(res.body, 'from login flow')
expect(res.status).toBe(200)
expect(res.body.message).toEqual("Login success" )

})
})
})

describe("auth-router.js", () => {
beforeEach(async () => {
await db("users").truncate();
})

describe("POST /register", () => {
it('should return status 201 OK', async () => {
let user = {
username: "legacy",
password: "mypw"
}
return await supertest(server)
.post('/api/auth/register')
.send(user)
.then(res => {
console.log(res.body)
expect(res.status).toBe(201);
expect(res.body.data.username).toBe(user.username)
})
})

it('should give 400 error for no username or password', async () => {
let user = {
username: "Bass",
password: null
}

return await supertest(server)
.post('/api/auth/register')
.send(user)
.then(res => {
console.log(res.status)
console.log(res.body)
expect(res.status).toBe(400);
expect(res.body).toEqual({ message: 'Provide a username and password' })
})
})
})

describe("POST /login", () => {
it("should return status 401", async () => {
let user = {
username: "legacy",
password: "mypw"
}
return await supertest(server)
.post('/api/auth/login')
.send(user)
.then(res => {
console.log(res.status, 'fail login')
expect(res.status).toBe(401) // no record on server
})
})
})

// describe("POST /login flow", () => {
// it('should return status 200 OK', async () => {
// let user = {
// username: "legacy",
// password: "mypw"
// }
// return await supertest(server)
// .post('/api/auth/register')
// .send(user)
// .then(res => {
// // console.log(res.body, 'asdfasdf')
// // console.log(res.status)
// expect(res.status).toBe(201);
// // expect(res.body.data.username).toBe(user.username)
// })
// })

// it("Should succesfully give 200 status, succesful message", async() => {
// let user = {
// username: "legacy",
// password: "mypw"
// }

// return await supertest(server)
// .post('/api/auth/login')
// .send(user)
// .then(res => {
// console.log(res.status, "from login")
// })
// })
// })
})
22 changes: 21 additions & 1 deletion auth/authenticate-middleware.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,28 @@
let jwt = require('jsonwebtoken');
let constants = require('../utils/constants');
const { jwtSecret } = require('../utils/constants');

/*
complete the middleware code to check if the user is logged in
before granting access to the next middleware/route handler
*/

module.exports = (req, res, next) => {
res.status(401).json({ you: 'shall not pass!' });
let token = req.headers.authorization; // grabs token from request headers property
let secret = constants.jwtSecret;

if(token) {
jwt.verify(token, secret, (err, decodedToken) => {
if(err) {
res.status(401).json({ message: "Invalid token" });
} else {
req.decodedToken = decodedToken; // creates a decoded token inside req
next();
}
})
} else {
res.status(401).json({ message: "valid credentials required" });
}

// res.status(401).json({ you: 'shall not pass!' });
};
Binary file modified database/auth.db3
Binary file not shown.
13 changes: 11 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"description": "Authentication Sprint Challenge",
"main": "index.js",
"scripts": {
"server": "nodemon index.js"
"server": "nodemon index.js",
"test": "cross-env DB_ENV=testing jest --watch --runInBand"
},
"repository": {
"type": "git",
Expand All @@ -19,13 +20,21 @@
"homepage": "https://github.com/LambdaSchool/Sprint-Challenge-Authentication#readme",
"dependencies": {
"axios": "^0.19.2",
"bcryptjs": "^2.4.3",
"cors": "^2.8.5",
"cross-env": "^7.0.2",
"express": "^4.17.1",
"helmet": "^3.22.0",
"jsonwebtoken": "^8.5.1",
"knex": "^0.21.0",
"sqlite3": "^4.1.1"
},
"devDependencies": {
"nodemon": "^2.0.3"
"jest": "^26.0.1",
"nodemon": "^2.0.3",
"supertest": "^4.0.2"
},
"jest": {
"testEnvironment": "node"
}
}
28 changes: 28 additions & 0 deletions users/users-model.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
let db = require('../database/dbConfig');

async function create(user) {
try {
const [id] = await db("users").insert(user, "id"); // returns id from new user

return findById(id);// uses findById to return the user
} catch (error) {
throw error; // gives back error if error is found
}
}

function findById(id) {
return db("users").where({ id }).first().select("id", "username"); // made it to return only id and username
}

function findBy(username) {
return db("users as u")
.select("u.id", "u.username", "u.password")
.where(username)
.orderBy("u.id");
}

module.exports = {
create,
findById,
findBy,
}
7 changes: 7 additions & 0 deletions users/users-router.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
let router = require('express').Router();

router.get('/', (req, res) => {
res.status(200).json({ message: "Hello user" })
})

module.exports = router;
3 changes: 3 additions & 0 deletions utils/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
jwtSecret: process.env.JWT_SECRET || "real safe, real safe",
}
Loading