groups refactor

v1.18.x
barisusakli 8 years ago
parent 2ccf60a6ec
commit 1bee91fa22

@ -6,215 +6,197 @@ var validator = require('validator');
var user = require('./user');
var db = require('./database');
var plugins = require('./plugins');
var posts = require('./posts');
var privileges = require('./privileges');
var utils = require('../public/src/utils');
(function (Groups) {
require('./groups/create')(Groups);
require('./groups/delete')(Groups);
require('./groups/update')(Groups);
require('./groups/membership')(Groups);
require('./groups/ownership')(Groups);
require('./groups/search')(Groups);
require('./groups/cover')(Groups);
var ephemeralGroups = ['guests'];
var Groups = module.exports;
require('./groups/data')(Groups);
require('./groups/create')(Groups);
require('./groups/delete')(Groups);
require('./groups/update')(Groups);
require('./groups/membership')(Groups);
require('./groups/ownership')(Groups);
require('./groups/search')(Groups);
require('./groups/cover')(Groups);
require('./groups/posts')(Groups);
require('./groups/user')(Groups);
Groups.ephemeralGroups = ['guests'];
Groups.getEphemeralGroup = function (groupName) {
return {
name: groupName,
slug: utils.slugify(groupName),
description: '',
deleted: '0',
hidden: '0',
system: '1',
};
};
var internals = {
getEphemeralGroup: function (groupName) {
return {
name: groupName,
slug: utils.slugify(groupName),
description: '',
deleted: '0',
hidden: '0',
system: '1',
};
},
removeEphemeralGroups: function (groups) {
for (var x = groups.length; x >= 0; x -= 1) {
if (ephemeralGroups.indexOf(groups[x]) !== -1) {
groups.splice(x, 1);
}
Groups.removeEphemeralGroups = function (groups) {
for (var x = groups.length; x >= 0; x -= 1) {
if (Groups.ephemeralGroups.indexOf(groups[x]) !== -1) {
groups.splice(x, 1);
}
}
return groups;
};
var isPrivilegeGroupRegex = /^cid:\d+:privileges:[\w:]+$/;
Groups.isPrivilegeGroup = function (groupName) {
return isPrivilegeGroupRegex.test(groupName);
};
Groups.getGroupsFromSet = function (set, uid, start, stop, callback) {
async.waterfall([
function (next) {
if (set === 'groups:visible:name') {
db.getSortedSetRangeByLex(set, '-', '+', start, stop - start + 1, next);
} else {
db.getSortedSetRevRange(set, start, stop, next);
}
return groups;
},
};
Groups.internals = internals;
var isPrivilegeGroupRegex = /^cid:\d+:privileges:[\w:]+$/;
Groups.isPrivilegeGroup = function (groupName) {
return isPrivilegeGroupRegex.test(groupName);
};
Groups.getEphemeralGroups = function () {
return ephemeralGroups;
};
Groups.getGroupsFromSet = function (set, uid, start, stop, callback) {
async.waterfall([
function (next) {
if (set === 'groups:visible:name') {
db.getSortedSetRangeByLex(set, '-', '+', start, stop - start + 1, next);
} else {
db.getSortedSetRevRange(set, start, stop, next);
}
},
function (groupNames, next) {
if (set === 'groups:visible:name') {
groupNames = groupNames.map(function (name) {
return name.split(':')[1];
});
}
Groups.getGroupsAndMembers(groupNames, next);
},
], callback);
};
Groups.getGroups = function (set, start, stop, callback) {
db.getSortedSetRevRange(set, start, stop, callback);
};
Groups.getGroupsAndMembers = function (groupNames, callback) {
async.parallel({
groups: function (next) {
Groups.getGroupsData(groupNames, next);
},
members: function (next) {
Groups.getMemberUsers(groupNames, 0, 3, next);
},
}, function (err, data) {
if (err) {
return callback(err);
function (groupNames, next) {
if (set === 'groups:visible:name') {
groupNames = groupNames.map(function (name) {
return name.split(':')[1];
});
}
Groups.getGroupsAndMembers(groupNames, next);
},
], callback);
};
Groups.getGroups = function (set, start, stop, callback) {
db.getSortedSetRevRange(set, start, stop, callback);
};
Groups.getGroupsAndMembers = function (groupNames, callback) {
async.waterfall([
function (next) {
async.parallel({
groups: function (next) {
Groups.getGroupsData(groupNames, next);
},
members: function (next) {
Groups.getMemberUsers(groupNames, 0, 3, next);
},
}, next);
},
function (data, next) {
data.groups.forEach(function (group, index) {
if (!group) {
return;
if (group) {
group.members = data.members[index] || [];
group.truncated = group.memberCount > data.members.length;
}
group.members = data.members[index] || [];
group.truncated = group.memberCount > data.members.length;
});
next(null, data.groups);
},
], callback);
};
Groups.get = function (groupName, options, callback) {
if (!groupName) {
return callback(new Error('[[error:invalid-group]]'));
}
var stop = -1;
var results;
async.waterfall([
function (next) {
async.parallel({
base: function (next) {
db.getObject('group:' + groupName, next);
},
members: function (next) {
if (options.truncateUserList) {
stop = (parseInt(options.userListCount, 10) || 4) - 1;
}
callback(null, data.groups);
});
};
Groups.get = function (groupName, options, callback) {
if (!groupName) {
return callback(new Error('[[error:invalid-group]]'));
}
var stop = -1;
async.parallel({
base: function (next) {
db.getObject('group:' + groupName, next);
},
members: function (next) {
if (options.truncateUserList) {
stop = (parseInt(options.userListCount, 10) || 4) - 1;
}
Groups.getOwnersAndMembers(groupName, options.uid, 0, stop, next);
},
pending: function (next) {
async.waterfall([
function (next) {
db.getSetMembers('group:' + groupName + ':pending', next);
},
function (uids, next) {
user.getUsersData(uids, next);
},
], next);
},
invited: function (next) {
async.waterfall([
function (next) {
db.getSetMembers('group:' + groupName + ':invited', next);
},
function (uids, next) {
user.getUsersData(uids, next);
},
], next);
},
isMember: async.apply(Groups.isMember, options.uid, groupName),
isPending: async.apply(Groups.isPending, options.uid, groupName),
isInvited: async.apply(Groups.isInvited, options.uid, groupName),
isOwner: async.apply(Groups.ownership.isOwner, options.uid, groupName),
}, function (err, results) {
if (err) {
return callback(err);
} else if (!results.base) {
Groups.getOwnersAndMembers(groupName, options.uid, 0, stop, next);
},
pending: function (next) {
Groups.getUsersFromSet('group:' + groupName + ':pending', next);
},
invited: function (next) {
Groups.getUsersFromSet('group:' + groupName + ':invited', next);
},
isMember: async.apply(Groups.isMember, options.uid, groupName),
isPending: async.apply(Groups.isPending, options.uid, groupName),
isInvited: async.apply(Groups.isInvited, options.uid, groupName),
isOwner: async.apply(Groups.ownership.isOwner, options.uid, groupName),
}, next);
},
function (_results, next) {
results = _results;
if (!results.base) {
return callback(new Error('[[error:no-group]]'));
}
results.base['cover:url'] = results.base['cover:url'] || require('./coverPhoto').getDefaultGroupCover(groupName);
results.base['cover:position'] = validator.escape(String(results.base['cover:position'] || '50% 50%'));
results.base.labelColor = validator.escape(String(results.base.labelColor || '#000000'));
results.base.icon = validator.escape(String(results.base.icon || ''));
plugins.fireHook('filter:parse.raw', results.base.description, function (err, descriptionParsed) {
if (err) {
return callback(err);
}
Groups.escapeGroupData(results.base);
results.base.descriptionParsed = descriptionParsed;
results.base.userTitleEnabled = results.base.userTitleEnabled ? !!parseInt(results.base.userTitleEnabled, 10) : true;
results.base.createtimeISO = utils.toISOString(results.base.createtime);
results.base.members = results.members;
results.base.membersNextStart = stop + 1;
results.base.pending = results.pending.filter(Boolean);
results.base.invited = results.invited.filter(Boolean);
results.base.deleted = !!parseInt(results.base.deleted, 10);
results.base.hidden = !!parseInt(results.base.hidden, 10);
results.base.system = !!parseInt(results.base.system, 10);
results.base.memberCount = parseInt(results.base.memberCount, 10);
results.base.private = (results.base.private === null || results.base.private === undefined) ? true : !!parseInt(results.base.private, 10);
results.base.disableJoinRequests = parseInt(results.base.disableJoinRequests, 10) === 1;
results.base.isMember = results.isMember;
results.base.isPending = results.isPending;
results.base.isInvited = results.isInvited;
results.base.isOwner = results.isOwner;
plugins.fireHook('filter:group.get', { group: results.base }, function (err, data) {
callback(err, data ? data.group : null);
});
});
});
};
Groups.getOwners = function (groupName, callback) {
db.getSetMembers('group:' + groupName + ':owners', callback);
};
Groups.getOwnersAndMembers = function (groupName, uid, start, stop, callback) {
async.parallel({
owners: function (next) {
async.waterfall([
function (next) {
db.getSetMembers('group:' + groupName + ':owners', next);
},
function (uids, next) {
user.getUsers(uids, uid, next);
},
], next);
},
members: function (next) {
user.getUsersFromSet('group:' + groupName + ':members', uid, start, stop, next);
},
}, function (err, results) {
if (err) {
return callback(err);
}
plugins.fireHook('filter:parse.raw', results.base.description, next);
},
function (descriptionParsed, next) {
var groupData = results.base;
Groups.escapeGroupData(groupData);
groupData.descriptionParsed = descriptionParsed;
groupData.userTitleEnabled = groupData.userTitleEnabled ? !!parseInt(groupData.userTitleEnabled, 10) : true;
groupData.createtimeISO = utils.toISOString(groupData.createtime);
groupData.members = results.members;
groupData.membersNextStart = stop + 1;
groupData.pending = results.pending.filter(Boolean);
groupData.invited = results.invited.filter(Boolean);
groupData.deleted = !!parseInt(groupData.deleted, 10);
groupData.hidden = !!parseInt(groupData.hidden, 10);
groupData.system = !!parseInt(groupData.system, 10);
groupData.memberCount = parseInt(groupData.memberCount, 10);
groupData.private = (groupData.private === null || groupData.private === undefined) ? true : !!parseInt(groupData.private, 10);
groupData.disableJoinRequests = parseInt(groupData.disableJoinRequests, 10) === 1;
groupData.isMember = results.isMember;
groupData.isPending = results.isPending;
groupData.isInvited = results.isInvited;
groupData.isOwner = results.isOwner;
groupData['cover:url'] = groupData['cover:url'] || require('./coverPhoto').getDefaultGroupCover(groupName);
groupData['cover:position'] = validator.escape(String(groupData['cover:position'] || '50% 50%'));
groupData.labelColor = validator.escape(String(groupData.labelColor || '#000000'));
groupData.icon = validator.escape(String(groupData.icon || ''));
plugins.fireHook('filter:group.get', { group: groupData }, next);
},
function (results, next) {
next(null, results.group);
},
], callback);
};
Groups.getOwners = function (groupName, callback) {
db.getSetMembers('group:' + groupName + ':owners', callback);
};
Groups.getOwnersAndMembers = function (groupName, uid, start, stop, callback) {
async.waterfall([
function (next) {
async.parallel({
owners: function (next) {
async.waterfall([
function (next) {
db.getSetMembers('group:' + groupName + ':owners', next);
},
function (uids, next) {
user.getUsers(uids, uid, next);
},
], next);
},
members: function (next) {
user.getUsersFromSet('group:' + groupName + ':members', uid, start, stop, next);
},
}, next);
},
function (results, next) {
var ownerUids = [];
results.owners.forEach(function (user) {
if (user) {
@ -228,229 +210,97 @@ var utils = require('../public/src/utils');
});
results.members = results.owners.concat(results.members);
callback(null, results.members);
});
};
Groups.escapeGroupData = function (group) {
if (group) {
group.nameEncoded = encodeURIComponent(group.name);
group.displayName = validator.escape(String(group.name));
group.description = validator.escape(String(group.description || ''));
group.userTitle = validator.escape(String(group.userTitle || '')) || group.displayName;
}
};
Groups.getByGroupslug = function (slug, options, callback) {
db.getObjectField('groupslug:groupname', slug, function (err, groupName) {
if (err) {
return callback(err);
} else if (!groupName) {
return callback(new Error('[[error:no-group]]'));
}
Groups.get(groupName, options, callback);
});
};
Groups.getGroupNameByGroupSlug = function (slug, callback) {
db.getObjectField('groupslug:groupname', slug, callback);
};
Groups.getGroupFields = function (groupName, fields, callback) {
Groups.getMultipleGroupFields([groupName], fields, function (err, groups) {
callback(err, groups ? groups[0] : null);
});
};
Groups.getMultipleGroupFields = function (groups, fields, callback) {
db.getObjectsFields(groups.map(function (group) {
return 'group:' + group;
}), fields, callback);
};
Groups.setGroupField = function (groupName, field, value, callback) {
db.setObjectField('group:' + groupName, field, value, function (err) {
if (err) {
return callback(err);
next(null, results.members);
},
], callback);
};
Groups.escapeGroupData = function (group) {
if (group) {
group.nameEncoded = encodeURIComponent(group.name);
group.displayName = validator.escape(String(group.name));
group.description = validator.escape(String(group.description || ''));
group.userTitle = validator.escape(String(group.userTitle || '')) || group.displayName;
}
};
Groups.getByGroupslug = function (slug, options, callback) {
async.waterfall([
function (next) {
db.getObjectField('groupslug:groupname', slug, next);
},
function (groupName, next) {
if (!groupName) {
return next(new Error('[[error:no-group]]'));
}
plugins.fireHook('action:group.set', { field: field, value: value, type: 'set' });
callback();
});
};
Groups.get(groupName, options, next);
},
], callback);
};
Groups.isPrivate = function (groupName, callback) {
db.getObjectField('group:' + groupName, 'private', function (err, isPrivate) {
if (err) {
return callback(err);
}
Groups.getGroupNameByGroupSlug = function (slug, callback) {
db.getObjectField('groupslug:groupname', slug, callback);
};
callback(null, parseInt(isPrivate, 10) !== 0);
});
};
Groups.isPrivate = function (groupName, callback) {
async.waterfall([
function (next) {
db.getObjectField('group:' + groupName, 'private', next);
},
function (isPrivate, next) {
next(null, parseInt(isPrivate, 10) !== 0);
},
], callback);
};
Groups.isHidden = function (groupName, callback) {
db.getObjectField('group:' + groupName, 'hidden', function (err, isHidden) {
if (err) {
return callback(err);
}
Groups.isHidden = function (groupName, callback) {
async.waterfall([
function (next) {
db.getObjectField('group:' + groupName, 'hidden', next);
},
function (isHidden, next) {
next(null, parseInt(isHidden, 10) === 1);
},
], callback);
};
callback(null, parseInt(isHidden, 10) === 1);
Groups.exists = function (name, callback) {
if (Array.isArray(name)) {
var slugs = name.map(function (groupName) {
return utils.slugify(groupName);
});
};
Groups.exists = function (name, callback) {
if (Array.isArray(name)) {
var slugs = name.map(function (groupName) {
return utils.slugify(groupName);
});
async.parallel([
function (next) {
next(null, slugs.map(function (slug) {
return ephemeralGroups.indexOf(slug) !== -1;
}));
},
async.apply(db.isSortedSetMembers, 'groups:createtime', name),
], function (err, results) {
if (err) {
return callback(err);
}
callback(null, name.map(function (n, index) {
return results[0][index] || results[1][index];
}));
});
} else {
var slug = utils.slugify(name);
async.parallel([
function (next) {
next(null, ephemeralGroups.indexOf(slug) !== -1);
},
async.apply(db.isSortedSetMember, 'groups:createtime', name),
], function (err, results) {
callback(err, !err ? (results[0] || results[1]) : null);
});
}
};
Groups.existsBySlug = function (slug, callback) {
if (Array.isArray(slug)) {
db.isObjectFields('groupslug:groupname', slug, callback);
} else {
db.isObjectField('groupslug:groupname', slug, callback);
}
};
Groups.getLatestMemberPosts = function (groupName, max, uid, callback) {
async.waterfall([
async.parallel([
function (next) {
Groups.getMembers(groupName, 0, -1, next);
},
function (uids, next) {
if (!Array.isArray(uids) || !uids.length) {
return callback(null, []);
}
var keys = uids.map(function (uid) {
return 'uid:' + uid + ':posts';
});
db.getSortedSetRevRange(keys, 0, max - 1, next);
},
function (pids, next) {
privileges.posts.filter('read', pids, uid, next);
},
function (pids, next) {
posts.getPostSummaryByPids(pids, uid, { stripTags: false }, next);
next(null, slugs.map(function (slug) {
return Groups.ephemeralGroups.indexOf(slug) !== -1;
}));
},
], callback);
};
Groups.getGroupData = function (groupName, callback) {
Groups.getGroupsData([groupName], function (err, groupsData) {
callback(err, Array.isArray(groupsData) && groupsData[0] ? groupsData[0] : null);
});
};
Groups.getGroupsData = function (groupNames, callback) {
if (!Array.isArray(groupNames) || !groupNames.length) {
return callback(null, []);
}
var keys = groupNames.map(function (groupName) {
return 'group:' + groupName;
});
var ephemeralIdx = groupNames.reduce(function (memo, cur, idx) {
if (ephemeralGroups.indexOf(cur) !== -1) {
memo.push(idx);
}
return memo;
}, []);
db.getObjects(keys, function (err, groupData) {
async.apply(db.isSortedSetMembers, 'groups:createtime', name),
], function (err, results) {
if (err) {
return callback(err);
}
if (ephemeralIdx.length) {
ephemeralIdx.forEach(function (idx) {
groupData[idx] = internals.getEphemeralGroup(groupNames[idx]);
});
}
groupData.forEach(function (group) {
if (group) {
Groups.escapeGroupData(group);
group.userTitleEnabled = group.userTitleEnabled ? parseInt(group.userTitleEnabled, 10) === 1 : true;
group.labelColor = validator.escape(String(group.labelColor || '#000000'));
group.icon = validator.escape(String(group.icon || ''));
group.createtimeISO = utils.toISOString(group.createtime);
group.hidden = parseInt(group.hidden, 10) === 1;
group.system = parseInt(group.system, 10) === 1;
group.private = (group.private === null || group.private === undefined) ? true : !!parseInt(group.private, 10);
group.disableJoinRequests = parseInt(group.disableJoinRequests, 10) === 1;
group['cover:url'] = group['cover:url'] || require('./coverPhoto').getDefaultGroupCover(group.name);
group['cover:thumb:url'] = group['cover:thumb:url'] || group['cover:url'];
group['cover:position'] = validator.escape(String(group['cover:position'] || '50% 50%'));
}
});
plugins.fireHook('filter:groups.get', { groups: groupData }, function (err, data) {
callback(err, data ? data.groups : null);
});
callback(null, name.map(function (n, index) {
return results[0][index] || results[1][index];
}));
});
};
Groups.getUserGroups = function (uids, callback) {
Groups.getUserGroupsFromSet('groups:visible:createtime', uids, callback);
};
Groups.getUserGroupsFromSet = function (set, uids, callback) {
async.waterfall([
} else {
var slug = utils.slugify(name);
async.parallel([
function (next) {
db.getSortedSetRevRange(set, 0, -1, next);
},
function (groupNames, next) {
var groupSets = groupNames.map(function (name) {
return 'group:' + name + ':members';
});
async.map(uids, function (uid, next) {
db.isMemberOfSortedSets(groupSets, uid, function (err, isMembers) {
if (err) {
return next(err);
}
var memberOf = [];
isMembers.forEach(function (isMember, index) {
if (isMember) {
memberOf.push(groupNames[index]);
}
});
Groups.getGroupsData(memberOf, next);
});
}, next);
next(null, Groups.ephemeralGroups.indexOf(slug) !== -1);
},
], callback);
};
}(module.exports));
async.apply(db.isSortedSetMember, 'groups:createtime', name),
], function (err, results) {
callback(err, !err ? (results[0] || results[1]) : null);
});
}
};
Groups.existsBySlug = function (slug, callback) {
if (Array.isArray(slug)) {
db.isObjectFields('groupslug:groupname', slug, callback);
} else {
db.isObjectField('groupslug:groupname', slug, callback);
}
};

@ -0,0 +1,93 @@
'use strict';
var async = require('async');
var validator = require('validator');
var db = require('../database');
var plugins = require('../plugins');
var utils = require('../../public/src/utils');
module.exports = function (Groups) {
Groups.getGroupsData = function (groupNames, callback) {
if (!Array.isArray(groupNames) || !groupNames.length) {
return callback(null, []);
}
var keys = groupNames.map(function (groupName) {
return 'group:' + groupName;
});
var ephemeralIdx = groupNames.reduce(function (memo, cur, idx) {
if (Groups.ephemeralGroups.indexOf(cur) !== -1) {
memo.push(idx);
}
return memo;
}, []);
async.waterfall([
function (next) {
db.getObjects(keys, next);
},
function (groupData, next) {
if (ephemeralIdx.length) {
ephemeralIdx.forEach(function (idx) {
groupData[idx] = Groups.getEphemeralGroup(groupNames[idx]);
});
}
groupData.forEach(function (group) {
if (group) {
Groups.escapeGroupData(group);
group.userTitleEnabled = group.userTitleEnabled ? parseInt(group.userTitleEnabled, 10) === 1 : true;
group.labelColor = validator.escape(String(group.labelColor || '#000000'));
group.icon = validator.escape(String(group.icon || ''));
group.createtimeISO = utils.toISOString(group.createtime);
group.hidden = parseInt(group.hidden, 10) === 1;
group.system = parseInt(group.system, 10) === 1;
group.private = (group.private === null || group.private === undefined) ? true : !!parseInt(group.private, 10);
group.disableJoinRequests = parseInt(group.disableJoinRequests, 10) === 1;
group['cover:url'] = group['cover:url'] || require('../coverPhoto').getDefaultGroupCover(group.name);
group['cover:thumb:url'] = group['cover:thumb:url'] || group['cover:url'];
group['cover:position'] = validator.escape(String(group['cover:position'] || '50% 50%'));
}
});
plugins.fireHook('filter:groups.get', { groups: groupData }, next);
},
function (results, next) {
next(null, results.groups);
},
], callback);
};
Groups.getGroupData = function (groupName, callback) {
Groups.getGroupsData([groupName], function (err, groupsData) {
callback(err, Array.isArray(groupsData) && groupsData[0] ? groupsData[0] : null);
});
};
Groups.getGroupFields = function (groupName, fields, callback) {
Groups.getMultipleGroupFields([groupName], fields, function (err, groups) {
callback(err, groups ? groups[0] : null);
});
};
Groups.getMultipleGroupFields = function (groups, fields, callback) {
db.getObjectsFields(groups.map(function (group) {
return 'group:' + group;
}), fields, callback);
};
Groups.setGroupField = function (groupName, field, value, callback) {
async.waterfall([
function (next) {
db.setObjectField('group:' + groupName, field, value, next);
},
function (next) {
plugins.fireHook('action:group.set', { field: field, value: value, type: 'set' });
next();
},
], callback);
};
};

@ -413,32 +413,33 @@ module.exports = function (Groups) {
};
Groups.getMemberCount = function (groupName, callback) {
db.getObjectField('group:' + groupName, 'memberCount', function (err, count) {
if (err) {
return callback(err);
}
callback(null, parseInt(count, 10));
});
async.waterfall([
function (next) {
db.getObjectField('group:' + groupName, 'memberCount', next);
},
function (count, next) {
next(null, parseInt(count, 10));
},
], callback);
};
Groups.isMemberOfGroupList = function (uid, groupListKey, callback) {
db.getSortedSetRange('group:' + groupListKey + ':members', 0, -1, function (err, groupNames) {
if (err) {
return callback(err);
}
groupNames = Groups.internals.removeEphemeralGroups(groupNames);
if (groupNames.length === 0) {
return callback(null, false);
}
Groups.isMemberOfGroups(uid, groupNames, function (err, isMembers) {
if (err) {
return callback(err);
async.waterfall([
function (next) {
db.getSortedSetRange('group:' + groupListKey + ':members', 0, -1, next);
},
function (groupNames, next) {
groupNames = Groups.removeEphemeralGroups(groupNames);
if (groupNames.length === 0) {
return callback(null, false);
}
callback(null, isMembers.indexOf(true) !== -1);
});
});
Groups.isMemberOfGroups(uid, groupNames, next);
},
function (isMembers, next) {
next(null, isMembers.indexOf(true) !== -1);
},
], callback);
};
Groups.isMemberOfGroupsList = function (uid, groupListKeys, callback) {
@ -446,19 +447,20 @@ module.exports = function (Groups) {
return 'group:' + groupName + ':members';
});
db.getSortedSetsMembers(sets, function (err, members) {
if (err) {
return callback(err);
}
var uniqueGroups = _.unique(_.flatten(members));
uniqueGroups = Groups.internals.removeEphemeralGroups(uniqueGroups);
Groups.isMemberOfGroups(uid, uniqueGroups, function (err, isMembers) {
if (err) {
return callback(err);
}
var uniqueGroups;
var members;
async.waterfall([
function (next) {
db.getSortedSetsMembers(sets, next);
},
function (_members, next) {
members = _members;
uniqueGroups = _.unique(_.flatten(members));
uniqueGroups = Groups.removeEphemeralGroups(uniqueGroups);
Groups.isMemberOfGroups(uid, uniqueGroups, next);
},
function (isMembers, next) {
var map = {};
uniqueGroups.forEach(function (groupName, index) {
@ -474,62 +476,63 @@ module.exports = function (Groups) {
return false;
});
callback(null, result);
});
});
next(null, result);
},
], callback);
};
Groups.isMembersOfGroupList = function (uids, groupListKey, callback) {
db.getSortedSetRange('group:' + groupListKey + ':members', 0, -1, function (err, groupNames) {
if (err) {
return callback(err);
}
var groupNames;
var results = [];
uids.forEach(function () {
results.push(false);
});
var results = [];
uids.forEach(function () {
results.push(false);
});
async.waterfall([
function (next) {
db.getSortedSetRange('group:' + groupListKey + ':members', 0, -1, next);
},
function (_groupNames, next) {
groupNames = Groups.removeEphemeralGroups(_groupNames);
groupNames = Groups.internals.removeEphemeralGroups(groupNames);
if (groupNames.length === 0) {
return callback(null, results);
}
if (groupNames.length === 0) {
return callback(null, results);
}
async.each(groupNames, function (groupName, next) {
Groups.isMembers(uids, groupName, function (err, isMembers) {
if (err) {
return next(err);
}
async.map(groupNames, function (groupName, next) {
Groups.isMembers(uids, groupName, next);
}, next);
},
function (isGroupMembers, next) {
isGroupMembers.forEach(function (isMembers) {
results.forEach(function (isMember, index) {
if (!isMember && isMembers[index]) {
results[index] = true;
}
});
next();
});
}, function (err) {
callback(err, results);
});
});
next(null, results);
},
], callback);
};
Groups.isInvited = function (uid, groupName, callback) {
if (!uid) {
return callback(null, false);
return setImmediate(callback, null, false);
}
db.isSetMember('group:' + groupName + ':invited', uid, callback);
};
Groups.isPending = function (uid, groupName, callback) {
if (!uid) {
return callback(null, false);
return setImmediate(callback, null, false);
}
db.isSetMember('group:' + groupName + ':pending', uid, callback);
};
Groups.getPending = function (groupName, callback) {
if (!groupName) {
return callback(null, []);
return setImmediate(callback, null, []);
}
db.getSetMembers('group:' + groupName + ':pending', callback);
};

@ -0,0 +1,32 @@
'use strict';
var async = require('async');
var db = require('../database');
var privileges = require('../privileges');
var posts = require('../posts');
module.exports = function (Groups) {
Groups.getLatestMemberPosts = function (groupName, max, uid, callback) {
async.waterfall([
function (next) {
Groups.getMembers(groupName, 0, -1, next);
},
function (uids, next) {
if (!Array.isArray(uids) || !uids.length) {
return callback(null, []);
}
var keys = uids.map(function (uid) {
return 'uid:' + uid + ':posts';
});
db.getSortedSetRevRange(keys, 0, max - 1, next);
},
function (pids, next) {
privileges.posts.filter('read', pids, uid, next);
},
function (pids, next) {
posts.getPostSummaryByPids(pids, uid, { stripTags: false }, next);
},
], callback);
};
};

@ -16,7 +16,7 @@ module.exports = function (Groups) {
async.apply(db.getObjectValues, 'groupslug:groupname'),
function (groupNames, next) {
// Ephemeral groups and the registered-users groups are searchable
groupNames = Groups.getEphemeralGroups().concat(groupNames).concat('registered-users');
groupNames = Groups.ephemeralGroups.concat(groupNames).concat('registered-users');
groupNames = groupNames.filter(function (name) {
return name.toLowerCase().indexOf(query) !== -1 && name !== 'administrators' && !Groups.isPrivilegeGroup(name);
});

@ -0,0 +1,50 @@
'use strict';
var async = require('async');
var db = require('../database');
var user = require('../user');
module.exports = function (Groups) {
Groups.getUsersFromSet = function (set, callback) {
async.waterfall([
function (next) {
db.getSetMembers(set, next);
},
function (uids, next) {
user.getUsersData(uids, next);
},
], callback);
};
Groups.getUserGroups = function (uids, callback) {
Groups.getUserGroupsFromSet('groups:visible:createtime', uids, callback);
};
Groups.getUserGroupsFromSet = function (set, uids, callback) {
async.waterfall([
function (next) {
db.getSortedSetRevRange(set, 0, -1, next);
},
function (groupNames, next) {
async.map(uids, function (uid, next) {
async.waterfall([
function (next) {
Groups.isMemberOfGroups(uid, groupNames, next);
},
function (isMembers, next) {
var memberOf = [];
isMembers.forEach(function (isMember, index) {
if (isMember) {
memberOf.push(groupNames[index]);
}
});
Groups.getGroupsData(memberOf, next);
},
], next);
}, next);
},
], callback);
};
};

@ -96,7 +96,7 @@ module.exports = function (privileges) {
return groupName.indexOf(':privileges:') === -1 && uniqueGroups.indexOf(groupName) !== -1;
});
groupNames = groups.getEphemeralGroups().concat(groupNames);
groupNames = groups.ephemeralGroups.concat(groupNames);
var registeredUsersIndex = groupNames.indexOf('registered-users');
if (registeredUsersIndex !== -1) {
groupNames.splice(0, 0, groupNames.splice(registeredUsersIndex, 1)[0]);

Loading…
Cancel
Save