mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-11-01 11:35:55 +01:00
Merge branch 'master' of https://github.com/designcreateplay/NodeBB
This commit is contained in:
44
app.js
44
app.js
@@ -55,7 +55,7 @@
|
|||||||
winston.info('');
|
winston.info('');
|
||||||
|
|
||||||
|
|
||||||
if (fs.existsSync(__dirname + '/config.json') && (!nconf.get('setup') && !nconf.get('upgrade'))) {
|
if (!nconf.get('help') && !nconf.get('setup') && !nconf.get('upgrade') && fs.existsSync(__dirname + '/config.json')) {
|
||||||
// Load server-side configs
|
// Load server-side configs
|
||||||
nconf.file({
|
nconf.file({
|
||||||
file: __dirname + '/config.json'
|
file: __dirname + '/config.json'
|
||||||
@@ -66,7 +66,7 @@
|
|||||||
nconf.set('upload_url', nconf.get('url') + 'uploads/');
|
nconf.set('upload_url', nconf.get('url') + 'uploads/');
|
||||||
|
|
||||||
winston.info('Initializing NodeBB v' + pkg.version + ', on port ' + nconf.get('port') + ', using Redis store at ' + nconf.get('redis:host') + ':' + nconf.get('redis:port') + '.');
|
winston.info('Initializing NodeBB v' + pkg.version + ', on port ' + nconf.get('port') + ', using Redis store at ' + nconf.get('redis:host') + ':' + nconf.get('redis:port') + '.');
|
||||||
winston.info('NodeBB instance bound to: ' + (nconf.get('bind_address') || 'Any address'));
|
winston.info('NodeBB instance bound to: ' + ((nconf.get('bind_address') === "0.0.0.0" || !nconf.get('bind_address')) ? 'Any address (0.0.0.0)' : nconf.get('bind_address')));
|
||||||
|
|
||||||
if (process.env.NODE_ENV === 'development') {
|
if (process.env.NODE_ENV === 'development') {
|
||||||
winston.info('Base Configuration OK.');
|
winston.info('Base Configuration OK.');
|
||||||
@@ -87,7 +87,8 @@
|
|||||||
SocketIO = require('socket.io').listen(global.server, { log: false, transports: ['websocket', 'xhr-polling', 'jsonp-polling', 'flashsocket']}),
|
SocketIO = require('socket.io').listen(global.server, { log: false, transports: ['websocket', 'xhr-polling', 'jsonp-polling', 'flashsocket']}),
|
||||||
websockets = require('./src/websockets.js'),
|
websockets = require('./src/websockets.js'),
|
||||||
posts = require('./src/posts.js'),
|
posts = require('./src/posts.js'),
|
||||||
plugins = require('./src/plugins'); // Don't remove this - plugins initializes itself
|
plugins = require('./src/plugins'), // Don't remove this - plugins initializes itself
|
||||||
|
Notifications = require('./src/notifications');
|
||||||
|
|
||||||
websockets.init(SocketIO);
|
websockets.init(SocketIO);
|
||||||
|
|
||||||
@@ -106,18 +107,10 @@
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
templates.ready(webserver.init);
|
templates.ready(webserver.init);
|
||||||
});
|
|
||||||
|
|
||||||
} else if (nconf.get('upgrade')) {
|
Notifications.init();
|
||||||
nconf.file({
|
|
||||||
file: __dirname + '/config.json'
|
|
||||||
});
|
});
|
||||||
meta = require('./src/meta.js');
|
} else if (nconf.get('setup') || !fs.existsSync(__dirname + '/config.json')) {
|
||||||
|
|
||||||
meta.configs.init(function () {
|
|
||||||
require('./src/upgrade').upgrade();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// New install, ask setup questions
|
// New install, ask setup questions
|
||||||
if (nconf.get('setup')) {
|
if (nconf.get('setup')) {
|
||||||
winston.info('NodeBB Setup Triggered via Command Line');
|
winston.info('NodeBB Setup Triggered via Command Line');
|
||||||
@@ -135,10 +128,29 @@
|
|||||||
if (err) {
|
if (err) {
|
||||||
winston.error('There was a problem completing NodeBB setup: ', err.message);
|
winston.error('There was a problem completing NodeBB setup: ', err.message);
|
||||||
} else {
|
} else {
|
||||||
winston.info('NodeBB Setup Completed.');
|
winston.info('NodeBB Setup Completed. Run \'node app\' to manually start your NodeBB server.');
|
||||||
}
|
}
|
||||||
|
|
||||||
process.exit();
|
process.exit();
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}());
|
} else if (nconf.get('upgrade')) {
|
||||||
|
nconf.file({
|
||||||
|
file: __dirname + '/config.json'
|
||||||
|
});
|
||||||
|
meta = require('./src/meta.js');
|
||||||
|
|
||||||
|
meta.configs.init(function () {
|
||||||
|
require('./src/upgrade').upgrade();
|
||||||
|
});
|
||||||
|
} else/* if (nconf.get('help') */{
|
||||||
|
winston.info('Usage: node app [options] [arguments]');
|
||||||
|
winston.info(' [NODE_ENV=development | NODE_ENV=production] node app [--start] [arguments]');
|
||||||
|
winston.info('');
|
||||||
|
winston.info('Options:');
|
||||||
|
winston.info(' --help displays this usage information');
|
||||||
|
winston.info(' --setup configure your environment and setup NodeBB');
|
||||||
|
winston.info(' --upgrade upgrade NodeBB, first read: github.com/designcreateplay/NodeBB/wiki/Upgrading-NodeBB');
|
||||||
|
winston.info(' --start manually start NodeBB (default when no options are given)');
|
||||||
|
};
|
||||||
|
}());
|
||||||
|
@@ -44,7 +44,8 @@
|
|||||||
"nodebb-plugin-mentions": "~0.1.13",
|
"nodebb-plugin-mentions": "~0.1.13",
|
||||||
"nodebb-plugin-markdown": "~0.1.7",
|
"nodebb-plugin-markdown": "~0.1.7",
|
||||||
"nodebb-theme-vanilla": "designcreateplay/nodebb-theme-vanilla",
|
"nodebb-theme-vanilla": "designcreateplay/nodebb-theme-vanilla",
|
||||||
"nodebb-theme-cerulean": "0.0.3"
|
"nodebb-theme-cerulean": "0.0.3",
|
||||||
|
"cron": "~1.0.1"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"hiredis": "~0.1.15"
|
"hiredis": "~0.1.15"
|
||||||
|
@@ -101,6 +101,7 @@
|
|||||||
numUnread = data.unread.length,
|
numUnread = data.unread.length,
|
||||||
x;
|
x;
|
||||||
notifList.innerHTML = '';
|
notifList.innerHTML = '';
|
||||||
|
console.log(data);
|
||||||
if ((data.read.length + data.unread.length) > 0) {
|
if ((data.read.length + data.unread.length) > 0) {
|
||||||
for (x = 0; x < numUnread; x++) {
|
for (x = 0; x < numUnread; x++) {
|
||||||
notifEl.setAttribute('data-nid', data.unread[x].nid);
|
notifEl.setAttribute('data-nid', data.unread[x].nid);
|
||||||
@@ -115,15 +116,16 @@
|
|||||||
notifFrag.appendChild(notifEl.cloneNode(true));
|
notifFrag.appendChild(notifEl.cloneNode(true));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
notifEl.className = 'no-notifs';
|
||||||
notifEl.innerHTML = '<a>You have no notifications</a>';
|
notifEl.innerHTML = '<a>You have no notifications</a>';
|
||||||
notifFrag.appendChild(notifEl);
|
notifFrag.appendChild(notifEl.cloneNode(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add dedicated link to /notifications
|
// Add dedicated link to /notifications
|
||||||
notifEl.removeAttribute('data-nid');
|
notifEl.removeAttribute('data-nid');
|
||||||
notifEl.className = 'pagelink';
|
notifEl.className = 'pagelink';
|
||||||
notifEl.innerHTML = '<a href="' + RELATIVE_PATH + '/notifications">See all Notifications</a>';
|
notifEl.innerHTML = '<a href="' + RELATIVE_PATH + '/notifications">See all Notifications</a>';
|
||||||
notifFrag.appendChild(notifEl);
|
notifFrag.appendChild(notifEl.cloneNode(true));
|
||||||
|
|
||||||
notifList.appendChild(notifFrag);
|
notifList.appendChild(notifFrag);
|
||||||
|
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
generateUUID: function() {
|
generateUUID: function() {
|
||||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
||||||
var r = Math.random() * 16 | 0,
|
var r = Math.random() * 16 | 0,
|
||||||
v = c == 'x' ? r : (r & 0x3 | 0x8);
|
v = c === 'x' ? r : (r & 0x3 | 0x8);
|
||||||
return v.toString(16);
|
return v.toString(16);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -225,4 +225,4 @@
|
|||||||
module: {
|
module: {
|
||||||
exports: {}
|
exports: {}
|
||||||
}
|
}
|
||||||
} : module)
|
} : module);
|
@@ -24,9 +24,6 @@
|
|||||||
"forum": '../forum'
|
"forum": '../forum'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
requirejs.onError = function(err) {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<link rel="stylesheet" type="text/css" href="{relative_path}/css/theme.css" />
|
<link rel="stylesheet" type="text/css" href="{relative_path}/css/theme.css" />
|
||||||
|
@@ -1,16 +1,30 @@
|
|||||||
var RDB = require('./redis.js'),
|
var RDB = require('./redis.js'),
|
||||||
async = require('async'),
|
async = require('async'),
|
||||||
utils = require('../public/src/utils.js'),
|
utils = require('../public/src/utils.js'),
|
||||||
|
winston = require('winston'),
|
||||||
|
cron = require('cron').CronJob,
|
||||||
|
|
||||||
notifications = {
|
notifications = {
|
||||||
|
init: function() {
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
winston.info('[notifications.init] Registering jobs.');
|
||||||
|
}
|
||||||
|
|
||||||
|
new cron('0 0 * * *', notifications.prune, null, true);
|
||||||
|
},
|
||||||
get: function(nid, uid, callback) {
|
get: function(nid, uid, callback) {
|
||||||
RDB.multi()
|
RDB.multi()
|
||||||
.hmget('notifications:' + nid, 'text', 'score', 'path', 'datetime', 'uniqueId')
|
.hmget('notifications:' + nid, 'text', 'score', 'path', 'datetime', 'uniqueId')
|
||||||
.zrank('uid:' + uid + ':notifications:read', nid)
|
.zrank('uid:' + uid + ':notifications:read', nid)
|
||||||
|
.exists('notifications:' + nid)
|
||||||
.exec(function(err, results) {
|
.exec(function(err, results) {
|
||||||
var notification = results[0]
|
var notification = results[0],
|
||||||
readIdx = results[1];
|
readIdx = results[1];
|
||||||
|
|
||||||
|
if (!results[2]) {
|
||||||
|
return callback(null);
|
||||||
|
}
|
||||||
|
|
||||||
callback({
|
callback({
|
||||||
nid: nid,
|
nid: nid,
|
||||||
text: notification[0],
|
text: notification[0],
|
||||||
@@ -30,16 +44,32 @@ var RDB = require('./redis.js'),
|
|||||||
* the new one put in its place.
|
* the new one put in its place.
|
||||||
*/
|
*/
|
||||||
RDB.incr('notifications:next_nid', function(err, nid) {
|
RDB.incr('notifications:next_nid', function(err, nid) {
|
||||||
|
RDB.sadd('notifications', nid);
|
||||||
RDB.hmset('notifications:' + nid, {
|
RDB.hmset('notifications:' + nid, {
|
||||||
text: text || '',
|
text: text || '',
|
||||||
path: path || null,
|
path: path || null,
|
||||||
datetime: Date.now(),
|
datetime: Date.now(),
|
||||||
uniqueId: uniqueId || utils.generateUUID()
|
uniqueId: uniqueId || utils.generateUUID()
|
||||||
}, function(err, status) {
|
}, function(err, status) {
|
||||||
if (!err) callback(nid);
|
if (!err) {
|
||||||
|
callback(nid);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
destroy: function(nid) {
|
||||||
|
var multi = RDB.multi();
|
||||||
|
|
||||||
|
multi.del('notifications:' + nid);
|
||||||
|
multi.srem('notifications', nid);
|
||||||
|
|
||||||
|
multi.exec(function(err) {
|
||||||
|
if (err) {
|
||||||
|
winston.error('Problem deleting expired notifications. Stack follows.');
|
||||||
|
winston.error(err.stack);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
push: function(nid, uids, callback) {
|
push: function(nid, uids, callback) {
|
||||||
if (!Array.isArray(uids)) uids = [uids];
|
if (!Array.isArray(uids)) uids = [uids];
|
||||||
|
|
||||||
@@ -48,12 +78,14 @@ var RDB = require('./redis.js'),
|
|||||||
|
|
||||||
notifications.get(nid, null, function(notif_data) {
|
notifications.get(nid, null, function(notif_data) {
|
||||||
for (x = 0; x < numUids; x++) {
|
for (x = 0; x < numUids; x++) {
|
||||||
if (parseInt(uids[x]) > 0) {
|
if (parseInt(uids[x], 10) > 0) {
|
||||||
(function(uid) {
|
(function(uid) {
|
||||||
notifications.remove_by_uniqueId(notif_data.uniqueId, uid, function() {
|
notifications.remove_by_uniqueId(notif_data.uniqueId, uid, function() {
|
||||||
RDB.zadd('uid:' + uid + ':notifications:unread', notif_data.datetime, nid);
|
RDB.zadd('uid:' + uid + ':notifications:unread', notif_data.datetime, nid);
|
||||||
global.io.sockets.in('uid_' + uid).emit('event:new_notification');
|
global.io.sockets.in('uid_' + uid).emit('event:new_notification');
|
||||||
if (callback) callback(true);
|
if (callback) {
|
||||||
|
callback(true);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
})(uids[x]);
|
})(uids[x]);
|
||||||
}
|
}
|
||||||
@@ -67,13 +99,18 @@ var RDB = require('./redis.js'),
|
|||||||
if (nids && nids.length > 0) {
|
if (nids && nids.length > 0) {
|
||||||
async.each(nids, function(nid, next) {
|
async.each(nids, function(nid, next) {
|
||||||
notifications.get(nid, uid, function(nid_info) {
|
notifications.get(nid, uid, function(nid_info) {
|
||||||
if (nid_info.uniqueId === uniqueId) RDB.zrem('uid:' + uid + ':notifications:unread', nid);
|
if (nid_info.uniqueId === uniqueId) {
|
||||||
|
RDB.zrem('uid:' + uid + ':notifications:unread', nid);
|
||||||
|
}
|
||||||
|
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
} else next();
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
function(next) {
|
function(next) {
|
||||||
@@ -81,17 +118,24 @@ var RDB = require('./redis.js'),
|
|||||||
if (nids && nids.length > 0) {
|
if (nids && nids.length > 0) {
|
||||||
async.each(nids, function(nid, next) {
|
async.each(nids, function(nid, next) {
|
||||||
notifications.get(nid, uid, function(nid_info) {
|
notifications.get(nid, uid, function(nid_info) {
|
||||||
if (nid_info.uniqueId === uniqueId) RDB.zrem('uid:' + uid + ':notifications:read', nid);
|
if (nid_info.uniqueId === uniqueId) {
|
||||||
|
RDB.zrem('uid:' + uid + ':notifications:read', nid);
|
||||||
|
}
|
||||||
|
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
} else next();
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
], function(err) {
|
], function(err) {
|
||||||
if (!err) callback(true);
|
if (!err) {
|
||||||
|
callback(true);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
mark_read: function(nid, uid, callback) {
|
mark_read: function(nid, uid, callback) {
|
||||||
@@ -99,38 +143,126 @@ var RDB = require('./redis.js'),
|
|||||||
notifications.get(nid, uid, function(notif_data) {
|
notifications.get(nid, uid, function(notif_data) {
|
||||||
RDB.zrem('uid:' + uid + ':notifications:unread', nid);
|
RDB.zrem('uid:' + uid + ':notifications:unread', nid);
|
||||||
RDB.zadd('uid:' + uid + ':notifications:read', notif_data.datetime, nid);
|
RDB.zadd('uid:' + uid + ':notifications:read', notif_data.datetime, nid);
|
||||||
if (callback) callback();
|
if (callback) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mark_read_multiple: function(nids, uid, callback) {
|
mark_read_multiple: function(nids, uid, callback) {
|
||||||
if (!Array.isArray(nids) && parseInt(nids, 10) > 0) nids = [nids];
|
if (!Array.isArray(nids) && parseInt(nids, 10) > 0) {
|
||||||
|
nids = [nids];
|
||||||
|
}
|
||||||
|
|
||||||
async.each(nids, function(nid, next) {
|
async.each(nids, function(nid, next) {
|
||||||
notifications.mark_read(nid, uid, function(err) {
|
notifications.mark_read(nid, uid, function(err) {
|
||||||
if (!err) next(null);
|
if (!err) {
|
||||||
|
next(null);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
if (callback) callback(err);
|
if (callback) {
|
||||||
|
callback(err);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
mark_all_read: function(uid, callback) {
|
mark_all_read: function(uid, callback) {
|
||||||
RDB.zrange('uid:' + uid + ':notifications:unread', 0, 10, function(err, nids) {
|
RDB.zrange('uid:' + uid + ':notifications:unread', 0, 10, function(err, nids) {
|
||||||
if (err) return callback(err);
|
if (err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
|
||||||
if (nids.length > 0) {
|
if (nids.length > 0) {
|
||||||
notifications.mark_read_multiple(nids, uid, function(err) {
|
notifications.mark_read_multiple(nids, uid, function(err) {
|
||||||
callback(err);
|
callback(err);
|
||||||
});
|
});
|
||||||
} else callback();
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
prune: function(cutoff) {
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
winston.info('[notifications.prune] Removing expired notifications from the database.');
|
||||||
|
}
|
||||||
|
|
||||||
|
var today = new Date(),
|
||||||
|
numPruned = 0;
|
||||||
|
|
||||||
|
if (!cutoff) {
|
||||||
|
cutoff = new Date(today.getFullYear(), today.getMonth(), today.getDate() - 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
var cutoffTime = cutoff.getTime();
|
||||||
|
|
||||||
|
async.parallel({
|
||||||
|
"inboxes": function(next) {
|
||||||
|
RDB.keys('uid:*:notifications:unread', next);
|
||||||
|
},
|
||||||
|
"nids": function(next) {
|
||||||
|
RDB.smembers('notifications', function(err, nids) {
|
||||||
|
async.filter(nids, function(nid, next) {
|
||||||
|
RDB.hget('notifications:' + nid, 'datetime', function(err, datetime) {
|
||||||
|
if (parseInt(datetime, 10) < cutoffTime) {
|
||||||
|
next(true);
|
||||||
|
} else {
|
||||||
|
next(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, function(expiredNids) {
|
||||||
|
next(null, expiredNids);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, function(err, results) {
|
||||||
|
if (!err) {
|
||||||
|
var numInboxes = results.inboxes.length,
|
||||||
|
x;
|
||||||
|
|
||||||
|
async.eachSeries(results.nids, function(nid, next) {
|
||||||
|
var multi = RDB.multi();
|
||||||
|
|
||||||
|
for(x=0;x<numInboxes;x++) {
|
||||||
|
multi.zscore(results.inboxes[x], nid);
|
||||||
|
}
|
||||||
|
|
||||||
|
multi.exec(function(err, results) {
|
||||||
|
// If the notification is not present in any inbox, delete it altogether
|
||||||
|
var expired = results.every(function(present) {
|
||||||
|
if (present === null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (expired) {
|
||||||
|
notifications.destroy(nid);
|
||||||
|
numPruned++;
|
||||||
|
}
|
||||||
|
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
}, function(err) {
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
winston.info('[notifications.prune] Notification pruning completed. ' + numPruned + ' expired notification' + (numPruned !== 1 ? 's' : '') + ' removed.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
winston.error('[notifications.prune] Ran into trouble pruning expired notifications. Stack trace to follow.');
|
||||||
|
winston.error(err.stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
init: notifications.init,
|
||||||
get: notifications.get,
|
get: notifications.get,
|
||||||
create: notifications.create,
|
create: notifications.create,
|
||||||
push: notifications.push,
|
push: notifications.push,
|
||||||
mark_read: notifications.mark_read_multiple,
|
mark_read: notifications.mark_read_multiple,
|
||||||
mark_all_read: notifications.mark_all_read
|
mark_all_read: notifications.mark_all_read,
|
||||||
}
|
prune: notifications.prune
|
||||||
|
};
|
||||||
|
20
src/routes/debug.js
Normal file
20
src/routes/debug.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
var DebugRoute = function(app) {
|
||||||
|
app.namespace('/debug', function() {
|
||||||
|
app.get('/prune', function(req, res) {
|
||||||
|
var Notifications = require('../notifications');
|
||||||
|
|
||||||
|
Notifications.prune(new Date(), function() {
|
||||||
|
console.log('done');
|
||||||
|
});
|
||||||
|
res.send();
|
||||||
|
});
|
||||||
|
|
||||||
|
app.get('/uuidtest', function(req, res) {
|
||||||
|
var Utils = require('../../public/src/utils.js');
|
||||||
|
|
||||||
|
res.send(Utils.generateUUID());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = DebugRoute;
|
@@ -59,6 +59,28 @@ Upgrade.upgrade = function() {
|
|||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
function(next) {
|
||||||
|
RDB.exists('notifications', function(err, exists) {
|
||||||
|
if (!exists) {
|
||||||
|
RDB.keys('notifications:*', function(err, keys) {
|
||||||
|
var multi = RDB.multi();
|
||||||
|
|
||||||
|
keys = keys.filter(function(key) {
|
||||||
|
if (key === 'notifications:next_nid') return false;
|
||||||
|
else return true;
|
||||||
|
}).map(function(key) {
|
||||||
|
return key.slice(14);
|
||||||
|
});
|
||||||
|
|
||||||
|
winston.info('[2013/10/23] Adding existing notifications to set');
|
||||||
|
RDB.sadd('notifications', keys, next);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
winston.info('[2013/10/23] Updates to Notifications skipped.');
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
// Add new schema updates here
|
// Add new schema updates here
|
||||||
], function(err) {
|
], function(err) {
|
||||||
|
16
src/user.js
16
src/user.js
@@ -903,7 +903,13 @@ var utils = require('./../public/src/utils.js'),
|
|||||||
if (nids && nids.length > 0) {
|
if (nids && nids.length > 0) {
|
||||||
async.eachSeries(nids, function(nid, next) {
|
async.eachSeries(nids, function(nid, next) {
|
||||||
notifications.get(nid, uid, function(notif_data) {
|
notifications.get(nid, uid, function(notif_data) {
|
||||||
unread.push(notif_data);
|
// If the notification could not be found, silently drop it
|
||||||
|
if (notif_data) {
|
||||||
|
unread.push(notif_data);
|
||||||
|
} else {
|
||||||
|
RDB.zrem('uid:' + uid + ':notifications:unread', nid);
|
||||||
|
}
|
||||||
|
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
@@ -925,7 +931,13 @@ var utils = require('./../public/src/utils.js'),
|
|||||||
if (nids && nids.length > 0) {
|
if (nids && nids.length > 0) {
|
||||||
async.eachSeries(nids, function(nid, next) {
|
async.eachSeries(nids, function(nid, next) {
|
||||||
notifications.get(nid, uid, function(notif_data) {
|
notifications.get(nid, uid, function(notif_data) {
|
||||||
read.push(notif_data);
|
// If the notification could not be found, silently drop it
|
||||||
|
if (notif_data) {
|
||||||
|
read.push(notif_data);
|
||||||
|
} else {
|
||||||
|
RDB.zrem('uid:' + uid + ':notifications:read', nid);
|
||||||
|
}
|
||||||
|
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
|
@@ -136,6 +136,10 @@ var express = require('express'),
|
|||||||
app.use(function (req, res, next) {
|
app.use(function (req, res, next) {
|
||||||
nconf.set('https', req.secure);
|
nconf.set('https', req.secure);
|
||||||
res.locals.csrf_token = req.session._csrf;
|
res.locals.csrf_token = req.session._csrf;
|
||||||
|
|
||||||
|
// Disable framing
|
||||||
|
res.setHeader("X-Frame-Options", "DENY");
|
||||||
|
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -667,6 +671,10 @@ var express = require('express'),
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Debug routes
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
require('./routes/debug')(app);
|
||||||
|
}
|
||||||
|
|
||||||
var custom_routes = {
|
var custom_routes = {
|
||||||
'routes': [],
|
'routes': [],
|
||||||
|
9
tests/.jshintrc
Normal file
9
tests/.jshintrc
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"strict" : false, // true: Requires all functions run in ES5 Strict Mode
|
||||||
|
|
||||||
|
// Custom Globals
|
||||||
|
"globals" : {
|
||||||
|
"it": false,
|
||||||
|
"describe": false
|
||||||
|
}
|
||||||
|
}
|
@@ -8,5 +8,28 @@ describe("Utility Methods", function(){
|
|||||||
var username = "John\"'-. Doeäâèéë1234";
|
var username = "John\"'-. Doeäâèéë1234";
|
||||||
assert(utils.isUserNameValid(username), 'invalid username');
|
assert(utils.isUserNameValid(username), 'invalid username');
|
||||||
});
|
});
|
||||||
|
it("rejects empty string", function(){
|
||||||
|
var username = "";
|
||||||
|
assert.ifError(utils.isUserNameValid(username), 'accepted as valid username');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("email validation", function(){
|
||||||
|
it("accepts sample address", function(){
|
||||||
|
var email = 'sample@example.com';
|
||||||
|
assert(utils.isEmailValid(email), 'invalid email');
|
||||||
|
});
|
||||||
|
it("rejects empty address", function(){
|
||||||
|
var email = '';
|
||||||
|
assert.ifError(utils.isEmailValid(email), 'accepted as valid email');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("UUID generation", function(){
|
||||||
|
it("return unique random value every time", function(){
|
||||||
|
var uuid1 = utils.generateUUID(),
|
||||||
|
uuid2 = utils.generateUUID();
|
||||||
|
assert.notEqual(uuid1, uuid2, "matches");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user