Skip to content

Staging #45

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

Open
wants to merge 40 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
bc5a0e6
Project scaffolded. Server up.
dkulp23 Mar 6, 2017
184b287
Followed online tutorial on workaround for .env file. Typed out error…
dkulp23 Mar 6, 2017
1abedef
Created user model.
dkulp23 Mar 6, 2017
87ef09b
Created middleware to check for authorization header in request and p…
dkulp23 Mar 6, 2017
fb7da42
Wrote basic authorization routes and test for POST.
dkulp23 Mar 7, 2017
dcaf0a3
POST and GET routes passing tests with valid body.
dkulp23 Mar 7, 2017
1eb815d
All require tests written and passing. Some extra.
dkulp23 Mar 7, 2017
80d097f
readme update.
dkulp23 Mar 7, 2017
d0e8098
Removed a console log.
dkulp23 Mar 7, 2017
d3544d1
Created necessary files for gallery feature.
dkulp23 Mar 7, 2017
da7e0df
Created bearer auth middleware module.
dkulp23 Mar 7, 2017
f04637e
Created mongoose schema psuedo constructor for new gallery object.
dkulp23 Mar 7, 2017
8e6bcde
Created the POST and GET routes for the gallery endpoint.
dkulp23 Mar 7, 2017
74571f9
POST and GET routes passing tests with valid requests.
dkulp23 Mar 7, 2017
234c111
PUT route defined and test passing.
dkulp23 Mar 8, 2017
15ed51a
DELETE route passing test with valid id request.
dkulp23 Mar 8, 2017
f0f12bd
POST routes tested for all errors and passing.
dkulp23 Mar 8, 2017
2ee0049
GET routes passing all errors testing.
dkulp23 Mar 8, 2017
8ecd695
22 tests passing...and counting
dkulp23 Mar 8, 2017
d3fcfcd
Woohoo, all tests passing.
dkulp23 Mar 8, 2017
df262e8
DELETE routes passing all tests.
dkulp23 Mar 8, 2017
bd9e49f
User authorization layer added to PUT and DELETE routes.
dkulp23 Mar 8, 2017
d1a10c0
Updated .env variables.
dkulp23 Mar 8, 2017
e59cc99
Created mongoose schema for the pic resource data model.
dkulp23 Mar 8, 2017
3fbbbef
Installed new dependencies and worked through pic POST route.
dkulp23 Mar 8, 2017
58b43c4
Created server toggle helper module for testing.
dkulp23 Mar 8, 2017
9d3b06a
Wrote setup and first test for POST route.
dkulp23 Mar 8, 2017
98f8a01
Updtated server file to include pic router and export server as module.
dkulp23 Mar 8, 2017
689e6ef
Woohoo POST route passing test with valid request and posting to S3.
dkulp23 Mar 9, 2017
542a764
Starting to write test for DELETE route.
dkulp23 Mar 9, 2017
159ead2
Cleaned up DELETE route test. Not going to get to it tonight.
dkulp23 Mar 9, 2017
2d6eaa3
Took the data directory out of my gitignore.
dkulp23 Mar 9, 2017
036732e
Added travis.yml file.
dkulp23 Mar 9, 2017
324928f
Removed lint test from travis.yml
dkulp23 Mar 9, 2017
18ad4b9
added coveralls yml file.
dkulp23 Mar 9, 2017
d72ee21
Added coveralls yml file.
dkulp23 Mar 9, 2017
5ccdb2c
Added morgan format variable.
dkulp23 Mar 9, 2017
79109c0
Adding aws mocks functionality.
dkulp23 Mar 10, 2017
1292103
Debugged error in test file. Passing all tests and gulp lint.
dkulp23 Mar 10, 2017
cbebbd0
Change before commit to staging.
dkulp23 Mar 10, 2017
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
2 changes: 2 additions & 0 deletions .coveralls.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
service_name: travis-ci
repo_token: Us3RCO6VIKHWZVKBsUOymzK7JPJl020Hb
21 changes: 21 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"rules": {
"no-console": "off",
"indent": [ "error", 2 ],
"quotes": [ "error", "single" ],
"semi": ["error", "always"],
"linebreak-style": [ "error", "unix" ]
},
"env": {
"es6": true,
"node": true,
"mocha": true,
"jasmine": true
},
"ecmaFeatures": {
"modules": true,
"experimentalObjectRestSpread": true,
"impliedStrict": true
},
"extends": "eslint:recommended"
}
93 changes: 93 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@

# Created by https://www.gitignore.io/api/node,macos

### macOS ###
*.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

### 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
.env


# End of https://www.gitignore.io/api/node,macos
5 changes: 5 additions & 0 deletions .sample_env
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
MONGODB_URI=' '
APP_SECRET=' '
AWS_BUCKET=' '
AWS_ACCESS_KEY_ID=' '
AWS_SECRET_ACCESS_KEY=' '
18 changes: 18 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
language: node_js
node_js:
- 'node'
services:
- mongodb
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- gcc-4.8
- g++-4.8
env:
- CXX=g++-4.8
sudo: required
before_script: npm i
script:
- npm run test
78 changes: 23 additions & 55 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,59 +1,27 @@
![cf](https://i.imgur.com/7v5ASc8.png) Lab 16 - Basic Auth
======
After cloning down the repository, in the root directory run:

## To Submit this Assignment
* fork this repository
* write all of your code in a directory named `lab-` + `<your name>` **e.g.** `lab-brian`
* push to your repository
* submit a pull request to this repository
* submit a link to your PR in canvas
* write a question and observation on canvas
```sh
$ node setup
```
Then, copy the values submitted with this pull request and paste them in the newly created `.env` file copy inside of the quotes:
```sh
MONGODB_URI='<secret mongodb env var goes here>'
APP_SECRET='<token goes here>'
```
Now you'll have the necessary environment variables needed for authentication.

## Include
* `package.json`
* `.eslintrc`
* `gulpfile.js`
* `.gitignore`
* `.env`
* `README.md`

## Description
* Create the following directories to organize your code:
* **lib**
* **model**
* **route**
* **test**
* Create an HTTP server using `express`
* Using `mongoose`, create a **User** model with the following properties and options:
* `username` - *required and unique*
* `email` - *required and unique*
* `password` - *required - this must be hashed and can not stored as plain text*
* `findHash` - *unique*
* Use the **npm** `debug` module to log function calls that are used within your application
* Use the **express** `Router` to create a custom router for allowing users to **sign up** and **sign in**
* Use the **npm** `dotenv` module to house the following environment variables:
* `PORT`
* `MONGODB_URI`
* `APP_SECRET` *(used for signing and verify tokens)*

## Server Endpoints
### `/api/signup`
* `POST` request
* the client should pass the username and password in the body of the request
* the server should respond with a token (generated using `jwt` and `findHash`
* the server should respond with **400 Bad Request** to a failed request

### `/api/signin`
* `GET` request
* the client should pass the username and password to the server using a `Basic:` authorization header
* the server should respond with a token for authenticated users
* the server should respond with **401 Unauthorized** for non-authenticated users

## Tests
* Create a test that will ensure that your API returns a status code of **404** for any routes that have not been registered
* `/api/signup`
* `POST` - test **400**, if no request body has been provided or the body is invalid
* `POST` - test **200**, if the request body has been provided and is valid
* `/api/signin`
* `GET` - test **401**, if the user could not be authenticated
* `GET` - test **200**, responds with token for a request with a valid basic authorization header
After that's done, install the dependency modules using the command line:
```
$ npm install
```
Once they're all loaded up, to run tests use:
```
$ npm test
```
Or to run the app use:
```
$ npm start
```
Current existing routes allow user to sign up and sign in using an unique username, a password of their choice (which is encrypted using bcrypt before storage) and an email.
23 changes: 23 additions & 0 deletions gulpfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
'use strict';

const gulp = require('gulp');
const eslint = require('gulp-eslint');
const mocha = require('gulp-mocha');

gulp.task('lint', function() {
return gulp.src(['**/*.js', '!node_modules'])
.pipe(eslint())
.pipe(eslint.format())
.pipe(eslint.failAfterError());
});

gulp.task('test', function() {
gulp.src('./test/*-test.js', { read: false })
.pipe(mocha({ reporter: 'spec'}));
});

gulp.task('dev', function() {
gulp.watch(['**/*.js', '!node_modules'], ['lint', 'test']);
});

gulp.task('default', ['lint', 'test']);
36 changes: 36 additions & 0 deletions lib/basic-auth-middleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
'use strict';

const debug = require('debug')('cfgram:basic-auth-middleware');
const createError = require('http-errors');

module.exports = function(req, res, next) {
debug('basic auth');

let authHeader = req.headers.authorization;
if (!authHeader) {
return next(createError(401, 'auth header required'));
}

let base64str = authHeader.split('Basic ')[1];
if (!base64str) {
return next(createError(401, 'username and password required'));
}

let utf8str = new Buffer(base64str, 'base64').toString();
let authArr = utf8str.split(':');

req.auth = {
username: authArr[0],
password: authArr[1]
};

if (!req.auth.username) {
return next(createError(401, 'username required'));
}

if (!req.auth.password) {
return next(createError(401, 'password required'));
}

next();
};
32 changes: 32 additions & 0 deletions lib/bearer-auth-middleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'use strict';

const jwt = require('jsonwebtoken');
const createError = require('http-errors');
const debug = require('debug')('cfgram:bearer-auth-middleware');

const User = require('../model/user.js');

module.exports = function(req, res, next) {
debug('bearer auth');

var authHeader = req.headers.authorization;
if (!authHeader) {
return next(createError(401, 'authorization header required'));
}

var token = authHeader.split('Bearer ')[1];
if (!token) {
return next(createError(401, 'token required'));
}

jwt.verify(token, process.env.APP_SECRET, (err, decoded) => {
User.findOne({ findHash: decoded.token })
.then( user => {
req.user = user;
next();
})
.catch(err => {
next(createError(401, err.message));
});
});
};
28 changes: 28 additions & 0 deletions lib/error-middleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
'use strict';

const createError = require('http-errors');
const debug = require('debug')('cfgram:error-middleware');

module.exports = function(err, req, res, next) {
debug('error middleware');

console.error('msg:', err.message);
console.error('name:', err.name);

if (err.status) {
res.status(err.status).send(err.name);
next();
return;
}

if (err.name === 'ValidationError') {
err = createError(400, err.message);
res.status(err.status).send(err.name);
next();
return;
}

err = createError(500, err.message);
res.status(err.status).send(err.name);
next();
};
13 changes: 13 additions & 0 deletions model/gallery.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
'use strict';

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const gallerySchema = Schema({
name: { type: String, required: true },
desc: { type: String, required: true },
created: { type: Date, required: true, default: Date.now },
userID: { type: Schema.Types.ObjectId, required: true }
});

module.exports = mongoose.model('gallery', gallerySchema);
16 changes: 16 additions & 0 deletions model/pic.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
'use strict';

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const picSchema = Schema({
name: { type: String, required: true },
desc: { type: String, required: true },
userID: { type: Schema.Types.ObjectId, required: true },
galleryID: { type: Schema.Types.ObjectId, required: true },
imageURI: { type: String, required: true, unique: true },
objectKey: { type: String, required: true, unique: true },
created: { type: Date, default: Date.now }
});

module.exports = mongoose.model('pic', picSchema);
Loading