mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-03-04 19:41:16 +01:00
Merge remote-tracking branch 'origin/master' into email-revamp
This commit is contained in:
@@ -38,8 +38,8 @@
|
||||
"prompt": "~0.2.11",
|
||||
"uglify-js": "~2.4.0",
|
||||
"validator": "~1.5.1",
|
||||
"nodebb-plugin-mentions": "~0.1.16",
|
||||
"nodebb-plugin-markdown": "~0.2.1",
|
||||
"nodebb-plugin-mentions": "~0.1",
|
||||
"nodebb-plugin-markdown": "~0.3",
|
||||
"nodebb-theme-vanilla": "~0.0.12",
|
||||
"nodebb-theme-cerulean": "0.0.10",
|
||||
"cron": "~1.0.1",
|
||||
|
||||
@@ -94,9 +94,8 @@ define(['taskbar'], function(taskbar) {
|
||||
|
||||
var postContainer = $(composerTemplate[0]);
|
||||
|
||||
if(config.imgurClientIDSet) {
|
||||
if(config.allowFileUploads || config.imgurClientIDSet)
|
||||
initializeFileReader(post_uuid);
|
||||
}
|
||||
|
||||
var postData = composer.posts[post_uuid],
|
||||
titleEl = postContainer.find('.title'),
|
||||
|
||||
@@ -123,7 +123,7 @@
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" data-field="disableSocialButtons"> <strong>Disable social buttons on posts</strong>
|
||||
<input type="checkbox" data-field="disableSocialButtons"> <strong>Disable social buttons</strong>
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
|
||||
@@ -10,12 +10,13 @@
|
||||
|
||||
<div>
|
||||
<button id="new_post" class="btn btn-primary {show_topic_button}">[[category:new_topic_button]]</button>
|
||||
|
||||
<!-- IF !disableSocialButtons -->
|
||||
<div class="inline-block pull-right">
|
||||
<a href="#" id="facebook-share"><i class="fa fa-facebook-square fa-2x"></i></a>
|
||||
<a href="#" id="twitter-intent"><i class="fa fa-twitter-square fa-2x"></i></a>
|
||||
<a href="#" id="google-share"><i class="fa fa-google-plus-square fa-2x"></i></a>
|
||||
</div>
|
||||
<!-- ENDIF !disableSocialButtons -->
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
@@ -80,6 +80,7 @@ var db = require('./database.js'),
|
||||
'category_id': category_id,
|
||||
'active_users': [],
|
||||
'topics': [],
|
||||
'disableSocialButtons': meta.config.disableSocialButtons !== undefined ? parseInt(meta.config.disableSocialButtons, 10) !== 0 : false,
|
||||
'twitter-intent-url': 'https://twitter.com/intent/tweet?url=' + encodeURIComponent(nconf.get('url') + 'category/' + category_slug) + '&text=' + encodeURIComponent(category_name),
|
||||
'facebook-share-url': 'https://www.facebook.com/sharer/sharer.php?u=' + encodeURIComponent(nconf.get('url') + 'category/' + category_slug),
|
||||
'google-share-url': 'https://plus.google.com/share?url=' + encodeURIComponent(nconf.get('url') + 'category/' + category_slug),
|
||||
|
||||
@@ -50,13 +50,20 @@
|
||||
function createCollections() {
|
||||
db.createCollection('objects', function(err, collection) {
|
||||
if(err) {
|
||||
winston.error("Error creating collection " + err.message);
|
||||
winston.error('Error creating collection ' + err.message);
|
||||
return;
|
||||
}
|
||||
|
||||
if(collection) {
|
||||
collection.ensureIndex({_key :1}, {background:true}, function(err, name){
|
||||
collection.ensureIndex({_key :1}, {background:true}, function(err, name) {
|
||||
if(err) {
|
||||
winston.error("Error creating index " + err.message);
|
||||
winston.error('Error creating index ' + err.message);
|
||||
}
|
||||
});
|
||||
|
||||
collection.ensureIndex({'expireAt':1}, {expireAfterSeconds:0, background:true}, function(err, name) {
|
||||
if(err) {
|
||||
winston.error('Error creating index ' + err.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -64,13 +71,13 @@
|
||||
|
||||
db.createCollection('search', function(err, collection) {
|
||||
if(err) {
|
||||
winston.error("Error creating collection " + err.message);
|
||||
winston.error('Error creating collection ' + err.message);
|
||||
return;
|
||||
}
|
||||
if(collection) {
|
||||
collection.ensureIndex({content:'text'}, {background:true}, function(err, name){
|
||||
if(err) {
|
||||
winston.error("Error creating index " + err.message);
|
||||
winston.error('Error creating index ' + err.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -241,6 +248,14 @@
|
||||
});
|
||||
}
|
||||
|
||||
module.expire = function(key, seconds, callback) {
|
||||
module.expireAt(key, Math.round(Date.now() / 1000) + seconds, callback);
|
||||
}
|
||||
|
||||
module.expireAt = function(key, timestamp, callback) {
|
||||
module.setObjectField(key, 'expireAt', new Date(timestamp * 1000), callback);
|
||||
}
|
||||
|
||||
//hashes
|
||||
module.setObject = function(key, data, callback) {
|
||||
data['_key'] = key;
|
||||
@@ -254,6 +269,9 @@
|
||||
module.setObjectField = function(key, field, value, callback) {
|
||||
var data = {};
|
||||
// if there is a '.' in the field name it inserts subdocument in mongo, replace '.'s with \uff0E
|
||||
if(typeof field !== 'string') {
|
||||
field = field.toString();
|
||||
}
|
||||
field = field.replace(/\./g, '\uff0E');
|
||||
data[field] = value;
|
||||
db.collection('objects').update({_key:key}, {$set:data}, {upsert:true, w: 1}, function(err, result) {
|
||||
@@ -303,7 +321,7 @@
|
||||
|
||||
var _fields = {};
|
||||
for(var i=0; i<fields.length; ++i) {
|
||||
if(typeof fields[i] !== string) {
|
||||
if(typeof fields[i] !== 'string') {
|
||||
_fields[fields[i].toString().replace(/\./g, '\uff0E')] = 1;
|
||||
} else {
|
||||
_fields[fields[i].replace(/\./g, '\uff0E')] = 1;
|
||||
@@ -348,6 +366,9 @@
|
||||
|
||||
module.isObjectField = function(key, field, callback) {
|
||||
var data = {};
|
||||
if(typeof field !== 'string') {
|
||||
field = field.toString();
|
||||
}
|
||||
field = field.replace(/\./g, '\uff0E');
|
||||
data[field] = '';
|
||||
db.collection('objects').findOne({_key:key}, {fields:data}, function(err, item) {
|
||||
@@ -360,6 +381,9 @@
|
||||
|
||||
module.deleteObjectField = function(key, field, callback) {
|
||||
var data = {};
|
||||
if(typeof field !== 'string') {
|
||||
field = field.toString();
|
||||
}
|
||||
field = field.replace(/\./g, '\uff0E');
|
||||
data[field] = "";
|
||||
db.collection('objects').update({_key:key}, {$unset : data}, function(err, result) {
|
||||
@@ -379,6 +403,9 @@
|
||||
|
||||
module.incrObjectFieldBy = function(key, field, value, callback) {
|
||||
var data = {};
|
||||
if(typeof field !== 'string') {
|
||||
field = field.toString();
|
||||
}
|
||||
field = field.replace(/\./g, '\uff0E');
|
||||
data[field] = value;
|
||||
db.collection('objects').update({_key:key}, {$inc : data}, {upsert:true}, function(err, result) {
|
||||
|
||||
@@ -211,6 +211,14 @@
|
||||
redisClient.keys(key, callback);
|
||||
}
|
||||
|
||||
module.expire = function(key, seconds, callback) {
|
||||
redisClient.expire(key, seconds, callback);
|
||||
}
|
||||
|
||||
module.expireAt = function(key, timestamp, callback) {
|
||||
redisClient.expireat(key, timestamp, callback);
|
||||
}
|
||||
|
||||
//hashes
|
||||
|
||||
module.setObject = function(key, data, callback) {
|
||||
|
||||
@@ -3,11 +3,12 @@
|
||||
*/
|
||||
|
||||
var fs = require('fs'),
|
||||
path = require('path'),
|
||||
express = require('express'),
|
||||
winston = require('winston'),
|
||||
util = require('util'),
|
||||
socketio = require('socket.io'),
|
||||
meta = require('./meta.js');
|
||||
meta = require('./meta');
|
||||
|
||||
var opts = {
|
||||
/*
|
||||
@@ -72,10 +73,20 @@ var opts = {
|
||||
/* Open the streams to log to: either a path or stdout */
|
||||
var stream;
|
||||
if(value && fs.existsSync(value)) {
|
||||
stream = fs.createWriteStream(value, {flags: 'a'});
|
||||
}
|
||||
else
|
||||
fs.stat(value, function(err, stats) {
|
||||
if(stats.isDirectory()) {
|
||||
stream = fs.createWriteStream(path.join(value, 'nodebb.log'), {flags: 'a'});
|
||||
} else {
|
||||
stream = fs.createWriteStream(value, {flags: 'a'});
|
||||
}
|
||||
stream.on('error', function(err) {
|
||||
winston.error(err.message);
|
||||
});
|
||||
});
|
||||
|
||||
} else {
|
||||
stream = process.stdout;
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
@@ -112,8 +123,7 @@ var opts = {
|
||||
*/
|
||||
if(meta.config.loggerStatus > 0) {
|
||||
return opts.express.ofn(req,res,next);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return next();
|
||||
}
|
||||
}
|
||||
@@ -140,11 +150,13 @@ var opts = {
|
||||
for(var v in clients) {
|
||||
var client = clients[v];
|
||||
|
||||
if(client.oEmit != undefined && client.oEmit != client.emit)
|
||||
if(client.oEmit != undefined && client.oEmit != client.emit) {
|
||||
client.emit = client.oEmit;
|
||||
}
|
||||
|
||||
if(client.$oEmit != undefined && client.$oEmit != client.$emit)
|
||||
if(client.$oEmit != undefined && client.$oEmit != client.$emit) {
|
||||
client.$emit = client.$oEmit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -152,7 +152,7 @@ var winston = require('winston'),
|
||||
// Delete the thread if it is the last undeleted post
|
||||
threadTools.getLatestUndeletedPid(postData.tid, function(err, pid) {
|
||||
if (err && err.message === 'no-undeleted-pids-found') {
|
||||
threadTools.delete(postData.tid, function(err) {
|
||||
threadTools.delete(postData.tid, uid, function(err) {
|
||||
if (err) {
|
||||
winston.error('Could not delete topic (tid: ' + postData.tid + ')', err.stack);
|
||||
}
|
||||
|
||||
38
src/posts.js
38
src/posts.js
@@ -360,24 +360,26 @@ var db = require('./database'),
|
||||
|
||||
Posts.uploadPostImage = function(image, callback) {
|
||||
|
||||
if(!meta.config.imgurClientID) {
|
||||
return callback('imgurClientID not set', null);
|
||||
}
|
||||
|
||||
if(!image) {
|
||||
return callback('invalid image', null);
|
||||
}
|
||||
|
||||
require('./imgur').upload(meta.config.imgurClientID, image.data, 'base64', function(err, data) {
|
||||
if(err) {
|
||||
callback(err.message, null);
|
||||
} else {
|
||||
callback(null, {
|
||||
url: data.link,
|
||||
name: image.name
|
||||
});
|
||||
if(meta.config.imgurClientID) {
|
||||
if(!image) {
|
||||
return callback('invalid image', null);
|
||||
}
|
||||
});
|
||||
|
||||
require('./imgur').upload(meta.config.imgurClientID, image.data, 'base64', function(err, data) {
|
||||
if(err) {
|
||||
callback(err.message, null);
|
||||
} else {
|
||||
callback(null, {
|
||||
url: data.link,
|
||||
name: image.name
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if (meta.config.allowFileUploads) {
|
||||
Posts.uploadPostFile(image, callback);
|
||||
} else {
|
||||
callback('Uploads are disabled!');
|
||||
}
|
||||
}
|
||||
|
||||
Posts.uploadPostFile = function(file, callback) {
|
||||
@@ -400,7 +402,7 @@ var db = require('./database'),
|
||||
var uploadPath = path.join(nconf.get('base_dir'), nconf.get('upload_path'), filename);
|
||||
|
||||
fs.writeFile(uploadPath, buffer, function (err) {
|
||||
if(err) {
|
||||
if(err) {
|
||||
callback(err.message, null);
|
||||
} else {
|
||||
callback(null, {
|
||||
|
||||
@@ -66,7 +66,7 @@ var path = require('path'),
|
||||
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 = require('marked')(meta.config.motd || "<div class=\"pull-right btn-group\"><a target=\"_blank\" href=\"http://www.nodebb.org\" class=\"btn btn-default btn-lg\"><i class=\"fa fa-comment\"></i><span class='hidden-mobile'> Get NodeBB</span></a> <a target=\"_blank\" href=\"https://github.com/designcreateplay/NodeBB\" class=\"btn btn-default btn-lg\"><i class=\"fa fa-github\"></i><span class='hidden-mobile'> Fork us on Github</span></a> <a target=\"_blank\" href=\"https://twitter.com/dcplabs\" class=\"btn btn-default btn-lg\"><i class=\"fa fa-twitter\"></i><span class='hidden-mobile'> @NodeBB</span></a></div>\n\n# NodeBB <span>v" + pkg.version + "</span>\nWelcome to NodeBB, the discussion platform of the future.");
|
||||
data.motd = require('marked')(meta.config.motd || "<div class=\"pull-right btn-group\"><a target=\"_blank\" href=\"http://www.nodebb.org\" class=\"btn btn-default btn-lg\"><i class=\"fa fa-comment\"></i><span class='hidden-mobile'> Get NodeBB</span></a> <a target=\"_blank\" href=\"https://github.com/designcreateplay/NodeBB\" class=\"btn btn-default btn-lg\"><i class=\"fa fa-github\"></i><span class='hidden-mobile'> Fork us on Github</span></a> <a target=\"_blank\" href=\"https://twitter.com/NodeBB\" class=\"btn btn-default btn-lg\"><i class=\"fa fa-twitter\"></i><span class='hidden-mobile'> @NodeBB</span></a></div>\n\n# NodeBB <span>v" + pkg.version + "</span>\nWelcome to NodeBB, the discussion platform of the future.");
|
||||
res.json(data);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -539,7 +539,7 @@ var fs = require('fs'),
|
||||
if (!data.birthday) {
|
||||
data.age = '';
|
||||
} else {
|
||||
data.age = new Date().getFullYear() - new Date(data.birthday).getFullYear();
|
||||
data.age = Math.floor((new Date().getTime() - new Date(data.birthday).getTime()) / 31536000000);
|
||||
}
|
||||
|
||||
function canSeeEmail() {
|
||||
@@ -581,4 +581,4 @@ var fs = require('fs'),
|
||||
|
||||
};
|
||||
|
||||
}(exports));
|
||||
}(exports));
|
||||
|
||||
@@ -91,7 +91,7 @@ var winston = require('winston'),
|
||||
}
|
||||
}
|
||||
|
||||
ThreadTools.delete = function(tid, callback) {
|
||||
ThreadTools.delete = function(tid, uid, callback) {
|
||||
topics.delete(tid);
|
||||
|
||||
db.decrObjectField('global', 'topicCount');
|
||||
@@ -112,7 +112,7 @@ var winston = require('winston'),
|
||||
}
|
||||
}
|
||||
|
||||
ThreadTools.restore = function(tid, socket, callback) {
|
||||
ThreadTools.restore = function(tid, uid, callback) {
|
||||
topics.restore(tid);
|
||||
db.incrObjectField('global', 'topicCount');
|
||||
ThreadTools.unlock(tid);
|
||||
|
||||
@@ -55,7 +55,7 @@ var path = require('path'),
|
||||
|
||||
/**
|
||||
* `options` object requires: req, res
|
||||
* accepts: metaTags
|
||||
* accepts: metaTags, linkTags
|
||||
*/
|
||||
app.build_header = function (options, callback) {
|
||||
var custom_header = {
|
||||
@@ -83,8 +83,6 @@ var path = require('path'),
|
||||
rel: 'apple-touch-icon',
|
||||
href: meta.config['brand:logo'] || nconf.get('relative_path') + '/logo.png'
|
||||
}],
|
||||
metaString = utils.buildMetaTags(defaultMetaTags.concat(options.metaTags || [])),
|
||||
linkTags = utils.buildLinkTags(defaultLinkTags.concat(options.linkTags || [])),
|
||||
templateValues = {
|
||||
cssSrc: meta.config['theme:src'] || nconf.get('relative_path') + '/vendor/bootstrap/css/bootstrap.min.css',
|
||||
pluginCSS: plugins.cssFiles.map(function(file) { return { path: file + (meta.config['cache-buster'] ? '?v=' + meta.config['cache-buster'] : '') }; }),
|
||||
@@ -96,16 +94,30 @@ var path = require('path'),
|
||||
browserTitle: meta.config.title || 'NodeBB',
|
||||
csrf: options.res.locals.csrf_token,
|
||||
relative_path: nconf.get('relative_path'),
|
||||
meta_tags: metaString,
|
||||
link_tags: linkTags,
|
||||
clientScripts: clientScripts,
|
||||
navigation: custom_header.navigation,
|
||||
'cache-buster': meta.config['cache-buster'] ? 'v=' + meta.config['cache-buster'] : '',
|
||||
allowRegistration: meta.config.allowRegistration === undefined || parseInt(meta.config.allowRegistration, 10) === 1
|
||||
},
|
||||
escapeList = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
"'": ''',
|
||||
'"': '"'
|
||||
};
|
||||
|
||||
var uid = '0';
|
||||
|
||||
// Meta Tags
|
||||
templateValues.meta_tags = utils.buildMetaTags(defaultMetaTags.concat(options.metaTags || []).map(function(tag) {
|
||||
tag.content = tag.content.replace(/[&<>'"]/g, function(tag) {
|
||||
return escapeList[tag] || tag;
|
||||
});
|
||||
return tag;
|
||||
}));
|
||||
templateValues.link_tags = utils.buildLinkTags(defaultLinkTags.concat(options.linkTags || []));
|
||||
|
||||
if(options.req.user && options.req.user.uid) {
|
||||
uid = options.req.user.uid;
|
||||
}
|
||||
|
||||
@@ -562,7 +562,7 @@ websockets.init = function(io) {
|
||||
socket.on('api:topic.delete', function(data) {
|
||||
threadTools.privileges(data.tid, uid, function(err, privileges) {
|
||||
if (!err && privileges.editable) {
|
||||
threadTools.delete(data.tid, function(err) {
|
||||
threadTools.delete(data.tid, uid, function(err) {
|
||||
if (!err) {
|
||||
emitTopicPostStats();
|
||||
socket.emit('api:topic.delete', {
|
||||
@@ -578,7 +578,7 @@ websockets.init = function(io) {
|
||||
socket.on('api:topic.restore', function(data) {
|
||||
threadTools.privileges(data.tid, uid, function(err, privileges) {
|
||||
if (!err && privileges.editable) {
|
||||
threadTools.restore(data.tid, socket, function(err) {
|
||||
threadTools.restore(data.tid, uid, function(err) {
|
||||
emitTopicPostStats();
|
||||
|
||||
socket.emit('api:topic.restore', {
|
||||
|
||||
Reference in New Issue
Block a user