mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-11-02 03:55:55 +01:00
style changes
This commit is contained in:
@@ -36,9 +36,7 @@ rewards.checkConditionAndRewardUser = function (uid, condition, method, callback
|
|||||||
return next(null, false);
|
return next(null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
checkCondition(reward, method, function (result) {
|
checkCondition(reward, method, next);
|
||||||
next(null, result);
|
|
||||||
});
|
|
||||||
}, function (err, eligible) {
|
}, function (err, eligible) {
|
||||||
if (err || !eligible) {
|
if (err || !eligible) {
|
||||||
return next(false);
|
return next(false);
|
||||||
@@ -59,29 +57,30 @@ function getIDsByCondition(condition, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function filterCompletedRewards(uid, rewards, callback) {
|
function filterCompletedRewards(uid, rewards, callback) {
|
||||||
db.getSortedSetRangeByScoreWithScores('uid:' + uid + ':rewards', 0, -1, 1, '+inf', function (err, data) {
|
async.waterfall([
|
||||||
if (err) {
|
function (next) {
|
||||||
return callback(err);
|
db.getSortedSetRangeByScoreWithScores('uid:' + uid + ':rewards', 0, -1, 1, '+inf', next);
|
||||||
}
|
},
|
||||||
|
function (data, next) {
|
||||||
|
var userRewards = {};
|
||||||
|
|
||||||
var userRewards = {};
|
data.forEach(function (obj) {
|
||||||
|
userRewards[obj.value] = parseInt(obj.score, 10);
|
||||||
|
});
|
||||||
|
|
||||||
data.forEach(function (obj) {
|
rewards = rewards.filter(function (reward) {
|
||||||
userRewards[obj.value] = parseInt(obj.score, 10);
|
if (!reward) {
|
||||||
});
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
rewards = rewards.filter(function (reward) {
|
var claimable = parseInt(reward.claimable, 10);
|
||||||
if (!reward) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var claimable = parseInt(reward.claimable, 10);
|
return claimable === 0 || (userRewards[reward.id] < reward.claimable);
|
||||||
|
});
|
||||||
|
|
||||||
return claimable === 0 || (userRewards[reward.id] < reward.claimable);
|
next(null, rewards);
|
||||||
});
|
},
|
||||||
|
], callback);
|
||||||
callback(null, rewards);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRewardDataByIDs(ids, callback) {
|
function getRewardDataByIDs(ids, callback) {
|
||||||
@@ -97,26 +96,29 @@ function getRewardsByRewardData(rewards, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function checkCondition(reward, method, callback) {
|
function checkCondition(reward, method, callback) {
|
||||||
method(function (err, value) {
|
async.waterfall([
|
||||||
if (err) {
|
function (next) {
|
||||||
return callback(err);
|
method(next);
|
||||||
}
|
},
|
||||||
|
function (value, next) {
|
||||||
plugins.fireHook('filter:rewards.checkConditional:' + reward.conditional, { left: value, right: reward.value }, function (err, bool) {
|
plugins.fireHook('filter:rewards.checkConditional:' + reward.conditional, { left: value, right: reward.value }, next);
|
||||||
callback(err || bool);
|
},
|
||||||
});
|
function (bool, next) {
|
||||||
});
|
next(null, bool);
|
||||||
|
},
|
||||||
|
], callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
function giveRewards(uid, rewards, callback) {
|
function giveRewards(uid, rewards, callback) {
|
||||||
getRewardsByRewardData(rewards, function (err, rewardData) {
|
async.waterfall([
|
||||||
if (err) {
|
function (next) {
|
||||||
return callback(err);
|
getRewardsByRewardData(rewards, next);
|
||||||
}
|
},
|
||||||
|
function (rewardData, next) {
|
||||||
async.each(rewards, function (reward, next) {
|
async.each(rewards, function (reward, next) {
|
||||||
plugins.fireHook('action:rewards.award:' + reward.rid, { uid: uid, reward: rewardData[rewards.indexOf(reward)] });
|
plugins.fireHook('action:rewards.award:' + reward.rid, { uid: uid, reward: rewardData[rewards.indexOf(reward)] });
|
||||||
db.sortedSetIncrBy('uid:' + uid + ':rewards', 1, reward.id, next);
|
db.sortedSetIncrBy('uid:' + uid + ':rewards', 1, reward.id, next);
|
||||||
}, callback);
|
}, next);
|
||||||
});
|
},
|
||||||
|
], callback);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,54 +1,55 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
(function (Auth) {
|
var async = require('async');
|
||||||
var passport = require('passport');
|
var passport = require('passport');
|
||||||
var passportLocal = require('passport-local').Strategy;
|
var passportLocal = require('passport-local').Strategy;
|
||||||
var nconf = require('nconf');
|
var nconf = require('nconf');
|
||||||
var winston = require('winston');
|
var winston = require('winston');
|
||||||
var express = require('express');
|
var express = require('express');
|
||||||
|
|
||||||
var controllers = require('../controllers');
|
var controllers = require('../controllers');
|
||||||
var plugins = require('../plugins');
|
var plugins = require('../plugins');
|
||||||
var hotswap = require('../hotswap');
|
var hotswap = require('../hotswap');
|
||||||
|
|
||||||
var loginStrategies = [];
|
var loginStrategies = [];
|
||||||
|
|
||||||
Auth.initialize = function (app, middleware) {
|
var Auth = module.exports;
|
||||||
app.use(passport.initialize());
|
|
||||||
app.use(passport.session());
|
|
||||||
|
|
||||||
app.use(function (req, res, next) {
|
Auth.initialize = function (app, middleware) {
|
||||||
req.uid = req.user ? parseInt(req.user.uid, 10) : 0;
|
app.use(passport.initialize());
|
||||||
next();
|
app.use(passport.session());
|
||||||
});
|
|
||||||
|
|
||||||
Auth.app = app;
|
app.use(function (req, res, next) {
|
||||||
Auth.middleware = middleware;
|
req.uid = req.user ? parseInt(req.user.uid, 10) : 0;
|
||||||
};
|
next();
|
||||||
|
});
|
||||||
|
|
||||||
Auth.getLoginStrategies = function () {
|
Auth.app = app;
|
||||||
return loginStrategies;
|
Auth.middleware = middleware;
|
||||||
};
|
};
|
||||||
|
|
||||||
Auth.reloadRoutes = function (callback) {
|
Auth.getLoginStrategies = function () {
|
||||||
var router = express.Router();
|
return loginStrategies;
|
||||||
router.hotswapId = 'auth';
|
};
|
||||||
|
|
||||||
loginStrategies.length = 0;
|
Auth.reloadRoutes = function (callback) {
|
||||||
|
var router = express.Router();
|
||||||
|
router.hotswapId = 'auth';
|
||||||
|
|
||||||
if (plugins.hasListeners('action:auth.overrideLogin')) {
|
loginStrategies.length = 0;
|
||||||
winston.warn('[authentication] Login override detected, skipping local login strategy.');
|
|
||||||
plugins.fireHook('action:auth.overrideLogin');
|
|
||||||
} else {
|
|
||||||
passport.use(new passportLocal({ passReqToCallback: true }, controllers.authentication.localLogin));
|
|
||||||
}
|
|
||||||
|
|
||||||
plugins.fireHook('filter:auth.init', loginStrategies, function (err) {
|
if (plugins.hasListeners('action:auth.overrideLogin')) {
|
||||||
if (err) {
|
winston.warn('[authentication] Login override detected, skipping local login strategy.');
|
||||||
winston.error('filter:auth.init - plugin failure');
|
plugins.fireHook('action:auth.overrideLogin');
|
||||||
return callback(err);
|
} else {
|
||||||
}
|
passport.use(new passportLocal({ passReqToCallback: true }, controllers.authentication.localLogin));
|
||||||
|
}
|
||||||
|
|
||||||
|
async.waterfall([
|
||||||
|
function (next) {
|
||||||
|
plugins.fireHook('filter:auth.init', loginStrategies, next);
|
||||||
|
},
|
||||||
|
function (loginStrategies, next) {
|
||||||
loginStrategies.forEach(function (strategy) {
|
loginStrategies.forEach(function (strategy) {
|
||||||
if (strategy.url) {
|
if (strategy.url) {
|
||||||
router.get(strategy.url, passport.authenticate(strategy.name, {
|
router.get(strategy.url, passport.authenticate(strategy.name, {
|
||||||
@@ -70,19 +71,17 @@
|
|||||||
router.post('/logout', Auth.middleware.applyCSRF, controllers.authentication.logout);
|
router.post('/logout', Auth.middleware.applyCSRF, controllers.authentication.logout);
|
||||||
|
|
||||||
hotswap.replace('auth', router);
|
hotswap.replace('auth', router);
|
||||||
if (typeof callback === 'function') {
|
next();
|
||||||
callback();
|
},
|
||||||
}
|
], callback);
|
||||||
});
|
};
|
||||||
};
|
|
||||||
|
|
||||||
passport.serializeUser(function (user, done) {
|
passport.serializeUser(function (user, done) {
|
||||||
done(null, user.uid);
|
done(null, user.uid);
|
||||||
});
|
});
|
||||||
|
|
||||||
passport.deserializeUser(function (uid, done) {
|
passport.deserializeUser(function (uid, done) {
|
||||||
done(null, {
|
done(null, {
|
||||||
uid: uid,
|
uid: uid,
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}(exports));
|
});
|
||||||
|
|||||||
@@ -205,11 +205,11 @@ module.exports = function (app, middleware, hotswapIds, callback) {
|
|||||||
async.apply(plugins.reloadRoutes),
|
async.apply(plugins.reloadRoutes),
|
||||||
async.apply(authRoutes.reloadRoutes),
|
async.apply(authRoutes.reloadRoutes),
|
||||||
async.apply(user.addInterstitials),
|
async.apply(user.addInterstitials),
|
||||||
|
function (next) {
|
||||||
|
winston.info('Routes added');
|
||||||
|
next();
|
||||||
|
},
|
||||||
], function (err) {
|
], function (err) {
|
||||||
if (err) {
|
callback(err);
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
winston.info('Routes added');
|
|
||||||
callback();
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -38,13 +38,18 @@ var SocketAdmin = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
SocketAdmin.before = function (socket, method, data, next) {
|
SocketAdmin.before = function (socket, method, data, next) {
|
||||||
user.isAdministrator(socket.uid, function (err, isAdmin) {
|
async.waterfall([
|
||||||
if (err || isAdmin) {
|
function (next) {
|
||||||
return next(err);
|
user.isAdministrator(socket.uid, next);
|
||||||
}
|
},
|
||||||
winston.warn('[socket.io] Call to admin method ( ' + method + ' ) blocked (accessed by uid ' + socket.uid + ')');
|
function (isAdmin) {
|
||||||
next(new Error('[[error:no-privileges]]'));
|
if (isAdmin) {
|
||||||
});
|
return next();
|
||||||
|
}
|
||||||
|
winston.warn('[socket.io] Call to admin method ( ' + method + ' ) blocked (accessed by uid ' + socket.uid + ')');
|
||||||
|
next(new Error('[[error:no-privileges]]'));
|
||||||
|
},
|
||||||
|
], next);
|
||||||
};
|
};
|
||||||
|
|
||||||
SocketAdmin.reload = function (socket, data, callback) {
|
SocketAdmin.reload = function (socket, data, callback) {
|
||||||
@@ -58,26 +63,27 @@ SocketAdmin.reload = function (socket, data, callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
SocketAdmin.restart = function (socket, data, callback) {
|
SocketAdmin.restart = function (socket, data, callback) {
|
||||||
require('../meta/build').buildAll(function (err) {
|
async.waterfall([
|
||||||
if (err) {
|
function (next) {
|
||||||
return callback(err);
|
require('../meta/build').buildAll(next);
|
||||||
}
|
},
|
||||||
|
function (next) {
|
||||||
|
events.log({
|
||||||
|
type: 'build',
|
||||||
|
uid: socket.uid,
|
||||||
|
ip: socket.ip,
|
||||||
|
});
|
||||||
|
|
||||||
events.log({
|
events.log({
|
||||||
type: 'build',
|
type: 'restart',
|
||||||
uid: socket.uid,
|
uid: socket.uid,
|
||||||
ip: socket.ip,
|
ip: socket.ip,
|
||||||
});
|
});
|
||||||
|
|
||||||
events.log({
|
meta.restart();
|
||||||
type: 'restart',
|
next();
|
||||||
uid: socket.uid,
|
},
|
||||||
ip: socket.ip,
|
], callback);
|
||||||
});
|
|
||||||
|
|
||||||
meta.restart();
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SocketAdmin.fireEvent = function (socket, data, callback) {
|
SocketAdmin.fireEvent = function (socket, data, callback) {
|
||||||
|
|||||||
@@ -30,13 +30,7 @@ Categories.getAll = function (socket, data, callback) {
|
|||||||
function (result, next) {
|
function (result, next) {
|
||||||
next(null, categories.getTree(result.categories, 0));
|
next(null, categories.getTree(result.categories, 0));
|
||||||
},
|
},
|
||||||
], function (err, categoriesTree) {
|
], callback);
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
callback(null, categoriesTree);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Categories.getNames = function (socket, data, callback) {
|
Categories.getNames = function (socket, data, callback) {
|
||||||
@@ -93,27 +87,31 @@ Categories.getPrivilegeSettings = function (socket, cid, callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Categories.copyPrivilegesToChildren = function (socket, cid, callback) {
|
Categories.copyPrivilegesToChildren = function (socket, cid, callback) {
|
||||||
categories.getCategories([cid], socket.uid, function (err, categories) {
|
async.waterfall([
|
||||||
if (err) {
|
function (next) {
|
||||||
return callback(err);
|
categories.getCategories([cid], socket.uid, next);
|
||||||
}
|
},
|
||||||
var category = categories[0];
|
function (categories, next) {
|
||||||
|
var category = categories[0];
|
||||||
|
|
||||||
async.eachSeries(category.children, function (child, next) {
|
async.eachSeries(category.children, function (child, next) {
|
||||||
copyPrivilegesToChildrenRecursive(cid, child, next);
|
copyPrivilegesToChildrenRecursive(cid, child, next);
|
||||||
}, callback);
|
}, next);
|
||||||
});
|
},
|
||||||
|
], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
function copyPrivilegesToChildrenRecursive(parentCid, category, callback) {
|
function copyPrivilegesToChildrenRecursive(parentCid, category, callback) {
|
||||||
categories.copyPrivilegesFrom(parentCid, category.cid, function (err) {
|
async.waterfall([
|
||||||
if (err) {
|
function (next) {
|
||||||
return callback(err);
|
categories.copyPrivilegesFrom(parentCid, category.cid, next);
|
||||||
}
|
},
|
||||||
async.eachSeries(category.children, function (child, next) {
|
function (next) {
|
||||||
copyPrivilegesToChildrenRecursive(parentCid, child, next);
|
async.eachSeries(category.children, function (child, next) {
|
||||||
}, callback);
|
copyPrivilegesToChildrenRecursive(parentCid, child, next);
|
||||||
});
|
}, next);
|
||||||
|
},
|
||||||
|
], callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
Categories.copySettingsFrom = function (socket, data, callback) {
|
Categories.copySettingsFrom = function (socket, data, callback) {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
var async = require('async');
|
var async = require('async');
|
||||||
var groups = require('../../groups');
|
var groups = require('../../groups');
|
||||||
|
|
||||||
var Groups = {};
|
var Groups = module.exports;
|
||||||
|
|
||||||
Groups.create = function (socket, data, callback) {
|
Groups.create = function (socket, data, callback) {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
@@ -66,5 +66,3 @@ Groups.update = function (socket, data, callback) {
|
|||||||
|
|
||||||
groups.update(data.groupName, data.values, callback);
|
groups.update(data.groupName, data.values, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = Groups;
|
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var navigationAdmin = require('../../navigation/admin');
|
var navigationAdmin = require('../../navigation/admin');
|
||||||
var SocketNavigation = {};
|
var SocketNavigation = module.exports;
|
||||||
|
|
||||||
SocketNavigation.save = function (socket, data, callback) {
|
SocketNavigation.save = function (socket, data, callback) {
|
||||||
navigationAdmin.save(data, callback);
|
navigationAdmin.save(data, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = SocketNavigation;
|
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ var pubsub = require('../../pubsub');
|
|||||||
|
|
||||||
var stats = {};
|
var stats = {};
|
||||||
var totals = {};
|
var totals = {};
|
||||||
var SocketRooms = {
|
|
||||||
stats: stats,
|
|
||||||
totals: totals,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
var SocketRooms = module.exports;
|
||||||
|
|
||||||
|
SocketRooms.stats = stats;
|
||||||
|
SocketRooms.totals = totals;
|
||||||
|
|
||||||
pubsub.on('sync:stats:start', function () {
|
pubsub.on('sync:stats:start', function () {
|
||||||
SocketRooms.getLocalStats(function (err, stats) {
|
SocketRooms.getLocalStats(function (err, stats) {
|
||||||
@@ -181,6 +181,3 @@ SocketRooms.getLocalStats = function (callback) {
|
|||||||
|
|
||||||
callback(null, socketData);
|
callback(null, socketData);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
module.exports = SocketRooms;
|
|
||||||
|
|||||||
@@ -10,28 +10,29 @@ var events = require('../../events');
|
|||||||
var meta = require('../../meta');
|
var meta = require('../../meta');
|
||||||
var plugins = require('../../plugins');
|
var plugins = require('../../plugins');
|
||||||
|
|
||||||
var User = {};
|
var User = module.exports;
|
||||||
|
|
||||||
User.makeAdmins = function (socket, uids, callback) {
|
User.makeAdmins = function (socket, uids, callback) {
|
||||||
if (!Array.isArray(uids)) {
|
if (!Array.isArray(uids)) {
|
||||||
return callback(new Error('[[error:invalid-data]]'));
|
return callback(new Error('[[error:invalid-data]]'));
|
||||||
}
|
}
|
||||||
|
|
||||||
user.getUsersFields(uids, ['banned'], function (err, userData) {
|
async.waterfall([
|
||||||
if (err) {
|
function (next) {
|
||||||
return callback(err);
|
user.getUsersFields(uids, ['banned'], next);
|
||||||
}
|
},
|
||||||
|
function (userData, next) {
|
||||||
for (var i = 0; i < userData.length; i += 1) {
|
for (var i = 0; i < userData.length; i += 1) {
|
||||||
if (userData[i] && parseInt(userData[i].banned, 10) === 1) {
|
if (userData[i] && parseInt(userData[i].banned, 10) === 1) {
|
||||||
return callback(new Error('[[error:cant-make-banned-users-admin]]'));
|
return callback(new Error('[[error:cant-make-banned-users-admin]]'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
async.each(uids, function (uid, next) {
|
async.each(uids, function (uid, next) {
|
||||||
groups.join('administrators', uid, next);
|
groups.join('administrators', uid, next);
|
||||||
}, callback);
|
}, next);
|
||||||
});
|
},
|
||||||
|
], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
User.removeAdmins = function (socket, uids, callback) {
|
User.removeAdmins = function (socket, uids, callback) {
|
||||||
@@ -40,17 +41,18 @@ User.removeAdmins = function (socket, uids, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async.eachSeries(uids, function (uid, next) {
|
async.eachSeries(uids, function (uid, next) {
|
||||||
groups.getMemberCount('administrators', function (err, count) {
|
async.waterfall([
|
||||||
if (err) {
|
function (next) {
|
||||||
return next(err);
|
groups.getMemberCount('administrators', next);
|
||||||
}
|
},
|
||||||
|
function (count, next) {
|
||||||
|
if (count === 1) {
|
||||||
|
return next(new Error('[[error:cant-remove-last-admin]]'));
|
||||||
|
}
|
||||||
|
|
||||||
if (count === 1) {
|
groups.leave('administrators', uid, next);
|
||||||
return next(new Error('[[error:cant-remove-last-admin]]'));
|
},
|
||||||
}
|
], next);
|
||||||
|
|
||||||
groups.leave('administrators', uid, next);
|
|
||||||
});
|
|
||||||
}, callback);
|
}, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -78,14 +80,16 @@ User.validateEmail = function (socket, uids, callback) {
|
|||||||
return parseInt(uid, 10);
|
return parseInt(uid, 10);
|
||||||
});
|
});
|
||||||
|
|
||||||
async.each(uids, function (uid, next) {
|
async.waterfall([
|
||||||
user.setUserField(uid, 'email:confirmed', 1, next);
|
function (next) {
|
||||||
}, function (err) {
|
async.each(uids, function (uid, next) {
|
||||||
if (err) {
|
user.setUserField(uid, 'email:confirmed', 1, next);
|
||||||
return callback(err);
|
}, next);
|
||||||
}
|
},
|
||||||
db.sortedSetRemove('users:notvalidated', uids, callback);
|
function (next) {
|
||||||
});
|
db.sortedSetRemove('users:notvalidated', uids, next);
|
||||||
|
},
|
||||||
|
], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
User.sendValidationEmail = function (socket, uids, callback) {
|
User.sendValidationEmail = function (socket, uids, callback) {
|
||||||
@@ -123,15 +127,17 @@ User.sendPasswordResetEmail = function (socket, uids, callback) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
async.each(uids, function (uid, next) {
|
async.each(uids, function (uid, next) {
|
||||||
user.getUserFields(uid, ['email', 'username'], function (err, userData) {
|
async.waterfall([
|
||||||
if (err) {
|
function (next) {
|
||||||
return next(err);
|
user.getUserFields(uid, ['email', 'username'], next);
|
||||||
}
|
},
|
||||||
if (!userData.email) {
|
function (userData, next) {
|
||||||
return next(new Error('[[error:user-doesnt-have-email, ' + userData.username + ']]'));
|
if (!userData.email) {
|
||||||
}
|
return next(new Error('[[error:user-doesnt-have-email, ' + userData.username + ']]'));
|
||||||
user.reset.send(userData.email, next);
|
}
|
||||||
});
|
user.reset.send(userData.email, next);
|
||||||
|
},
|
||||||
|
], next);
|
||||||
}, callback);
|
}, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -257,5 +263,3 @@ User.rejectRegistration = function (socket, data, callback) {
|
|||||||
User.restartJobs = function (socket, data, callback) {
|
User.restartJobs = function (socket, data, callback) {
|
||||||
user.startJobs(callback);
|
user.startJobs(callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = User;
|
|
||||||
|
|||||||
@@ -1,24 +1,28 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
var async = require('async');
|
||||||
|
|
||||||
var user = require('../user');
|
var user = require('../user');
|
||||||
var meta = require('../meta');
|
var meta = require('../meta');
|
||||||
|
|
||||||
var SocketBlacklist = {};
|
var SocketBlacklist = module.exports;
|
||||||
|
|
||||||
SocketBlacklist.validate = function (socket, data, callback) {
|
SocketBlacklist.validate = function (socket, data, callback) {
|
||||||
meta.blacklist.validate(data.rules, callback);
|
meta.blacklist.validate(data.rules, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
SocketBlacklist.save = function (socket, rules, callback) {
|
SocketBlacklist.save = function (socket, rules, callback) {
|
||||||
user.isAdminOrGlobalMod(socket.uid, function (err, isAdminOrGlobalMod) {
|
async.waterfall([
|
||||||
if (err || !isAdminOrGlobalMod) {
|
function (next) {
|
||||||
return callback(err || new Error('[[error:no-privileges]]'));
|
user.isAdminOrGlobalMod(socket.uid, next);
|
||||||
}
|
},
|
||||||
|
function (isAdminOrGlobalMod, next) {
|
||||||
|
if (!isAdminOrGlobalMod) {
|
||||||
|
return callback(new Error('[[error:no-privileges]]'));
|
||||||
|
}
|
||||||
|
|
||||||
meta.blacklist.save(rules, callback);
|
meta.blacklist.save(rules, next);
|
||||||
});
|
},
|
||||||
|
], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
module.exports = SocketBlacklist;
|
|
||||||
|
|||||||
@@ -8,133 +8,134 @@ var user = require('../user');
|
|||||||
var topics = require('../topics');
|
var topics = require('../topics');
|
||||||
var apiController = require('../controllers/api');
|
var apiController = require('../controllers/api');
|
||||||
|
|
||||||
var SocketCategories = {};
|
var SocketCategories = module.exports;
|
||||||
|
|
||||||
SocketCategories.getRecentReplies = function (socket, cid, callback) {
|
SocketCategories.getRecentReplies = function (socket, cid, callback) {
|
||||||
categories.getRecentReplies(cid, socket.uid, 4, callback);
|
categories.getRecentReplies(cid, socket.uid, 4, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
SocketCategories.get = function (socket, data, callback) {
|
SocketCategories.get = function (socket, data, callback) {
|
||||||
async.parallel({
|
async.waterfall([
|
||||||
isAdmin: async.apply(user.isAdministrator, socket.uid),
|
function (next) {
|
||||||
categories: function (next) {
|
async.parallel({
|
||||||
async.waterfall([
|
isAdmin: async.apply(user.isAdministrator, socket.uid),
|
||||||
async.apply(db.getSortedSetRange, 'categories:cid', 0, -1),
|
categories: function (next) {
|
||||||
async.apply(categories.getCategoriesData),
|
async.waterfall([
|
||||||
], next);
|
async.apply(db.getSortedSetRange, 'categories:cid', 0, -1),
|
||||||
|
async.apply(categories.getCategoriesData),
|
||||||
|
], next);
|
||||||
|
},
|
||||||
|
}, next);
|
||||||
},
|
},
|
||||||
}, function (err, results) {
|
function (results, next) {
|
||||||
if (err) {
|
results.categories = results.categories.filter(function (category) {
|
||||||
return callback(err);
|
return category && (!category.disabled || results.isAdmin);
|
||||||
}
|
});
|
||||||
|
|
||||||
results.categories = results.categories.filter(function (category) {
|
next(null, results.categories);
|
||||||
return category && (!category.disabled || results.isAdmin);
|
},
|
||||||
});
|
], callback);
|
||||||
|
|
||||||
callback(null, results.categories);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SocketCategories.getWatchedCategories = function (socket, data, callback) {
|
SocketCategories.getWatchedCategories = function (socket, data, callback) {
|
||||||
async.parallel({
|
async.waterfall([
|
||||||
categories: async.apply(categories.getCategoriesByPrivilege, 'cid:0:children', socket.uid, 'find'),
|
function (next) {
|
||||||
ignoredCids: async.apply(user.getIgnoredCategories, socket.uid),
|
async.parallel({
|
||||||
}, function (err, results) {
|
categories: async.apply(categories.getCategoriesByPrivilege, 'cid:0:children', socket.uid, 'find'),
|
||||||
if (err) {
|
ignoredCids: async.apply(user.getIgnoredCategories, socket.uid),
|
||||||
return callback(err);
|
}, next);
|
||||||
}
|
},
|
||||||
var watchedCategories = results.categories.filter(function (category) {
|
function (results, next) {
|
||||||
return category && results.ignoredCids.indexOf(category.cid.toString()) === -1;
|
var watchedCategories = results.categories.filter(function (category) {
|
||||||
});
|
return category && results.ignoredCids.indexOf(category.cid.toString()) === -1;
|
||||||
|
});
|
||||||
|
|
||||||
callback(null, watchedCategories);
|
next(null, watchedCategories);
|
||||||
});
|
},
|
||||||
|
], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
SocketCategories.loadMore = function (socket, data, callback) {
|
SocketCategories.loadMore = function (socket, data, callback) {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return callback(new Error('[[error:invalid-data]]'));
|
return callback(new Error('[[error:invalid-data]]'));
|
||||||
}
|
}
|
||||||
|
var userPrivileges;
|
||||||
async.parallel({
|
async.waterfall([
|
||||||
privileges: function (next) {
|
function (next) {
|
||||||
privileges.categories.get(data.cid, socket.uid, next);
|
async.parallel({
|
||||||
|
privileges: function (next) {
|
||||||
|
privileges.categories.get(data.cid, socket.uid, next);
|
||||||
|
},
|
||||||
|
settings: function (next) {
|
||||||
|
user.getSettings(socket.uid, next);
|
||||||
|
},
|
||||||
|
targetUid: function (next) {
|
||||||
|
if (data.author) {
|
||||||
|
user.getUidByUserslug(data.author, next);
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}, next);
|
||||||
},
|
},
|
||||||
settings: function (next) {
|
function (results, next) {
|
||||||
user.getSettings(socket.uid, next);
|
userPrivileges = results.privileges;
|
||||||
},
|
if (!userPrivileges.read) {
|
||||||
targetUid: function (next) {
|
return callback(new Error('[[error:no-privileges]]'));
|
||||||
if (data.author) {
|
|
||||||
user.getUidByUserslug(data.author, next);
|
|
||||||
} else {
|
|
||||||
next();
|
|
||||||
}
|
}
|
||||||
},
|
var infScrollTopicsPerPage = 20;
|
||||||
}, function (err, results) {
|
var set = 'cid:' + data.cid + ':tids';
|
||||||
if (err) {
|
var reverse = false;
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!results.privileges.read) {
|
if (data.categoryTopicSort === 'newest_to_oldest') {
|
||||||
return callback(new Error('[[error:no-privileges]]'));
|
reverse = true;
|
||||||
}
|
} else if (data.categoryTopicSort === 'most_posts') {
|
||||||
|
reverse = true;
|
||||||
var infScrollTopicsPerPage = 20;
|
set = 'cid:' + data.cid + ':tids:posts';
|
||||||
var set = 'cid:' + data.cid + ':tids';
|
|
||||||
var reverse = false;
|
|
||||||
|
|
||||||
if (data.categoryTopicSort === 'newest_to_oldest') {
|
|
||||||
reverse = true;
|
|
||||||
} else if (data.categoryTopicSort === 'most_posts') {
|
|
||||||
reverse = true;
|
|
||||||
set = 'cid:' + data.cid + ':tids:posts';
|
|
||||||
}
|
|
||||||
|
|
||||||
var start = Math.max(0, parseInt(data.after, 10));
|
|
||||||
|
|
||||||
if (data.direction === -1) {
|
|
||||||
start -= reverse ? infScrollTopicsPerPage : -infScrollTopicsPerPage;
|
|
||||||
}
|
|
||||||
|
|
||||||
var stop = start + infScrollTopicsPerPage - 1;
|
|
||||||
|
|
||||||
start = Math.max(0, start);
|
|
||||||
stop = Math.max(0, stop);
|
|
||||||
|
|
||||||
if (results.targetUid) {
|
|
||||||
set = 'cid:' + data.cid + ':uid:' + results.targetUid + ':tids';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.tag) {
|
|
||||||
set = [set, 'tag:' + data.tag + ':topics'];
|
|
||||||
}
|
|
||||||
|
|
||||||
categories.getCategoryTopics({
|
|
||||||
cid: data.cid,
|
|
||||||
set: set,
|
|
||||||
reverse: reverse,
|
|
||||||
start: start,
|
|
||||||
stop: stop,
|
|
||||||
uid: socket.uid,
|
|
||||||
targetUid: results.targetUid,
|
|
||||||
settings: results.settings,
|
|
||||||
}, function (err, data) {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
categories.modifyTopicsByPrivilege(data.topics, results.privileges);
|
var start = Math.max(0, parseInt(data.after, 10));
|
||||||
|
|
||||||
data.privileges = results.privileges;
|
if (data.direction === -1) {
|
||||||
|
start -= reverse ? infScrollTopicsPerPage : -infScrollTopicsPerPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
var stop = start + infScrollTopicsPerPage - 1;
|
||||||
|
|
||||||
|
start = Math.max(0, start);
|
||||||
|
stop = Math.max(0, stop);
|
||||||
|
|
||||||
|
if (results.targetUid) {
|
||||||
|
set = 'cid:' + data.cid + ':uid:' + results.targetUid + ':tids';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.tag) {
|
||||||
|
set = [set, 'tag:' + data.tag + ':topics'];
|
||||||
|
}
|
||||||
|
|
||||||
|
categories.getCategoryTopics({
|
||||||
|
cid: data.cid,
|
||||||
|
set: set,
|
||||||
|
reverse: reverse,
|
||||||
|
start: start,
|
||||||
|
stop: stop,
|
||||||
|
uid: socket.uid,
|
||||||
|
targetUid: results.targetUid,
|
||||||
|
settings: results.settings,
|
||||||
|
}, next);
|
||||||
|
},
|
||||||
|
function (data, next) {
|
||||||
|
categories.modifyTopicsByPrivilege(data.topics, userPrivileges);
|
||||||
|
|
||||||
|
data.privileges = userPrivileges;
|
||||||
data.template = {
|
data.template = {
|
||||||
category: true,
|
category: true,
|
||||||
name: 'category',
|
name: 'category',
|
||||||
};
|
};
|
||||||
|
|
||||||
callback(null, data);
|
next(null, data);
|
||||||
});
|
},
|
||||||
});
|
], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
SocketCategories.getPageCount = function (socket, cid, callback) {
|
SocketCategories.getPageCount = function (socket, cid, callback) {
|
||||||
@@ -150,32 +151,33 @@ SocketCategories.getCategoriesByPrivilege = function (socket, privilege, callbac
|
|||||||
};
|
};
|
||||||
|
|
||||||
SocketCategories.getMoveCategories = function (socket, data, callback) {
|
SocketCategories.getMoveCategories = function (socket, data, callback) {
|
||||||
async.parallel({
|
async.waterfall([
|
||||||
isAdmin: async.apply(user.isAdministrator, socket.uid),
|
function (next) {
|
||||||
categories: function (next) {
|
async.parallel({
|
||||||
async.waterfall([
|
isAdmin: async.apply(user.isAdministrator, socket.uid),
|
||||||
function (next) {
|
categories: function (next) {
|
||||||
db.getSortedSetRange('cid:0:children', 0, -1, next);
|
async.waterfall([
|
||||||
|
function (next) {
|
||||||
|
db.getSortedSetRange('cid:0:children', 0, -1, next);
|
||||||
|
},
|
||||||
|
function (cids, next) {
|
||||||
|
privileges.categories.filterCids('read', cids, socket.uid, next);
|
||||||
|
},
|
||||||
|
function (cids, next) {
|
||||||
|
categories.getCategories(cids, socket.uid, next);
|
||||||
|
},
|
||||||
|
], next);
|
||||||
},
|
},
|
||||||
function (cids, next) {
|
}, next);
|
||||||
privileges.categories.filterCids('read', cids, socket.uid, next);
|
|
||||||
},
|
|
||||||
function (cids, next) {
|
|
||||||
categories.getCategories(cids, socket.uid, next);
|
|
||||||
},
|
|
||||||
], next);
|
|
||||||
},
|
},
|
||||||
}, function (err, results) {
|
function (results, next) {
|
||||||
if (err) {
|
results.categories = results.categories.filter(function (category) {
|
||||||
return callback(err);
|
return category && (!category.disabled || results.isAdmin) && !category.link;
|
||||||
}
|
});
|
||||||
|
|
||||||
results.categories = results.categories.filter(function (category) {
|
next(null, results.categories);
|
||||||
return category && (!category.disabled || results.isAdmin) && !category.link;
|
},
|
||||||
});
|
], callback);
|
||||||
|
|
||||||
callback(null, results.categories);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SocketCategories.watch = function (socket, cid, callback) {
|
SocketCategories.watch = function (socket, cid, callback) {
|
||||||
@@ -231,5 +233,3 @@ SocketCategories.isModerator = function (socket, cid, callback) {
|
|||||||
SocketCategories.getCategory = function (socket, cid, callback) {
|
SocketCategories.getCategory = function (socket, cid, callback) {
|
||||||
apiController.getCategoryData(cid, socket.uid, callback);
|
apiController.getCategoryData(cid, socket.uid, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = SocketCategories;
|
|
||||||
|
|||||||
@@ -26,14 +26,11 @@ SocketFlags.create = function (socket, data, callback) {
|
|||||||
// If we got here, then no errors occurred
|
// If we got here, then no errors occurred
|
||||||
flags.create(data.type, data.id, socket.uid, data.reason, next);
|
flags.create(data.type, data.id, socket.uid, data.reason, next);
|
||||||
},
|
},
|
||||||
], function (err, flagObj) {
|
function (flagObj, next) {
|
||||||
if (err) {
|
flags.notify(flagObj, socket.uid);
|
||||||
return callback(err);
|
next(null, flagObj);
|
||||||
}
|
},
|
||||||
|
], callback);
|
||||||
flags.notify(flagObj, socket.uid);
|
|
||||||
callback(null, flagObj);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SocketFlags.update = function (socket, data, callback) {
|
SocketFlags.update = function (socket, data, callback) {
|
||||||
|
|||||||
@@ -8,8 +8,7 @@ var user = require('../user');
|
|||||||
var utils = require('../utils');
|
var utils = require('../utils');
|
||||||
var groupsController = require('../controllers/groups');
|
var groupsController = require('../controllers/groups');
|
||||||
|
|
||||||
var SocketGroups = {};
|
var SocketGroups = module.exports;
|
||||||
|
|
||||||
|
|
||||||
SocketGroups.before = function (socket, method, data, next) {
|
SocketGroups.before = function (socket, method, data, next) {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
@@ -304,5 +303,3 @@ SocketGroups.cover.remove = function (socket, data, callback) {
|
|||||||
},
|
},
|
||||||
], callback);
|
], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = SocketGroups;
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ var utils = require('../utils');
|
|||||||
|
|
||||||
var apiController = require('../controllers/api');
|
var apiController = require('../controllers/api');
|
||||||
|
|
||||||
var SocketPosts = {};
|
var SocketPosts = module.exports;
|
||||||
|
|
||||||
require('./posts/edit')(SocketPosts);
|
require('./posts/edit')(SocketPosts);
|
||||||
require('./posts/move')(SocketPosts);
|
require('./posts/move')(SocketPosts);
|
||||||
@@ -152,6 +152,3 @@ SocketPosts.getReplies = function (socket, pid, callback) {
|
|||||||
},
|
},
|
||||||
], callback);
|
], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
module.exports = SocketPosts;
|
|
||||||
|
|||||||
@@ -60,25 +60,30 @@ module.exports = function (SocketPosts) {
|
|||||||
return callback(new Error('[[error:invalid-data]]'));
|
return callback(new Error('[[error:invalid-data]]'));
|
||||||
}
|
}
|
||||||
|
|
||||||
posts.getUpvotedUidsByPids(pids, function (err, data) {
|
async.waterfall([
|
||||||
if (err || !Array.isArray(data) || !data.length) {
|
function (next) {
|
||||||
return callback(err, []);
|
posts.getUpvotedUidsByPids(pids, next);
|
||||||
}
|
},
|
||||||
|
function (data, next) {
|
||||||
async.map(data, function (uids, next) {
|
if (!data.length) {
|
||||||
var otherCount = 0;
|
return callback(null, []);
|
||||||
if (uids.length > 6) {
|
|
||||||
otherCount = uids.length - 5;
|
|
||||||
uids = uids.slice(0, 5);
|
|
||||||
}
|
}
|
||||||
user.getUsernamesByUids(uids, function (err, usernames) {
|
|
||||||
next(err, {
|
async.map(data, function (uids, next) {
|
||||||
otherCount: otherCount,
|
var otherCount = 0;
|
||||||
usernames: usernames,
|
if (uids.length > 6) {
|
||||||
|
otherCount = uids.length - 5;
|
||||||
|
uids = uids.slice(0, 5);
|
||||||
|
}
|
||||||
|
user.getUsernamesByUids(uids, function (err, usernames) {
|
||||||
|
next(err, {
|
||||||
|
otherCount: otherCount,
|
||||||
|
usernames: usernames,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
}, next);
|
||||||
}, callback);
|
},
|
||||||
});
|
], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
SocketPosts.upvote = function (socket, data, callback) {
|
SocketPosts.upvote = function (socket, data, callback) {
|
||||||
|
|||||||
@@ -197,17 +197,18 @@ SocketUser.unfollow = function (socket, data, callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function toggleFollow(method, uid, theiruid, callback) {
|
function toggleFollow(method, uid, theiruid, callback) {
|
||||||
user[method](uid, theiruid, function (err) {
|
async.waterfall([
|
||||||
if (err) {
|
function (next) {
|
||||||
return callback(err);
|
user[method](uid, theiruid, next);
|
||||||
}
|
},
|
||||||
|
function (next) {
|
||||||
plugins.fireHook('action:user.' + method, {
|
plugins.fireHook('action:user.' + method, {
|
||||||
fromUid: uid,
|
fromUid: uid,
|
||||||
toUid: theiruid,
|
toUid: theiruid,
|
||||||
});
|
});
|
||||||
callback();
|
next();
|
||||||
});
|
},
|
||||||
|
], callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
SocketUser.saveSettings = function (socket, data, callback) {
|
SocketUser.saveSettings = function (socket, data, callback) {
|
||||||
|
|||||||
@@ -121,11 +121,11 @@ module.exports = function (SocketUser) {
|
|||||||
function (next) {
|
function (next) {
|
||||||
if (!reason) {
|
if (!reason) {
|
||||||
return translator.translate('[[user:info.banned-no-reason]]', function (translated) {
|
return translator.translate('[[user:info.banned-no-reason]]', function (translated) {
|
||||||
next(false, translated);
|
next(null, translated);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
next(false, reason);
|
next(null, reason);
|
||||||
},
|
},
|
||||||
function (_reason, next) {
|
function (_reason, next) {
|
||||||
websockets.in('uid_' + uid).emit('event:banned', {
|
websockets.in('uid_' + uid).emit('event:banned', {
|
||||||
|
|||||||
@@ -67,32 +67,34 @@ module.exports = function (SocketUser) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function isAdminOrSelfAndPasswordMatch(uid, data, callback) {
|
function isAdminOrSelfAndPasswordMatch(uid, data, callback) {
|
||||||
async.parallel({
|
async.waterfall([
|
||||||
isAdmin: async.apply(user.isAdministrator, uid),
|
function (next) {
|
||||||
hasPassword: async.apply(user.hasPassword, data.uid),
|
async.parallel({
|
||||||
passwordMatch: function (next) {
|
isAdmin: async.apply(user.isAdministrator, uid),
|
||||||
if (data.password) {
|
hasPassword: async.apply(user.hasPassword, data.uid),
|
||||||
user.isPasswordCorrect(data.uid, data.password, next);
|
passwordMatch: function (next) {
|
||||||
} else {
|
if (data.password) {
|
||||||
next(null, false);
|
user.isPasswordCorrect(data.uid, data.password, next);
|
||||||
}
|
} else {
|
||||||
|
next(null, false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}, next);
|
||||||
},
|
},
|
||||||
}, function (err, results) {
|
function (results, next) {
|
||||||
if (err) {
|
var isSelf = parseInt(uid, 10) === parseInt(data.uid, 10);
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
var isSelf = parseInt(uid, 10) === parseInt(data.uid, 10);
|
|
||||||
|
|
||||||
if (!results.isAdmin && !isSelf) {
|
if (!results.isAdmin && !isSelf) {
|
||||||
return callback(new Error('[[error:no-privileges]]'));
|
return next(new Error('[[error:no-privileges]]'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isSelf && results.hasPassword && !results.passwordMatch) {
|
if (isSelf && results.hasPassword && !results.passwordMatch) {
|
||||||
return callback(new Error('[[error:invalid-password]]'));
|
return next(new Error('[[error:invalid-password]]'));
|
||||||
}
|
}
|
||||||
|
|
||||||
callback();
|
next();
|
||||||
});
|
},
|
||||||
|
], callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
SocketUser.changePassword = function (socket, data, callback) {
|
SocketUser.changePassword = function (socket, data, callback) {
|
||||||
@@ -103,20 +105,20 @@ module.exports = function (SocketUser) {
|
|||||||
if (!data || !data.uid) {
|
if (!data || !data.uid) {
|
||||||
return callback(new Error('[[error:invalid-data]]'));
|
return callback(new Error('[[error:invalid-data]]'));
|
||||||
}
|
}
|
||||||
|
async.waterfall([
|
||||||
user.changePassword(socket.uid, data, function (err) {
|
function (next) {
|
||||||
if (err) {
|
user.changePassword(socket.uid, data, next);
|
||||||
return callback(err);
|
},
|
||||||
}
|
function (next) {
|
||||||
|
events.log({
|
||||||
events.log({
|
type: 'password-change',
|
||||||
type: 'password-change',
|
uid: socket.uid,
|
||||||
uid: socket.uid,
|
targetUid: data.uid,
|
||||||
targetUid: data.uid,
|
ip: socket.ip,
|
||||||
ip: socket.ip,
|
});
|
||||||
});
|
next();
|
||||||
callback();
|
},
|
||||||
});
|
], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
SocketUser.updateProfile = function (socket, data, callback) {
|
SocketUser.updateProfile = function (socket, data, callback) {
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
var async = require('async');
|
||||||
|
|
||||||
var user = require('../../user');
|
var user = require('../../user');
|
||||||
var meta = require('../../meta');
|
var meta = require('../../meta');
|
||||||
var pagination = require('../../pagination');
|
var pagination = require('../../pagination');
|
||||||
@@ -9,25 +11,29 @@ module.exports = function (SocketUser) {
|
|||||||
if (!data) {
|
if (!data) {
|
||||||
return callback(new Error('[[error:invalid-data]]'));
|
return callback(new Error('[[error:invalid-data]]'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!socket.uid && parseInt(meta.config.allowGuestUserSearching, 10) !== 1) {
|
if (!socket.uid && parseInt(meta.config.allowGuestUserSearching, 10) !== 1) {
|
||||||
return callback(new Error('[[error:not-logged-in]]'));
|
return callback(new Error('[[error:not-logged-in]]'));
|
||||||
}
|
}
|
||||||
user.search({
|
|
||||||
query: data.query,
|
async.waterfall([
|
||||||
page: data.page,
|
function (next) {
|
||||||
searchBy: data.searchBy,
|
user.search({
|
||||||
sortBy: data.sortBy,
|
query: data.query,
|
||||||
onlineOnly: data.onlineOnly,
|
page: data.page,
|
||||||
bannedOnly: data.bannedOnly,
|
searchBy: data.searchBy,
|
||||||
flaggedOnly: data.flaggedOnly,
|
sortBy: data.sortBy,
|
||||||
uid: socket.uid,
|
onlineOnly: data.onlineOnly,
|
||||||
}, function (err, result) {
|
bannedOnly: data.bannedOnly,
|
||||||
if (err) {
|
flaggedOnly: data.flaggedOnly,
|
||||||
return callback(err);
|
uid: socket.uid,
|
||||||
}
|
}, next);
|
||||||
result.pagination = pagination.create(data.page, result.pageCount);
|
},
|
||||||
result['route_users:' + data.sortBy] = true;
|
function (result, next) {
|
||||||
callback(null, result);
|
result.pagination = pagination.create(data.page, result.pageCount);
|
||||||
});
|
result['route_users:' + data.sortBy] = true;
|
||||||
|
next(null, result);
|
||||||
|
},
|
||||||
|
], callback);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
var async = require('async');
|
||||||
var validator = require('validator');
|
var validator = require('validator');
|
||||||
|
|
||||||
var db = require('../database');
|
var db = require('../database');
|
||||||
@@ -21,27 +22,29 @@ function escapeTitle(topicData) {
|
|||||||
|
|
||||||
module.exports = function (Topics) {
|
module.exports = function (Topics) {
|
||||||
Topics.getTopicField = function (tid, field, callback) {
|
Topics.getTopicField = function (tid, field, callback) {
|
||||||
db.getObjectField('topic:' + tid, field, function (err, value) {
|
async.waterfall([
|
||||||
if (err) {
|
function (next) {
|
||||||
return callback(err);
|
db.getObjectField('topic:' + tid, field, next);
|
||||||
}
|
},
|
||||||
|
function (value, next) {
|
||||||
if (field === 'title') {
|
if (field === 'title') {
|
||||||
value = translator.escape(validator.escape(String(value)));
|
value = translator.escape(validator.escape(String(value)));
|
||||||
}
|
}
|
||||||
callback(null, value);
|
next(null, value);
|
||||||
});
|
},
|
||||||
|
], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
Topics.getTopicFields = function (tid, fields, callback) {
|
Topics.getTopicFields = function (tid, fields, callback) {
|
||||||
db.getObjectFields('topic:' + tid, fields, function (err, topic) {
|
async.waterfall([
|
||||||
if (err) {
|
function (next) {
|
||||||
return callback(err);
|
db.getObjectFields('topic:' + tid, fields, next);
|
||||||
}
|
},
|
||||||
|
function (topic, next) {
|
||||||
escapeTitle(topic);
|
escapeTitle(topic);
|
||||||
callback(null, topic);
|
next(null, topic);
|
||||||
});
|
},
|
||||||
|
], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
Topics.getTopicsFields = function (tids, fields, callback) {
|
Topics.getTopicsFields = function (tids, fields, callback) {
|
||||||
@@ -51,42 +54,38 @@ module.exports = function (Topics) {
|
|||||||
var keys = tids.map(function (tid) {
|
var keys = tids.map(function (tid) {
|
||||||
return 'topic:' + tid;
|
return 'topic:' + tid;
|
||||||
});
|
});
|
||||||
db.getObjectsFields(keys, fields, function (err, topics) {
|
async.waterfall([
|
||||||
if (err) {
|
function (next) {
|
||||||
return callback(err);
|
if (fields.length) {
|
||||||
}
|
db.getObjectsFields(keys, fields, next);
|
||||||
|
} else {
|
||||||
topics.forEach(escapeTitle);
|
db.getObjects(keys, next);
|
||||||
callback(null, topics);
|
}
|
||||||
});
|
},
|
||||||
|
function (topics, next) {
|
||||||
|
topics.forEach(modifyTopic);
|
||||||
|
next(null, topics);
|
||||||
|
},
|
||||||
|
], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
Topics.getTopicData = function (tid, callback) {
|
Topics.getTopicData = function (tid, callback) {
|
||||||
db.getObject('topic:' + tid, function (err, topic) {
|
async.waterfall([
|
||||||
if (err || !topic) {
|
function (next) {
|
||||||
return callback(err);
|
db.getObject('topic:' + tid, next);
|
||||||
}
|
},
|
||||||
|
function (topic, next) {
|
||||||
modifyTopic(topic);
|
if (!topic) {
|
||||||
callback(null, topic);
|
return next(null, null);
|
||||||
});
|
}
|
||||||
|
modifyTopic(topic);
|
||||||
|
next(null, topic);
|
||||||
|
},
|
||||||
|
], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
Topics.getTopicsData = function (tids, callback) {
|
Topics.getTopicsData = function (tids, callback) {
|
||||||
var keys = [];
|
Topics.getTopicsFields(tids, [], callback);
|
||||||
|
|
||||||
for (var i = 0; i < tids.length; i += 1) {
|
|
||||||
keys.push('topic:' + tids[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
db.getObjects(keys, function (err, topics) {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
topics.forEach(modifyTopic);
|
|
||||||
callback(null, topics);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function modifyTopic(topic) {
|
function modifyTopic(topic) {
|
||||||
@@ -102,13 +101,14 @@ module.exports = function (Topics) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Topics.getCategoryData = function (tid, callback) {
|
Topics.getCategoryData = function (tid, callback) {
|
||||||
Topics.getTopicField(tid, 'cid', function (err, cid) {
|
async.waterfall([
|
||||||
if (err) {
|
function (next) {
|
||||||
return callback(err);
|
Topics.getTopicField(tid, 'cid', next);
|
||||||
}
|
},
|
||||||
|
function (cid, next) {
|
||||||
categories.getCategoryData(cid, callback);
|
categories.getCategoryData(cid, next);
|
||||||
});
|
},
|
||||||
|
], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
Topics.setTopicField = function (tid, field, value, callback) {
|
Topics.setTopicField = function (tid, field, value, callback) {
|
||||||
|
|||||||
@@ -126,33 +126,35 @@ module.exports = function (Topics) {
|
|||||||
async.parallel([
|
async.parallel([
|
||||||
async.apply(updateRecentTopic, tid),
|
async.apply(updateRecentTopic, tid),
|
||||||
async.apply(updateRecentTopic, postData.tid),
|
async.apply(updateRecentTopic, postData.tid),
|
||||||
], next);
|
], function (err) {
|
||||||
|
next(err);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
], function (err) {
|
function (next) {
|
||||||
if (err) {
|
plugins.fireHook('action:post.move', { post: postData, tid: tid });
|
||||||
return callback(err);
|
next();
|
||||||
}
|
},
|
||||||
plugins.fireHook('action:post.move', { post: postData, tid: tid });
|
], callback);
|
||||||
callback();
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function updateCategoryPostCount(oldTid, tid, callback) {
|
function updateCategoryPostCount(oldTid, tid, callback) {
|
||||||
Topics.getTopicsFields([oldTid, tid], ['cid'], function (err, topicData) {
|
async.waterfall([
|
||||||
if (err) {
|
function (next) {
|
||||||
return callback(err);
|
Topics.getTopicsFields([oldTid, tid], ['cid'], next);
|
||||||
}
|
},
|
||||||
if (!topicData[0].cid || !topicData[1].cid) {
|
function (topicData, next) {
|
||||||
return callback();
|
if (!topicData[0].cid || !topicData[1].cid) {
|
||||||
}
|
return callback();
|
||||||
if (parseInt(topicData[0].cid, 10) === parseInt(topicData[1].cid, 10)) {
|
}
|
||||||
return callback();
|
if (parseInt(topicData[0].cid, 10) === parseInt(topicData[1].cid, 10)) {
|
||||||
}
|
return callback();
|
||||||
async.parallel([
|
}
|
||||||
async.apply(db.incrObjectFieldBy, 'category:' + topicData[0].cid, 'post_count', -1),
|
async.parallel([
|
||||||
async.apply(db.incrObjectFieldBy, 'category:' + topicData[1].cid, 'post_count', 1),
|
async.apply(db.incrObjectFieldBy, 'category:' + topicData[0].cid, 'post_count', -1),
|
||||||
], callback);
|
async.apply(db.incrObjectFieldBy, 'category:' + topicData[1].cid, 'post_count', 1),
|
||||||
});
|
], next);
|
||||||
|
},
|
||||||
|
], callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateRecentTopic(tid, callback) {
|
function updateRecentTopic(tid, callback) {
|
||||||
|
|||||||
@@ -9,33 +9,35 @@ var search = require('../search');
|
|||||||
|
|
||||||
module.exports = function (Topics) {
|
module.exports = function (Topics) {
|
||||||
Topics.getSuggestedTopics = function (tid, uid, start, stop, callback) {
|
Topics.getSuggestedTopics = function (tid, uid, start, stop, callback) {
|
||||||
async.parallel({
|
async.waterfall([
|
||||||
tagTids: function (next) {
|
function (next) {
|
||||||
getTidsWithSameTags(tid, next);
|
async.parallel({
|
||||||
|
tagTids: function (next) {
|
||||||
|
getTidsWithSameTags(tid, next);
|
||||||
|
},
|
||||||
|
searchTids: function (next) {
|
||||||
|
getSearchTids(tid, next);
|
||||||
|
},
|
||||||
|
categoryTids: function (next) {
|
||||||
|
getCategoryTids(tid, next);
|
||||||
|
},
|
||||||
|
}, next);
|
||||||
},
|
},
|
||||||
searchTids: function (next) {
|
function (results, next) {
|
||||||
getSearchTids(tid, next);
|
var tids = results.tagTids.concat(results.searchTids).concat(results.categoryTids);
|
||||||
},
|
tids = tids.filter(function (_tid, index, array) {
|
||||||
categoryTids: function (next) {
|
return parseInt(_tid, 10) !== parseInt(tid, 10) && array.indexOf(_tid) === index;
|
||||||
getCategoryTids(tid, next);
|
});
|
||||||
},
|
|
||||||
}, function (err, results) {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
var tids = results.tagTids.concat(results.searchTids).concat(results.categoryTids);
|
|
||||||
tids = tids.filter(function (_tid, index, array) {
|
|
||||||
return parseInt(_tid, 10) !== parseInt(tid, 10) && array.indexOf(_tid) === index;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (stop === -1) {
|
if (stop === -1) {
|
||||||
tids = tids.slice(start);
|
tids = tids.slice(start);
|
||||||
} else {
|
} else {
|
||||||
tids = tids.slice(start, stop + 1);
|
tids = tids.slice(start, stop + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Topics.getTopics(tids, uid, callback);
|
Topics.getTopics(tids, uid, next);
|
||||||
});
|
},
|
||||||
|
], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
function getTidsWithSameTags(tid, callback) {
|
function getTidsWithSameTags(tid, callback) {
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ module.exports = function (Topics) {
|
|||||||
var topicTools = {};
|
var topicTools = {};
|
||||||
Topics.tools = topicTools;
|
Topics.tools = topicTools;
|
||||||
|
|
||||||
|
|
||||||
topicTools.delete = function (tid, uid, callback) {
|
topicTools.delete = function (tid, uid, callback) {
|
||||||
toggleDelete(tid, uid, true, callback);
|
toggleDelete(tid, uid, true, callback);
|
||||||
};
|
};
|
||||||
@@ -246,6 +245,7 @@ module.exports = function (Topics) {
|
|||||||
|
|
||||||
topicTools.move = function (tid, cid, uid, callback) {
|
topicTools.move = function (tid, cid, uid, callback) {
|
||||||
var topic;
|
var topic;
|
||||||
|
var oldCid;
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
function (next) {
|
function (next) {
|
||||||
Topics.exists(tid, next);
|
Topics.exists(tid, next);
|
||||||
@@ -276,41 +276,41 @@ module.exports = function (Topics) {
|
|||||||
topic.postcount = topic.postcount || 0;
|
topic.postcount = topic.postcount || 0;
|
||||||
db.sortedSetAdd('cid:' + cid + ':tids:posts', topic.postcount, tid, next);
|
db.sortedSetAdd('cid:' + cid + ':tids:posts', topic.postcount, tid, next);
|
||||||
},
|
},
|
||||||
], next);
|
], function (err) {
|
||||||
|
next(err);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
], function (err) {
|
function (next) {
|
||||||
if (err) {
|
oldCid = topic.cid;
|
||||||
return callback(err);
|
categories.moveRecentReplies(tid, oldCid, cid);
|
||||||
}
|
|
||||||
var oldCid = topic.cid;
|
|
||||||
categories.moveRecentReplies(tid, oldCid, cid);
|
|
||||||
|
|
||||||
async.parallel([
|
async.parallel([
|
||||||
function (next) {
|
function (next) {
|
||||||
categories.incrementCategoryFieldBy(oldCid, 'topic_count', -1, next);
|
categories.incrementCategoryFieldBy(oldCid, 'topic_count', -1, next);
|
||||||
},
|
},
|
||||||
function (next) {
|
function (next) {
|
||||||
categories.incrementCategoryFieldBy(cid, 'topic_count', 1, next);
|
categories.incrementCategoryFieldBy(cid, 'topic_count', 1, next);
|
||||||
},
|
},
|
||||||
function (next) {
|
function (next) {
|
||||||
Topics.setTopicFields(tid, {
|
Topics.setTopicFields(tid, {
|
||||||
cid: cid,
|
cid: cid,
|
||||||
oldCid: oldCid,
|
oldCid: oldCid,
|
||||||
}, next);
|
}, next);
|
||||||
},
|
},
|
||||||
], function (err) {
|
], function (err) {
|
||||||
if (err) {
|
next(err);
|
||||||
return callback(err);
|
});
|
||||||
}
|
},
|
||||||
|
function (next) {
|
||||||
plugins.fireHook('action:topic.move', {
|
plugins.fireHook('action:topic.move', {
|
||||||
tid: tid,
|
tid: tid,
|
||||||
fromCid: oldCid,
|
fromCid: oldCid,
|
||||||
toCid: cid,
|
toCid: cid,
|
||||||
uid: uid,
|
uid: uid,
|
||||||
});
|
});
|
||||||
callback();
|
next();
|
||||||
});
|
},
|
||||||
});
|
], callback);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -326,30 +326,31 @@ module.exports = function (Topics) {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
async.parallel({
|
async.waterfall([
|
||||||
recentScores: function (next) {
|
function (next) {
|
||||||
db.sortedSetScores('topics:recent', tids, next);
|
async.parallel({
|
||||||
|
recentScores: function (next) {
|
||||||
|
db.sortedSetScores('topics:recent', tids, next);
|
||||||
|
},
|
||||||
|
userScores: function (next) {
|
||||||
|
db.sortedSetScores('uid:' + uid + ':tids_read', tids, next);
|
||||||
|
},
|
||||||
|
tids_unread: function (next) {
|
||||||
|
db.sortedSetScores('uid:' + uid + ':tids_unread', tids, next);
|
||||||
|
},
|
||||||
|
}, next);
|
||||||
},
|
},
|
||||||
userScores: function (next) {
|
function (results, next) {
|
||||||
db.sortedSetScores('uid:' + uid + ':tids_read', tids, next);
|
var cutoff = Topics.unreadCutoff();
|
||||||
},
|
var result = tids.map(function (tid, index) {
|
||||||
tids_unread: function (next) {
|
return !results.tids_unread[index] &&
|
||||||
db.sortedSetScores('uid:' + uid + ':tids_unread', tids, next);
|
(results.recentScores[index] < cutoff ||
|
||||||
},
|
!!(results.userScores[index] && results.userScores[index] >= results.recentScores[index]));
|
||||||
}, function (err, results) {
|
});
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
var cutoff = Topics.unreadCutoff();
|
next(null, result);
|
||||||
var result = tids.map(function (tid, index) {
|
},
|
||||||
return !results.tids_unread[index] &&
|
], callback);
|
||||||
(results.recentScores[index] < cutoff ||
|
|
||||||
!!(results.userScores[index] && results.userScores[index] >= results.recentScores[index]));
|
|
||||||
});
|
|
||||||
|
|
||||||
callback(null, result);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Topics.hasReadTopic = function (tid, uid, callback) {
|
Topics.hasReadTopic = function (tid, uid, callback) {
|
||||||
|
|||||||
@@ -11,23 +11,24 @@ module.exports = function (User) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
User.getWatchedCategories = function (uid, callback) {
|
User.getWatchedCategories = function (uid, callback) {
|
||||||
async.parallel({
|
async.waterfall([
|
||||||
ignored: function (next) {
|
function (next) {
|
||||||
User.getIgnoredCategories(uid, next);
|
async.parallel({
|
||||||
|
ignored: function (next) {
|
||||||
|
User.getIgnoredCategories(uid, next);
|
||||||
|
},
|
||||||
|
all: function (next) {
|
||||||
|
db.getSortedSetRange('categories:cid', 0, -1, next);
|
||||||
|
},
|
||||||
|
}, next);
|
||||||
},
|
},
|
||||||
all: function (next) {
|
function (results, next) {
|
||||||
db.getSortedSetRange('categories:cid', 0, -1, next);
|
var watched = results.all.filter(function (cid) {
|
||||||
|
return cid && results.ignored.indexOf(cid) === -1;
|
||||||
|
});
|
||||||
|
next(null, watched);
|
||||||
},
|
},
|
||||||
}, function (err, results) {
|
], callback);
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
var watched = results.all.filter(function (cid) {
|
|
||||||
return cid && results.ignored.indexOf(cid) === -1;
|
|
||||||
});
|
|
||||||
callback(null, watched);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
User.ignoreCategory = function (uid, cid, callback) {
|
User.ignoreCategory = function (uid, cid, callback) {
|
||||||
|
|||||||
@@ -15,137 +15,129 @@ module.exports = function (User) {
|
|||||||
if (data.email !== undefined) {
|
if (data.email !== undefined) {
|
||||||
data.email = validator.escape(String(data.email).trim());
|
data.email = validator.escape(String(data.email).trim());
|
||||||
}
|
}
|
||||||
|
var timestamp = data.timestamp || Date.now();
|
||||||
|
var userData;
|
||||||
|
var userNameChanged = false;
|
||||||
|
|
||||||
User.isDataValid(data, function (err) {
|
async.waterfall([
|
||||||
if (err) {
|
function (next) {
|
||||||
return callback(err);
|
User.isDataValid(data, next);
|
||||||
}
|
},
|
||||||
var timestamp = data.timestamp || Date.now();
|
function (next) {
|
||||||
|
userData = {
|
||||||
|
username: data.username,
|
||||||
|
userslug: data.userslug,
|
||||||
|
email: data.email || '',
|
||||||
|
joindate: timestamp,
|
||||||
|
lastonline: timestamp,
|
||||||
|
picture: data.picture || '',
|
||||||
|
fullname: data.fullname || '',
|
||||||
|
location: data.location || '',
|
||||||
|
birthday: data.birthday || '',
|
||||||
|
website: '',
|
||||||
|
signature: '',
|
||||||
|
uploadedpicture: '',
|
||||||
|
profileviews: 0,
|
||||||
|
reputation: 0,
|
||||||
|
postcount: 0,
|
||||||
|
topiccount: 0,
|
||||||
|
lastposttime: 0,
|
||||||
|
banned: 0,
|
||||||
|
status: 'online',
|
||||||
|
};
|
||||||
|
|
||||||
var userData = {
|
User.uniqueUsername(userData, next);
|
||||||
username: data.username,
|
},
|
||||||
userslug: data.userslug,
|
function (renamedUsername, next) {
|
||||||
email: data.email || '',
|
userNameChanged = !!renamedUsername;
|
||||||
joindate: timestamp,
|
|
||||||
lastonline: timestamp,
|
|
||||||
picture: data.picture || '',
|
|
||||||
fullname: data.fullname || '',
|
|
||||||
location: data.location || '',
|
|
||||||
birthday: data.birthday || '',
|
|
||||||
website: '',
|
|
||||||
signature: '',
|
|
||||||
uploadedpicture: '',
|
|
||||||
profileviews: 0,
|
|
||||||
reputation: 0,
|
|
||||||
postcount: 0,
|
|
||||||
topiccount: 0,
|
|
||||||
lastposttime: 0,
|
|
||||||
banned: 0,
|
|
||||||
status: 'online',
|
|
||||||
};
|
|
||||||
|
|
||||||
async.parallel({
|
|
||||||
renamedUsername: function (next) {
|
|
||||||
User.uniqueUsername(userData, next);
|
|
||||||
},
|
|
||||||
userData: function (next) {
|
|
||||||
plugins.fireHook('filter:user.create', { user: userData, data: data }, next);
|
|
||||||
},
|
|
||||||
}, function (err, results) {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
var userNameChanged = !!results.renamedUsername;
|
|
||||||
|
|
||||||
if (userNameChanged) {
|
if (userNameChanged) {
|
||||||
userData.username = results.renamedUsername;
|
userData.username = renamedUsername;
|
||||||
userData.userslug = utils.slugify(results.renamedUsername);
|
userData.userslug = utils.slugify(renamedUsername);
|
||||||
}
|
}
|
||||||
|
plugins.fireHook('filter:user.create', { user: userData, data: data }, next);
|
||||||
async.waterfall([
|
},
|
||||||
|
function (results, next) {
|
||||||
|
userData = results.user;
|
||||||
|
db.incrObjectField('global', 'nextUid', next);
|
||||||
|
},
|
||||||
|
function (uid, next) {
|
||||||
|
userData.uid = uid;
|
||||||
|
db.setObject('user:' + uid, userData, next);
|
||||||
|
},
|
||||||
|
function (next) {
|
||||||
|
async.parallel([
|
||||||
function (next) {
|
function (next) {
|
||||||
db.incrObjectField('global', 'nextUid', next);
|
db.incrObjectField('global', 'userCount', next);
|
||||||
},
|
|
||||||
function (uid, next) {
|
|
||||||
userData.uid = uid;
|
|
||||||
db.setObject('user:' + uid, userData, next);
|
|
||||||
},
|
},
|
||||||
function (next) {
|
function (next) {
|
||||||
async.parallel([
|
db.sortedSetAdd('username:uid', userData.uid, userData.username, next);
|
||||||
function (next) {
|
|
||||||
db.incrObjectField('global', 'userCount', next);
|
|
||||||
},
|
|
||||||
function (next) {
|
|
||||||
db.sortedSetAdd('username:uid', userData.uid, userData.username, next);
|
|
||||||
},
|
|
||||||
function (next) {
|
|
||||||
db.sortedSetAdd('username:sorted', 0, userData.username.toLowerCase() + ':' + userData.uid, next);
|
|
||||||
},
|
|
||||||
function (next) {
|
|
||||||
db.sortedSetAdd('userslug:uid', userData.uid, userData.userslug, next);
|
|
||||||
},
|
|
||||||
function (next) {
|
|
||||||
var sets = ['users:joindate', 'users:online'];
|
|
||||||
if (parseInt(userData.uid, 10) !== 1) {
|
|
||||||
sets.push('users:notvalidated');
|
|
||||||
}
|
|
||||||
db.sortedSetsAdd(sets, timestamp, userData.uid, next);
|
|
||||||
},
|
|
||||||
function (next) {
|
|
||||||
db.sortedSetsAdd(['users:postcount', 'users:reputation'], 0, userData.uid, next);
|
|
||||||
},
|
|
||||||
function (next) {
|
|
||||||
groups.join('registered-users', userData.uid, next);
|
|
||||||
},
|
|
||||||
function (next) {
|
|
||||||
User.notifications.sendWelcomeNotification(userData.uid, next);
|
|
||||||
},
|
|
||||||
function (next) {
|
|
||||||
if (userData.email) {
|
|
||||||
async.parallel([
|
|
||||||
async.apply(db.sortedSetAdd, 'email:uid', userData.uid, userData.email.toLowerCase()),
|
|
||||||
async.apply(db.sortedSetAdd, 'email:sorted', 0, userData.email.toLowerCase() + ':' + userData.uid),
|
|
||||||
], next);
|
|
||||||
|
|
||||||
if (parseInt(userData.uid, 10) !== 1 && parseInt(meta.config.requireEmailConfirmation, 10) === 1) {
|
|
||||||
User.email.sendValidationEmail(userData.uid, userData.email);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
function (next) {
|
|
||||||
if (!data.password) {
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
|
|
||||||
User.hashPassword(data.password, function (err, hash) {
|
|
||||||
if (err) {
|
|
||||||
return next(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
async.parallel([
|
|
||||||
async.apply(User.setUserField, userData.uid, 'password', hash),
|
|
||||||
async.apply(User.reset.updateExpiry, userData.uid),
|
|
||||||
], next);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
function (next) {
|
|
||||||
User.updateDigestSetting(userData.uid, meta.config.dailyDigestFreq, next);
|
|
||||||
},
|
|
||||||
], next);
|
|
||||||
},
|
},
|
||||||
function (results, next) {
|
function (next) {
|
||||||
if (userNameChanged) {
|
db.sortedSetAdd('username:sorted', 0, userData.username.toLowerCase() + ':' + userData.uid, next);
|
||||||
User.notifications.sendNameChangeNotification(userData.uid, userData.username);
|
},
|
||||||
|
function (next) {
|
||||||
|
db.sortedSetAdd('userslug:uid', userData.uid, userData.userslug, next);
|
||||||
|
},
|
||||||
|
function (next) {
|
||||||
|
var sets = ['users:joindate', 'users:online'];
|
||||||
|
if (parseInt(userData.uid, 10) !== 1) {
|
||||||
|
sets.push('users:notvalidated');
|
||||||
}
|
}
|
||||||
plugins.fireHook('action:user.create', { user: userData });
|
db.sortedSetsAdd(sets, timestamp, userData.uid, next);
|
||||||
next(null, userData.uid);
|
|
||||||
},
|
},
|
||||||
], callback);
|
function (next) {
|
||||||
});
|
db.sortedSetsAdd(['users:postcount', 'users:reputation'], 0, userData.uid, next);
|
||||||
});
|
},
|
||||||
|
function (next) {
|
||||||
|
groups.join('registered-users', userData.uid, next);
|
||||||
|
},
|
||||||
|
function (next) {
|
||||||
|
User.notifications.sendWelcomeNotification(userData.uid, next);
|
||||||
|
},
|
||||||
|
function (next) {
|
||||||
|
if (userData.email) {
|
||||||
|
async.parallel([
|
||||||
|
async.apply(db.sortedSetAdd, 'email:uid', userData.uid, userData.email.toLowerCase()),
|
||||||
|
async.apply(db.sortedSetAdd, 'email:sorted', 0, userData.email.toLowerCase() + ':' + userData.uid),
|
||||||
|
], next);
|
||||||
|
|
||||||
|
if (parseInt(userData.uid, 10) !== 1 && parseInt(meta.config.requireEmailConfirmation, 10) === 1) {
|
||||||
|
User.email.sendValidationEmail(userData.uid, userData.email);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
function (next) {
|
||||||
|
if (!data.password) {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
User.hashPassword(data.password, function (err, hash) {
|
||||||
|
if (err) {
|
||||||
|
return next(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
async.parallel([
|
||||||
|
async.apply(User.setUserField, userData.uid, 'password', hash),
|
||||||
|
async.apply(User.reset.updateExpiry, userData.uid),
|
||||||
|
], next);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function (next) {
|
||||||
|
User.updateDigestSetting(userData.uid, meta.config.dailyDigestFreq, next);
|
||||||
|
},
|
||||||
|
], next);
|
||||||
|
},
|
||||||
|
function (results, next) {
|
||||||
|
if (userNameChanged) {
|
||||||
|
User.notifications.sendNameChangeNotification(userData.uid, userData.username);
|
||||||
|
}
|
||||||
|
plugins.fireHook('action:user.create', { user: userData });
|
||||||
|
next(null, userData.uid);
|
||||||
|
},
|
||||||
|
], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
User.isDataValid = function (userData, callback) {
|
User.isDataValid = function (userData, callback) {
|
||||||
@@ -201,26 +193,23 @@ module.exports = function (User) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
User.uniqueUsername = function (userData, callback) {
|
User.uniqueUsername = function (userData, callback) {
|
||||||
meta.userOrGroupExists(userData.userslug, function (err, exists) {
|
var numTries = 0;
|
||||||
if (err || !exists) {
|
function go(username) {
|
||||||
return callback(err);
|
async.waterfall([
|
||||||
}
|
function (next) {
|
||||||
|
meta.userOrGroupExists(username, next);
|
||||||
var num = 0;
|
},
|
||||||
|
function (exists) {
|
||||||
function go() {
|
if (!exists) {
|
||||||
var username = userData.username + ' ' + num.toString(32);
|
return callback(null, numTries ? username : null);
|
||||||
meta.userOrGroupExists(username, function (err, exists) {
|
|
||||||
if (err || !exists) {
|
|
||||||
return callback(err, username);
|
|
||||||
}
|
}
|
||||||
|
username = userData.username + ' ' + numTries.toString(32);
|
||||||
|
numTries += 1;
|
||||||
|
go(username);
|
||||||
|
},
|
||||||
|
], callback);
|
||||||
|
}
|
||||||
|
|
||||||
num += 1;
|
go(userData.userslug);
|
||||||
go();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
go();
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -191,7 +191,6 @@ UserNotifications.getUnreadCount = function (uid, callback) {
|
|||||||
return callback(null, 0);
|
return callback(null, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
function (next) {
|
function (next) {
|
||||||
db.getSortedSetRevRange('uid:' + uid + ':notifications:unread', 0, 99, next);
|
db.getSortedSetRevRange('uid:' + uid + ':notifications:unread', 0, 99, next);
|
||||||
|
|||||||
@@ -17,22 +17,21 @@ module.exports = function (User) {
|
|||||||
|
|
||||||
User.isPasswordCorrect = function (uid, password, callback) {
|
User.isPasswordCorrect = function (uid, password, callback) {
|
||||||
password = password || '';
|
password = password || '';
|
||||||
|
var hashedPassword;
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
function (next) {
|
function (next) {
|
||||||
db.getObjectField('user:' + uid, 'password', next);
|
db.getObjectField('user:' + uid, 'password', next);
|
||||||
},
|
},
|
||||||
function (hashedPassword, next) {
|
function (_hashedPassword, next) {
|
||||||
|
hashedPassword = _hashedPassword;
|
||||||
if (!hashedPassword) {
|
if (!hashedPassword) {
|
||||||
return callback(null, true);
|
return callback(null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
User.isPasswordValid(password, function (err) {
|
User.isPasswordValid(password, next);
|
||||||
if (err) {
|
},
|
||||||
return next(err);
|
function (next) {
|
||||||
}
|
Password.compare(password, hashedPassword, next);
|
||||||
|
|
||||||
Password.compare(password, hashedPassword, next);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
], callback);
|
], callback);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -183,14 +183,15 @@ module.exports = function (User) {
|
|||||||
if (!convertToPNG) {
|
if (!convertToPNG) {
|
||||||
return setImmediate(callback, null, path);
|
return setImmediate(callback, null, path);
|
||||||
}
|
}
|
||||||
|
async.waterfall([
|
||||||
image.normalise(path, extension, function (err, newPath) {
|
function (next) {
|
||||||
if (err) {
|
image.normalise(path, extension, next);
|
||||||
return callback(err);
|
},
|
||||||
}
|
function (newPath, next) {
|
||||||
file.delete(path);
|
file.delete(path);
|
||||||
callback(null, newPath);
|
next(null, newPath);
|
||||||
});
|
},
|
||||||
|
], callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
function uploadProfileOrCover(filename, image, callback) {
|
function uploadProfileOrCover(filename, image, callback) {
|
||||||
|
|||||||
@@ -10,55 +10,55 @@ module.exports = function (User) {
|
|||||||
if (parseInt(uid, 10) === 0) {
|
if (parseInt(uid, 10) === 0) {
|
||||||
return callback();
|
return callback();
|
||||||
}
|
}
|
||||||
|
async.waterfall([
|
||||||
async.parallel({
|
function (next) {
|
||||||
userData: function (next) {
|
async.parallel({
|
||||||
User.getUserFields(uid, ['banned', 'lastposttime', 'joindate', 'email', 'email:confirmed', 'reputation'], next);
|
userData: function (next) {
|
||||||
|
User.getUserFields(uid, ['banned', 'lastposttime', 'joindate', 'email', 'email:confirmed', 'reputation'], next);
|
||||||
|
},
|
||||||
|
exists: function (next) {
|
||||||
|
db.exists('user:' + uid, next);
|
||||||
|
},
|
||||||
|
isAdminOrMod: function (next) {
|
||||||
|
privileges.categories.isAdminOrMod(cid, uid, next);
|
||||||
|
},
|
||||||
|
}, next);
|
||||||
},
|
},
|
||||||
exists: function (next) {
|
function (results, next) {
|
||||||
db.exists('user:' + uid, next);
|
if (!results.exists) {
|
||||||
|
return next(new Error('[[error:no-user]]'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (results.isAdminOrMod) {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
var userData = results.userData;
|
||||||
|
|
||||||
|
if (parseInt(userData.banned, 10) === 1) {
|
||||||
|
return next(new Error('[[error:user-banned]]'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parseInt(meta.config.requireEmailConfirmation, 10) === 1 && parseInt(userData['email:confirmed'], 10) !== 1) {
|
||||||
|
return next(new Error('[[error:email-not-confirmed]]'));
|
||||||
|
}
|
||||||
|
|
||||||
|
var now = Date.now();
|
||||||
|
if (now - parseInt(userData.joindate, 10) < parseInt(meta.config.initialPostDelay, 10) * 1000) {
|
||||||
|
return next(new Error('[[error:user-too-new, ' + meta.config.initialPostDelay + ']]'));
|
||||||
|
}
|
||||||
|
|
||||||
|
var lastposttime = userData.lastposttime || 0;
|
||||||
|
|
||||||
|
if (parseInt(meta.config.newbiePostDelay, 10) > 0 && parseInt(meta.config.newbiePostDelayThreshold, 10) > parseInt(userData.reputation, 10) && now - parseInt(lastposttime, 10) < parseInt(meta.config.newbiePostDelay, 10) * 1000) {
|
||||||
|
return next(new Error('[[error:too-many-posts-newbie, ' + meta.config.newbiePostDelay + ', ' + meta.config.newbiePostDelayThreshold + ']]'));
|
||||||
|
} else if (now - parseInt(lastposttime, 10) < parseInt(meta.config.postDelay, 10) * 1000) {
|
||||||
|
return next(new Error('[[error:too-many-posts, ' + meta.config.postDelay + ']]'));
|
||||||
|
}
|
||||||
|
|
||||||
|
next();
|
||||||
},
|
},
|
||||||
isAdminOrMod: function (next) {
|
], callback);
|
||||||
privileges.categories.isAdminOrMod(cid, uid, next);
|
|
||||||
},
|
|
||||||
}, function (err, results) {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!results.exists) {
|
|
||||||
return callback(new Error('[[error:no-user]]'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (results.isAdminOrMod) {
|
|
||||||
return callback();
|
|
||||||
}
|
|
||||||
|
|
||||||
var userData = results.userData;
|
|
||||||
|
|
||||||
if (parseInt(userData.banned, 10) === 1) {
|
|
||||||
return callback(new Error('[[error:user-banned]]'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parseInt(meta.config.requireEmailConfirmation, 10) === 1 && parseInt(userData['email:confirmed'], 10) !== 1) {
|
|
||||||
return callback(new Error('[[error:email-not-confirmed]]'));
|
|
||||||
}
|
|
||||||
|
|
||||||
var now = Date.now();
|
|
||||||
if (now - parseInt(userData.joindate, 10) < parseInt(meta.config.initialPostDelay, 10) * 1000) {
|
|
||||||
return callback(new Error('[[error:user-too-new, ' + meta.config.initialPostDelay + ']]'));
|
|
||||||
}
|
|
||||||
|
|
||||||
var lastposttime = userData.lastposttime || 0;
|
|
||||||
|
|
||||||
if (parseInt(meta.config.newbiePostDelay, 10) > 0 && parseInt(meta.config.newbiePostDelayThreshold, 10) > parseInt(userData.reputation, 10) && now - parseInt(lastposttime, 10) < parseInt(meta.config.newbiePostDelay, 10) * 1000) {
|
|
||||||
return callback(new Error('[[error:too-many-posts-newbie, ' + meta.config.newbiePostDelay + ', ' + meta.config.newbiePostDelayThreshold + ']]'));
|
|
||||||
} else if (now - parseInt(lastposttime, 10) < parseInt(meta.config.postDelay, 10) * 1000) {
|
|
||||||
return callback(new Error('[[error:too-many-posts, ' + meta.config.postDelay + ']]'));
|
|
||||||
}
|
|
||||||
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
User.onNewPostMade = function (postData, callback) {
|
User.onNewPostMade = function (postData, callback) {
|
||||||
@@ -84,15 +84,17 @@ module.exports = function (User) {
|
|||||||
|
|
||||||
User.incrementUserPostCountBy = function (uid, value, callback) {
|
User.incrementUserPostCountBy = function (uid, value, callback) {
|
||||||
callback = callback || function () {};
|
callback = callback || function () {};
|
||||||
User.incrementUserFieldBy(uid, 'postcount', value, function (err, newpostcount) {
|
async.waterfall([
|
||||||
if (err) {
|
function (next) {
|
||||||
return callback(err);
|
User.incrementUserFieldBy(uid, 'postcount', value, next);
|
||||||
}
|
},
|
||||||
if (!parseInt(uid, 10)) {
|
function (newpostcount, next) {
|
||||||
return callback();
|
if (!parseInt(uid, 10)) {
|
||||||
}
|
return next();
|
||||||
db.sortedSetAdd('users:postcount', newpostcount, uid, callback);
|
}
|
||||||
});
|
db.sortedSetAdd('users:postcount', newpostcount, uid, next);
|
||||||
|
},
|
||||||
|
], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
User.getPostIds = function (uid, start, stop, callback) {
|
User.getPostIds = function (uid, start, stop, callback) {
|
||||||
|
|||||||
@@ -63,9 +63,9 @@ module.exports.listen = function (callback) {
|
|||||||
helpers.register();
|
helpers.register();
|
||||||
|
|
||||||
logger.init(app);
|
logger.init(app);
|
||||||
next();
|
|
||||||
|
initializeNodeBB(next);
|
||||||
},
|
},
|
||||||
initializeNodeBB,
|
|
||||||
function (next) {
|
function (next) {
|
||||||
winston.info('NodeBB Ready');
|
winston.info('NodeBB Ready');
|
||||||
|
|
||||||
|
|||||||
26
test/user.js
26
test/user.js
@@ -69,6 +69,31 @@ describe('User', function () {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should error with invalid password', function (done) {
|
||||||
|
User.create({ username: 'test', password: '1' }, function (err) {
|
||||||
|
assert.equal(err.message, '[[user:change_password_error_length]]');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should error with invalid password', function (done) {
|
||||||
|
User.create({ username: 'test', password: {} }, function (err) {
|
||||||
|
assert.equal(err.message, '[[error:invalid-password]]');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should error with a too long password', function (done) {
|
||||||
|
var toolong = '';
|
||||||
|
for (var i = 0; i < 5000; i++) {
|
||||||
|
toolong += 'a';
|
||||||
|
}
|
||||||
|
User.create({ username: 'test', password: toolong }, function (err) {
|
||||||
|
assert.equal(err.message, '[[error:password-too-long]]');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('.uniqueUsername()', function () {
|
describe('.uniqueUsername()', function () {
|
||||||
@@ -77,7 +102,6 @@ describe('User', function () {
|
|||||||
for (var i = 0; i < 10; i += 1) {
|
for (var i = 0; i < 10; i += 1) {
|
||||||
users.push({
|
users.push({
|
||||||
username: 'Jane Doe',
|
username: 'Jane Doe',
|
||||||
password: 'abcdefghi',
|
|
||||||
email: 'jane.doe' + i + '@example.com',
|
email: 'jane.doe' + i + '@example.com',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user