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

Corrected all bugs and completed README. #1

Merged
merged 3 commits into from
Dec 7, 2022
Merged
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
145 changes: 145 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# 401 JS
db
.env
temp
build
memory

# Created by https://www.gitignore.io/api/vim,osx,node,linux,windows
### Linux ###
*~

# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*

# KDE directory preferences
.directory

# Linux trash folder which might appear on any partition or disk
.Trash-*

# .nfs files are created when an open file is removed but is still being accessed
.nfs*

### Node ###
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Typescript v1 declaration files
typings/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file


### OSX ###
*.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon

# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

### Vim ###
# swap
[._]*.s[a-v][a-z]
[._]*.sw[a-p]
[._]s[a-v][a-z]
[._]sw[a-p]
# session
Session.vim
# temporary
.netrwhist
# auto-generated tag files
tags

### Windows ###
# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
ehthumbs_vista.db

# Folder config file
Desktop.ini

# Recycle Bin used on file shares
$RECYCLE.BIN/

# Windows Installer files
*.cab
*.msi
*.msm
*.msp

# Windows shortcuts
*.lnk

# End of https://www.gitignore.io/api/vim,osx,node,linux,windows
51 changes: 50 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,50 @@
# bearer-auth
# LAB - Class 07

## Project: Bearer Authorization

### Author: Kenny W. Lino

### Problem Domain

In this lab, we were given starter code that contained numerous bugs that needed fixing in order to get the application to work. In order to make sure everything worked as expected, we had a number of tests given to us to test against as we corrected the errors.

### Links and Resources

- [ci/cd](https://github.com/kennywlino/bearer-auth/actions/new)
- [back-end server (production)](https://bearer-auth-y7xw.onrender.com)
- [Main PR from dev](https://github.com/kennywlino/bearer-auth/pull/1)

### Setup

#### `.env` requirements (where applicable)

i.e.

- `PORT` - Port Number
- `DATABASE_URL` - location of Postgres DB (i.e. postgres://localhost:5432/api-app?sslmode=disable)
- `SECRET` - secret used with bearer auth

#### How to initialize/run your application

- nodemon

#### How to use your library (where applicable)

#### Features / Routes

- POST: `/signin` - route to signin with given user and password
- POST: `/signup` - route to signup with given user and password
- GET: `/users` - route to get all users with given bearer auth token
- GET: `/secret` - route to access a secret

#### Tests

- How do you run tests?
- npm test

- Any tests of note?


#### UML

![Class-06 UML](./assets/CLASS-07_Authentication.jpeg)
68 changes: 68 additions & 0 deletions __tests__/src/auth/middleware/basic-auth-middleware.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
'use strict';

process.env.SECRET = "TEST_SECRET";

const base64 = require('base-64');
const middleware = require('../../../../src/auth/middleware/basic.js');
const { db, users } = require('../../../../src/auth/models/index.js');

let userInfo = {
admin: { username: 'admin-basic', password: 'password' },
};

// Pre-load our database with fake users
beforeAll(async () => {
await db.sync();
await users.create(userInfo.admin);
});
afterAll(async () => {
await db.drop();
});

describe('Auth Middleware', () => {

// admin:password: YWRtaW46cGFzc3dvcmQ=
// admin:foo: YWRtaW46Zm9v

// Mock the express req/res/next that we need for each middleware call
const req = {};
const res = {
status: jest.fn(() => res),
send: jest.fn(() => res)
}
const next = jest.fn();

describe('user authentication', () => {

it('fails a login for a user (admin) with the incorrect basic credentials', () => {
const basicAuthString = base64.encode('username:password');

// Change the request to match this test case
req.headers = {
authorization: `Basic ${basicAuthString}`,
};

return middleware(req, res, next)
.then(() => {
expect(next).not.toHaveBeenCalled();
expect(res.status).toHaveBeenCalledWith(403);
});

});

it('logs in an admin user with the right credentials', () => {
let basicAuthString = base64.encode(`${userInfo.admin.username}:${userInfo.admin.password}`);

// Change the request to match this test case
req.headers = {
authorization: `Basic ${basicAuthString}`,
};

return middleware(req, res, next)
.then(() => {
expect(next).toHaveBeenCalledWith();
});

});
});
});
65 changes: 65 additions & 0 deletions __tests__/src/auth/middleware/bearer-auth-middleware.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
'use strict';

process.env.SECRET = "TEST_SECRET";

const bearer = require('../../../../src/auth/middleware/bearer.js');
const { db, users } = require('../../../../src/auth/models/index.js');
const jwt = require('jsonwebtoken');

let userInfo = {
admin: { username: 'admin', password: 'password' },
};

// Pre-load our database with fake users
beforeAll(async () => {
await db.sync();
await users.create(userInfo.admin);
});
afterAll(async () => {
await db.drop();
});

describe('Auth Middleware', () => {

// Mock the express req/res/next that we need for each middleware call
const req = {};
const res = {
status: jest.fn(() => res),
send: jest.fn(() => res),
json: jest.fn(() => res),
}
const next = jest.fn();

describe('user authentication', () => {

it('fails a login for a user (admin) with an incorrect token', () => {

req.headers = {
authorization: 'Bearer thisisabadtoken',
};

return bearer(req, res, next)
.then(() => {
expect(next).not.toHaveBeenCalled();
expect(res.status).toHaveBeenCalledWith(403);
});

});

it('logs in a user with a proper token', () => {

const user = { username: 'admin' };
const token = jwt.sign(user, process.env.SECRET);

req.headers = {
authorization: `Bearer ${token}`,
};

return bearer(req, res, next)
.then(() => {
expect(next).toHaveBeenCalledWith();
});

});
});
});
23 changes: 23 additions & 0 deletions __tests__/src/auth/router/handlers/getSecret.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
'use strict';

process.env.SECRET = "TEST_SECRET";

const { handleSecret } = require('../../../../../src/auth/router/handlers.js');

describe('testing the users route handler', () => {

const res = {
send: jest.fn(() => res),
status: jest.fn(() => res),
json: jest.fn(() => res),
}
const next = jest.fn();

test('Should respond with a secret response', () => {
let req = {};

handleSecret(req, res, next);
expect(res.status).toHaveBeenCalledWith(200);
expect(res.send).toHaveBeenCalledWith(expect.anything());
});
});
34 changes: 34 additions & 0 deletions __tests__/src/auth/router/handlers/getUsers.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
'use strict';

process.env.SECRET = "TEST_SECRET";

const { db, } = require('../../../../../src/auth/models');
const { handleGetUsers } = require('../../../../../src/auth/router/handlers.js');

beforeAll(async () => {
await db.sync();
});
afterAll(async () => {
await db.drop();
});


describe('Router handler for getUsers', () => {

const res = {
send: jest.fn(() => res),
status: jest.fn(() => res),
json: jest.fn(() => res),
}
const next = jest.fn();

test('Should fetch users and send user objects in the response', async () => {

let req = {};

await handleGetUsers(req, res, next);
expect(res.status).toHaveBeenCalledWith(200);
expect(res.json).toHaveBeenCalledWith(expect.anything());
});

});
Loading