mirror of
https://github.com/wassname/talk.git
synced 2026-07-04 07:01:55 +08:00
Merge branch 'master' into auth-refactor
This commit is contained in:
@@ -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": [
|
||||
|
||||
@@ -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
|
||||
//==============================================================================
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
@@ -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;
|
||||
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user