Merge branch 'master' into auth-refactor

This commit is contained in:
Kim Gardner
2018-02-14 17:55:06 -05:00
committed by GitHub
15 changed files with 64 additions and 162 deletions
-1
View File
@@ -1,6 +1,5 @@
{
"exec": "npm-run-all --parallel generate-introspection start:development",
"verbose": true,
"ignore": ["test/*", "client/*", "dist/*", "plugins/*/client"],
"ext": "js,json,graphql,yml",
"watch": [
-4
View File
@@ -5,7 +5,6 @@ const uuid = require('uuid');
const merge = require('lodash/merge');
const helmet = require('helmet');
const plugins = require('./services/plugins');
const compression = require('compression');
const { HELMET_CONFIGURATION } = require('./config');
const { MOUNT_PATH } = require('./url');
const routes = require('./routes');
@@ -72,9 +71,6 @@ app.use(
)
);
// Compress the responses if appropriate.
app.use(compression());
//==============================================================================
// VIEW CONFIGURATION
//==============================================================================
-11
View File
@@ -1,11 +0,0 @@
const pubsub = require('../services/pubsub');
// To handle dependancy injection safer, we inject the pubsub handle onto the
// request object.
module.exports = (req, res, next) => {
// Attach the pubsub handle to the requests.
req.pubsub = pubsub.getClient();
// Forward on the request.
next();
};
+6
View File
@@ -1,6 +1,12 @@
const express = require('express');
const router = express.Router();
if (process.env.NODE_ENV !== 'production') {
router.get('/docs', (req, res) => {
res.render('admin/docs');
});
}
router.get('/confirm-email', (req, res) => {
res.render('admin/confirm-email');
});
+2 -12
View File
@@ -1,17 +1,7 @@
const express = require('express');
const pkg = require('../../package.json');
const router = express.Router();
router.get('/', (req, res) => {
res.json({ version: pkg.version });
});
router.use('/assets', require('./assets'));
router.use('/settings', require('./settings'));
router.use('/auth', require('./auth'));
router.use('/users', require('./users'));
router.use('/account', require('./account'));
router.use('/setup', require('./setup'));
// Return the current version.
router.use('/v1', require('./v1'));
module.exports = router;
-29
View File
@@ -1,29 +0,0 @@
const express = require('express');
const SettingsService = require('../../../services/settings');
const authorization = require('../../../middleware/authorization');
const router = express.Router();
router.get(
'/',
authorization.needed('ADMIN', 'MODERATOR'),
async (req, res, next) => {
try {
let settings = await SettingsService.retrieve();
res.json(settings);
} catch (e) {
return next(e);
}
}
);
router.put('/', authorization.needed('ADMIN'), async (req, res, next) => {
try {
await SettingsService.update(req.body);
res.status(204).end();
} catch (e) {
return next(e);
}
});
module.exports = router;
@@ -5,10 +5,7 @@ const mailer = require('../../../services/mailer');
const authorization = require('../../../middleware/authorization');
const errors = require('../../../errors');
//==============================================================================
// ROUTES
//==============================================================================
// Return the current logged in user.
router.get('/', authorization.needed(), (req, res, next) => {
res.json(req.user);
});
@@ -45,9 +42,8 @@ const tokenCheck = (verifier, error) => async (req, res, next) => {
next();
};
// POST /email/confirm takes the password confirmation token available as a
// payload parameter and if it verifies, it updates the confirmed_at date on the
// local profile.
// Takes the password confirmation token available as a payload parameter and if
// it verifies, it updates the confirmed_at date on the local profile.
router.post(
'/email/verify',
tokenCheck(
@@ -67,6 +63,7 @@ router.post(
}
);
// Sends the password reset email if the user exists.
router.post('/password/reset', async (req, res, next) => {
const { email, loc } = req.body;
@@ -93,6 +90,7 @@ router.post('/password/reset', async (req, res, next) => {
}
});
// Executes the password reset.
router.put(
'/password/reset',
tokenCheck(
@@ -1,10 +1,8 @@
const express = require('express');
const router = express.Router();
const authorization = require('../../../middleware/authorization');
const errors = require('../../../errors');
const AssetsService = require('../../../services/assets');
const AssetModel = require('../../../models/asset');
const FilterOpenAssets = (query, filter) => {
@@ -4,7 +4,6 @@ const {
HandleGenerateCredentials,
HandleLogout,
} = require('../../../services/passport');
const router = express.Router();
/**
@@ -27,15 +26,14 @@ router.get('/', (req, res, next) => {
/**
* This blacklists the token used to authenticate.
*/
router.delete('/', HandleLogout);
// =============================================================================
//==============================================================================
// PASSPORT ROUTES
//==============================================================================
/**
* Local auth endpoint, will recieve a email and password
* Local auth endpoint, will receive a email and password
*/
router.post('/local', (req, res, next) => {
// Perform the local authentication.
+19
View File
@@ -0,0 +1,19 @@
const express = require('express');
const apollo = require('apollo-server-express');
const { createGraphOptions } = require('../../../graph');
const staticTemplate = require('../../../middleware/staticTemplate');
const router = express.Router();
router.use('/ql', apollo.graphqlExpress(createGraphOptions));
// Only include the graphiql tool if we aren't in production mode.
if (process.env.NODE_ENV !== 'production') {
// Interactive graphiql interface.
router.use('/iql', staticTemplate, (req, res) => {
res.render('graphiql', {
endpointURL: 'api/v1/graph/ql',
});
});
}
module.exports = router;
+17
View File
@@ -0,0 +1,17 @@
const express = require('express');
const pkg = require('../../../package.json');
const router = express.Router();
// Return the current version.
router.get('/', (req, res) => {
res.json({ version: pkg.version });
});
router.use('/account', require('./account'));
router.use('/assets', require('./assets'));
router.use('/auth', require('./auth'));
router.use('/graph', require('./graph'));
router.use('/setup', require('./setup'));
router.use('/users', require('./users'));
module.exports = router;
@@ -1,7 +1,5 @@
const express = require('express');
const SetupService = require('../../../services/setup');
const router = express.Router();
router.get('/', async (req, res, next) => {
+13 -34
View File
@@ -1,5 +1,4 @@
const SetupService = require('../services/setup');
const apollo = require('apollo-server-express');
const authentication = require('../middleware/authentication');
const cookieParser = require('cookie-parser');
const debug = require('debug')('talk:routes');
@@ -8,12 +7,11 @@ const errors = require('../errors');
const express = require('express');
const i18n = require('../middleware/i18n');
const path = require('path');
const compression = require('compression');
const plugins = require('../services/plugins');
const staticTemplate = require('../middleware/staticTemplate');
const pubsub = require('../middleware/pubsub');
const staticMiddleware = require('express-static-gzip');
const { DISABLE_STATIC_SERVER } = require('../config');
const { createGraphOptions } = require('../graph');
const { passport } = require('../services/passport');
const { MOUNT_PATH } = require('../url');
@@ -33,10 +31,9 @@ if (!DISABLE_STATIC_SERVER) {
/**
* Redirect old embed calls.
*/
const oldEmbed = path.resolve(MOUNT_PATH, 'embed.js');
const newEmbed = path.resolve(MOUNT_PATH, 'static/embed.js');
router.get('/embed.js', (req, res) => {
const oldEmbed = path.resolve(MOUNT_PATH, 'embed.js');
const newEmbed = path.resolve(MOUNT_PATH, 'static/embed.js');
console.warn(
`deprecation warning: ${oldEmbed} will be phased out soon, please replace calls from ${oldEmbed} to ${newEmbed}`
);
@@ -69,6 +66,9 @@ if (!DISABLE_STATIC_SERVER) {
// Add the i18n middleware to all routes.
router.use(i18n);
// Compress all API responses if appropriate.
router.use(compression());
//==============================================================================
// STATIC ROUTES
//==============================================================================
@@ -103,37 +103,12 @@ router.use(passport.initialize());
// Attach the authentication middleware, this will be responsible for decoding
// (if present) the JWT on the request.
router.use('/api', authentication, pubsub);
router.use('/api', authentication, require('./api'));
//==============================================================================
// GraphQL Router
// DEVELOPMENT ROUTES
//==============================================================================
// GraphQL endpoint.
router.use('/api/v1/graph/ql', apollo.graphqlExpress(createGraphOptions));
// Only include the graphiql tool if we aren't in production mode.
if (process.env.NODE_ENV !== 'production') {
// Interactive graphiql interface.
router.use('/api/v1/graph/iql', staticTemplate, (req, res) => {
res.render('graphiql', {
endpointURL: 'api/v1/graph/ql',
});
});
// GraphQL documentation.
router.get('/admin/docs', (req, res) => {
res.render('admin/docs');
});
}
router.use('/api/v1', require('./api'));
//==============================================================================
// ROUTES
//==============================================================================
// Development routes.
if (process.env.NODE_ENV !== 'production') {
router.use('/assets', staticTemplate, require('./assets'));
router.get('/', staticTemplate, async (req, res) => {
@@ -161,6 +136,10 @@ if (process.env.NODE_ENV !== 'production') {
});
}
//==============================================================================
// PLUGIN ROUTES
//==============================================================================
// Inject server route plugins.
plugins.get('server', 'router').forEach(plugin => {
debug(`added plugin '${plugin.plugin.name}'`);
@@ -178,7 +157,7 @@ router.use((req, res, next) => {
next(errors.ErrNotFound);
});
// General api error handler. Respond with the message and error if we have it
// General API error handler. Respond with the message and error if we have it
// while returning a status code that makes sense.
router.use('/api', (err, req, res, next) => {
if (err !== errors.ErrNotFound) {
-56
View File
@@ -1,56 +0,0 @@
const passport = require('../../../passport');
const app = require('../../../../../app');
const chai = require('chai');
chai.should();
chai.use(require('chai-http'));
const expect = chai.expect;
const SettingsService = require('../../../../../services/settings');
const defaults = { id: '1', moderation: 'PRE' };
describe('/api/v1/settings', () => {
beforeEach(() => SettingsService.init(defaults));
describe('#get', () => {
it('should return a settings object', async () => {
for (let role of ['ADMIN', 'MODERATOR']) {
const res = await chai
.request(app)
.get('/api/v1/settings')
.set(passport.inject({ role }));
expect(res).to.have.status(200);
expect(res).to.be.json;
expect(res.body).to.have.property('moderation', 'PRE');
}
});
});
describe('#put', () => {
it('should update the settings', () => {
return chai
.request(app)
.put('/api/v1/settings')
.set(passport.inject({ role: 'ADMIN' }))
.send({ moderation: 'POST' })
.then(res => {
expect(res).to.have.status(204);
return SettingsService.retrieve();
})
.then(settings => {
expect(settings).to.have.property('moderation', 'POST');
});
});
it('should require ADMIN role', () => {
const promise = chai
.request(app)
.put('/api/v1/settings')
.set(passport.inject({ role: 'MODERATOR' }))
.send({ moderation: 'POST' });
return expect(promise).to.eventually.be.rejected;
});
});
});