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

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

@ -283,7 +283,10 @@ module.exports = function (User) {
}, },
function (hashedPassword, next) { function (hashedPassword, next) {
async.parallel([ 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.reset.updateExpiry, data.uid),
async.apply(User.auth.revokeAllSessions, data.uid), async.apply(User.auth.revokeAllSessions, data.uid),
], function (err) { ], function (err) {

Loading…
Cancel
Save