proof of concept for #5740

v1.18.x
psychobunny 8 years ago
parent a509ccab84
commit 228e9ab8e3

@ -22,6 +22,7 @@ categoryController.get = function (req, res, callback) {
var pageCount = 1;
var userPrivileges;
var settings;
var rssToken;
if ((req.params.topic_index && !utils.isNumber(req.params.topic_index)) || !utils.isNumber(cid)) {
return callback();
@ -39,10 +40,14 @@ categoryController.get = function (req, res, callback) {
userSettings: function (next) {
user.getSettings(req.uid, next);
},
rssToken: function (next) {
user.auth.getFeedToken(req.uid, next);
},
}, next);
},
function (results, next) {
userPrivileges = results.privileges;
rssToken = results.rssToken;
if (!results.categoryData.slug || (results.categoryData && parseInt(results.categoryData.disabled, 10) === 1)) {
return callback();
@ -150,14 +155,16 @@ categoryController.get = function (req, res, callback) {
categoryData.privileges = userPrivileges;
categoryData.showSelect = categoryData.privileges.editable;
addTags(categoryData, res);
if (parseInt(req.uid, 10)) {
categories.markAsRead([cid], req.uid);
categoryData.rssFeedUrl = nconf.get('url') + '/category/' + categoryData.cid + '.rss?uid=' + req.uid + '&token=' + rssToken;
} else {
categoryData.rssFeedUrl = nconf.get('url') + '/category/' + categoryData.cid + '.rss';
}
addTags(categoryData, res);
categoryData['feeds:disableRSS'] = parseInt(meta.config['feeds:disableRSS'], 10) === 1;
categoryData.rssFeedUrl = nconf.get('relative_path') + '/category/' + categoryData.cid + '.rss';
categoryData.title = translator.escape(categoryData.name);
pageCount = Math.max(1, Math.ceil(categoryData.topic_count / settings.topicsPerPage));
categoryData.pagination = pagination.create(currentPage, pageCount, req.query);
@ -220,7 +227,7 @@ function addTags(categoryData, res) {
{
rel: 'alternate',
type: 'application/rss+xml',
href: nconf.get('url') + '/category/' + categoryData.cid + '.rss',
href: categoryData.rssFeedUrl,
},
{
rel: 'up',

@ -26,6 +26,37 @@ module.exports = function (app, middleware) {
app.get('/tags/:tag.rss', middleware.maintenanceMode, generateForTag);
};
function validateTokenIfRequiresLogin(requiresLogin, req, res, callback) {
var uid = req.query.uid;
var token = req.query.token;
if (!requiresLogin) {
return callback();
}
if (!uid || !token) {
return helpers.notAllowed(req, res);
}
user.getUserField(uid, 'rss_token', function (err, _token) {
if (err) {
return callback(err);
}
if (token === _token) {
return callback();
}
user.auth.logAttempt(uid, req.ip, function (err) {
if (err) {
return callback(err);
}
return helpers.notAllowed(req, res);
});
});
}
function generateForTopic(req, res, callback) {
if (parseInt(meta.config['feeds:disableRSS'], 10) === 1) {
return controllers404.send404(req, res);
@ -48,11 +79,15 @@ function generateForTopic(req, res, callback) {
if (!results.topic || (parseInt(results.topic.deleted, 10) && !results.privileges.view_deleted)) {
return controllers404.send404(req, res);
}
if (!results.privileges['topics:read']) {
return helpers.notAllowed(req, res);
}
userPrivileges = results.privileges;
topics.getTopicWithPosts(results.topic, 'tid:' + tid + ':posts', req.uid, 0, 25, false, next);
validateTokenIfRequiresLogin(!results.privileges['topics:read'], req, res, function (err) {
if (err) {
return next(err);
}
userPrivileges = results.privileges;
topics.getTopicWithPosts(results.topic, 'tid:' + tid + ':posts', req.uid, 0, 25, false, next);
});
},
function (topicData) {
topics.modifyPostsByPrivilege(topicData, userPrivileges);
@ -149,16 +184,19 @@ function generateForCategory(req, res, next) {
}, next);
},
function (results, next) {
if (!results.privileges.read) {
return helpers.notAllowed(req, res);
}
generateTopicsFeed({
uid: req.uid,
title: results.category.name,
description: results.category.description,
feed_url: '/category/' + cid + '.rss',
site_url: '/category/' + results.category.cid,
}, results.category.topics, next);
validateTokenIfRequiresLogin(!results.privileges.read, req, res, function (err) {
if (err) {
return next(err);
}
generateTopicsFeed({
uid: req.uid,
title: results.category.name,
description: results.category.description,
feed_url: '/category/' + cid + '.rss',
site_url: '/category/' + results.category.cid,
}, results.category.topics, next);
});
},
function (feed) {
sendFeed(feed, res);
@ -317,18 +355,20 @@ function generateForCategoryRecentPosts(req, res, next) {
return next();
}
if (!results.privileges.read) {
return helpers.notAllowed(req, res);
}
validateTokenIfRequiresLogin(!results.privileges.read, req, res, function (err) {
if (err) {
return next(err);
}
var feed = generateForPostsFeed({
title: results.category.name + ' Recent Posts',
description: 'A list of recent posts from ' + results.category.name,
feed_url: '/category/' + cid + '/recentposts.rss',
site_url: '/category/' + cid + '/recentposts',
}, results.posts);
var feed = generateForPostsFeed({
title: results.category.name + ' Recent Posts',
description: 'A list of recent posts from ' + results.category.name,
feed_url: '/category/' + cid + '/recentposts.rss',
site_url: '/category/' + cid + '/recentposts',
}, results.posts);
sendFeed(feed, res);
sendFeed(feed, res);
});
},
], next);
}
@ -381,4 +421,3 @@ function sendFeed(feed, res) {
var xml = feed.xml();
res.type('xml').set('Content-Length', Buffer.byteLength(xml)).send(xml);
}

@ -6,6 +6,7 @@ var db = require('../database');
var meta = require('../meta');
var events = require('../events');
var batch = require('../batch');
var utils = require('../utils');
module.exports = function (User) {
User.auth = {};
@ -47,6 +48,25 @@ module.exports = function (User) {
], callback);
};
User.auth.getFeedToken = function (uid, callback) {
if (!uid) {
return callback();
}
User.getUserField(uid, 'rss_token', function (err, token) {
if (err) {
return callback(err);
}
if (!token) {
token = utils.generateUUID();
User.setUserField(uid, 'rss_token', token);
}
callback(false, token);
});
};
User.auth.clearLoginAttempts = function (uid) {
db.delete('loginAttempts:' + uid);
};

@ -283,7 +283,10 @@ module.exports = function (User) {
},
function (hashedPassword, next) {
async.parallel([
async.apply(User.setUserField, data.uid, 'password', hashedPassword),
async.apply(User.setUserFields, data.uid, {
password: hashedPassword,
rss_token: utils.generateUUID(),
}),
async.apply(User.reset.updateExpiry, data.uid),
async.apply(User.auth.revokeAllSessions, data.uid),
], function (err) {

Loading…
Cancel
Save