Skip to content

Commit

Permalink
Unify restricted token usage - #70
Browse files Browse the repository at this point in the history
  • Loading branch information
tiblu committed Dec 19, 2018
1 parent ce66d1e commit b4359a6
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 88 deletions.
4 changes: 2 additions & 2 deletions libs/email.js
Original file line number Diff line number Diff line change
Expand Up @@ -750,11 +750,11 @@ module.exports = function (app) {
var token = jwt.sign(
{
paths: [
'POST_/api/topics/:topicId/comments/:commentId/reports/:reportId/moderate'
'POST /api/topics/:topicId/comments/:commentId/reports/:reportId/moderate'
.replace(':topicId', commentInfo.topic.id)
.replace(':commentId', commentInfo.comment.id)
.replace(':reportId', report.id),
'GET_/api/topics/:topicId/comments/:commentId/reports/:reportId'
'GET /api/topics/:topicId/comments/:commentId/reports/:reportId'
.replace(':topicId', commentInfo.topic.id)
.replace(':commentId', commentInfo.comment.id)
.replace(':reportId', report.id)
Expand Down
66 changes: 66 additions & 0 deletions libs/middleware/authTokenRistrictedUse.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
'use strict';

/**
* Middleware to parse authorization token that is issued for limited use.
* Such tokens are issued for example to Moderators to moderate a Topic or a Comment (argument)
*
* The token is read from:
* * Authorization header
* * URL parameter "token"
*
* Every new presence overrides previous one. So URL parameter "token" overrides "Authorization" header.
*
* @param {object} req Express request object
* @param {object} res Express response object
* @param {function} next Express middleware function
*
* @returns {void}
*/
module.exports = function (req, res, next) {
var app = req.app;
var config = app.get('config');
var logger = app.get('logger');
var jwt = app.get('jwt');

var token;

if (req.headers && req.headers.authorization) {
var headerInfoArr = req.headers.authorization.split(' '); // "Bearer <token>"

if (headerInfoArr[0] === 'Bearer') {
token = headerInfoArr[1];
}
}

if (req.query && req.query.token) {
token = req.query.token;
}

if (!token) {
return res.unauthorised('Missing authorization token. Specify it in authorization header or as a "token" query parameter');
}

jwt.verify(token, config.session.publicKey, {algorithms: [config.session.algorithm]}, function (err, eventTokenData) {
if (err) {
if (err.name === 'TokenExpiredError') {
logger.info('loginCheck - JWT token has expired', req.method, req.path, err);

return res.unauthorised('JWT token has expired');
} else {
logger.warn('loginCheck - JWT error', req.method, req.path, req.headers, err);

return res.unauthorised('Invalid JWT token');
}
}

// FIXME: Implement - https://github.com/citizenos/citizenos-api/issues/70
if (!eventTokenData || !eventTokenData.paths || eventTokenData.paths.indexOf(req.method + ' ' + req.path) < 0) {
logger.warn('Invalid token used to access path', req.method + '_' + req.path, '. Token was issued for path', eventTokenData.paths);

return res.unauthorised('Invalid JWT token');
}

return next();
});

};
185 changes: 101 additions & 84 deletions routes/api/topic.js
Original file line number Diff line number Diff line change
Expand Up @@ -3450,6 +3450,69 @@ module.exports = function (app) {
app.get('/api/users/:userId/topics/:topicId/attachments', loginCheck(['partner']), hasPermission(TopicMemberUser.LEVELS.read, true), topicAttachmentsList);
app.get('/api/topics/:topicId/attachments', hasVisibility(Topic.VISIBILITY.public), topicAttachmentsList);

var topicReportsCreate = function (req, res, next) {
var topicId = req.params.topicId;

db
.transaction(function (t) {
return Report
.create(
{
type: req.body.type,
text: req.body.text,
creatorId: req.user.id,
creatorIp: req.ip
},
{
transaction: t
}
)
.then(function (report) {
// FIXME: Topic report create activity!
return TopicReport
.create(
{
topicId: topicId,
reportId: report.id
},
{
transaction: t
}
)
.then(function () {
return report;
});
});
})
.then(function (report) {
//FIXME: Send TopicReport e-mail - emailLib.sendCommentReport(commentId, report); // Fire and forget

return res.ok(report);
})
.catch(next);
};

app.post(['/api/users/:userId/topics/:topicId/reports', '/api/topics/:topicId/reports'], loginCheck(['partner']), topicReportsCreate);

/**
* Read Topic Report
*/
app.get(['/api/topics/:topicId/reports/:reportId', '/api/users/:userId/topics/:topicId/reports/:reportId'], function (req, res, next) {
//FIXME Implement
return res.notImplemented();
});

/**
* Moderate a Topic
*/
app.post('/api/topics/:topicId/comments/:commentId/reports/:reportId/moderate', function (req, res, next) {
var reportType = req.body.type; // Delete reason type which is provided in case deleted/hidden by moderator due to a user report
var reportText = req.body.text; // Free text with reason why the comment was deleted/hidden

// FIXME: Implement
return res.notImplemented();
});

/**
* Create Topic Comment
*/
Expand Down Expand Up @@ -3995,58 +4058,12 @@ module.exports = function (app) {
.catch(next);
};

var topicReportsCreate = function (req, res, next) {
var topicId = req.params.topicId;

db
.transaction(function (t) {
return Report
.create(
{
type: req.body.type,
text: req.body.text,
creatorId: req.user.id,
creatorIp: req.ip
},
{
transaction: t
}
)
.then(function (report) {
// FIXME: Topic report create activity!
return TopicReport
.create(
{
topicId: topicId,
reportId: report.id
},
{
transaction: t
}
)
.then(function () {
return report;
});
});
})
.then(function (report) {
//FIXME: Send TopicReport e-mail - emailLib.sendCommentReport(commentId, report); // Fire and forget

return res.ok(report);
})
.catch(next);
};

app.post(['/api/users/:userId/topics/:topicId/reports', '/api/topics/:topicId/reports'], loginCheck(['partner']), topicReportsCreate);


/**
* Read (List) Topic Comments
*/
app.get('/api/users/:userId/topics/:topicId/comments', loginCheck(['partner']), hasPermission(TopicMemberUser.LEVELS.read, true), isModerator(), topicCommentsList);
app.get('/api/v2/users/:userId/topics/:topicId/comments', loginCheck(['partner']), hasPermission(TopicMemberUser.LEVELS.read, true), isModerator(), topicCommentsList2);


/**
* Read (List) public Topic Comments
*/
Expand Down Expand Up @@ -4254,7 +4271,7 @@ module.exports = function (app) {


/**
* Read Report
* Read Comment (Argument) report
*/
app.get(['/api/topics/:topicId/comments/:commentId/reports/:reportId', '/api/users/:userId/topics/:topicId/comments/:commentId/reports/:reportId'], function (req, res, next) {
if (!req.headers || !req.headers.authorization) {
Expand Down Expand Up @@ -6718,42 +6735,42 @@ module.exports = function (app) {
var userId = req.user.id;
var topicId = req.params.topicId;

return db.transaction(function (t) {
return TopicFavourite
.findOrCreate({
where: {
topicId: topicId,
userId: userId
},
transaction: t
})
.spread(function (topicFavourite, created) {
if (created) {
return Topic
.findOne({
where: {
id: topicId
}
})
.then(function (topic) {
topic.description = null;
db.transaction(function (t) {
return TopicFavourite
.findOrCreate({
where: {
topicId: topicId,
userId: userId
},
transaction: t
})
.spread(function (topicFavourite, created) {
if (created) {
return Topic
.findOne({
where: {
id: topicId
}
})
.then(function (topic) {
topic.description = null;

return cosActivities
.addActivity(
topic,
{
type: 'User',
id: userId
},
null,
topicFavourite,
req.method + ' ' + req.path,
t
);
});
}
});
})
return cosActivities
.addActivity(
topic,
{
type: 'User',
id: userId
},
null,
topicFavourite,
req.method + ' ' + req.path,
t
);
});
}
});
})
.then(function () {
return res.ok();
})
Expand Down Expand Up @@ -6786,8 +6803,8 @@ module.exports = function (app) {

return cosActivities
.deleteActivity(
topicFavourite,
topic,
topicFavourite,
topic,
{
type: 'User',
id: req.user.id
Expand Down
4 changes: 2 additions & 2 deletions test/api/topic.js
Original file line number Diff line number Diff line change
Expand Up @@ -9377,7 +9377,7 @@ suite('Topics', function () {
var token = jwt.sign(
{
paths: [
'POST_/api/topics/:topicId/comments/:commentId/reports/:reportId/moderate'
'POST /api/topics/:topicId/comments/:commentId/reports/:reportId/moderate'
.replace(':topicId', topic.id)
.replace(':commentId', comment.id)
.replace(':reportId', report.id)
Expand Down Expand Up @@ -9466,7 +9466,7 @@ suite('Topics', function () {
var token = jwt.sign(
{
paths: [
'POST_/api/topics/:topicId/comments/:commentId/reports/:reportId/moderate'
'POST /api/topics/:topicId/comments/:commentId/reports/:reportId/moderate'
.replace(':topicId', topic.id)
.replace(':commentId', comment.id)
.replace(':reportId', report.id)
Expand Down

0 comments on commit b4359a6

Please sign in to comment.