From bfee23adeebed66861441cdf37044e08583ef1e2 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 19 Apr 2018 16:24:36 -0400 Subject: [PATCH] basic methods and initial integration for #6463 --- src/categories/topics.js | 2 ++ src/middleware/user.js | 23 +++++++++++++ src/posts.js | 1 + src/posts/summary.js | 4 ++- src/routes/accounts.js | 4 +-- src/topics/teaser.js | 1 + src/user.js | 1 + src/user/blocks.js | 73 ++++++++++++++++++++++++++++++++++++++++ 8 files changed, 106 insertions(+), 3 deletions(-) create mode 100644 src/user/blocks.js diff --git a/src/categories/topics.js b/src/categories/topics.js index 32022b7a96..a56545cfa9 100644 --- a/src/categories/topics.js +++ b/src/categories/topics.js @@ -7,6 +7,7 @@ var db = require('../database'); var topics = require('../topics'); var plugins = require('../plugins'); var meta = require('../meta'); +var user = require('../user'); module.exports = function (Categories) { Categories.getCategoryTopics = function (data, callback) { @@ -20,6 +21,7 @@ module.exports = function (Categories) { function (tids, next) { topics.getTopicsByTids(tids, data.uid, next); }, + async.apply(user.blocks.filter, data.uid), function (topics, next) { if (!topics.length) { return next(null, { topics: [], uid: data.uid }); diff --git a/src/middleware/user.js b/src/middleware/user.js index 9ddbbf086d..247424b891 100644 --- a/src/middleware/user.js +++ b/src/middleware/user.js @@ -220,4 +220,27 @@ module.exports = function (middleware) { return next(); } }; + + middleware.exposeUid = function (req, res, next) { + if (!req.params.userslug) { + return next(); + } + + user.getUidByUserslug(req.params.userslug, function (err, uid) { + res.locals.uid = uid; + next(err, uid); + }); + }; + + middleware.handleBlocking = function (req, res, next) { + user.blocks.is(res.locals.uid, req.uid, function (err, blocked) { + if (err) { + return next(err); + } else if (blocked) { + res.status(404).render('404', { title: '[[global:404.title]]' }); + } else { + return next(); + } + }); + }; }; diff --git a/src/posts.js b/src/posts.js index 6061017b89..5c5bd993a4 100644 --- a/src/posts.js +++ b/src/posts.js @@ -63,6 +63,7 @@ Posts.getPostsByPids = function (pids, uid, callback) { Posts.parsePost(post, next); }, next); }, + async.apply(user.blocks.filter, uid), function (posts, next) { plugins.fireHook('filter:post.getPosts', { posts: posts, uid: uid }, next); }, diff --git a/src/posts/summary.js b/src/posts/summary.js index 902a003445..139fea16a8 100644 --- a/src/posts/summary.js +++ b/src/posts/summary.js @@ -30,7 +30,9 @@ module.exports = function (Posts) { }, function (_posts, next) { posts = _posts.filter(Boolean); - + user.blocks.filter(uid, posts, next); + }, + function (_posts, next) { var uids = []; var topicKeys = []; diff --git a/src/routes/accounts.js b/src/routes/accounts.js index 5c040b6af1..f636a3a66e 100644 --- a/src/routes/accounts.js +++ b/src/routes/accounts.js @@ -4,8 +4,8 @@ var helpers = require('./helpers'); var setupPageRoute = helpers.setupPageRoute; module.exports = function (app, middleware, controllers) { - var middlewares = [middleware.checkGlobalPrivacySettings]; - var accountMiddlewares = [middleware.checkGlobalPrivacySettings, middleware.checkAccountPermissions]; + var middlewares = [middleware.checkGlobalPrivacySettings, middleware.exposeUid, middleware.handleBlocking]; + var accountMiddlewares = [middleware.checkGlobalPrivacySettings, middleware.checkAccountPermissions, middleware.exposeUid, middleware.handleBlocking]; setupPageRoute(app, '/me/*', middleware, [], middleware.redirectMeToUserslug); setupPageRoute(app, '/uid/:uid*', middleware, [], middleware.redirectUidToUserslug); diff --git a/src/topics/teaser.js b/src/topics/teaser.js index 28fbeb9a35..508bd51bc8 100644 --- a/src/topics/teaser.js +++ b/src/topics/teaser.js @@ -57,6 +57,7 @@ module.exports = function (Topics) { function (next) { posts.getPostsFields(teaserPids, ['pid', 'uid', 'timestamp', 'tid', 'content'], next); }, + async.apply(user.blocks.filter, uid), function (_postData, next) { postData = _postData; var uids = _.uniq(postData.map(function (post) { diff --git a/src/user.js b/src/user.js index caf47fdcb9..4ded5ca410 100644 --- a/src/user.js +++ b/src/user.js @@ -36,6 +36,7 @@ require('./user/invite')(User); require('./user/password')(User); require('./user/info')(User); require('./user/online')(User); +require('./user/blocks')(User); User.getUidsFromSet = function (set, start, stop, callback) { if (set === 'users:online') { diff --git a/src/user/blocks.js b/src/user/blocks.js new file mode 100644 index 0000000000..b1682ed83f --- /dev/null +++ b/src/user/blocks.js @@ -0,0 +1,73 @@ +'use strict'; + +var async = require('async'); +var db = require('../database'); +var LRU = require('lru-cache'); + +module.exports = function (User) { + User.blocks = { + _cache: LRU({ + max: 100, + length: function () { return 1; }, + maxAge: 0, + }), + }; + + User.blocks.is = function (targetUid, uid, callback) { + User.blocks.list(uid, function (err, blocks) { + callback(err, blocks.includes(parseInt(targetUid, 10))); + }); + }; + + User.blocks.list = function (uid, callback) { + if (User.blocks._cache.has(uid)) { + return setImmediate(callback, null, User.blocks._cache.get(uid)); + } + + db.getSortedSetRange('uid:' + uid + ':blocked_uids', 0, -1, function (err, blocked) { + if (err) { + return callback(err); + } + + // for debugging + blocked = [2]; + + blocked = blocked.map(uid => parseInt(uid, 10)).filter(Boolean); + User.blocks._cache.set(uid, blocked); + callback(null, blocked); + }); + }; + + User.blocks.add = function (targetUid, uid, callback) { + async.waterfall([ + async.apply(db.sortedSetAdd.bind(db), 'uid:' + uid + ':blocked_uids', Date.now(), targetUid), + async.apply(User.blocks.list, uid), + ], callback); + }; + + User.blocks.remove = function (targetUid, uid, callback) { + async.waterfall([ + async.apply(db.sortedSetRemove.bind(db), 'uid:' + uid + ':blocked_uids', targetUid), + async.apply(User.blocks.list, uid), + ], callback); + }; + + User.blocks.filter = function (uid, set, callback) { + // Given whatever is passed in, iterates through it, and removes made by blocked uids + if (!Array.isArray(set) || !set[0].hasOwnProperty('uid')) { + return callback(null, set); + } + + User.blocks.list(uid, function (err, blocked_uids) { + if (err) { + return callback(err); + } + + set = set.filter(function (item) { + return !blocked_uids.includes(parseInt(item.uid, 10)); + }); + + callback(null, set); + }); + }; +};