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
5 changes: 5 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
**/node_modules/*
**/vendor/*
**/*.min.js
**/coverage/*
**/build/*
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"
}
137 changes: 137 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# Created by https://www.gitignore.io/api/osx,vim,node,macos,windows

### 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*
node_modules

# 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


### OSX ###

# Icon must end with two \r

# Thumbnails

# Files that might appear in the root of a volume

# Directories potentially created on remote AFP share

### 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/osx,vim,node,macos,windows
Binary file added data/11b81b4f4cabe49eeee07405c59a07f7
Binary file not shown.
Binary file added data/196ece84603c4fe9bb5b9c1e9ec36c03
Binary file not shown.
Binary file added data/1c13022c7d2d1ead36c29ca14abb32d3
Binary file not shown.
Binary file added data/21295a5a002c42c2d37e34a53eb249f0
Binary file not shown.
Binary file added data/25a8abe40f5bdbfb917429086dba3367
Binary file not shown.
Binary file added data/274b3cd56e8697d5f7c6bad6b9effe26
Binary file not shown.
Binary file added data/2c62064cf9ace120d37ff2948a698749
Binary file not shown.
Binary file added data/2d6483593c993a77ea1b68fe1bbe7b91
Binary file not shown.
Binary file added data/2ed7aa97874969ef42122689888e8e34
Binary file not shown.
Binary file added data/3332579b14fdd9238e53eae33d615e46
Binary file not shown.
Binary file added data/3497361f402c194700e0ea3e15d90a17
Binary file not shown.
Binary file added data/375220bd7c3d4657d578a913c87e382f
Binary file not shown.
Binary file added data/37c7b91687fbdd7298d60913d8a6d4a1
Binary file not shown.
Binary file added data/3b5d1cd36b20660557fdc9a081c7737a
Binary file not shown.
Binary file added data/3b6cce3f9722ce679e5428d11c2bd1f5
Binary file not shown.
Binary file added data/406387310bc20c48ca78d16a2c498629
Binary file not shown.
Binary file added data/4ecae05c4ca805453a87c7994ca8a876
Binary file not shown.
Binary file added data/511444b3b930f7a3d3151cfd564a9121
Binary file not shown.
Binary file added data/59e8268b180fa373f908cf1c6277d3e1
Binary file not shown.
Binary file added data/66f4769d24273acaf6bfe41a515f31a8
Binary file not shown.
Binary file added data/715eb3ff7fc4ccf202a09d58f3a6f26f
Binary file not shown.
Binary file added data/756d3a4516b0947774955c25794b852f
Binary file not shown.
Binary file added data/8115a78a0455c2050ad1c4cc0801059e
Binary file not shown.
Binary file added data/826f5673a8c975ae6af3d7aed5976ae8
Binary file not shown.
Binary file added data/85c0c5fb702715a89f235049b007d11b
Binary file not shown.
Binary file added data/8b751f4f8359d3b7633d1697cfdb0358
Binary file not shown.
Binary file added data/a101c3ef401eedb1a2184cb613e79479
Binary file not shown.
Binary file added data/a7a6f9995692381e6077490ebc327071
Binary file not shown.
Binary file added data/ae3bde926aefa0f9e6ac1660d4b2005b
Binary file not shown.
Binary file added data/b1cdfc4aa23805ad9a8c0c668609ee50
Binary file not shown.
Binary file added data/b71e6ec8c204e2c307e4f396e702dd42
Binary file not shown.
Binary file added data/bc3a4d6a68b31fcef9f590eba9a78e16
Binary file not shown.
Binary file added data/c435bcff6149352692c3eaf56aa2d18b
Binary file not shown.
Binary file added data/c53f6ae409b4d122deff03164a26ad83
Binary file not shown.
Binary file added data/c63a5222295eaff1ad2522caa3467e6b
Binary file not shown.
Binary file added data/c899404a07c5573276982d7b17bc0fba
Binary file not shown.
Binary file added data/ca61155c1321e5c40fbc501cd8204e37
Binary file not shown.
Binary file added data/d0443839438f41a5717bf9ec4a6fa53e
Binary file not shown.
Binary file added data/d3c3df456f7c7f409977accb76e4d588
Binary file not shown.
Binary file added data/d705c85cd26db07c02376995e8b8fd33
Binary file not shown.
Binary file added data/e69665b6c65a948588022a8785245371
Binary file not shown.
Binary file added data/f2b728692bf9b174884b52dd50c2d622.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added data/f606ee4c3fec55da07d7552bc95e52e1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added data/tester.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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 createError = require('http-errors');
const debug = require('debug')('userex:basic-auth-middleware');

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

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

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

var utf8str = new Buffer(base64str, 'base64').toString();
var 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();
}
34 changes: 34 additions & 0 deletions lib/bearer-auth-middleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
'use strict';

const jwt = require('jsonwebtoken');
const createError = require('http-errors');
const debug = require('debug')('userex: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) => {
if (err) return next(err);

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')('userex:error-middleware');

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

console.error('message:', 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/comment.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 commentSchema = 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('comment', commentSchema);
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 },
commentID: { 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);
74 changes: 74 additions & 0 deletions model/user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
'use strict';

const crypto = require('crypto');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const mongoose = require('mongoose');
const createError = require('http-errors');
const Promise = require('bluebird');
const debug = require('debug')('userex:user');

const Schema = mongoose.Schema;

const userSchema = Schema({
username: { type: String, required: true, unique: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
findHash: { type: String, unique: true }
});

userSchema.methods.generatePasswordHash = function(password) {
debug('generatePasswordHash');

return new Promise((resolve, reject) => {
bcrypt.hash(password, 10, (err, hash) => {
if (err) return reject(err);
this.password = hash;
resolve(this);
});
});
}

userSchema.methods.comparePasswordHash = function(password) {
debug('comparePasswordHash');
return new Promise((resolve, reject) => {
bcrypt.compare(password, this.password, (err, valid) => {
if (err) return reject(err);
if (!valid) return reject(createError(401, 'invalid password'));
resolve(this);
});
});
}

userSchema.methods.generateFindHash = function() {
debug('generateFindHash');

return new Promise((resolve, reject) => {
let tries = 0;

_generateFindHash.call(this);

function _generateFindHash() {
this.findHash = crypto.randomBytes(32).toString('hex');
this.save()
.then(() => resolve(this.findHash))
.catch(err => {
if (tries > 3) return reject(err);
tries++;
_generateFindHash.call(this);
});
}
});
}

userSchema.methods.generateToken = function() {
debug('generateToken');

return new Promise((resolve, reject) => {
this.generateFindHash()
.then(findHash => resolve(jwt.sign({ token: findHash }, process.env.APP_SECRET)))
.catch(err => reject(err));
});
}

module.exports = mongoose.model('user', userSchema);
Loading