diff --git a/src/categories.js b/src/categories.js
index 640122598d..0e47e7b1a8 100644
--- a/src/categories.js
+++ b/src/categories.js
@@ -58,25 +58,6 @@ var db = require('./database'),
Categories.getCategoryTopics(category_id, start, end, current_user, next);
}
- function getActiveUsers(next) {
- Categories.getActiveUsers(category_id, function(err, uids) {
- if(err) {
- return next(err);
- }
- user.getMultipleUserFields(uids, ['uid', 'username', 'userslug', 'picture'], next);
- });
- }
-
- function getModerators(next) {
- Categories.getModerators(category_id, next);
- }
-
- function getSidebars(next) {
- plugins.fireHook('filter:category.build_sidebars', [], function(err, sidebars) {
- next(err, sidebars);
- });
- }
-
function getPageCount(next) {
Categories.getPageCount(category_id, current_user, next);
}
@@ -84,9 +65,6 @@ var db = require('./database'),
async.parallel({
'category': getCategoryData,
'topics': getTopics,
- 'active_users': getActiveUsers,
- 'moderators': getModerators,
- 'sidebars': getSidebars,
'pageCount': getPageCount
}, function(err, results) {
if(err) {
@@ -100,13 +78,10 @@ var db = require('./database'),
'disabled': results.category.disabled,
'topic_row_size': 'col-md-9',
'category_id': category_id,
- 'active_users': results.active_users,
- 'moderators': results.moderators,
'topics': results.topics.topics,
'nextStart': results.topics.nextStart,
'pageCount': results.pageCount,
'disableSocialButtons': meta.config.disableSocialButtons !== undefined ? parseInt(meta.config.disableSocialButtons, 10) !== 0 : false,
- 'sidebars': results.sidebars
};
callback(null, category);
diff --git a/src/meta.js b/src/meta.js
index bd77781b17..d95614b082 100644
--- a/src/meta.js
+++ b/src/meta.js
@@ -171,8 +171,6 @@ var fs = require('fs'),
var user = require('./user');
Meta.title.parseFragment(decodeURIComponent(urlFragment), function(err, title) {
- var title;
-
if (err) {
title = Meta.config.browserTitle || 'NodeBB';
} else {
diff --git a/src/plugins.js b/src/plugins.js
index d2b7a6cc98..9614777524 100644
--- a/src/plugins.js
+++ b/src/plugins.js
@@ -375,8 +375,10 @@ var fs = require('fs'),
dirs = dirs.map(function(file) {
return path.join(npmPluginPath, file);
}).filter(function(file) {
- var stats = fs.statSync(file);
- if (stats.isDirectory() && file.substr(npmPluginPath.length + 1, 14) === 'nodebb-plugin-') return true;
+ var stats = fs.statSync(file),
+ isPlugin = file.substr(npmPluginPath.length + 1, 14) === 'nodebb-plugin-' || file.substr(npmPluginPath.length + 1, 14) === 'nodebb-widget-';
+
+ if (stats.isDirectory() && isPlugin) return true;
else return false;
});
diff --git a/src/routes/admin.js b/src/routes/admin.js
index af1f534f13..d04ac78b80 100644
--- a/src/routes/admin.js
+++ b/src/routes/admin.js
@@ -12,6 +12,7 @@ var nconf = require('nconf'),
categories = require('./../categories'),
meta = require('../meta'),
plugins = require('../plugins'),
+ widgets = require('../widgets'),
image = require('./../image'),
file = require('./../file'),
Languages = require('../languages'),
@@ -414,7 +415,32 @@ var nconf = require('nconf'),
});
app.get('/themes', function (req, res) {
- res.json(200, {});
+ async.parallel({
+ areas: function(next) {
+ plugins.fireHook('filter:widgets.getAreas', [], next);
+ },
+ widgets: function(next) {
+ plugins.fireHook('filter:widgets.getWidgets', [], next);
+ }
+ }, function(err, data) {
+ async.each(data.areas, function(area, next) {
+ widgets.getArea(area.template, area.location, function(err, areaData) {
+ area.data = areaData;
+ next(err);
+ });
+ }, function(err) {
+ for (var w in data.widgets) {
+ if (data.widgets.hasOwnProperty(w)) {
+ data.widgets[w].content += "
Title: Container: ";
+ }
+ }
+
+ res.json(200, {
+ areas: data.areas,
+ widgets: data.widgets
+ });
+ });
+ });
});
app.get('/testing/categories', function (req, res) {
diff --git a/src/routes/api.js b/src/routes/api.js
index 5942f995f5..74c434010a 100644
--- a/src/routes/api.js
+++ b/src/routes/api.js
@@ -108,45 +108,7 @@ var path = require('path'),
data.categories = visibleCategories;
async.each(data.categories, getRecentReplies, function (err) {
-
- var motdString,
- assemble = function() {
- data.motd_class = (parseInt(meta.config.show_motd, 10) === 1 || meta.config.show_motd === undefined) ? '' : ' none';
- data.motd_class += (meta.config.motd && meta.config.motd.length > 0) ? '' : ' default';
- data.motd_class += meta.config.motd_class ? ' ' + meta.config.motd_class : '';
-
- data.motd = motdString;
- res.json(data);
- };
-
- if (!meta.config.motd) {
- translator.translate('\n\n
NodeBB v' + pkg.version + ' \n\n
[[global:motd.welcome]] \
-
\
- ', function(motd) {
- motdString = motd;
- assemble();
- });
- } else {
- motdString = meta.config.motd;
- assemble();
- }
+ res.json(data);
});
});
});
diff --git a/src/routes/authentication.js b/src/routes/authentication.js
index 2476b391f2..5f40c1133b 100644
--- a/src/routes/authentication.js
+++ b/src/routes/authentication.js
@@ -13,16 +13,6 @@
login_strategies = [];
- passport.use(new passportLocal(function(user, password, next) {
- Auth.login(user, password, function(err, login) {
- if (!err) {
- next(null, login.user);
- } else {
- next(null, false, err);
- }
- });
- }));
-
plugins.ready(function() {
plugins.fireHook('filter:auth.init', login_strategies, function(err) {
if (err) {
@@ -33,16 +23,6 @@
});
});
- passport.serializeUser(function(user, done) {
- done(null, user.uid);
- });
-
- passport.deserializeUser(function(uid, done) {
- done(null, {
- uid: uid
- });
- });
-
Auth.initialize = function(app) {
app.use(passport.initialize());
app.use(passport.session());
@@ -107,11 +87,9 @@
if (err) {
return next(err);
}
+
if (!user) {
- return res.send({
- success: false,
- message: info.message
- });
+ return res.json(403, info);
}
// Alter user cookie depending on passed-in option
@@ -127,10 +105,7 @@
req.login({
uid: user.uid
}, function() {
- res.send({
- success: true,
- message: 'authentication succeeded'
- });
+ res.json(info);
});
})(req, res, next);
});
@@ -163,50 +138,60 @@
Auth.login = function(username, password, next) {
if (!username || !password) {
- return next({
- status: 'error',
- message: 'invalid-user'
- });
- } else {
+ return next(new Error('invalid-user'));
+ }
- var userslug = utils.slugify(username);
+ var userslug = utils.slugify(username);
- user.getUidByUserslug(userslug, function(err, uid) {
+ user.getUidByUserslug(userslug, function(err, uid) {
+ if (err) {
+ return next(err);
+ }
+
+ if(!uid) {
+ return next(null, false, 'user doesn\'t exist');
+ }
+
+ user.getUserFields(uid, ['password', 'banned'], function(err, userData) {
if (err) {
- return next(new Error('redis-error'));
- } else if (uid == null) {
- return next(new Error('invalid-user'));
+ return next(err);
}
- user.getUserFields(uid, ['password', 'banned'], function(err, userData) {
- if (err) return next(err);
+ if (!userData || !userData.password) {
+ return next(new Error('invalid userdata or password'));
+ }
- if (userData.banned && parseInt(userData.banned, 10) === 1) {
- return next({
- status: "error",
- message: "user-banned"
- });
+ if (userData.banned && parseInt(userData.banned, 10) === 1) {
+ return next(null, false, 'User banned');
+ }
+
+ bcrypt.compare(password, userData.password, function(err, res) {
+ if (err) {
+ winston.err(err.message);
+ return next(new Error('bcrypt compare error'));
}
- bcrypt.compare(password, userData.password, function(err, res) {
- if (err) {
- winston.err(err.message);
- next(new Error('bcrypt compare error'));
- return;
- }
+ if (!res) {
+ next(null, false, 'invalid-password');
+ }
- if (res) {
- next(null, {
- user: {
- uid: uid
- }
- });
- } else {
- next(new Error('invalid-password'));
- }
- });
+ next(null, {
+ uid: uid
+ }, 'Authentication successful');
});
});
- }
+ });
}
+
+ passport.use(new passportLocal(Auth.login));
+
+ passport.serializeUser(function(user, done) {
+ done(null, user.uid);
+ });
+
+ passport.deserializeUser(function(uid, done) {
+ done(null, {
+ uid: uid
+ });
+ });
}(exports));
\ No newline at end of file
diff --git a/src/routes/user.js b/src/routes/user.js
index be3b474374..45a0c7f20c 100644
--- a/src/routes/user.js
+++ b/src/routes/user.js
@@ -45,18 +45,17 @@ var fs = require('fs'),
app.namespace('/user', function () {
- function createRoute(routeName, path, templateName) {
- app.get(routeName, function(req, res, next) {
- if (!req.params.userslug) {
- return next();
- }
+ function createRoute(routeName, path, templateName, access) {
- if (!req.user && (path === '/favourites' || !!parseInt(meta.config.privateUserInfo, 10))) {
+ function isAllowed(req, res, next) {
+ var callerUID = req.user ? parseInt(req.user.uid, 10) : 0;
+
+ if (!callerUID && !!parseInt(meta.config.privateUserInfo, 10)) {
return res.redirect('/403');
}
user.getUidByUserslug(req.params.userslug, function (err, uid) {
- if(err) {
+ if (err) {
return next(err);
}
@@ -64,17 +63,41 @@ var fs = require('fs'),
return res.redirect('/404');
}
- app.build_header({
- req: req,
- res: res
- }, function (err, header) {
- if(err) {
- return next(err);
- }
- res.send(header + app.create_route('user/' + req.params.userslug + path, templateName) + templates['footer']);
- });
+ if (parseInt(uid, 10) === callerUID) {
+ return next();
+ }
+
+ if (req.path.indexOf('/edit') !== -1) {
+ user.isAdministrator(callerUID, function(err, isAdmin) {
+ if(err) {
+ return next(err);
+ }
+
+ if(!isAdmin) {
+ return res.redirect('/403');
+ }
+
+ next();
+ });
+ } else if (req.path.indexOf('/settings') !== -1 || req.path.indexOf('/favourites') !== -1) {
+ res.redirect('/403')
+ } else {
+ next();
+ }
});
- })
+ }
+
+ app.get(routeName, isAllowed, function(req, res, next) {
+ app.build_header({
+ req: req,
+ res: res
+ }, function (err, header) {
+ if(err) {
+ return next(err);
+ }
+ res.send(header + app.create_route('user/' + req.params.userslug + path, templateName) + templates['footer']);
+ });
+ });
}
createRoute('/:userslug', '', 'account');
@@ -82,66 +105,8 @@ var fs = require('fs'),
createRoute('/:userslug/followers', '/followers', 'followers');
createRoute('/:userslug/favourites', '/favourites', 'favourites');
createRoute('/:userslug/posts', '/posts', 'accountposts');
-
- app.get('/:userslug/edit', function (req, res, next) {
-
- if (!req.user) {
- return res.redirect('/403');
- }
-
- user.getUserField(req.user.uid, 'userslug', function (err, userslug) {
- function done() {
- app.build_header({
- req: req,
- res: res
- }, function (err, header) {
- res.send(header + app.create_route('user/' + req.params.userslug + '/edit', 'accountedit') + templates['footer']);
- });
- }
-
- if(err || !userslug) {
- return next(err);
- }
-
- if (userslug === req.params.userslug) {
- return done();
- }
-
- user.isAdministrator(req.user.uid, function(err, isAdmin) {
- if(err) {
- return next(err);
- }
-
- if(!isAdmin) {
- return res.redirect('/403');
- }
-
- done();
- });
- });
- });
-
- app.get('/:userslug/settings', function (req, res) {
-
- if (!req.user) {
- return res.redirect('/403');
- }
-
- user.getUserField(req.user.uid, 'userslug', function (err, userslug) {
- if (req.params.userslug && userslug === req.params.userslug) {
- app.build_header({
- req: req,
- res: res
- }, function (err, header) {
- res.send(header + app.create_route('user/' + req.params.userslug + '/settings', 'accountsettings') + templates['footer']);
- })
- } else {
- return res.redirect('/404');
- }
- });
- });
-
-
+ createRoute('/:userslug/edit', '/edit', 'accountedit');
+ createRoute('/:userslug/settings', '/settings', 'accountsettings');
app.post('/uploadpicture', function (req, res) {
if (!req.user) {
@@ -257,164 +222,77 @@ var fs = require('fs'),
next();
}
- app.get('/api/user/:userslug/following', isAllowed, function (req, res, next) {
- var callerUID = req.user ? req.user.uid : '0';
+ app.get('/api/user/:userslug/following', isAllowed, getUserFollowing);
+ app.get('/api/user/:userslug/followers', isAllowed, getUserFollowers);
+ app.get('/api/user/:userslug/edit', isAllowed, getUserEdit);
+ app.get('/api/user/:userslug/settings', isAllowed, getUserSettings);
+ app.get('/api/user/:userslug/favourites', isAllowed, getUserFavourites);
+ app.get('/api/user/:userslug/posts', isAllowed, getUserPosts);
+ app.get('/api/user/uid/:uid', isAllowed, getUserData);
+ app.get('/api/user/:userslug', isAllowed, getUserProfile);
+ app.get('/api/users', isAllowed, getOnlineUsers);
+ app.get('/api/users/sort-posts', isAllowed, getUsersSortedByPosts);
+ app.get('/api/users/sort-reputation', isAllowed, getUsersSortedByReputation);
+ app.get('/api/users/latest', isAllowed, getUsersSortedByJoinDate);
+ app.get('/api/users/online', isAllowed, getOnlineUsers);
+ app.get('/api/users/search', isAllowed, getUsersForSearch);
+
+
+ function getUserProfile(req, res, next) {
+ var callerUID = req.user ? parseInt(req.user.uid, 10) : 0;
getUserDataByUserSlug(req.params.userslug, callerUID, function (err, userData) {
if(err) {
return next(err);
}
- if (userData) {
- user.getFollowing(userData.uid, function (err, followingData) {
- if(err) {
- return next(err);
- }
- userData.following = followingData;
- userData.followingCount = followingData.length;
- res.json(userData);
- });
-
- } else {
- res.json(404, {
+ if(!userData) {
+ return res.json(404, {
error: 'User not found!'
});
}
- });
- });
- app.get('/api/user/:userslug/followers', isAllowed, function (req, res, next) {
- var callerUID = req.user ? req.user.uid : '0';
+ user.isFollowing(callerUID, userData.theirid, function (isFollowing) {
- getUserDataByUserSlug(req.params.userslug, callerUID, function (err, userData) {
- if(err) {
- return next(err);
- }
+ posts.getPostsByUid(callerUID, userData.theirid, 0, 9, function (err, userPosts) {
- if (userData) {
- user.getFollowers(userData.uid, function (err, followersData) {
if(err) {
return next(err);
}
- userData.followers = followersData;
- userData.followersCount = followersData.length;
- res.json(userData);
- });
- } else {
- res.json(404, {
- error: 'User not found!'
- });
- }
- });
- });
- app.get('/api/user/:userslug/edit', function (req, res, next) {
- var callerUID = req.user ? req.user.uid : '0';
+ userData.posts = userPosts.posts.filter(function (p) {
+ return p && parseInt(p.deleted, 10) !== 1;
+ });
- if(!parseInt(callerUID, 10)) {
- return res.json(403, {
- error: 'Not allowed!'
+ userData.isFollowing = isFollowing;
+
+ if (!userData.profileviews) {
+ userData.profileviews = 1;
+ }
+
+ if (callerUID !== parseInt(userData.uid, 10) && callerUID) {
+ user.incrementUserFieldBy(userData.uid, 'profileviews', 1);
+ }
+
+ postTools.parse(userData.signature, function (err, signature) {
+ userData.signature = signature;
+ res.json(userData);
+ });
+ });
});
- }
+ });
+ }
- getUserDataByUserSlug(req.params.userslug, callerUID, function (err, userData) {
- if(err) {
- return next(err);
- }
+ function getUserData(req, res, next) {
+ var uid = req.params.uid ? req.params.uid : 0;
+
+ user.getUserData(uid, function(err, userData) {
res.json(userData);
});
- });
+ }
- app.get('/api/user/:userslug/settings', function(req, res, next) {
- var callerUID = req.user ? req.user.uid : '0';
-
- user.getUidByUserslug(req.params.userslug, function(err, uid) {
- if (err) {
- return next(err);
- }
-
- if (!uid) {
- return res.json(404, {
- error: 'User not found!'
- });
- }
-
- if (uid != callerUID || callerUID == '0') {
- return res.json(403, {
- error: 'Not allowed!'
- });
- }
-
- plugins.fireHook('filter:user.settings', [], function(err, settings) {
- if (err) {
- return next(err);
- }
-
- user.getUserFields(uid, ['username', 'userslug'], function(err, userData) {
- if (err) {
- return next(err);
- }
-
- if(!userData) {
- return res.json(404, {
- error: 'User not found!'
- });
- }
- userData.yourid = req.user.uid;
- userData.theirid = uid;
- userData.settings = settings;
- res.json(userData);
- });
- });
-
- });
- });
-
- app.get('/api/user/:userslug/favourites', isAllowed, function (req, res, next) {
- var callerUID = req.user ? req.user.uid : '0';
-
- user.getUidByUserslug(req.params.userslug, function (err, uid) {
- if (!uid) {
- return res.json(404, {
- error: 'User not found!'
- });
- }
-
- if (uid != callerUID || callerUID == '0') {
- return res.json(403, {
- error: 'Not allowed!'
- });
- }
-
- user.getUserFields(uid, ['username', 'userslug'], function (err, userData) {
- if (err) {
- return next(err);
- }
-
- if (!userData) {
- return res.json(404, {
- error: 'User not found!'
- });
- }
-
- posts.getFavourites(uid, 0, 9, function (err, favourites) {
- if (err) {
- return next(err);
- }
-
- userData.theirid = uid;
- userData.yourid = callerUID;
- userData.posts = favourites.posts;
- userData.nextStart = favourites.nextStart;
-
- res.json(userData);
- });
- });
- });
- });
-
- app.get('/api/user/:userslug/posts', isAllowed, function (req, res, next) {
- var callerUID = req.user ? req.user.uid : '0';
+ function getUserPosts(req, res, next) {
+ var callerUID = req.user ? parseInt(req.user.uid, 10) : 0;
user.getUidByUserslug(req.params.userslug, function (err, uid) {
if (!uid) {
@@ -448,70 +326,157 @@ var fs = require('fs'),
});
});
});
- });
+ }
+ function getUserFavourites(req, res, next) {
+ var callerUID = req.user ? parseInt(req.user.uid, 10) : 0;
- app.get('/api/user/uid/:uid', isAllowed, function(req, res, next) {
- var uid = req.params.uid ? req.params.uid : 0;
+ user.getUidByUserslug(req.params.userslug, function (err, uid) {
+ if (!uid) {
+ return res.json(404, {
+ error: 'User not found!'
+ });
+ }
- user.getUserData(uid, function(err, userData) {
+ if (parseInt(uid, 10) !== callerUID) {
+ return res.json(403, {
+ error: 'Not allowed!'
+ });
+ }
+
+ user.getUserFields(uid, ['username', 'userslug'], function (err, userData) {
+ if (err) {
+ return next(err);
+ }
+
+ if (!userData) {
+ return res.json(404, {
+ error: 'User not found!'
+ });
+ }
+
+ posts.getFavourites(uid, 0, 9, function (err, favourites) {
+ if (err) {
+ return next(err);
+ }
+
+ userData.theirid = uid;
+ userData.yourid = callerUID;
+ userData.posts = favourites.posts;
+ userData.nextStart = favourites.nextStart;
+
+ res.json(userData);
+ });
+ });
+ });
+ }
+
+ function getUserSettings(req, res, next) {
+ var callerUID = req.user ? parseInt(req.user.uid, 10) : 0;
+
+ user.getUidByUserslug(req.params.userslug, function(err, uid) {
+ if (err) {
+ return next(err);
+ }
+
+ if (!uid) {
+ return res.json(404, {
+ error: 'User not found!'
+ });
+ }
+
+ if (parseInt(uid, 10) !== callerUID) {
+ return res.json(403, {
+ error: 'Not allowed!'
+ });
+ }
+
+ plugins.fireHook('filter:user.settings', [], function(err, settings) {
+ if (err) {
+ return next(err);
+ }
+
+ user.getUserFields(uid, ['username', 'userslug'], function(err, userData) {
+ if (err) {
+ return next(err);
+ }
+
+ if(!userData) {
+ return res.json(404, {
+ error: 'User not found!'
+ });
+ }
+ userData.yourid = req.user.uid;
+ userData.theirid = uid;
+ userData.settings = settings;
+ res.json(userData);
+ });
+ });
+
+ });
+ }
+
+ function getUserEdit(req, res, next) {
+ var callerUID = req.user ? parseInt(req.user.uid, 10) : 0;
+
+ getUserDataByUserSlug(req.params.userslug, callerUID, function (err, userData) {
+ if(err) {
+ return next(err);
+ }
res.json(userData);
});
- });
+ }
- app.get('/api/user/:userslug', isAllowed, function (req, res, next) {
- var callerUID = req.user ? req.user.uid : '0';
+ function getUserFollowers(req, res, next) {
+ var callerUID = req.user ? parseInt(req.user.uid, 10) : 0;
getUserDataByUserSlug(req.params.userslug, callerUID, function (err, userData) {
if(err) {
return next(err);
}
- if(!userData) {
- return res.json(404, {
- error: 'User not found!'
- });
- }
-
- user.isFollowing(callerUID, userData.theirid, function (isFollowing) {
-
- posts.getPostsByUid(callerUID, userData.theirid, 0, 9, function (err, userPosts) {
-
+ if (userData) {
+ user.getFollowers(userData.uid, function (err, followersData) {
if(err) {
return next(err);
}
-
- userData.posts = userPosts.posts.filter(function (p) {
- return p && parseInt(p.deleted, 10) !== 1;
- });
-
- userData.isFollowing = isFollowing;
-
- if (!userData.profileviews) {
- userData.profileviews = 1;
- }
-
- if (parseInt(callerUID, 10) !== parseInt(userData.uid, 10) && parseInt(callerUID, 0)) {
- user.incrementUserFieldBy(userData.uid, 'profileviews', 1);
- }
-
- postTools.parse(userData.signature, function (err, signature) {
- userData.signature = signature;
- res.json(userData);
- });
+ userData.followers = followersData;
+ userData.followersCount = followersData.length;
+ res.json(userData);
});
- });
-
+ } else {
+ res.json(404, {
+ error: 'User not found!'
+ });
+ }
});
- });
+ }
- app.get('/api/users', isAllowed, getOnlineUsers);
- app.get('/api/users/sort-posts', isAllowed, getUsersSortedByPosts);
- app.get('/api/users/sort-reputation', isAllowed, getUsersSortedByReputation);
- app.get('/api/users/latest', isAllowed, getUsersSortedByJoinDate);
- app.get('/api/users/online', isAllowed, getOnlineUsers);
- app.get('/api/users/search', isAllowed, getUsersForSearch);
+ function getUserFollowing(req, res, next) {
+ var callerUID = req.user ? parseInt(req.user.uid, 10) : 0;
+ getUserDataByUserSlug(req.params.userslug, callerUID, function (err, userData) {
+ if(err) {
+ return next(err);
+ }
+
+ if (userData) {
+ user.getFollowing(userData.uid, function (err, followingData) {
+ if(err) {
+ return next(err);
+ }
+ userData.following = followingData;
+ userData.followingCount = followingData.length;
+ res.json(userData);
+ });
+
+ } else {
+ res.json(404, {
+ error: 'User not found!'
+ });
+ }
+ });
+ }
function getUsersSortedByJoinDate(req, res) {
user.getUsers('users:joindate', 0, 49, function (err, data) {
@@ -607,78 +572,76 @@ var fs = require('fs'),
}
function getUserDataByUserSlug(userslug, callerUID, callback) {
- var userData;
- async.waterfall([
- function(next) {
- user.getUidByUserslug(userslug, next);
- },
- function(uid, next) {
- if (!uid) {
- return next(new Error('invalid-user'));
+ user.getUidByUserslug(userslug, function(err, uid) {
+ if(err || !uid) {
+ return callback(err || new Error('invalid-user'));
+ }
+
+ async.parallel({
+ userData : function(next) {
+ user.getUserData(uid, next);
+ },
+ userSettings : function(next) {
+ user.getSettings(uid, next);
+ },
+ isAdmin : function(next) {
+ user.isAdministrator(callerUID, next);
+ },
+ followStats: function(next) {
+ user.getFollowStats(uid, next);
+ }
+ }, function(err, results) {
+ if(err || !results.userData) {
+ return callback(err || new Error('invalid-user'));
}
- user.getUserData(uid, next);
- },
- function(data, next) {
- userData = data;
- if (!userData) {
- return callback(new Error('invalid-user'));
+ var userData = results.userData;
+ var userSettings = results.userSettings;
+ var isAdmin = results.isAdmin;
+
+ userData.joindate = utils.toISOString(userData.joindate);
+ if(userData.lastonline) {
+ userData.lastonline = utils.toISOString(userData.lastonline);
+ } else {
+ userData.lastonline = userData.joindate;
}
- user.isAdministrator(callerUID, next);
- }
- ], function(err, isAdmin) {
- if(err) {
- return callback(err);
- }
-
- userData.joindate = utils.toISOString(userData.joindate);
- if(userData.lastonline) {
- userData.lastonline = utils.toISOString(userData.lastonline);
- } else {
- userData.lastonline = userData.joindate;
- }
-
- if (!userData.birthday) {
- userData.age = '';
- } else {
- userData.age = Math.floor((new Date().getTime() - new Date(userData.birthday).getTime()) / 31536000000);
- }
-
- function canSeeEmail() {
- return isAdmin || callerUID == userData.uid || (userData.email && (userData.showemail && parseInt(userData.showemail, 10) === 1));
- }
-
- if (!canSeeEmail()) {
- userData.email = "";
- }
-
- if (callerUID == userData.uid && (!userData.showemail || parseInt(userData.showemail, 10) === 0)) {
- userData.emailClass = "";
- } else {
- userData.emailClass = "hide";
- }
-
- userData.websiteName = userData.website.replace('http://', '').replace('https://', '');
- userData.banned = parseInt(userData.banned, 10) === 1;
- userData.uid = userData.uid;
- userData.yourid = callerUID;
- userData.theirid = userData.uid;
-
- userData.disableSignatures = meta.config.disableSignatures !== undefined && parseInt(meta.config.disableSignatures, 10) === 1;
-
- user.getFollowStats(userData.uid, function (err, followStats) {
- if(err) {
- return callback(err);
+ if (!userData.birthday) {
+ userData.age = '';
+ } else {
+ userData.age = Math.floor((new Date().getTime() - new Date(userData.birthday).getTime()) / 31536000000);
}
- userData.followingCount = followStats.followingCount;
- userData.followerCount = followStats.followerCount;
+
+ function canSeeEmail() {
+ return isAdmin || parseInt(callerUID, 10) === parseInt(userData.uid, 10) || (userData.email && userSettings.showemail);
+ }
+
+ if (!canSeeEmail()) {
+ userData.email = "";
+ }
+
+ if (parseInt(callerUID, 10) === parseInt(userData.uid, 10) && !userSettings.showemail) {
+ userData.emailClass = "";
+ } else {
+ userData.emailClass = "hide";
+ }
+
+ userData.websiteName = userData.website.replace('http://', '').replace('https://', '');
+ userData.banned = parseInt(userData.banned, 10) === 1;
+ userData.uid = userData.uid;
+ userData.yourid = callerUID;
+ userData.theirid = userData.uid;
+
+ userData.disableSignatures = meta.config.disableSignatures !== undefined && parseInt(meta.config.disableSignatures, 10) === 1;
+
+ userData.followingCount = results.followStats.followingCount;
+ userData.followerCount = results.followStats.followerCount;
+
callback(null, userData);
});
});
}
-
};
}(exports));
diff --git a/src/socket.io/admin.js b/src/socket.io/admin.js
index da1de17596..21f3d8bf11 100644
--- a/src/socket.io/admin.js
+++ b/src/socket.io/admin.js
@@ -3,6 +3,7 @@
var groups = require('../groups'),
meta = require('../meta'),
plugins = require('../plugins'),
+ widgets = require('../widgets'),
user = require('../user'),
topics = require('../topics'),
categories = require('../categories'),
@@ -255,10 +256,11 @@ SocketAdmin.categories.groupsList = function(socket, cid, callback) {
});
};
-/* Themes & Plugins */
+/* Themes, Widgets, and Plugins */
SocketAdmin.themes = {};
SocketAdmin.plugins = {};
+SocketAdmin.widgets = {};
SocketAdmin.themes.getInstalled = function(socket, data, callback) {
meta.themes.get(callback);
@@ -269,7 +271,7 @@ SocketAdmin.themes.set = function(socket, data, callback) {
return callback(new Error('invalid data'));
}
meta.themes.set(data, callback);
-}
+};
SocketAdmin.plugins.toggle = function(socket, plugin_id) {
plugins.toggleActive(plugin_id, function(status) {
@@ -277,6 +279,14 @@ SocketAdmin.plugins.toggle = function(socket, plugin_id) {
});
};
+SocketAdmin.widgets.set = function(socket, data, callback) {
+ if(!data) {
+ return callback(new Error('invalid data'));
+ }
+
+ widgets.setArea(data, callback);
+};
+
/* Configs */
SocketAdmin.config = {};
diff --git a/src/socket.io/widgets.js b/src/socket.io/widgets.js
new file mode 100644
index 0000000000..6347cc249a
--- /dev/null
+++ b/src/socket.io/widgets.js
@@ -0,0 +1,11 @@
+"use strict";
+
+var widgets = require('../widgets'),
+
+ SocketWidgets = {};
+
+SocketWidgets.render = function(socket, data, callback) {
+ widgets.render(socket.uid, data, callback);
+};
+
+module.exports = SocketWidgets;
\ No newline at end of file
diff --git a/src/upgrade.js b/src/upgrade.js
index 8ebab4f102..41076ef259 100644
--- a/src/upgrade.js
+++ b/src/upgrade.js
@@ -19,7 +19,7 @@ var db = require('./database'),
Upgrade.check = function(callback) {
// IMPORTANT: REMEMBER TO UPDATE VALUE OF latestSchema
- var latestSchema = new Date(2014, 1, 14, 21, 50).getTime();
+ var latestSchema = new Date(2014, 1, 20, 20, 25).getTime();
db.get('schemaDate', function(err, value) {
if (parseInt(value, 10) >= latestSchema) {
@@ -685,6 +685,134 @@ Upgrade.upgrade = function(callback) {
winston.info('[2014/2/14] Added posts to sorted set - skipped');
next();
}
+ },
+ function(next) {
+ thisSchemaDate = new Date(2014, 1, 19, 18, 15).getTime();
+
+ if (schemaDate < thisSchemaDate) {
+ updatesMade = true;
+
+ db.setObjectField('widgets:home.tpl', 'motd', JSON.stringify([
+ {
+ "widget": "html",
+ "data": {
+ "html": Meta.config['motd'] || "Welcome to NodeBB, if you are an administrator of this forum visit the
Themes ACP to modify and add widgets."
+ }
+ }
+ ]), function(err) {
+ Meta.configs.remove('motd');
+ Meta.configs.remove('motd_class');
+ Meta.configs.remove('show_motd');
+
+ winston.info('[2014/2/19] Updated MOTD to use the HTML widget.');
+ next(err);
+ });
+ } else {
+ winston.info('[2014/2/19] Updating MOTD to use the HTML widget - skipped');
+ next();
+ }
+ },
+ function(next) {
+ thisSchemaDate = new Date(2014, 1, 20, 15, 30).getTime();
+
+ if (schemaDate < thisSchemaDate) {
+ updatesMade = true;
+
+ var container = '
';
+
+ db.setObjectField('widgets:category.tpl', 'sidebar', JSON.stringify([
+ {
+ "widget": "recentreplies",
+ "data": {
+ "title": "Recent Replies",
+ "container": container
+ }
+ },
+ {
+ "widget": "activeusers",
+ "data": {
+ "title": "Active Users",
+ "container": container
+ }
+ },
+ {
+ "widget": "moderators",
+ "data": {
+ "title": "Moderators",
+ "container": container
+ }
+ }
+ ]), function(err) {
+ winston.info('[2014/2/20] Adding Recent Replies, Active Users, and Moderator widgets to category sidebar.');
+ next(err);
+ });
+ } else {
+ winston.info('[2014/2/20] Adding Recent Replies, Active Users, and Moderator widgets to category sidebar - skipped');
+ next();
+ }
+ },
+ function(next) {
+ thisSchemaDate = new Date(2014, 1, 20, 16, 15).getTime();
+
+ if (schemaDate < thisSchemaDate) {
+ updatesMade = true;
+
+ db.setObjectField('widgets:home.tpl', 'footer', JSON.stringify([
+ {
+ "widget": "forumstats",
+ "data": {}
+ }
+ ]), function(err) {
+ winston.info('[2014/2/20] Adding Forum Stats Widget to the Homepage Footer.');
+ next(err);
+ });
+ } else {
+ winston.info('[2014/2/20] Adding Forum Stats Widget to the Homepage Footer - skipped');
+ next();
+ }
+ },
+ function(next) {
+ thisSchemaDate = new Date(2014, 1, 20, 19, 45).getTime();
+
+ if (schemaDate < thisSchemaDate) {
+ updatesMade = true;
+
+ var container = '
';
+
+ db.setObjectField('widgets:home.tpl', 'sidebar', JSON.stringify([
+ {
+ "widget": "html",
+ "data": {
+ "html": Meta.config['motd'] || "Welcome to NodeBB, if you are an administrator of this forum visit the
Themes ACP to modify and add widgets.",
+ "container": container,
+ "title": "MOTD"
+ }
+ }
+ ]), function(err) {
+ winston.info('[2014/2/20] Updating Lavender MOTD');
+ next(err);
+ });
+ } else {
+ winston.info('[2014/2/20] Updating Lavender MOTD - skipped');
+ next();
+ }
+ },
+ function(next) {
+ thisSchemaDate = new Date(2014, 1, 20, 20, 25).getTime();
+
+ if (schemaDate < thisSchemaDate) {
+ updatesMade = true;
+
+ db.setAdd('plugins:active', 'nodebb-widget-essentials', function(err) {
+ winston.info('[2014/2/20] Activating NodeBB Essential Widgets');
+ Plugins.reload(function() {
+ next(err);
+ });
+ });
+ } else {
+ winston.info('[2014/2/20] Activating NodeBB Essential Widgets - skipped');
+ next();
+ }
}
// Add new schema updates here
// IMPORTANT: REMEMBER TO UPDATE VALUE OF latestSchema IN LINE 17!!!
diff --git a/src/user.js b/src/user.js
index 56d60f3c83..1a048c9d73 100644
--- a/src/user.js
+++ b/src/user.js
@@ -104,43 +104,46 @@ var bcrypt = require('bcryptjs'),
'postcount': 0,
'lastposttime': 0,
'banned': 0,
- 'status': 'online',
- 'showemail': 0
+ 'status': 'online'
};
- db.setObject('user:' + uid, userData);
+ db.setObject('user:' + uid, userData, function(err) {
- db.setObjectField('username:uid', userData.username, uid);
- db.setObjectField('userslug:uid', userData.userslug, uid);
-
- if (userData.email !== undefined) {
- db.setObjectField('email:uid', userData.email, uid);
- if (parseInt(uid, 10) !== 1) {
- User.email.verify(uid, userData.email);
+ if(err) {
+ return callback(err);
}
- }
+ db.setObjectField('username:uid', userData.username, uid);
+ db.setObjectField('userslug:uid', userData.userslug, uid);
- plugins.fireHook('action:user.create', userData);
- db.incrObjectField('global', 'userCount');
-
- db.sortedSetAdd('users:joindate', timestamp, uid);
- db.sortedSetAdd('users:postcount', 0, uid);
- db.sortedSetAdd('users:reputation', 0, uid);
-
- groups.joinByGroupName('registered-users', uid);
-
- if (password) {
- User.hashPassword(password, function(err, hash) {
- if(err) {
- return callback(err);
+ if (userData.email !== undefined) {
+ db.setObjectField('email:uid', userData.email, uid);
+ if (parseInt(uid, 10) !== 1) {
+ User.email.verify(uid, userData.email);
}
+ }
- User.setUserField(uid, 'password', hash);
+ plugins.fireHook('action:user.create', userData);
+ db.incrObjectField('global', 'userCount');
+
+ db.sortedSetAdd('users:joindate', timestamp, uid);
+ db.sortedSetAdd('users:postcount', 0, uid);
+ db.sortedSetAdd('users:reputation', 0, uid);
+
+ groups.joinByGroupName('registered-users', uid);
+
+ if (password) {
+ User.hashPassword(password, function(err, hash) {
+ if(err) {
+ return callback(err);
+ }
+
+ User.setUserField(uid, 'password', hash);
+ callback(null, uid);
+ });
+ } else {
callback(null, uid);
- });
- } else {
- callback(null, uid);
- }
+ }
+ });
});
});
};
@@ -209,7 +212,7 @@ var bcrypt = require('bcryptjs'),
settings = {}
}
- settings.showemail = settings.showemail ? parseInt(settings.showemail, 10) !== 0 : parseInt(meta.config.usePagination, 10) !== 0;
+ settings.showemail = settings.showemail ? parseInt(settings.showemail, 10) !== 0 : false;
settings.usePagination = settings.usePagination ? parseInt(settings.usePagination, 10) !== 0 : parseInt(meta.config.usePagination, 10) !== 0;
settings.topicsPerPage = settings.topicsPerPage ? parseInt(settings.topicsPerPage, 10) : parseInt(meta.config.topicsPerPage, 10) || 20;
settings.postsPerPage = settings.postsPerPage ? parseInt(settings.postsPerPage, 10) : parseInt(meta.config.postsPerPage, 10) || 10;
diff --git a/src/webserver.js b/src/webserver.js
index 687280bf14..d6fe44bbbd 100644
--- a/src/webserver.js
+++ b/src/webserver.js
@@ -88,10 +88,10 @@ module.exports.server = server;
property: 'keywords',
content: meta.config.keywords || ''
}],
- defaultLinkTags = [/*{
+ defaultLinkTags = [{
rel: 'apple-touch-icon',
- href: meta.config['brand:logo'] || nconf.get('relative_path') + '/logo.png'
- }*/],
+ href: '/apple-touch-icon'
+ }],
templateValues = {
bootswatchCSS: meta.config['theme:src'],
pluginCSS: plugins.cssFiles.map(function(file) { return { path: nconf.get('relative_path') + file.replace(/\\/g, '/') }; }),
@@ -203,7 +203,17 @@ module.exports.server = server;
logger.init(app);
+ // favicon & apple-touch-icon middleware
app.use(express.favicon(path.join(__dirname, '../', 'public', meta.config['brand:favicon'] ? meta.config['brand:favicon'] : 'favicon.ico')));
+ app.use('/apple-touch-icon', function(req, res) {
+ if (meta.config['brand:logo'] && validator.isURL(meta.config['brand:logo'])) {
+ return res.redirect(meta.config['brand:logo']);
+ } else {
+ return res.sendfile(path.join(__dirname, '../public', meta.config['brand:logo'] || nconf.get('relative_path') + '/logo.png'), {
+ maxAge: app.enabled('cache') ? 5184000000 : 0
+ });
+ }
+ });
app.use(require('less-middleware')({
src: path.join(__dirname, '../', 'public'),
diff --git a/src/widgets.js b/src/widgets.js
new file mode 100644
index 0000000000..b6de26752a
--- /dev/null
+++ b/src/widgets.js
@@ -0,0 +1,66 @@
+var async = require('async'),
+ winston = require('winston'),
+ plugins = require('./plugins'),
+ db = require('./database'),
+ templates = require('./../public/src/templates');
+
+
+(function(Widgets) {
+
+ Widgets.render = function(uid, area, callback) {
+ if (!area.location || !area.template) {
+ callback({
+ error: 'Missing location and template data'
+ });
+ }
+
+ var rendered = [];
+
+ Widgets.getArea(area.template, area.location, function(err, widgets) {
+ async.eachSeries(widgets, function(widget, next) {
+ plugins.fireHook('filter:widget.render:' + widget.widget, {
+ uid: uid,
+ area: area,
+ data: widget.data
+ }, function(err, html){
+ if (widget.data.container && widget.data.container.match('{body}')) {
+ html = templates.prepare(widget.data.container).parse({
+ title: widget.data.title,
+ body: html
+ });
+ }
+
+ rendered.push({
+ html: html
+ });
+
+ next(err);
+ });
+ }, function(err) {
+ callback(err, rendered);
+ });
+ });
+ };
+
+ Widgets.getArea = function(template, location, callback) {
+ db.getObjectField('widgets:' + template, location, function(err, widgets) {
+ if (!widgets) {
+ return callback(err, []);
+ }
+ callback(err, JSON.parse(widgets));
+ })
+ };
+
+ Widgets.setArea = function(area, callback) {
+ if (!area.location || !area.template) {
+ callback({
+ error: 'Missing location and template data'
+ });
+ }
+
+ db.setObjectField('widgets:' + area.template, area.location, JSON.stringify(area.widgets), function(err) {
+ callback(err);
+ });
+ };
+
+}(exports));
\ No newline at end of file