@@ -8,13 +8,8 @@ const passport = require('passport'); | |||
const canonicalizeRequest = require('../util/canonicalize').canonicalizeRequest; | |||
const requireAuth = require('../util/requireAuth').requireAuth; | |||
const wrap = require('../util/wrap.js').wrap; | |||
// Wraps an async middleware to catch promise rejection | |||
function asyncMiddleware(fn) { | |||
return (req, res, next) => { | |||
Promise.resolve(fn(req, res, next)).catch(next); | |||
} | |||
} | |||
// Wraps passport.authenticate to return a promise | |||
function authenticate(req, res, next) { | |||
@@ -65,7 +60,7 @@ async function validateInvite(code) { | |||
} | |||
router.post('/register', canonicalizeRequest, asyncMiddleware(async (req, res, next) => { | |||
router.post('/register', canonicalizeRequest, wrap(async (req, res, next) => { | |||
// Validate the invite and username | |||
const [inviteStatus, usernameStatus] = | |||
await Promise.all([ | |||
@@ -93,7 +88,7 @@ router.post('/register', canonicalizeRequest, asyncMiddleware(async (req, res, n | |||
res.status(200).json({'message': 'Registration successful.'}); | |||
})); | |||
router.post('/login', canonicalizeRequest, asyncMiddleware(async (req, res, next) => { | |||
router.post('/login', canonicalizeRequest, wrap(async (req, res, next) => { | |||
// Authenticate | |||
const user = await authenticate(req, res, next); | |||
if (!user) | |||
@@ -113,7 +108,11 @@ router.get('/logout', function (req, res) { | |||
res.status(200).json({'message': 'Logged out.'}); | |||
}); | |||
router.get('/session', requireAuth, (req, res, next) => { | |||
router.get('/ping', requireAuth(), (req, res, next) => { | |||
res.status(200).json({'message': 'pong'}); | |||
}); | |||
router.get('/session', requireAuth(), (req, res, next) => { | |||
res.status(200).json({ | |||
username: req.session.passport.username, | |||
canonicalname: req.session.passport.canonicalname, | |||
@@ -1,7 +1,15 @@ | |||
exports.requireAuth = | |||
(req, res, next) => { | |||
if (req.isAuthenticated()) | |||
const Key = require('../models/Key.js'); | |||
const wrap = require('./wrap.js').wrap; | |||
const verifyScope = (scope, requiredScope) => scope.indexOf(requiredScope) !== -1; | |||
const getKeyScope = async apikey => (await Key.findOne({key: apikey})).scope; | |||
exports.requireAuth = scope => | |||
wrap(async (req, res, next) => { | |||
if (req.isAuthenticated() && (scope ? verifyScope(req.session.passport.scope, scope) : true)) | |||
next(); | |||
else if (req.body.apikey && (scope ? verifyScope(getKeyScope(req.body.apikey), scope) : true)) | |||
next(); | |||
else | |||
res.status(401).json({'message:': 'Unauthorized.'}); | |||
}; | |||
res.status(401).json({'message': 'Unauthorized.'}); | |||
}); |
@@ -0,0 +1,3 @@ | |||
// Wraps an async middleware function to catch promise rejection | |||
exports.wrap = fn => | |||
(req, res, next) => Promise.resolve(fn(req, res, next)).catch(next); |
@@ -3,6 +3,10 @@ process.env.NODE_ENV = 'test'; | |||
const app = require('../server'); | |||
const server = app.server; | |||
const chai = require('chai'); | |||
chai.use(require('chai-http')); | |||
const should = chai.should(); | |||
const User = require('../app/models/User.js'); | |||
const Invite = require('../app/models/Invite.js'); | |||
const Upload = require('../app/models/Upload.js'); | |||
@@ -123,17 +127,25 @@ describe('Users', function() { | |||
describe('/POST login', () => { | |||
async function verifySuccessfulLogin(credentials) { | |||
const res = await util.login(credentials); | |||
const agent = chai.request.agent(server); | |||
const res = await util.login(credentials, agent); | |||
res.should.have.status(200); | |||
res.body.should.be.a('object'); | |||
res.body.should.have.property('message').eql('Logged in.'); | |||
res.body.should.have.property('message').equal('Logged in.'); | |||
res.should.have.cookie('session.id'); | |||
const ping = await util.ping(agent); | |||
ping.should.have.status(200); | |||
ping.body.should.have.property('message').equal('pong'); | |||
agent.close(); | |||
} | |||
async function verifyFailedLogin(credentials) { | |||
const res = await util.login(credentials); | |||
res.should.have.status(401); | |||
res.body.should.be.a('object'); | |||
res.body.should.have.property('message').eql('Unauthorized.'); | |||
res.body.should.have.property('message').equal('Unauthorized.'); | |||
} | |||
describe('0 Valid Request', () => { | |||
@@ -159,32 +171,47 @@ describe('Users', function() { | |||
}); | |||
}); | |||
/*describe('Uploads', function() { | |||
describe('/POST upload', function() { | |||
it('SHOULD accept logged in valid upload', function(done) { | |||
util.verifySuccessfulUpload({ | |||
username: 'TestUser2', | |||
password: 'TestPassword' | |||
}, done); | |||
/*describe('Uploads', () => { | |||
describe('/POST upload', () => { | |||
describe('0 Valid Request', () => { | |||
it('SHOULD accept logged in valid upload', function(done) { | |||
util.verifySuccessfulUpload({ | |||
username: 'TestUser2', | |||
password: 'TestPassword' | |||
}, done); | |||
}); | |||
}); | |||
it('SHOULD NOT accept unauthenticated valid upload', function(done) { | |||
util.verifyFailedAuthUpload(done); | |||
describe('1 Invalid Authentication', () => { | |||
it('SHOULD NOT accept unauthenticated request', function(done) { | |||
util.verifyFailedAuthUpload(done); | |||
}); | |||
}); | |||
it('SHOULD NOT accept invalid permission, valid upload', function(done) { | |||
util.verifyFailedPermissionUpload({ | |||
username: 'TestUser1', | |||
password: 'TestPassword' | |||
}, done); | |||
describe('2 Invalid Permission', () => { | |||
it('SHOULD NOT accept without file.upload permission', function(done) { | |||
util.verifyFailedPermissionUpload({ | |||
username: 'TestUser1', | |||
password: 'TestPassword' | |||
}, done); | |||
}); | |||
}); | |||
describe('3 Invalid File', () => { | |||
it('SHOULD NOT accept invalid size', function(done) { | |||
util.verifyFailedSizeUpload({ | |||
username: 'TestUser2', | |||
password: 'TestPassword' | |||
}, done); | |||
}) | |||
}); | |||
it('SHOULD NOT accept invalid size upload', function(done) { | |||
util.verifyFailedSizeUpload({ | |||
username: 'TestUser2', | |||
password: 'TestPassword' | |||
}, done); | |||
}) | |||
}); | |||
});*/ | |||
@@ -1,22 +1,15 @@ | |||
process.env.NODE_ENV = 'test'; | |||
const User = require('../app/models/User.js'); | |||
const Invite = require('../app/models/Invite.js'); | |||
const Upload = require('../app/models/Upload.js'); | |||
const chai = require('chai'); | |||
const http = require('chai-http'); | |||
chai.use(http); | |||
const should = chai.should(); | |||
const app = require('../server'); | |||
const server = app.server; | |||
//TODO: REMOVE | |||
const async = require('async'); | |||
const canonicalize = require("../app/util/canonicalize").canonicalize; | |||
const chai = require('chai'); | |||
chai.use(require('chai-http')); | |||
const should = chai.should(); | |||
const User = require('../app/models/User.js'); | |||
const Invite = require('../app/models/Invite.js'); | |||
const Upload = require('../app/models/Upload.js'); | |||
//---------------- DATABASE UTIL ----------------// | |||
@@ -29,10 +22,11 @@ exports.clearDatabase = async () => | |||
//---------------- API ROUTES ----------------// | |||
exports.login = async (credentials) => | |||
chai.request(server) | |||
exports.login = async (credentials, agent) => { | |||
return (agent ? agent : chai.request(server)) | |||
.post('/api/auth/login') | |||
.send(credentials); | |||
}; | |||
exports.createInvite = async (invite) => { | |||
if (!invite.code) invite.code = 'code'; | |||
@@ -51,6 +45,11 @@ exports.registerUser = async (user) => { | |||
.send(user); | |||
}; | |||
exports.ping = async (agent) => | |||
(agent ? agent : chai.request(server)) | |||
.get('/api/auth/ping') | |||
.send(); | |||
//---------------- TEST ENTRY CREATION ----------------// | |||
exports.createTestInvite = async () => | |||