mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-05-06 00:47:10 +02:00
10
install/data/footer.json
Normal file
10
install/data/footer.json
Normal file
@@ -0,0 +1,10 @@
|
||||
[
|
||||
{
|
||||
"widget": "html",
|
||||
"data" : {
|
||||
"html": "<footer id=\"footer\" class=\"container footer\">\r\n\t<div class=\"copyright\">\r\n\t\tCopyright © 2014 <a target=\"_blank\" href=\"https://nodebb.org\">NodeBB Forums</a> | <a target=\"_blank\" href=\"//github.com/NodeBB/NodeBB/graphs/contributors\">Contributors</a>\r\n\t</div>\r\n</footer>",
|
||||
"title":"",
|
||||
"container":""
|
||||
}
|
||||
}
|
||||
]
|
||||
10
install/data/welcome.md
Normal file
10
install/data/welcome.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# Welcome to your brand new NodeBB forum!
|
||||
|
||||
This is what a topic and post looks like. As an administator, you can edit the post\'s title and content.
|
||||
To customise your forum, go to the [Administrator Control Panel](../../admin). You can modify all aspects of your forum there, including installation of third-party plugins.
|
||||
|
||||
## Additional Resources
|
||||
|
||||
* [NodeBB Documentation](https://docs.nodebb.org)
|
||||
* [Community Support Forum](https://community.nodebb.org)
|
||||
* [Project repository](https://github.com/nodebb/nodebb)
|
||||
@@ -63,7 +63,7 @@
|
||||
"templates.js": "^0.1.15",
|
||||
"uglify-js": "git+https://github.com/julianlam/UglifyJS2.git",
|
||||
"underscore": "~1.7.0",
|
||||
"validator": "~3.28.0",
|
||||
"validator": "^3.30.0",
|
||||
"winston": "^0.9.0",
|
||||
"xregexp": "~2.0.0"
|
||||
},
|
||||
|
||||
@@ -52,6 +52,8 @@
|
||||
"invalid-title": "Invalid title!",
|
||||
"too-many-posts": "You can only post once every %1 seconds - please wait before posting again",
|
||||
"too-many-posts-newbie": "As a new user, you can only post once every %1 seconds until you have earned %2 reputation - please wait before posting again",
|
||||
"tag-too-short": "Please enter a longer tag. Tags should contain at least %1 characters",
|
||||
"tag-too-long": "Please enter a shorter tag. Tags can't be longer than %1 characters",
|
||||
"file-too-big": "Maximum allowed file size is %1 kbs - please upload a smaller file",
|
||||
|
||||
"cant-vote-self-post": "You cannot vote for your own post",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"no_tag_topics": "There are no topics with this tag.",
|
||||
"tags": "Tags",
|
||||
"enter_tags_here": "Enter tags here. Press enter after each tag.",
|
||||
"enter_tags_here": "Enter tags here. %1-%2 characters. Press enter after each tag.",
|
||||
"enter_tags_here_short": "Enter tags...",
|
||||
"no_tags": "There are no tags yet."
|
||||
}
|
||||
@@ -169,7 +169,6 @@
|
||||
border-radius: 3px;
|
||||
box-shadow: 0px 1px 3px 0px rgba(165, 165, 165, 0.75);
|
||||
margin-bottom: 20px;
|
||||
max-width: 1000px;
|
||||
|
||||
&.panel-default .panel-heading {
|
||||
background: #fefefe;
|
||||
@@ -232,7 +231,7 @@
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#acp-search {
|
||||
input {
|
||||
background: black;
|
||||
@@ -250,7 +249,7 @@
|
||||
width: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.search-match {
|
||||
font-weight: 700;
|
||||
color: black;
|
||||
|
||||
@@ -154,8 +154,8 @@ define('admin/manage/groups', [
|
||||
socket.emit('admin.user.search', {query: searchText}, function(err, results) {
|
||||
if (!err && results && results.users.length > 0) {
|
||||
var numResults = results.users.length, x;
|
||||
if (numResults > 4) {
|
||||
numResults = 4;
|
||||
if (numResults > 20) {
|
||||
numResults = 20;
|
||||
}
|
||||
|
||||
groupDetailsSearchResults.empty();
|
||||
|
||||
@@ -266,12 +266,15 @@ define('forum/account/edit', ['forum/account/header', 'uploader'], function(head
|
||||
password_confirm.on('blur', onPasswordConfirmChanged);
|
||||
|
||||
$('#changePasswordBtn').on('click', function() {
|
||||
var btn = $(this);
|
||||
if ((passwordvalid && passwordsmatch) || app.user.isAdmin) {
|
||||
btn.addClass('disabled').find('i').removeClass('hide');
|
||||
socket.emit('user.changePassword', {
|
||||
'currentPassword': currentPassword.val(),
|
||||
'newPassword': password.val(),
|
||||
'uid': ajaxify.variables.get('theirid')
|
||||
}, function(err) {
|
||||
btn.removeClass('disabled').find('i').addClass('hide');
|
||||
currentPassword.val('');
|
||||
password.val('');
|
||||
password_confirm.val('');
|
||||
|
||||
@@ -228,6 +228,8 @@ define('composer', [
|
||||
var data = {
|
||||
allowTopicsThumbnail: allowTopicsThumbnail,
|
||||
showTags: isTopic || isMain,
|
||||
minimumTagLength: config.minimumTagLength,
|
||||
maximumTagLength: config.maximumTagLength,
|
||||
isTopic: isTopic,
|
||||
showHandleInput: (app.user.uid === 0 || (isEditing && isGuestPost && app.user.isAdmin)) && config.allowGuestHandles,
|
||||
handle: composer.posts[post_uuid] ? composer.posts[post_uuid].handle || '' : undefined
|
||||
|
||||
@@ -14,7 +14,17 @@ define('composer/tags', function() {
|
||||
|
||||
tagEl.tagsinput({
|
||||
maxTags: config.tagsPerTopic,
|
||||
confirmKeys: [13, 44]
|
||||
confirmKeys: [13, 44],
|
||||
trimValue: true
|
||||
});
|
||||
|
||||
tagEl.on('beforeItemAdd', function(event) {
|
||||
event.cancel = event.item.length < config.minimumTagLength || event.item.length > config.maximumTagLength;
|
||||
if (event.item.length < config.minimumTagLength) {
|
||||
app.alertError('[[error:tag-too-short, ' + config.minimumTagLength + ']]');
|
||||
} else if (event.item.length > config.maximumTagLength) {
|
||||
app.alertError('[[error:tag-too-long, ' + config.maximumTagLength + ']]');
|
||||
}
|
||||
});
|
||||
|
||||
tagEl.on('itemAdded', function(event) {
|
||||
|
||||
@@ -53,8 +53,7 @@
|
||||
if (location === 'footer' && !$('#content [widget-area="footer"]').length) {
|
||||
$('#content').append($('<div class="row"><div widget-area="footer" class="col-xs-12"></div></div>'));
|
||||
} else if (location === 'sidebar' && !$('#content [widget-area="sidebar"]').length) {
|
||||
$('#content > *').wrapAll($('<div class="row"><div class="col-lg-9 col-xs-12"></div></div>'));
|
||||
$('#content').append($('<div class="row"><div widget-area="sidebar" class="col-lg-3 col-xs-12"></div></div>'));
|
||||
$('#content > *').wrapAll($('<div class="row"><div class="col-lg-9 col-xs-12"></div><div widget-area="sidebar" class="col-lg-3 col-xs-12"></div></div></div>'));
|
||||
} else if (location === 'header' && !$('#content [widget-area="header"]').length) {
|
||||
$('#content').prepend($('<div class="row"><div widget-area="header" class="col-xs-12"></div></div>'));
|
||||
}
|
||||
@@ -69,11 +68,11 @@
|
||||
ajaxify.widgets.reposition(location);
|
||||
}
|
||||
|
||||
$('#content [widget-area] img:not(.user-img)').addClass('img-responsive');
|
||||
$('#content [widget-area] img:not(.user-img)').addClass('img-responsive');
|
||||
}
|
||||
|
||||
|
||||
$(window).trigger('action:widgets.loaded', {});
|
||||
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback();
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
border-radius: 4px;
|
||||
max-width: 100%;
|
||||
line-height: 22px;
|
||||
cursor: text;
|
||||
}
|
||||
.bootstrap-tagsinput input {
|
||||
border: none;
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -64,7 +64,9 @@ var async = require('async'),
|
||||
category.isIgnored = results.isIgnored[0];
|
||||
category.topic_row_size = 'col-md-9';
|
||||
|
||||
callback(null, category);
|
||||
plugins.fireHook('filter:category.get', {category: category, uid: data.uid}, function(err, data) {
|
||||
callback(err, data ? data.category : null);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@@ -43,6 +43,8 @@ apiController.getConfig = function(req, res, next) {
|
||||
config.maxReconnectionAttempts = meta.config.maxReconnectionAttempts || 5;
|
||||
config.reconnectionDelay = meta.config.reconnectionDelay || 200;
|
||||
config.tagsPerTopic = meta.config.tagsPerTopic || 5;
|
||||
config.minimumTagLength = meta.config.minimumTagLength || 3;
|
||||
config.maximumTagLength = meta.config.maximumTagLength || 15;
|
||||
config.topicsPerPage = meta.config.topicsPerPage || 20;
|
||||
config.postsPerPage = meta.config.postsPerPage || 20;
|
||||
config.maximumFileSize = meta.config.maximumFileSize;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
var categoriesController = {},
|
||||
async = require('async'),
|
||||
nconf = require('nconf'),
|
||||
validator = require('validator'),
|
||||
privileges = require('../privileges'),
|
||||
user = require('../user'),
|
||||
categories = require('../categories'),
|
||||
@@ -22,7 +23,7 @@ categoriesController.recent = function(req, res, next) {
|
||||
}
|
||||
|
||||
data['feeds:disableRSS'] = parseInt(meta.config['feeds:disableRSS'], 10) === 1;
|
||||
data['rssFeedUrl'] = nconf.get('relative_path') + '/recent.rss';
|
||||
data.rssFeedUrl = nconf.get('relative_path') + '/recent.rss';
|
||||
data.breadcrumbs = helpers.buildBreadcrumbs([{text: '[[recent:title]]'}]);
|
||||
res.render('recent', data);
|
||||
});
|
||||
@@ -92,6 +93,72 @@ categoriesController.unreadTotal = function(req, res, next) {
|
||||
});
|
||||
};
|
||||
|
||||
categoriesController.list = function(req, res, next) {
|
||||
async.parallel({
|
||||
header: function (next) {
|
||||
res.locals.metaTags = [{
|
||||
name: "title",
|
||||
content: validator.escape(meta.config.title || 'NodeBB')
|
||||
}, {
|
||||
name: "description",
|
||||
content: validator.escape(meta.config.description || '')
|
||||
}, {
|
||||
property: 'og:title',
|
||||
content: 'Index | ' + validator.escape(meta.config.title || 'NodeBB')
|
||||
}, {
|
||||
property: 'og:type',
|
||||
content: 'website'
|
||||
}];
|
||||
|
||||
if(meta.config['brand:logo']) {
|
||||
res.locals.metaTags.push({
|
||||
property: 'og:image',
|
||||
content: meta.config['brand:logo']
|
||||
});
|
||||
}
|
||||
|
||||
next(null);
|
||||
},
|
||||
categories: function (next) {
|
||||
var uid = req.user ? req.user.uid : 0;
|
||||
categories.getCategoriesByPrivilege(uid, 'find', function (err, categoryData) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
var childCategories = [];
|
||||
|
||||
for(var i=categoryData.length - 1; i>=0; --i) {
|
||||
|
||||
if (Array.isArray(categoryData[i].children) && categoryData[i].children.length) {
|
||||
childCategories.push.apply(childCategories, categoryData[i].children);
|
||||
}
|
||||
|
||||
if (categoryData[i].parent && categoryData[i].parent.cid) {
|
||||
categoryData.splice(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
async.parallel([
|
||||
function(next) {
|
||||
categories.getRecentTopicReplies(categoryData, uid, next);
|
||||
},
|
||||
function(next) {
|
||||
categories.getRecentTopicReplies(childCategories, uid, next);
|
||||
}
|
||||
], function(err) {
|
||||
next(err, categoryData);
|
||||
});
|
||||
});
|
||||
}
|
||||
}, function (err, data) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
// TODO: template should be called categories.tpl
|
||||
res.render('home', data);
|
||||
});
|
||||
};
|
||||
|
||||
categoriesController.get = function(req, res, next) {
|
||||
var cid = req.params.category_id,
|
||||
page = req.query.page || 1,
|
||||
@@ -259,7 +326,7 @@ categoriesController.get = function(req, res, next) {
|
||||
|
||||
data.currentPage = page;
|
||||
data['feeds:disableRSS'] = parseInt(meta.config['feeds:disableRSS'], 10) === 1;
|
||||
data['rssFeedUrl'] = nconf.get('relative_path') + '/category/' + data.cid + '.rss';
|
||||
data.rssFeedUrl = nconf.get('relative_path') + '/category/' + data.cid + '.rss';
|
||||
data.pagination = pagination.create(data.currentPage, data.pageCount);
|
||||
|
||||
data.pagination.rel.forEach(function(rel) {
|
||||
|
||||
@@ -1,21 +1,10 @@
|
||||
"use strict";
|
||||
|
||||
var topicsController = require('./topics'),
|
||||
categoriesController = require('./categories'),
|
||||
tagsController = require('./tags'),
|
||||
searchController = require('./search'),
|
||||
usersController = require('./users'),
|
||||
groupsController = require('./groups'),
|
||||
accountsController = require('./accounts'),
|
||||
staticController = require('./static'),
|
||||
apiController = require('./api'),
|
||||
adminController = require('./admin'),
|
||||
helpers = require('./helpers'),
|
||||
|
||||
async = require('async'),
|
||||
var async = require('async'),
|
||||
nconf = require('nconf'),
|
||||
validator = require('validator'),
|
||||
winston = require('winston'),
|
||||
|
||||
auth = require('../routes/authentication'),
|
||||
meta = require('../meta'),
|
||||
user = require('../user'),
|
||||
@@ -23,85 +12,32 @@ var topicsController = require('./topics'),
|
||||
topics = require('../topics'),
|
||||
plugins = require('../plugins'),
|
||||
categories = require('../categories'),
|
||||
privileges = require('../privileges');
|
||||
privileges = require('../privileges'),
|
||||
helpers = require('./helpers');
|
||||
|
||||
var Controllers = {
|
||||
topics: topicsController,
|
||||
categories: categoriesController,
|
||||
tags: tagsController,
|
||||
search: searchController,
|
||||
users: usersController,
|
||||
groups: groupsController,
|
||||
accounts: accountsController,
|
||||
static: staticController,
|
||||
api: apiController,
|
||||
admin: adminController
|
||||
topics: require('./topics'),
|
||||
categories: require('./categories'),
|
||||
tags: require('./tags'),
|
||||
search: require('./search'),
|
||||
users: require('./users'),
|
||||
groups: require('./groups'),
|
||||
accounts: require('./accounts'),
|
||||
static: require('./static'),
|
||||
api: require('./api'),
|
||||
admin: require('./admin'),
|
||||
};
|
||||
|
||||
|
||||
Controllers.home = function(req, res, next) {
|
||||
async.parallel({
|
||||
header: function (next) {
|
||||
res.locals.metaTags = [{
|
||||
name: "title",
|
||||
content: validator.escape(meta.config.title || 'NodeBB')
|
||||
}, {
|
||||
name: "description",
|
||||
content: validator.escape(meta.config.description || '')
|
||||
}, {
|
||||
property: 'og:title',
|
||||
content: 'Index | ' + validator.escape(meta.config.title || 'NodeBB')
|
||||
}, {
|
||||
property: 'og:type',
|
||||
content: 'website'
|
||||
}];
|
||||
|
||||
if(meta.config['brand:logo']) {
|
||||
res.locals.metaTags.push({
|
||||
property: 'og:image',
|
||||
content: meta.config['brand:logo']
|
||||
});
|
||||
}
|
||||
|
||||
next(null);
|
||||
},
|
||||
categories: function (next) {
|
||||
var uid = req.user ? req.user.uid : 0;
|
||||
categories.getCategoriesByPrivilege(uid, 'find', function (err, categoryData) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
var childCategories = [];
|
||||
|
||||
for(var i=categoryData.length - 1; i>=0; --i) {
|
||||
|
||||
if (Array.isArray(categoryData[i].children) && categoryData[i].children.length) {
|
||||
childCategories.push.apply(childCategories, categoryData[i].children);
|
||||
}
|
||||
|
||||
if (categoryData[i].parent && categoryData[i].parent.cid) {
|
||||
categoryData.splice(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
async.parallel([
|
||||
function(next) {
|
||||
categories.getRecentTopicReplies(categoryData, uid, next);
|
||||
},
|
||||
function(next) {
|
||||
categories.getRecentTopicReplies(childCategories, uid, next);
|
||||
}
|
||||
], function(err) {
|
||||
next(err, categoryData);
|
||||
});
|
||||
});
|
||||
}
|
||||
}, function (err, data) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
res.render('home', data);
|
||||
});
|
||||
var route = meta.config.homePageRoute || 'home';
|
||||
if (route === 'home') {
|
||||
return Controllers.categories.list(req, res, next);
|
||||
} else if (route === 'recent') {
|
||||
Controllers.categories.recent(req, res, next);
|
||||
} else if (route === 'popular') {
|
||||
Controllers.categories.popular(req, res, next);
|
||||
}
|
||||
};
|
||||
|
||||
Controllers.reset = function(req, res, next) {
|
||||
|
||||
90
src/controllers/templates.js
Normal file
90
src/controllers/templates.js
Normal file
@@ -0,0 +1,90 @@
|
||||
"use strict";
|
||||
|
||||
var async = require('async'),
|
||||
nconf = require('nconf'),
|
||||
fs = require('fs'),
|
||||
path = require('path'),
|
||||
meta = require('../meta'),
|
||||
plugins = require('../plugins'),
|
||||
utils = require('../../public/src/utils'),
|
||||
templatesController = {};
|
||||
|
||||
|
||||
var availableTemplatesCache = null;
|
||||
var configCache = null;
|
||||
|
||||
templatesController.getTemplatesListing = function(req, res, next) {
|
||||
async.parallel({
|
||||
availableTemplates: function(next) {
|
||||
getAvailableTemplates(next);
|
||||
},
|
||||
templatesConfig: function(next) {
|
||||
async.waterfall([
|
||||
function(next) {
|
||||
readConfigFile(next);
|
||||
},
|
||||
function(config, next) {
|
||||
config.custom_mapping['^/?$'] = meta.config.homePageRoute || 'home';
|
||||
|
||||
plugins.fireHook('filter:templates.get_config', config, next);
|
||||
}
|
||||
], next);
|
||||
},
|
||||
}, function(err, results) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
res.json(results);
|
||||
});
|
||||
};
|
||||
|
||||
function readConfigFile(callback) {
|
||||
if (configCache) {
|
||||
return callback(null, configCache);
|
||||
}
|
||||
fs.readFile(path.join(nconf.get('views_dir'), 'config.json'), function(err, config) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
try {
|
||||
config = JSON.parse(config.toString());
|
||||
} catch (err) {
|
||||
return callback(err);
|
||||
}
|
||||
configCache = config;
|
||||
callback(null, config);
|
||||
});
|
||||
}
|
||||
|
||||
function getAvailableTemplates(callback) {
|
||||
if (availableTemplatesCache) {
|
||||
return callback(null, availableTemplatesCache);
|
||||
}
|
||||
|
||||
async.parallel({
|
||||
views: function(next) {
|
||||
utils.walk(nconf.get('views_dir'), next);
|
||||
},
|
||||
extended: function(next) {
|
||||
plugins.fireHook('filter:templates.get_virtual', [], next);
|
||||
}
|
||||
}, function(err, results) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
var availableTemplates = results.views.filter(function(value, index, self) {
|
||||
return value && self.indexOf(value) === index;
|
||||
}).map(function(el) {
|
||||
return el && el.replace(nconf.get('views_dir') + '/', '');
|
||||
});
|
||||
|
||||
availableTemplatesCache = availableTemplates.concat(results.extended);
|
||||
callback(null, availableTemplatesCache);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
module.exports = templatesController;
|
||||
@@ -389,13 +389,23 @@ function createWelcomePost(next) {
|
||||
var db = require('./database'),
|
||||
Topics = require('./topics');
|
||||
|
||||
db.sortedSetCard('topics:tid', function(err, numTopics) {
|
||||
if (numTopics === 0) {
|
||||
async.parallel([
|
||||
function(next) {
|
||||
fs.readFile(path.join(__dirname, '../', 'install/data/welcome.md'), next);
|
||||
},
|
||||
function(next) {
|
||||
db.getObjectField('global', 'topicCount', next);
|
||||
}
|
||||
], function(err, results) {
|
||||
var content = results[0],
|
||||
numTopics = results[1];
|
||||
|
||||
if (!parseInt(numTopics, 10)) {
|
||||
Topics.post({
|
||||
uid: 1,
|
||||
cid: 2,
|
||||
title: 'Welcome to your NodeBB!',
|
||||
content: '# Welcome to your brand new NodeBB forum!\n\nThis is what a topic and post looks like. As an administator, you can edit the post\'s title and content.\n\nTo customise your forum, go to the [Administrator Control Panel](../../admin). You can modify all aspects of your forum there, including installation of third-party plugins.\n\n## Additional Resources\n\n* [NodeBB Documentation](https://docs.nodebb.org)\n* [Community Support Forum](https://community.nodebb.org)\n* [Project repository](https://github.com/nodebb/nodebb)'
|
||||
content: content.toString()
|
||||
}, next);
|
||||
} else {
|
||||
next();
|
||||
@@ -420,12 +430,24 @@ function enableDefaultPlugins(next) {
|
||||
|
||||
function setCopyrightWidget(next) {
|
||||
var db = require('./database');
|
||||
|
||||
db.init(function(err) {
|
||||
if (!err) {
|
||||
db.setObjectField('widgets:global', 'footer', "[{\"widget\":\"html\",\"data\":{\"html\":\"<footer id=\\\"footer\\\" class=\\\"container footer\\\">\\r\\n\\t<div class=\\\"copyright\\\">\\r\\n\\t\\tCopyright © 2014 <a target=\\\"_blank\\\" href=\\\"https://nodebb.org\\\">NodeBB Forums</a> | <a target=\\\"_blank\\\" href=\\\"//github.com/NodeBB/NodeBB/graphs/contributors\\\">Contributors</a>\\r\\n\\t</div>\\r\\n</footer>\",\"title\":\"\",\"container\":\"\"}}]", next);
|
||||
async.parallel({
|
||||
footerJSON: function(next) {
|
||||
fs.readFile(path.join(__dirname, '../', 'install/data/footer.json'), next);
|
||||
},
|
||||
footer: function(next) {
|
||||
db.getObjectField('widgets:global', 'footer', next);
|
||||
}
|
||||
});
|
||||
}, function(err, results) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
if (!results.footer && results.footerJSON) {
|
||||
db.setObjectField('widgets:global', 'footer', results.footerJSON.toString(), next);
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
install.setup = function (callback) {
|
||||
|
||||
@@ -6,6 +6,7 @@ var fs = require('fs'),
|
||||
winston = require('winston'),
|
||||
semver = require('semver'),
|
||||
express = require('express'),
|
||||
nconf = require('nconf'),
|
||||
|
||||
db = require('./database'),
|
||||
emitter = require('./emitter'),
|
||||
@@ -13,6 +14,7 @@ var fs = require('fs'),
|
||||
translator = require('../public/src/translator'),
|
||||
utils = require('../public/src/utils'),
|
||||
hotswap = require('./hotswap'),
|
||||
pkg = require('../package.json'),
|
||||
|
||||
controllers = require('./controllers'),
|
||||
app, middleware;
|
||||
@@ -169,7 +171,7 @@ var fs = require('fs'),
|
||||
|
||||
Plugins.getAll = function(callback) {
|
||||
var request = require('request');
|
||||
request('https://packages.nodebb.org/api/v1/plugins', function(err, res, body) {
|
||||
request((nconf.get('registry') || 'https://packages.nodebb.org') + '/api/v1/plugins/' + pkg.version, function(err, res, body) {
|
||||
var plugins = [];
|
||||
|
||||
try {
|
||||
@@ -184,8 +186,9 @@ var fs = require('fs'),
|
||||
plugins[i].id = plugins[i].name;
|
||||
plugins[i].installed = false;
|
||||
plugins[i].active = false;
|
||||
plugins[i].url = plugins[i].repository ? plugins[i].repository.url : '';
|
||||
plugins[i].url = plugins[i].url ? plugins[i].url : plugins[i].repository ? plugins[i].repository.url : '';
|
||||
plugins[i].latest = getLatestVersion(plugins[i].versions);
|
||||
// plugins[i].latest = plugins[i].latest;
|
||||
pluginMap[plugins[i].name] = plugins[i];
|
||||
}
|
||||
|
||||
@@ -261,7 +264,7 @@ var fs = require('fs'),
|
||||
|
||||
function(dirs, next) {
|
||||
dirs = dirs.filter(function(dir){
|
||||
return dir.substr(0, 14) === 'nodebb-plugin-' || dir.substr(0, 14) === 'nodebb-widget-';
|
||||
return dir.startsWith('nodebb-plugin-') || dir.startsWith('nodebb-widget-') || dir.startsWith('nodebb-theme-')
|
||||
}).map(function(dir){
|
||||
return path.join(npmPluginPath, dir);
|
||||
});
|
||||
|
||||
@@ -34,13 +34,14 @@ var winston = require('winston'),
|
||||
},
|
||||
function(postData, next) {
|
||||
postData.content = data.content;
|
||||
plugins.fireHook('filter:post.save', postData, next);
|
||||
plugins.fireHook('filter:post.edit', {post: postData, uid: data.uid}, next);
|
||||
}
|
||||
], function(err, postData) {
|
||||
], function(err, result) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
var postData = result.post;
|
||||
async.parallel({
|
||||
post: function(next) {
|
||||
var d = {
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
"use strict";
|
||||
|
||||
var path = require('path'),
|
||||
async = require('async'),
|
||||
fs = require('fs'),
|
||||
nconf = require('nconf'),
|
||||
express = require('express'),
|
||||
var express = require('express'),
|
||||
|
||||
posts = require('../posts'),
|
||||
categories = require('../categories'),
|
||||
plugins = require('../plugins'),
|
||||
utils = require('../../public/src/utils'),
|
||||
uploadsController = require('../controllers/uploads');
|
||||
|
||||
uploadsController = require('../controllers/uploads'),
|
||||
templatesController = require('../controllers/templates');
|
||||
|
||||
module.exports = function(app, middleware, controllers) {
|
||||
|
||||
@@ -22,7 +16,7 @@ module.exports = function(app, middleware, controllers) {
|
||||
router.get('/widgets/render', controllers.api.renderWidgets);
|
||||
|
||||
router.get('/user/uid/:uid', middleware.checkGlobalPrivacySettings, controllers.accounts.getUserByUID);
|
||||
router.get('/get_templates_listing', getTemplatesListing);
|
||||
router.get('/get_templates_listing', templatesController.getTemplatesListing);
|
||||
router.get('/categories/:cid/moderators', getModerators);
|
||||
router.get('/recent/posts/:term?', getRecentPosts);
|
||||
|
||||
@@ -40,56 +34,6 @@ function getModerators(req, res, next) {
|
||||
});
|
||||
}
|
||||
|
||||
var templatesListingCache = {};
|
||||
|
||||
function getTemplatesListing(req, res, next) {
|
||||
if (templatesListingCache.availableTemplates && templatesListingCache.templatesConfig) {
|
||||
return res.json(templatesListingCache);
|
||||
}
|
||||
|
||||
async.parallel({
|
||||
views: function(next) {
|
||||
utils.walk(nconf.get('views_dir'), next);
|
||||
},
|
||||
extended: function(next) {
|
||||
plugins.fireHook('filter:templates.get_virtual', [], next);
|
||||
},
|
||||
config: function(next) {
|
||||
fs.readFile(path.join(nconf.get('views_dir'), 'config.json'), function(err, config) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
try {
|
||||
config = JSON.parse(config.toString());
|
||||
} catch (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
plugins.fireHook('filter:templates.get_config', config, next);
|
||||
});
|
||||
},
|
||||
}, function(err, results) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
var data = results.views.filter(function(value, index, self) {
|
||||
return value && self.indexOf(value) === index;
|
||||
}).map(function(el) {
|
||||
return el && el.replace(nconf.get('views_dir') + '/', '');
|
||||
});
|
||||
|
||||
data = data.concat(results.extended);
|
||||
|
||||
templatesListingCache = {
|
||||
availableTemplates: data,
|
||||
templatesConfig: results.config
|
||||
};
|
||||
|
||||
res.json(templatesListingCache);
|
||||
});
|
||||
}
|
||||
|
||||
function getRecentPosts(req, res, next) {
|
||||
var uid = (req.user) ? req.user.uid : 0;
|
||||
|
||||
@@ -50,6 +50,7 @@ function tagRoutes(app, middleware, controllers) {
|
||||
}
|
||||
|
||||
function categoryRoutes(app, middleware, controllers) {
|
||||
setupPageRoute(app, '/categories', middleware, [], controllers.categories.list);
|
||||
setupPageRoute(app, '/popular/:term?', middleware, [], controllers.categories.popular);
|
||||
setupPageRoute(app, '/recent', middleware, [], controllers.categories.recent);
|
||||
setupPageRoute(app, '/unread', middleware, [middleware.authenticate], controllers.categories.unread);
|
||||
|
||||
@@ -84,35 +84,38 @@ SocketUser.reset.send = function(socket, email, callback) {
|
||||
};
|
||||
|
||||
SocketUser.reset.commit = function(socket, data, callback) {
|
||||
if(data && data.code && data.password) {
|
||||
async.series([
|
||||
async.apply(db.getObjectField, 'reset:uid', data.code),
|
||||
async.apply(user.reset.commit, data.code, data.password)
|
||||
], function(err, data) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
var uid = data[0],
|
||||
now = new Date(),
|
||||
parsedDate = now.getFullYear() + '/' + (now.getMonth()+1) + '/' + now.getDate();
|
||||
|
||||
user.getUserField(uid, 'username', function(err, username) {
|
||||
emailer.send('reset_notify', uid, {
|
||||
username: username,
|
||||
date: parsedDate,
|
||||
site_title: meta.config.title || 'NodeBB',
|
||||
subject: '[[email:reset.notify.subject]]'
|
||||
});
|
||||
});
|
||||
events.log({
|
||||
type: 'password-reset',
|
||||
uid: socket.uid,
|
||||
ip: socket.ip
|
||||
});
|
||||
callback();
|
||||
});
|
||||
if (!data || !data.code || !data.password) {
|
||||
return callback(new Error('[[error:invalid-data]]'));
|
||||
}
|
||||
|
||||
async.parallel({
|
||||
uid: async.apply(db.getObjectField, 'reset:uid', data.code),
|
||||
reset: async.apply(user.reset.commit, data.code, data.password)
|
||||
}, function(err, results) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
var uid = results.uid,
|
||||
now = new Date(),
|
||||
parsedDate = now.getFullYear() + '/' + (now.getMonth()+1) + '/' + now.getDate();
|
||||
|
||||
user.getUserField(uid, 'username', function(err, username) {
|
||||
emailer.send('reset_notify', uid, {
|
||||
username: username,
|
||||
date: parsedDate,
|
||||
site_title: meta.config.title || 'NodeBB',
|
||||
subject: '[[email:reset.notify.subject]]'
|
||||
});
|
||||
});
|
||||
|
||||
events.log({
|
||||
type: 'password-reset',
|
||||
uid: uid,
|
||||
ip: socket.ip
|
||||
});
|
||||
callback();
|
||||
});
|
||||
};
|
||||
|
||||
SocketUser.checkStatus = function(socket, uid, callback) {
|
||||
@@ -151,6 +154,7 @@ SocketUser.changePassword = function(socket, data, callback) {
|
||||
targetUid: data.uid,
|
||||
ip: socket.ip
|
||||
});
|
||||
callback();
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
29
src/user.js
29
src/user.js
@@ -7,6 +7,7 @@ var async = require('async'),
|
||||
plugins = require('./plugins'),
|
||||
db = require('./database'),
|
||||
meta = require('./meta'),
|
||||
topics = require('./topics'),
|
||||
groups = require('./groups'),
|
||||
Password = require('./password');
|
||||
|
||||
@@ -147,25 +148,31 @@ var async = require('async'),
|
||||
|
||||
User.updateOnlineUsers = function(uid, callback) {
|
||||
callback = callback || function() {};
|
||||
db.sortedSetScore('users:online', uid, function(err, score) {
|
||||
var now = Date.now();
|
||||
if (err || now - parseInt(score, 10) < 300000) {
|
||||
return callback(err);
|
||||
}
|
||||
db.sortedSetAdd('users:online', now, uid, function(err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
|
||||
var now = Date.now();
|
||||
async.waterfall([
|
||||
function(next) {
|
||||
db.sortedSetScore('users:online', uid, next);
|
||||
},
|
||||
function(userOnlineTime, next) {
|
||||
if (now - parseInt(userOnlineTime, 10) < 300000) {
|
||||
return callback();
|
||||
}
|
||||
db.sortedSetAdd('users:online', now, uid, next);
|
||||
},
|
||||
function(next) {
|
||||
topics.pushUnreadCount(uid);
|
||||
plugins.fireHook('action:user.online', {uid: uid, timestamp: now});
|
||||
});
|
||||
});
|
||||
next();
|
||||
}
|
||||
], callback);
|
||||
};
|
||||
|
||||
User.setUserField = function(uid, field, value, callback) {
|
||||
callback = callback || function() {};
|
||||
db.setObjectField('user:' + uid, field, value, function(err) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
return callback(err);
|
||||
}
|
||||
plugins.fireHook('action:user.set', {uid: uid, field: field, value: value, type: 'set'});
|
||||
callback();
|
||||
|
||||
@@ -63,7 +63,7 @@ var async = require('async'),
|
||||
}
|
||||
|
||||
if (!validated) {
|
||||
return;
|
||||
return callback(new Error('[[error:reset-code-not-valid]]'));
|
||||
}
|
||||
|
||||
db.getObjectField('reset:uid', code, function(err, uid) {
|
||||
|
||||
@@ -28,6 +28,20 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Home Page</div>
|
||||
<div class="panel-body">
|
||||
<form>
|
||||
<label>Home Page Route</label>
|
||||
<select class="form-control" data-field="homePageRoute">
|
||||
<option value="home">Categories</option>
|
||||
<option value="recent">Recent</option>
|
||||
<option value="popular">Popular</option>
|
||||
</select>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Site Logo</div>
|
||||
|
||||
Reference in New Issue
Block a user