mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-07-09 06:01:28 +02:00
Merge branch 'master' into flagging-refactor
This commit is contained in:
@@ -35,7 +35,6 @@ module.exports = function (grunt) {
|
||||
incomplete.push(compiling);
|
||||
}
|
||||
|
||||
// @psychobunny, re: #5211, instead of this, just call `node app --build js` or `node app --build css,tpl`
|
||||
updateArgs.push('--build');
|
||||
updateArgs.push(incomplete.join(','));
|
||||
|
||||
|
||||
@@ -81,9 +81,9 @@
|
||||
"semver": "^5.1.0",
|
||||
"serve-favicon": "^2.1.5",
|
||||
"sitemap": "^1.4.0",
|
||||
"socket.io": "^1.4.8",
|
||||
"socket.io-client": "^1.4.0",
|
||||
"socket.io-redis": "1.1.1",
|
||||
"socket.io": "1.7.1",
|
||||
"socket.io-client": "1.7.1",
|
||||
"socket.io-redis": "2.0.0",
|
||||
"socketio-wildcard": "~0.3.0",
|
||||
"string": "^3.0.0",
|
||||
"templates.js": "0.3.4",
|
||||
|
||||
@@ -27,6 +27,7 @@ define('forum/chats/messages', ['components', 'sounds', 'translator'], function
|
||||
message: msg
|
||||
}, function (err) {
|
||||
if (err) {
|
||||
inputEl.val(msg);
|
||||
if (err.message === '[[error:email-not-confirmed-chat]]') {
|
||||
return app.showEmailConfirmWarning(err);
|
||||
}
|
||||
@@ -42,6 +43,8 @@ define('forum/chats/messages', ['components', 'sounds', 'translator'], function
|
||||
message: msg
|
||||
}, function (err) {
|
||||
if (err) {
|
||||
inputEl.val(msg);
|
||||
inputEl.attr('data-mid', mid);
|
||||
return app.alertError(err.message);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -258,7 +258,7 @@ define('chat', [
|
||||
Chats.addScrollHandler(chatModal.attr('roomId'), data.uid, chatModal.find('.chat-content'));
|
||||
|
||||
taskbar.push('chat', chatModal.attr('UUID'), {
|
||||
title: data.users.length ? data.users[0].username : '',
|
||||
title: data.roomName || (data.users.length ? data.users[0].username : ''),
|
||||
roomId: data.roomId,
|
||||
icon: 'fa-comment',
|
||||
state: ''
|
||||
|
||||
@@ -33,6 +33,9 @@ module.exports = function (Categories) {
|
||||
};
|
||||
|
||||
Categories.markAsUnreadForAll = function (cid, callback) {
|
||||
if (!parseInt(cid, 10)) {
|
||||
return callback();
|
||||
}
|
||||
callback = callback || function () {};
|
||||
db.delete('cid:' + cid + ':read_by_uid', callback);
|
||||
};
|
||||
|
||||
@@ -105,9 +105,9 @@ topicsController.get = function (req, res, callback) {
|
||||
} else if (!req.query.page) {
|
||||
var index;
|
||||
if (reverse) {
|
||||
index = Math.max(0, postCount - (req.params.post_index || postCount));
|
||||
index = Math.max(0, postCount - (req.params.post_index || postCount) + 2);
|
||||
} else {
|
||||
index = Math.max(0, req.params.post_index - 1) || 0;
|
||||
index = Math.max(0, req.params.post_index) || 0;
|
||||
}
|
||||
|
||||
currentPage = Math.max(1, Math.ceil(index / settings.postsPerPage));
|
||||
|
||||
@@ -12,48 +12,57 @@ module.exports = function (Groups) {
|
||||
|
||||
Groups.update = function (groupName, values, callback) {
|
||||
callback = callback || function () {};
|
||||
db.exists('group:' + groupName, function (err, exists) {
|
||||
if (err || !exists) {
|
||||
return callback(err || new Error('[[error:no-group]]'));
|
||||
}
|
||||
|
||||
plugins.fireHook('filter:group.update', {
|
||||
groupName: groupName,
|
||||
values: values
|
||||
}, function (err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
db.exists('group:' + groupName, next);
|
||||
},
|
||||
function (exists, next) {
|
||||
if (!exists) {
|
||||
return next(new Error('[[error:no-group]]'));
|
||||
}
|
||||
plugins.fireHook('filter:group.update', {
|
||||
groupName: groupName,
|
||||
values: values
|
||||
}, next);
|
||||
},
|
||||
function (result, next) {
|
||||
values = result.values;
|
||||
|
||||
var payload = {
|
||||
description: values.description || '',
|
||||
icon: values.icon || '',
|
||||
labelColor: values.labelColor || '#000000'
|
||||
};
|
||||
|
||||
|
||||
if (values.hasOwnProperty('userTitle')) {
|
||||
payload.userTitle = values.userTitle || '';
|
||||
}
|
||||
|
||||
|
||||
if (values.hasOwnProperty('userTitleEnabled')) {
|
||||
payload.userTitleEnabled = values.userTitleEnabled ? '1' : '0';
|
||||
}
|
||||
|
||||
|
||||
if (values.hasOwnProperty('hidden')) {
|
||||
payload.hidden = values.hidden ? '1' : '0';
|
||||
}
|
||||
|
||||
|
||||
if (values.hasOwnProperty('private')) {
|
||||
payload.private = values.private ? '1' : '0';
|
||||
}
|
||||
|
||||
|
||||
if (values.hasOwnProperty('disableJoinRequests')) {
|
||||
payload.disableJoinRequests = values.disableJoinRequests ? '1' : '0';
|
||||
}
|
||||
|
||||
async.series([
|
||||
async.apply(checkNameChange, groupName, values.name),
|
||||
async.apply(updatePrivacy, groupName, values.private),
|
||||
function (next) {
|
||||
if (values.hasOwnProperty('private')) {
|
||||
updatePrivacy(groupName, values.private, next);
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
},
|
||||
function (next) {
|
||||
if (values.hasOwnProperty('hidden')) {
|
||||
updateVisibility(groupName, values.hidden, next);
|
||||
@@ -63,19 +72,16 @@ module.exports = function (Groups) {
|
||||
},
|
||||
async.apply(db.setObject, 'group:' + groupName, payload),
|
||||
async.apply(renameGroup, groupName, values.name)
|
||||
], function (err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
plugins.fireHook('action:group.update', {
|
||||
name: groupName,
|
||||
values: values
|
||||
});
|
||||
callback();
|
||||
], next);
|
||||
},
|
||||
function (result, next) {
|
||||
plugins.fireHook('action:group.update', {
|
||||
name: groupName,
|
||||
values: values
|
||||
});
|
||||
});
|
||||
});
|
||||
next();
|
||||
}
|
||||
], callback);
|
||||
};
|
||||
|
||||
function updateVisibility(groupName, hidden, callback) {
|
||||
@@ -118,35 +124,33 @@ module.exports = function (Groups) {
|
||||
});
|
||||
}
|
||||
|
||||
function updatePrivacy(groupName, newValue, callback) {
|
||||
if (!newValue) {
|
||||
return callback();
|
||||
}
|
||||
function updatePrivacy(groupName, isPrivate, callback) {
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
Groups.getGroupFields(groupName, ['private'], next);
|
||||
},
|
||||
function (currentValue, next) {
|
||||
var currentlyPrivate = parseInt(currentValue.private, 10) === 1;
|
||||
if (!currentlyPrivate || currentlyPrivate === isPrivate) {
|
||||
return callback();
|
||||
}
|
||||
db.getSetMembers('group:' + groupName + ':pending', next);
|
||||
},
|
||||
function (uids, next) {
|
||||
if (!uids.length) {
|
||||
return callback();
|
||||
}
|
||||
var now = Date.now();
|
||||
var scores = uids.map(function () { return now; });
|
||||
|
||||
Groups.getGroupFields(groupName, ['private'], function (err, currentValue) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
currentValue = currentValue.private === '1';
|
||||
|
||||
if (currentValue !== newValue && currentValue === true) {
|
||||
// Group is now public, so all pending users are automatically considered members
|
||||
db.getSetMembers('group:' + groupName + ':pending', function (err, uids) {
|
||||
if (err) { return callback(err); }
|
||||
else if (!uids) { return callback(); } // No pending users, we're good to go
|
||||
|
||||
var now = Date.now(),
|
||||
scores = uids.map(function () { return now; }); // There's probably a better way to initialise an Array of size x with the same value...
|
||||
|
||||
winston.verbose('[groups.update] Group is now public, automatically adding ' + uids.length + ' new members, who were pending prior.');
|
||||
async.series([
|
||||
async.apply(db.sortedSetAdd, 'group:' + groupName + ':members', scores, uids),
|
||||
async.apply(db.delete, 'group:' + groupName + ':pending')
|
||||
], callback);
|
||||
});
|
||||
} else {
|
||||
callback();
|
||||
winston.verbose('[groups.update] Group is now public, automatically adding ' + uids.length + ' new members, who were pending prior.');
|
||||
async.series([
|
||||
async.apply(db.sortedSetAdd, 'group:' + groupName + ':members', scores, uids),
|
||||
async.apply(db.delete, 'group:' + groupName + ':pending')
|
||||
], next);
|
||||
}
|
||||
], function (err) {
|
||||
callback(err);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ module.exports = function (Meta) {
|
||||
scripts: {
|
||||
base: [
|
||||
'./node_modules/jquery/dist/jquery.js',
|
||||
'./node_modules/socket.io-client/socket.io.js',
|
||||
'./node_modules/socket.io-client/dist/socket.io.js',
|
||||
'public/vendor/jquery/timeago/jquery.timeago.js',
|
||||
'public/vendor/jquery/js/jquery.form.min.js',
|
||||
'public/vendor/visibility/visibility.min.js',
|
||||
|
||||
@@ -352,7 +352,9 @@ var utils = require('../public/src/utils');
|
||||
function (next) {
|
||||
db.sortedSetAdd('uid:' + uid + ':notifications:read', datetimes, nids, next);
|
||||
}
|
||||
], callback);
|
||||
], function (err) {
|
||||
callback(err);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -261,7 +261,7 @@ module.exports = function (Plugins) {
|
||||
}
|
||||
|
||||
var pathToFolder = path.join(__dirname, '../../node_modules/', pluginData.id, pluginData.languages);
|
||||
var defaultLang = pluginData.defaultLang.replace('_', '-').replace('@', '-x-');
|
||||
var defaultLang = (pluginData.defaultLang || 'en_GB').replace('_', '-').replace('@', '-x-');
|
||||
|
||||
utils.walk(pathToFolder, function (err, languages) {
|
||||
if (err) {
|
||||
@@ -346,9 +346,11 @@ module.exports = function (Plugins) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
var pluginData;
|
||||
var packageData;
|
||||
try {
|
||||
var pluginData = JSON.parse(results.plugin);
|
||||
var packageData = JSON.parse(results.package);
|
||||
pluginData = JSON.parse(results.plugin);
|
||||
packageData = JSON.parse(results.package);
|
||||
|
||||
pluginData.id = packageData.name;
|
||||
pluginData.name = packageData.name;
|
||||
@@ -356,16 +358,15 @@ module.exports = function (Plugins) {
|
||||
pluginData.version = packageData.version;
|
||||
pluginData.repository = packageData.repository;
|
||||
pluginData.nbbpm = packageData.nbbpm;
|
||||
|
||||
callback(null, pluginData);
|
||||
} catch(err) {
|
||||
var pluginDir = pluginPath.split(path.sep);
|
||||
pluginDir = pluginDir[pluginDir.length - 1];
|
||||
|
||||
winston.error('[plugins/' + pluginDir + '] Error in plugin.json or package.json! ' + err.message);
|
||||
|
||||
callback(new Error('[[error:parse-error]]'));
|
||||
return callback(new Error('[[error:parse-error]]'));
|
||||
}
|
||||
callback(null, pluginData);
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
@@ -9,13 +9,14 @@ var categories = require('./categories');
|
||||
var topics = require('./topics');
|
||||
var privileges = require('./privileges');
|
||||
var meta = require('./meta');
|
||||
var plugins = require('./plugins');
|
||||
var utils = require('../public/src/utils');
|
||||
|
||||
var sitemap = {
|
||||
maps: {
|
||||
topics: []
|
||||
}
|
||||
};
|
||||
maps: {
|
||||
topics: []
|
||||
}
|
||||
};
|
||||
|
||||
sitemap.render = function (callback) {
|
||||
var numTopics = parseInt(meta.config.sitemapTopics, 10) || 500;
|
||||
@@ -71,13 +72,18 @@ sitemap.getPages = function (callback) {
|
||||
priority: 0.4
|
||||
}];
|
||||
|
||||
sitemap.maps.pages = sm.createSitemap({
|
||||
hostname: nconf.get('url'),
|
||||
cacheTime: 1000 * 60 * 60 * 24, // Cached for 24 hours
|
||||
urls: urls
|
||||
});
|
||||
plugins.fireHook('filter:sitemap.getPages', {urls: urls}, function (err, data) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
sitemap.maps.pages = sm.createSitemap({
|
||||
hostname: nconf.get('url'),
|
||||
cacheTime: 1000 * 60 * 60 * 24, // Cached for 24 hours
|
||||
urls: data.urls
|
||||
});
|
||||
|
||||
sitemap.maps.pages.toXML(callback);
|
||||
sitemap.maps.pages.toXML(callback);
|
||||
});
|
||||
};
|
||||
|
||||
sitemap.getCategories = function (callback) {
|
||||
|
||||
@@ -44,7 +44,7 @@ SocketPosts.reply = function (socket, data, callback) {
|
||||
|
||||
callback(null, postData);
|
||||
|
||||
socket.emit('event:new_post', result);
|
||||
websockets.in('uid_' + socket.uid).emit('event:new_post', result);
|
||||
|
||||
user.updateOnlineUsers(socket.uid);
|
||||
|
||||
|
||||
@@ -11,61 +11,67 @@ module.exports = function (SocketTopics) {
|
||||
if (!Array.isArray(tids) || !socket.uid) {
|
||||
return callback(new Error('[[error:invalid-data]]'));
|
||||
}
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
topics.markAsRead(tids, socket.uid, next);
|
||||
},
|
||||
function (hasMarked, next) {
|
||||
if (hasMarked) {
|
||||
topics.pushUnreadCount(socket.uid);
|
||||
|
||||
topics.markAsRead(tids, socket.uid, function (err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
topics.markTopicNotificationsRead(tids, socket.uid);
|
||||
}
|
||||
next();
|
||||
}
|
||||
|
||||
topics.pushUnreadCount(socket.uid);
|
||||
|
||||
topics.markTopicNotificationsRead(tids, socket.uid);
|
||||
|
||||
callback();
|
||||
});
|
||||
], callback);
|
||||
};
|
||||
|
||||
SocketTopics.markTopicNotificationsRead = function (socket, tids, callback) {
|
||||
if (!Array.isArray(tids) || !socket.uid) {
|
||||
return callback(new Error('[[error:invalid-data]]'));
|
||||
}
|
||||
topics.markTopicNotificationsRead(tids, socket.uid);
|
||||
topics.markTopicNotificationsRead(tids, socket.uid, callback);
|
||||
};
|
||||
|
||||
SocketTopics.markAllRead = function (socket, data, callback) {
|
||||
topics.markAllRead(socket.uid, function (err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
if (!socket.uid) {
|
||||
return callback(new Error('[[error:invalid-uid]]'));
|
||||
}
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
topics.markAllRead(socket.uid, next);
|
||||
},
|
||||
function (next) {
|
||||
topics.pushUnreadCount(socket.uid);
|
||||
next();
|
||||
}
|
||||
|
||||
topics.pushUnreadCount(socket.uid);
|
||||
|
||||
callback();
|
||||
});
|
||||
], callback);
|
||||
};
|
||||
|
||||
SocketTopics.markCategoryTopicsRead = function (socket, cid, callback) {
|
||||
topics.getUnreadTids(cid, socket.uid, '', function (err, tids) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
topics.getUnreadTids(cid, socket.uid, '', next);
|
||||
},
|
||||
function (tids, next) {
|
||||
SocketTopics.markAsRead(socket, tids, next);
|
||||
}
|
||||
|
||||
SocketTopics.markAsRead(socket, tids, callback);
|
||||
});
|
||||
], callback);
|
||||
};
|
||||
|
||||
SocketTopics.markUnread = function (socket, tid, callback) {
|
||||
if (!tid || !socket.uid) {
|
||||
return callback(new Error('[[error:invalid-data]]'));
|
||||
}
|
||||
topics.markUnread(tid, socket.uid, function (err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
topics.markUnread(tid, socket.uid, next);
|
||||
},
|
||||
function (next) {
|
||||
topics.pushUnreadCount(socket.uid);
|
||||
next();
|
||||
}
|
||||
|
||||
topics.pushUnreadCount(socket.uid);
|
||||
callback();
|
||||
});
|
||||
], callback);
|
||||
};
|
||||
|
||||
SocketTopics.markAsUnreadForAll = function (socket, tids, callback) {
|
||||
@@ -77,42 +83,41 @@ module.exports = function (SocketTopics) {
|
||||
return callback(new Error('[[error:no-privileges]]'));
|
||||
}
|
||||
|
||||
user.isAdministrator(socket.uid, function (err, isAdmin) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
async.each(tids, function (tid, next) {
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
topics.exists(tid, next);
|
||||
},
|
||||
function (exists, next) {
|
||||
if (!exists) {
|
||||
return next(new Error('[[error:invalid-tid]]'));
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
user.isAdministrator(socket.uid, next);
|
||||
},
|
||||
function (isAdmin, next) {
|
||||
async.each(tids, function (tid, next) {
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
topics.exists(tid, next);
|
||||
},
|
||||
function (exists, next) {
|
||||
if (!exists) {
|
||||
return next(new Error('[[error:no-topic]]'));
|
||||
}
|
||||
topics.getTopicField(tid, 'cid', next);
|
||||
},
|
||||
function (cid, next) {
|
||||
user.isModerator(socket.uid, cid, next);
|
||||
},
|
||||
function (isMod, next) {
|
||||
if (!isAdmin && !isMod) {
|
||||
return next(new Error('[[error:no-privileges]]'));
|
||||
}
|
||||
topics.markAsUnreadForAll(tid, next);
|
||||
},
|
||||
function (next) {
|
||||
topics.updateRecent(tid, Date.now(), next);
|
||||
}
|
||||
topics.getTopicField(tid, 'cid', next);
|
||||
},
|
||||
function (cid, next) {
|
||||
user.isModerator(socket.uid, cid, next);
|
||||
},
|
||||
function (isMod, next) {
|
||||
if (!isAdmin && !isMod) {
|
||||
return next(new Error('[[error:no-privileges]]'));
|
||||
}
|
||||
topics.markAsUnreadForAll(tid, next);
|
||||
},
|
||||
function (next) {
|
||||
topics.updateRecent(tid, Date.now(), next);
|
||||
}
|
||||
], next);
|
||||
}, function (err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
], next);
|
||||
}, next);
|
||||
},
|
||||
function (next) {
|
||||
topics.pushUnreadCount(socket.uid);
|
||||
callback();
|
||||
});
|
||||
});
|
||||
next();
|
||||
}
|
||||
], callback);
|
||||
};
|
||||
};
|
||||
@@ -74,7 +74,10 @@ module.exports = function (Topics) {
|
||||
function (next) {
|
||||
method2(tid, uid, next);
|
||||
},
|
||||
async.apply(plugins.fireHook, hook, {uid: uid, tid: tid})
|
||||
function (next) {
|
||||
plugins.fireHook(hook, {uid: uid, tid: tid});
|
||||
next();
|
||||
}
|
||||
], callback);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
'use strict';
|
||||
|
||||
var async = require('async');
|
||||
var winston = require('winston');
|
||||
|
||||
var db = require('../database');
|
||||
var user = require('../user');
|
||||
@@ -277,9 +276,10 @@ module.exports = function (Topics) {
|
||||
], callback);
|
||||
};
|
||||
|
||||
Topics.markTopicNotificationsRead = function (tids, uid) {
|
||||
Topics.markTopicNotificationsRead = function (tids, uid, callback) {
|
||||
callback = callback || function () {};
|
||||
if (!Array.isArray(tids) || !tids.length) {
|
||||
return;
|
||||
return callback();
|
||||
}
|
||||
|
||||
async.waterfall([
|
||||
@@ -288,23 +288,23 @@ module.exports = function (Topics) {
|
||||
},
|
||||
function (nids, next) {
|
||||
notifications.markReadMultiple(nids, uid, next);
|
||||
},
|
||||
function (next) {
|
||||
user.notifications.pushCount(uid);
|
||||
next();
|
||||
}
|
||||
], function (err) {
|
||||
if (err) {
|
||||
return winston.error(err);
|
||||
}
|
||||
user.notifications.pushCount(uid);
|
||||
});
|
||||
], callback);
|
||||
};
|
||||
|
||||
Topics.markCategoryUnreadForAll = function (tid, callback) {
|
||||
Topics.getTopicField(tid, 'cid', function (err, cid) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
Topics.getTopicField(tid, 'cid', next);
|
||||
},
|
||||
function (cid, next) {
|
||||
categories.markAsUnreadForAll(cid, next);
|
||||
}
|
||||
|
||||
categories.markAsUnreadForAll(cid, callback);
|
||||
});
|
||||
], callback);
|
||||
};
|
||||
|
||||
Topics.hasReadTopics = function (tids, uid, callback) {
|
||||
|
||||
122
test/groups.js
122
test/groups.js
@@ -504,6 +504,128 @@ describe('Groups', function () {
|
||||
|
||||
});
|
||||
|
||||
describe('admin socket methods', function () {
|
||||
var socketGroups = require('../src/socket.io/admin/groups');
|
||||
|
||||
it('should fail to create group with invalid data', function (done) {
|
||||
socketGroups.create({uid: adminUid}, null, function (err) {
|
||||
assert.equal(err.message, '[[error:invalid-data]]');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail to create group if group name is privilege group', function (done) {
|
||||
socketGroups.create({uid: adminUid}, {name: 'cid:1:privileges:read'}, function (err) {
|
||||
assert.equal(err.message, '[[error:invalid-group-name]]');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should create a group', function (done) {
|
||||
socketGroups.create({uid: adminUid}, {name: 'newgroup', description: 'group created by admin'}, function (err, groupData) {
|
||||
assert.ifError(err);
|
||||
assert.equal(groupData.name, 'newgroup');
|
||||
assert.equal(groupData.description, 'group created by admin');
|
||||
assert.equal(groupData.ownerUid, adminUid);
|
||||
assert.equal(groupData.private, true);
|
||||
assert.equal(groupData.memberCount, 1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail to join with invalid data', function (done) {
|
||||
socketGroups.join({uid: adminUid}, null, function (err) {
|
||||
assert.equal(err.message, '[[error:invalid-data]]');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should add user to group', function (done) {
|
||||
socketGroups.join({uid: adminUid}, {uid: testUid, groupName: 'newgroup'}, function (err) {
|
||||
assert.ifError(err);
|
||||
Groups.isMember(testUid, 'newgroup', function (err, isMember) {
|
||||
assert.ifError(err);
|
||||
assert(isMember);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail to if user is already member', function (done) {
|
||||
socketGroups.join({uid: adminUid}, {uid: testUid, groupName: 'newgroup'}, function (err) {
|
||||
assert.equal(err.message, '[[error:group-already-member]]');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('it should fail with invalid data', function (done) {
|
||||
socketGroups.leave({uid: adminUid}, null, function (err) {
|
||||
assert.equal(err.message, '[[error:invalid-data]]');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('it should fail if admin tries to remove self', function (done) {
|
||||
socketGroups.leave({uid: adminUid}, {uid: adminUid, groupName: 'administrators'}, function (err) {
|
||||
assert.equal(err.message, '[[error:cant-remove-self-as-admin]]');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail if user is not member', function (done) {
|
||||
socketGroups.leave({uid: adminUid}, {uid: 3, groupName: 'newgroup'}, function (err) {
|
||||
assert.equal(err.message, '[[error:group-not-member]]');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should remove user from group', function (done) {
|
||||
socketGroups.leave({uid: adminUid}, {uid: testUid, groupName: 'newgroup'}, function (err) {
|
||||
assert.ifError(err);
|
||||
Groups.isMember(testUid, 'newgroup', function (err, isMember) {
|
||||
assert.ifError(err);
|
||||
assert(!isMember);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail with invalid data', function (done) {
|
||||
socketGroups.update({uid: adminUid}, null, function (err) {
|
||||
assert.equal(err.message, '[[error:invalid-data]]');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should update group', function (done) {
|
||||
var data = {
|
||||
groupName: 'newgroup',
|
||||
values: {
|
||||
name: 'renamedgroup',
|
||||
description: 'cat group',
|
||||
userTitle: 'cats',
|
||||
userTitleEnabled: 1,
|
||||
disableJoinRequests: 1,
|
||||
hidden: 1,
|
||||
private: 0
|
||||
}
|
||||
};
|
||||
socketGroups.update({uid: adminUid}, data, function (err) {
|
||||
assert.ifError(err);
|
||||
Groups.get('renamedgroup', {}, function (err, groupData) {
|
||||
assert.ifError(err);
|
||||
assert.equal(groupData.name, 'renamedgroup');
|
||||
assert.equal(groupData.userTitle, 'cats');
|
||||
assert.equal(groupData.description, 'cat group');
|
||||
assert.equal(groupData.hidden, true);
|
||||
assert.equal(groupData.disableJoinRequests, true);
|
||||
assert.equal(groupData.private, false);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
after(function (done) {
|
||||
db.emptydb(done);
|
||||
});
|
||||
|
||||
@@ -100,6 +100,9 @@
|
||||
function (next) {
|
||||
meta.configs.init(next);
|
||||
},
|
||||
function (next) {
|
||||
meta.dependencies.check(next);
|
||||
},
|
||||
function (next) {
|
||||
meta.config.postDelay = 0;
|
||||
meta.config.initialPostDelay = 0;
|
||||
@@ -107,6 +110,12 @@
|
||||
|
||||
enableDefaultPlugins(next);
|
||||
},
|
||||
function (next) {
|
||||
meta.themes.set({
|
||||
type: 'local',
|
||||
id: 'nodebb-theme-persona'
|
||||
}, next);
|
||||
},
|
||||
function (next) {
|
||||
// nconf defaults, if not set in config
|
||||
if (!nconf.get('upload_path')) {
|
||||
|
||||
194
test/topics.js
194
test/topics.js
@@ -683,6 +683,200 @@ describe('Topic\'s', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe('unread', function () {
|
||||
var socketTopics = require('../src/socket.io/topics');
|
||||
var tid;
|
||||
var mainPid;
|
||||
var uid;
|
||||
before(function (done) {
|
||||
async.parallel({
|
||||
topic: function (next) {
|
||||
topics.post({uid: topic.userId, title: 'unread topic', content: 'unread topic content', cid: topic.categoryId}, next);
|
||||
},
|
||||
user: function (next) {
|
||||
User.create({username: 'regularJoe'}, next);
|
||||
}
|
||||
}, function (err, results) {
|
||||
assert.ifError(err);
|
||||
tid = results.topic.topicData.tid;
|
||||
mainPid = results.topic.postData.pid;
|
||||
uid = results.user;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail with invalid data', function (done) {
|
||||
socketTopics.markUnread({uid: adminUid}, null, function (err) {
|
||||
assert.equal(err.message, '[[error:invalid-data]]');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail if topic does not exist', function (done) {
|
||||
socketTopics.markUnread({uid: adminUid}, 1231082, function (err) {
|
||||
assert.equal(err.message, '[[error:no-topic]]');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should mark topic unread', function (done) {
|
||||
socketTopics.markUnread({uid: adminUid}, tid, function (err) {
|
||||
assert.ifError(err);
|
||||
topics.hasReadTopic(tid, adminUid, function (err, hasRead) {
|
||||
assert.ifError(err);
|
||||
assert.equal(hasRead, false);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should fail with invalid data', function (done) {
|
||||
socketTopics.markAsRead({uid: 0}, null, function (err) {
|
||||
assert.equal(err.message, '[[error:invalid-data]]');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should mark topic read', function (done) {
|
||||
socketTopics.markAsRead({uid: adminUid}, [tid], function (err) {
|
||||
assert.ifError(err);
|
||||
topics.hasReadTopic(tid, adminUid, function (err, hasRead) {
|
||||
assert.ifError(err);
|
||||
assert(hasRead);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail with invalid data', function (done) {
|
||||
socketTopics.markTopicNotificationsRead({uid: 0}, null, function (err) {
|
||||
assert.equal(err.message, '[[error:invalid-data]]');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should mark topic notifications read', function (done) {
|
||||
var socketPosts = require('../src/socket.io/posts');
|
||||
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
socketTopics.follow({uid: adminUid}, tid, next);
|
||||
},
|
||||
function (next) {
|
||||
socketPosts.reply({uid: uid}, {content: 'some content', tid: tid}, next);
|
||||
},
|
||||
function (data, next) {
|
||||
setTimeout(next, 2500);
|
||||
},
|
||||
function (next) {
|
||||
User.notifications.getUnreadCount(adminUid, next);
|
||||
},
|
||||
function (count, next) {
|
||||
assert.equal(count, 1);
|
||||
socketTopics.markTopicNotificationsRead({uid: adminUid}, [tid], next);
|
||||
},
|
||||
function (next) {
|
||||
User.notifications.getUnreadCount(adminUid, next);
|
||||
},
|
||||
function (count, next) {
|
||||
assert.equal(count, 0);
|
||||
next();
|
||||
}
|
||||
], function (err) {
|
||||
assert.ifError(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail with invalid data', function (done) {
|
||||
socketTopics.markAllRead({uid: 0}, null, function (err) {
|
||||
assert.equal(err.message, '[[error:invalid-uid]]');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should mark all read', function (done) {
|
||||
socketTopics.markUnread({uid: adminUid}, tid, function (err) {
|
||||
assert.ifError(err);
|
||||
socketTopics.markAllRead({uid: adminUid}, {}, function (err) {
|
||||
assert.ifError(err);
|
||||
topics.hasReadTopic(tid, adminUid, function (err, hasRead) {
|
||||
assert.ifError(err);
|
||||
assert(hasRead);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should mark all read', function (done) {
|
||||
socketTopics.markUnread({uid: adminUid}, tid, function (err) {
|
||||
assert.ifError(err);
|
||||
socketTopics.markCategoryTopicsRead({uid: adminUid}, topic.categoryId, function (err) {
|
||||
assert.ifError(err);
|
||||
topics.hasReadTopic(tid, adminUid, function (err, hasRead) {
|
||||
assert.ifError(err);
|
||||
assert(hasRead);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should fail with invalid data', function (done) {
|
||||
socketTopics.markAsUnreadForAll({uid: adminUid}, null, function (err) {
|
||||
assert.equal(err.message, '[[error:invalid-tid]]');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail with invalid data', function (done) {
|
||||
socketTopics.markAsUnreadForAll({uid: 0}, [tid], function (err) {
|
||||
assert.equal(err.message, '[[error:no-privileges]]');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail if user is not admin', function (done) {
|
||||
socketTopics.markAsUnreadForAll({uid: uid}, [tid], function (err) {
|
||||
assert.equal(err.message, '[[error:no-privileges]]');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail if topic does not exist', function (done) {
|
||||
socketTopics.markAsUnreadForAll({uid: uid}, [12312313], function (err) {
|
||||
assert.equal(err.message, '[[error:no-topic]]');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should mark topic unread for everyone', function (done) {
|
||||
socketTopics.markAsUnreadForAll({uid: adminUid}, [tid], function (err) {
|
||||
assert.ifError(err);
|
||||
async.parallel({
|
||||
adminRead: function (next) {
|
||||
topics.hasReadTopic(tid, adminUid, next);
|
||||
},
|
||||
regularRead: function (next) {
|
||||
topics.hasReadTopic(tid, uid, next);
|
||||
}
|
||||
}, function (err, results) {
|
||||
assert.ifError(err);
|
||||
assert.equal(results.adminRead, false);
|
||||
assert.equal(results.regularRead, false);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
after(function (done) {
|
||||
|
||||
Reference in New Issue
Block a user