mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-11-10 16:05:49 +01:00
Merge remote-tracking branch 'origin/master' into composer-revamp
This commit is contained in:
2
nodebb
2
nodebb
@@ -20,7 +20,7 @@ case "$1" in
|
|||||||
echo "Launching NodeBB in \"development\" mode."
|
echo "Launching NodeBB in \"development\" mode."
|
||||||
echo "To run the production build of NodeBB, please use \"forever\"."
|
echo "To run the production build of NodeBB, please use \"forever\"."
|
||||||
echo "More Information: https://github.com/designcreateplay/NodeBB/wiki/How-to-run-NodeBB"
|
echo "More Information: https://github.com/designcreateplay/NodeBB/wiki/How-to-run-NodeBB"
|
||||||
NODE_ENV=development supervisor --extensions 'node|js|tpl' -- app $1
|
NODE_ENV=development supervisor -q --extensions 'node|js|tpl' -- app $1
|
||||||
;;
|
;;
|
||||||
|
|
||||||
language)
|
language)
|
||||||
|
|||||||
@@ -32,5 +32,8 @@
|
|||||||
"show_email": "Show My Email",
|
"show_email": "Show My Email",
|
||||||
|
|
||||||
"has_no_follower": "This user doesn't have any followers :(",
|
"has_no_follower": "This user doesn't have any followers :(",
|
||||||
"follows_no_one": "This user isn't following anyone :("
|
"follows_no_one": "This user isn't following anyone :(",
|
||||||
|
|
||||||
|
"email_hidden": "Email Hidden",
|
||||||
|
"hidden": "hidden"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -211,6 +211,7 @@ define(['uploader'], function(uploader) {
|
|||||||
var modal = $('#category-permissions-modal'),
|
var modal = $('#category-permissions-modal'),
|
||||||
searchEl = modal.find('#permission-search'),
|
searchEl = modal.find('#permission-search'),
|
||||||
resultsEl = modal.find('.search-results'),
|
resultsEl = modal.find('.search-results'),
|
||||||
|
groupsResultsEl = modal.find('.groups-results'),
|
||||||
searchDelay;
|
searchDelay;
|
||||||
|
|
||||||
searchEl.off().on('keyup', function() {
|
searchEl.off().on('keyup', function() {
|
||||||
@@ -263,6 +264,40 @@ define(['uploader'], function(uploader) {
|
|||||||
searchEl.keyup();
|
searchEl.keyup();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// User Groups and privileges
|
||||||
|
socket.emit('api:admin.categories.groupsearch', cid, function(err, results) {
|
||||||
|
var groupsFrag = document.createDocumentFragment(),
|
||||||
|
liEl = document.createElement('li');
|
||||||
|
var numResults = results.length,
|
||||||
|
resultObj;
|
||||||
|
|
||||||
|
for(var x=0;x<numResults;x++) {
|
||||||
|
resultObj = results[x];
|
||||||
|
liEl.setAttribute('data-gid', resultObj.gid);
|
||||||
|
liEl.innerHTML = '<div class="pull-right">' +
|
||||||
|
'<div class="btn-group">' +
|
||||||
|
'<button type="button" data-gpriv="+gr" class="btn btn-default' + (resultObj.privileges['+gr'] ? ' active' : '') + '">Read</button>' +
|
||||||
|
'<button type="button" data-gpriv="+gw" class="btn btn-default' + (resultObj.privileges['+gw'] ? ' active' : '') + '">Write</button>' +
|
||||||
|
'</div>' +
|
||||||
|
'</div>' +
|
||||||
|
' '+resultObj.name;
|
||||||
|
|
||||||
|
groupsFrag.appendChild(liEl.cloneNode(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
groupsResultsEl.html(groupsFrag);
|
||||||
|
});
|
||||||
|
|
||||||
|
groupsResultsEl.off().on('click', '[data-gpriv]', function(e) {
|
||||||
|
var btnEl = $(this),
|
||||||
|
gid = btnEl.parents('li[data-gid]').attr('data-gid'),
|
||||||
|
privilege = this.getAttribute('data-gpriv');
|
||||||
|
e.preventDefault();
|
||||||
|
socket.emit('api:admin.categories.setGroupPrivilege', cid, gid, privilege, !btnEl.hasClass('active'), function(err, privileges) {
|
||||||
|
btnEl.toggleClass('active', privileges[privilege]);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
modal.modal();
|
modal.modal();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ define(function() {
|
|||||||
|
|
||||||
var loadingEl = document.getElementById('categories-loading');
|
var loadingEl = document.getElementById('categories-loading');
|
||||||
if (loadingEl) {
|
if (loadingEl) {
|
||||||
socket.once('api:categories.get', function(data) {
|
socket.emit('api:categories.get', function(data) {
|
||||||
// Render categories
|
// Render categories
|
||||||
var categoriesFrag = document.createDocumentFragment(),
|
var categoriesFrag = document.createDocumentFragment(),
|
||||||
categoryEl = document.createElement('li'),
|
categoryEl = document.createElement('li'),
|
||||||
@@ -172,7 +172,6 @@ define(function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
socket.emit('api:categories.get');
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -483,7 +482,21 @@ define(function() {
|
|||||||
adjust_rep(-1, data.pid, data.uid);
|
adjust_rep(-1, data.pid, data.uid);
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('event:new_post', createNewPosts);
|
socket.on('event:new_post', function(data) {
|
||||||
|
var posts = data.posts;
|
||||||
|
for (var p in posts) {
|
||||||
|
if (posts.hasOwnProperty(p)) {
|
||||||
|
var post = posts[p],
|
||||||
|
postcount = jQuery('.user_postcount_' + post.uid),
|
||||||
|
ptotal = parseInt(postcount.html(), 10);
|
||||||
|
|
||||||
|
ptotal += 1;
|
||||||
|
postcount.html(ptotal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
createNewPosts(data);
|
||||||
|
});
|
||||||
|
|
||||||
socket.on('event:topic_deleted', function(data) {
|
socket.on('event:topic_deleted', function(data) {
|
||||||
if (data.tid === tid && data.status === 'ok') {
|
if (data.tid === tid && data.status === 'ok') {
|
||||||
|
|||||||
@@ -20,34 +20,51 @@
|
|||||||
<span class="label label-danger">[[user:banned]]</span>
|
<span class="label label-danger">[[user:banned]]</span>
|
||||||
</div>
|
</div>
|
||||||
<!-- ENDIF banned -->
|
<!-- ENDIF banned -->
|
||||||
|
<div>
|
||||||
|
<a id="chat-btn" href="#" class="btn btn-default hide">Chat</a>
|
||||||
|
</div>
|
||||||
<div id="user-actions">
|
<div id="user-actions">
|
||||||
<a id="follow-btn" href="#" class="btn btn-default">Follow</a>
|
<a id="follow-btn" href="#" class="btn btn-default hide">Follow</a>
|
||||||
<a id="unfollow-btn" href="#" class="btn btn-default">Unfollow</a>
|
<a id="unfollow-btn" href="#" class="btn btn-default hide">Unfollow</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<div class="inline-block">
|
<div class="inline-block">
|
||||||
<div class="account-bio-block">
|
<div class="account-bio-block">
|
||||||
<span class="account-bio-label">[[user:email]]</span><i class="fa fa-eye-slash {emailClass}" title="Email hidden"></i>
|
<span class="account-bio-label">[[user:email]]</span><i class="fa fa-eye-slash {emailClass}" title="[[user:email_hidden]]"></i>
|
||||||
|
<!-- IF email -->
|
||||||
<span>{email}</span>
|
<span>{email}</span>
|
||||||
|
<!-- ELSE -->
|
||||||
|
<i class="fa fa-eye-slash" title="[[user:email_hidden]]"></i> [[user:hidden]]
|
||||||
|
<!-- ENDIF email -->
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- IF fullname -->
|
||||||
<span class="account-bio-label">[[user:fullname]]</span>
|
<span class="account-bio-label">[[user:fullname]]</span>
|
||||||
<span>{fullname}</span>
|
<span>{fullname}</span>
|
||||||
<br/>
|
<br/>
|
||||||
|
<!-- ENDIF fullname -->
|
||||||
|
|
||||||
|
<!-- IF website -->
|
||||||
<span class="account-bio-label">[[user:website]]</span>
|
<span class="account-bio-label">[[user:website]]</span>
|
||||||
<span><a href="{website}">{websiteName}</a></span>
|
<span><a href="{website}">{websiteName}</a></span>
|
||||||
<br/>
|
<br/>
|
||||||
|
<!-- ENDIF website -->
|
||||||
|
|
||||||
|
<!-- IF location -->
|
||||||
<span class="account-bio-label">[[user:location]]</span>
|
<span class="account-bio-label">[[user:location]]</span>
|
||||||
<span>{location}</span>
|
<span>{location}</span>
|
||||||
<br/>
|
<br/>
|
||||||
|
<!-- ENDIF location -->
|
||||||
|
|
||||||
|
<!-- IF age -->
|
||||||
<span class="account-bio-label">[[user:age]]</span>
|
<span class="account-bio-label">[[user:age]]</span>
|
||||||
<span>{age}</span>
|
<span>{age}</span>
|
||||||
<br/>
|
<br/>
|
||||||
|
<!-- ENDIF age -->
|
||||||
|
|
||||||
<hr/>
|
<hr/>
|
||||||
<span class="account-bio-label">[[user:joined]]</span>
|
<span class="account-bio-label">[[user:joined]]</span>
|
||||||
<span class="timeago" title="{joindate}"></span>
|
<span class="timeago" title="{joindate}"></span>
|
||||||
@@ -74,10 +91,12 @@
|
|||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
<hr/>
|
<hr/>
|
||||||
|
<!-- IF signature -->
|
||||||
<span class="account-bio-label">[[user:signature]]</span>
|
<span class="account-bio-label">[[user:signature]]</span>
|
||||||
<div class="post-signature">
|
<div class="post-signature">
|
||||||
<span id='signature'>{signature}</span>
|
<span id='signature'>{signature}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- ENDIF signature -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -40,7 +40,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="col-lg-offset-2 col-lg-10">
|
<div class="col-lg-offset-2 col-lg-10">
|
||||||
<button class="btn btn-primary" id="login" type="submit">[[login:login]]</button> <a id="reset-link" class="hide" href="/reset">[[login:forgot_password]]</a>
|
<hr />
|
||||||
|
<button class="btn btn-primary btn-lg btn-block" id="login" type="submit">[[login:login]]</button> <a id="reset-link" class="hide" href="/reset">[[login:forgot_password]]</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<input type="hidden" name="_csrf" value="{token}" id="csrf-token" />
|
<input type="hidden" name="_csrf" value="{token}" id="csrf-token" />
|
||||||
|
|||||||
@@ -15,41 +15,54 @@
|
|||||||
|
|
||||||
<div class="category search">
|
<div class="category search">
|
||||||
<div class="{show_results}">
|
<div class="{show_results}">
|
||||||
<ul id="topics-container" data-search-query="{search_query}">
|
|
||||||
<h3>[[topic:topics]]</h3>
|
<h3>[[topic:topics]]</h3>
|
||||||
|
|
||||||
|
<!-- IF topic_matches -->
|
||||||
|
<small>{topic_matches} result(s) matching "{search_query}"</small>
|
||||||
|
<!-- ENDIF topic_matches -->
|
||||||
<div class="alert alert-info {show_no_topics}">[[topic:no_topics_found]]</div>
|
<div class="alert alert-info {show_no_topics}">[[topic:no_topics_found]]</div>
|
||||||
<!-- BEGIN topics -->
|
|
||||||
<a href="../../topic/{topics.slug}" id="tid-{topics.tid}">
|
|
||||||
<li class="category-item">
|
|
||||||
<div>
|
|
||||||
<div class="col-md-12 img-thumbnail">
|
|
||||||
<div class="search-result-post">
|
|
||||||
<img src="{topics.teaser_userpicture}" />
|
|
||||||
<strong>{topics.teaser_username}</strong>: <span class="search-result-text">{topics.title}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
<ul id="topics-container" data-search-query="{search_query}">
|
||||||
|
|
||||||
|
<!-- BEGIN topics -->
|
||||||
|
<li class="category-item">
|
||||||
|
<a href="../../topic/{topics.slug}" id="tid-{topics.tid}">
|
||||||
|
<div>
|
||||||
|
<div class="col-md-12 img-thumbnail">
|
||||||
|
<div class="search-result-post">
|
||||||
|
<img src="{topics.teaser_userpicture}" />
|
||||||
|
<strong>{topics.teaser_username}</strong>: <span class="search-result-text">{topics.title}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</a>
|
<!-- END topics -->
|
||||||
<!-- END topics -->
|
</ul>
|
||||||
|
|
||||||
<h3>Posts</h3>
|
<h3>Posts</h3>
|
||||||
|
<!-- IF post_matches -->
|
||||||
|
<small>{post_matches} result(s) matching "{search_query}"</small>
|
||||||
|
<!-- ENDIF post_matches -->
|
||||||
<div class="alert alert-info {show_no_posts}">No posts found!</div>
|
<div class="alert alert-info {show_no_posts}">No posts found!</div>
|
||||||
<!-- BEGIN posts -->
|
|
||||||
<a href="../../topic/{posts.topicSlug}#{posts.pid}" id="tid-{posts.tid}">
|
|
||||||
<li class="category-item">
|
|
||||||
<div>
|
|
||||||
<div class="col-md-12 img-thumbnail">
|
|
||||||
<div class="search-result-post">
|
|
||||||
<img src="{posts.picture}" />
|
|
||||||
<strong>{posts.username}</strong>: <span class="search-result-text">{posts.content}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
<ul id="topics-container" data-search-query="{search_query}">
|
||||||
|
<!-- BEGIN posts -->
|
||||||
|
<li class="category-item">
|
||||||
|
<a href="../../topic/{posts.topicSlug}#{posts.pid}" id="tid-{posts.tid}">
|
||||||
|
<div>
|
||||||
|
<div class="col-md-12 img-thumbnail">
|
||||||
|
<div class="search-result-post">
|
||||||
|
<img src="{posts.picture}" />
|
||||||
|
<strong>{posts.username}</strong>: <span class="search-result-text">{posts.content}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</a>
|
<!-- END posts -->
|
||||||
<!-- END posts -->
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -109,7 +109,7 @@
|
|||||||
|
|
||||||
<div class="post-info">
|
<div class="post-info">
|
||||||
<span class="pull-left">
|
<span class="pull-left">
|
||||||
[[topic:reputation]]: <i class='fa fa-star'></i> <span class='formatted-number'>{posts.user_rep}</span> | [[topic:posts]]: <i class='fa fa-pencil'></i> <span class='formatted-number'>{posts.user_postcount}</span>
|
[[topic:reputation]]: <i class='fa fa-star'></i> <span class='formatted-number post_rep_{posts.uid}'>{posts.user_rep}</span> | [[topic:posts]]: <i class='fa fa-pencil'></i> <span class='formatted-number user_postcount_{posts.uid}'>{posts.user_postcount}</span>
|
||||||
{posts.additional_profile_info}
|
{posts.additional_profile_info}
|
||||||
</span>
|
</span>
|
||||||
<span class="pull-right">
|
<span class="pull-right">
|
||||||
|
|||||||
@@ -65,4 +65,56 @@ CategoryTools.privileges = function(cid, uid, callback) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
CategoryTools.groupPrivileges = function(cid, gid, callback) {
|
||||||
|
async.parallel({
|
||||||
|
"+gr": function(next) {
|
||||||
|
var key = 'cid:' + cid + ':privileges:+gr';
|
||||||
|
Groups.exists(key, function(err, exists) {
|
||||||
|
if (exists) {
|
||||||
|
async.parallel({
|
||||||
|
isMember: function(next) {
|
||||||
|
Groups.isMemberByGroupName(gid, key, next);
|
||||||
|
},
|
||||||
|
isEmpty: function(next) {
|
||||||
|
Groups.isEmptyByGroupName(key, next);
|
||||||
|
}
|
||||||
|
}, next);
|
||||||
|
} else {
|
||||||
|
next(null, {
|
||||||
|
isMember: false,
|
||||||
|
isEmpty: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
"+gw": function(next) {
|
||||||
|
var key = 'cid:' + cid + ':privileges:+gw';
|
||||||
|
Groups.exists(key, function(err, exists) {
|
||||||
|
if (exists) {
|
||||||
|
async.parallel({
|
||||||
|
isMember: function(next) {
|
||||||
|
Groups.isMemberByGroupName(gid, key, next);
|
||||||
|
},
|
||||||
|
isEmpty: function(next) {
|
||||||
|
Groups.isEmptyByGroupName(key, next);
|
||||||
|
}
|
||||||
|
}, next);
|
||||||
|
} else {
|
||||||
|
next(null, {
|
||||||
|
isMember: false,
|
||||||
|
isEmpty: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, function(err, privileges) {
|
||||||
|
callback(err, !privileges ? null : {
|
||||||
|
"+gr": privileges['+gr'].isMember,
|
||||||
|
"+gw": privileges['+gw'].isMember,
|
||||||
|
read: (privileges['+gr'].isMember || privileges['+gr'].isEmpty),
|
||||||
|
write: (privileges['+gw'].isMember || privileges['+gw'].isEmpty),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = CategoryTools;
|
module.exports = CategoryTools;
|
||||||
@@ -176,7 +176,6 @@
|
|||||||
|
|
||||||
Groups.update = function(gid, values, callback) {
|
Groups.update = function(gid, values, callback) {
|
||||||
db.exists('gid:' + gid, function (err, exists) {
|
db.exists('gid:' + gid, function (err, exists) {
|
||||||
console.log('exists?', gid, exists, values);
|
|
||||||
if (!err && exists) {
|
if (!err && exists) {
|
||||||
db.setObject('gid:' + gid, values, callback);
|
db.setObject('gid:' + gid, values, callback);
|
||||||
} else {
|
} else {
|
||||||
@@ -199,7 +198,6 @@
|
|||||||
Groups.getGidFromName(groupName, function(err, gid) {
|
Groups.getGidFromName(groupName, function(err, gid) {
|
||||||
if (err || !gid) {
|
if (err || !gid) {
|
||||||
Groups.create(groupName, '', function(err, groupObj) {
|
Groups.create(groupName, '', function(err, groupObj) {
|
||||||
console.log('creating group, calling hide', groupObj.gid);
|
|
||||||
async.parallel([
|
async.parallel([
|
||||||
function(next) {
|
function(next) {
|
||||||
Groups.hide(groupObj.gid, next);
|
Groups.hide(groupObj.gid, next);
|
||||||
@@ -263,4 +261,40 @@
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Groups.getCategoryAccess = function(cid, uid, callback){
|
||||||
|
var access = false;
|
||||||
|
// check user group read access level
|
||||||
|
async.series([function(callback){
|
||||||
|
// get groups with read permission
|
||||||
|
db.getObjectField('group:gid', 'cid:' + cid + ':privileges:+gr', function(err, gid){
|
||||||
|
// get the user groups that belong to this read group
|
||||||
|
db.getSetMembers('gid:' + gid + ':members', function (err, gids) {
|
||||||
|
// check if user belong to any of these user groups
|
||||||
|
var groups_check = new Array();
|
||||||
|
gids.forEach(function(cgid){
|
||||||
|
groups_check.push(function(callback){
|
||||||
|
Groups.isMember(uid, cgid, function(err, isMember){
|
||||||
|
if (isMember){
|
||||||
|
access = true;
|
||||||
|
}
|
||||||
|
callback(null, gids);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// do a series check. We want to make sure we check all the groups before determining if the user
|
||||||
|
// has access or not.
|
||||||
|
async.series(groups_check, function(err, results){
|
||||||
|
callback(null, results);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
}],
|
||||||
|
function(err, results){
|
||||||
|
// if the read group is empty we will asume that read access has been granted to ALL
|
||||||
|
if (results[0].length == 0){ access = true; }
|
||||||
|
callback(false, access);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
}(module.exports));
|
}(module.exports));
|
||||||
|
|||||||
38
src/posts.js
38
src/posts.js
@@ -14,7 +14,8 @@ var db = require('./database'),
|
|||||||
async = require('async'),
|
async = require('async'),
|
||||||
nconf = require('nconf'),
|
nconf = require('nconf'),
|
||||||
validator = require('validator'),
|
validator = require('validator'),
|
||||||
winston = require('winston');
|
winston = require('winston'),
|
||||||
|
gravatar = require('gravatar');
|
||||||
|
|
||||||
(function(Posts) {
|
(function(Posts) {
|
||||||
var customUserInfo = {};
|
var customUserInfo = {};
|
||||||
@@ -202,12 +203,16 @@ var db = require('./database'),
|
|||||||
}
|
}
|
||||||
|
|
||||||
postTools.parseSignature(userData.signature, function(err, signature) {
|
postTools.parseSignature(userData.signature, function(err, signature) {
|
||||||
|
if(err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
|
||||||
post.username = userData.username || 'anonymous';
|
post.username = userData.username || 'anonymous';
|
||||||
post.userslug = userData.userslug || '';
|
post.userslug = userData.userslug || '';
|
||||||
post.user_rep = userData.reputation || 0;
|
post.user_rep = userData.reputation || 0;
|
||||||
post.user_postcount = userData.postcount || 0;
|
post.user_postcount = userData.postcount || 0;
|
||||||
post.user_banned = parseInt(userData.banned, 10) === 1;
|
post.user_banned = parseInt(userData.banned, 10) === 1;
|
||||||
post.picture = userData.picture || require('gravatar').url('', {}, https = nconf.get('https'));
|
post.picture = userData.picture || gravatar.url('', {}, https = nconf.get('https'));
|
||||||
post.signature = signature;
|
post.signature = signature;
|
||||||
|
|
||||||
for (var info in customUserInfo) {
|
for (var info in customUserInfo) {
|
||||||
@@ -217,11 +222,16 @@ var db = require('./database'),
|
|||||||
}
|
}
|
||||||
|
|
||||||
plugins.fireHook('filter:posts.custom_profile_info', {profile: "", uid: post.uid, pid: post.pid}, function(err, profile_info) {
|
plugins.fireHook('filter:posts.custom_profile_info', {profile: "", uid: post.uid, pid: post.pid}, function(err, profile_info) {
|
||||||
|
if(err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
post.additional_profile_info = profile_info.profile;
|
post.additional_profile_info = profile_info.profile;
|
||||||
|
|
||||||
if (post.editor !== '') {
|
if (post.editor !== '') {
|
||||||
user.getUserFields(post.editor, ['username', 'userslug'], function(err, editorData) {
|
user.getUserFields(post.editor, ['username', 'userslug'], function(err, editorData) {
|
||||||
if (err) return callback();
|
if (err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
|
||||||
post.editorname = editorData.username;
|
post.editorname = editorData.username;
|
||||||
post.editorslug = editorData.userslug;
|
post.editorslug = editorData.userslug;
|
||||||
@@ -439,8 +449,9 @@ var db = require('./database'),
|
|||||||
|
|
||||||
Posts.uploadPostImage = function(image, callback) {
|
Posts.uploadPostImage = function(image, callback) {
|
||||||
|
|
||||||
if(!image)
|
if(!image) {
|
||||||
return callback('invalid image', null);
|
return callback('invalid image', null);
|
||||||
|
}
|
||||||
|
|
||||||
require('./imgur').upload(meta.config.imgurClientID, image.data, 'base64', function(err, data) {
|
require('./imgur').upload(meta.config.imgurClientID, image.data, 'base64', function(err, data) {
|
||||||
if(err) {
|
if(err) {
|
||||||
@@ -455,22 +466,29 @@ var db = require('./database'),
|
|||||||
}
|
}
|
||||||
|
|
||||||
Posts.getPostsByUid = function(uid, start, end, callback) {
|
Posts.getPostsByUid = function(uid, start, end, callback) {
|
||||||
user.getPostIds(uid, start, end, function(pids) {
|
user.getPostIds(uid, start, end, function(err, pids) {
|
||||||
|
if(err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
|
||||||
if (pids && pids.length) {
|
if (pids && pids.length) {
|
||||||
plugins.fireHook('filter:post.getTopic', pids, function(err, posts) {
|
plugins.fireHook('filter:post.getTopic', pids, function(err, posts) {
|
||||||
|
if(err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
|
||||||
if (!err & 0 < posts.length) {
|
if (posts && posts.length) {
|
||||||
Posts.getPostsByPids(pids, function(err, posts) {
|
Posts.getPostsByPids(pids, function(err, posts) {
|
||||||
plugins.fireHook('action:post.gotTopic', posts);
|
plugins.fireHook('action:post.gotTopic', posts);
|
||||||
callback(posts);
|
callback(null, posts);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
callback(posts);
|
callback(null, []);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else
|
} else {
|
||||||
callback([]);
|
callback(null, []);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -244,7 +244,7 @@ var nconf = require('nconf'),
|
|||||||
|
|
||||||
var custom_routes = {
|
var custom_routes = {
|
||||||
'routes': [],
|
'routes': [],
|
||||||
'api_methods': []
|
'api': []
|
||||||
};
|
};
|
||||||
|
|
||||||
plugins.ready(function() {
|
plugins.ready(function() {
|
||||||
@@ -264,6 +264,19 @@ var nconf = require('nconf'),
|
|||||||
}(route));
|
}(route));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var apiRoutes = custom_routes.api;
|
||||||
|
for (var route in apiRoutes) {
|
||||||
|
if (apiRoutes.hasOwnProperty(route)) {
|
||||||
|
(function(route) {
|
||||||
|
app[apiRoutes[route].method || 'get']('/api/admin' + apiRoutes[route].route, function(req, res) {
|
||||||
|
apiRoutes[route].callback(req, res, function(data) {
|
||||||
|
res.json(data);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}(route));
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ var path = require('path'),
|
|||||||
|
|
||||||
db = require('../database'),
|
db = require('../database'),
|
||||||
user = require('../user'),
|
user = require('../user'),
|
||||||
|
groups = require('../groups'),
|
||||||
auth = require('./authentication'),
|
auth = require('./authentication'),
|
||||||
topics = require('../topics'),
|
topics = require('../topics'),
|
||||||
posts = require('../posts'),
|
posts = require('../posts'),
|
||||||
@@ -39,33 +40,26 @@ var path = require('path'),
|
|||||||
res.json(200, config);
|
res.json(200, config);
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get('/home', function (req, res, next) {
|
app.get('/home', function (req, res) {
|
||||||
var uid = (req.user) ? req.user.uid : 0;
|
var uid = (req.user) ? req.user.uid : 0;
|
||||||
categories.getAllCategories(uid, function (err, data) {
|
categories.getAllCategories(uid, function (err, data) {
|
||||||
data.categories = data.categories.filter(function (category) {
|
data.categories = data.categories.filter(function (category) {
|
||||||
return (!category.disabled || parseInt(category.disabled, 10) === 0);
|
return (!category.disabled || parseInt(category.disabled, 10) === 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
function getRecentReplies(category, callback) {
|
function iterator(category, callback) {
|
||||||
categories.getRecentReplies(category.cid, 2, function (err, posts) {
|
categories.getRecentReplies(category.cid, 2, function (err, posts) {
|
||||||
if(err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
category.posts = posts;
|
category.posts = posts;
|
||||||
category.post_count = posts.length > 2 ? 2 : posts.length;
|
category.post_count = posts.length > 2 ? 2 : posts.length;
|
||||||
callback(null);
|
callback(null);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async.each(data.categories, getRecentReplies, function (err) {
|
async.each(data.categories, iterator, function (err) {
|
||||||
if(err) {
|
|
||||||
return next(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
data.motd_class = (parseInt(meta.config.show_motd, 10) === 1 || meta.config.show_motd === undefined) ? '' : ' none';
|
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 && 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'> @dcplabs</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/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.");
|
||||||
res.json(data);
|
res.json(data);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -128,7 +122,15 @@ var path = require('path'),
|
|||||||
if (parseInt(data.deleted, 10) === 1 && parseInt(data.expose_tools, 10) === 0) {
|
if (parseInt(data.deleted, 10) === 1 && parseInt(data.expose_tools, 10) === 0) {
|
||||||
return res.json(404, {});
|
return res.json(404, {});
|
||||||
}
|
}
|
||||||
res.json(data);
|
// get the category this post belongs to and check category access
|
||||||
|
var cid = data.category_slug.split("/")[0];
|
||||||
|
groups.getCategoryAccess(cid, uid, function(err, access){
|
||||||
|
if (access){
|
||||||
|
res.json(data);
|
||||||
|
} else {
|
||||||
|
res.send(403);
|
||||||
|
}
|
||||||
|
})
|
||||||
} else next();
|
} else next();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -139,13 +141,20 @@ var path = require('path'),
|
|||||||
// Category Whitelisting
|
// Category Whitelisting
|
||||||
categoryTools.privileges(req.params.id, uid, function(err, privileges) {
|
categoryTools.privileges(req.params.id, uid, function(err, privileges) {
|
||||||
if (!err && privileges.read) {
|
if (!err && privileges.read) {
|
||||||
categories.getCategoryById(req.params.id, uid, function (err, data) {
|
groups.getCategoryAccess(req.params.id, uid, function(err, access){
|
||||||
if (!err && data && parseInt(data.disabled, 10) === 0) {
|
if (access){
|
||||||
res.json(data);
|
categories.getCategoryById(req.params.id, uid, function (err, data) {
|
||||||
|
if (!err && data && parseInt(data.disabled, 10) === 0) {
|
||||||
|
res.json(data);
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}, req.params.id, uid);
|
||||||
} else {
|
} else {
|
||||||
next();
|
res.send(403);
|
||||||
}
|
}
|
||||||
}, req.params.id, uid);
|
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
res.send(403);
|
res.send(403);
|
||||||
}
|
}
|
||||||
@@ -244,10 +253,6 @@ var path = require('path'),
|
|||||||
return callback(err, null);
|
return callback(err, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pids.length > 50) {
|
|
||||||
pids = pids.splice(0, 50);
|
|
||||||
}
|
|
||||||
|
|
||||||
posts.getPostSummaryByPids(pids, false, function (err, posts) {
|
posts.getPostSummaryByPids(pids, false, function (err, posts) {
|
||||||
if (err){
|
if (err){
|
||||||
return callback(err, null);
|
return callback(err, null);
|
||||||
@@ -263,10 +268,6 @@ var path = require('path'),
|
|||||||
return callback(err, null);
|
return callback(err, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(tids.length > 50) {
|
|
||||||
tids = tids.splice(0, 50);
|
|
||||||
}
|
|
||||||
|
|
||||||
topics.getTopicsByTids(tids, 0, function (topics) {
|
topics.getTopicsByTids(tids, 0, function (topics) {
|
||||||
callback(null, topics);
|
callback(null, topics);
|
||||||
}, 0);
|
}, 0);
|
||||||
@@ -285,7 +286,9 @@ var path = require('path'),
|
|||||||
show_results: '',
|
show_results: '',
|
||||||
search_query: req.params.term,
|
search_query: req.params.term,
|
||||||
posts: results[0],
|
posts: results[0],
|
||||||
topics: results[1]
|
topics: results[1],
|
||||||
|
post_matches : results[0].length,
|
||||||
|
topic_matches : results[1].length
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -313,7 +316,7 @@ var path = require('path'),
|
|||||||
|
|
||||||
app.get('/500', function(req, res) {
|
app.get('/500', function(req, res) {
|
||||||
res.json({errorMessage: 'testing'});
|
res.json({errorMessage: 'testing'});
|
||||||
})
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}(exports));
|
}(exports));
|
||||||
@@ -72,7 +72,7 @@
|
|||||||
login_strategies.push({
|
login_strategies.push({
|
||||||
name: 'google',
|
name: 'google',
|
||||||
url: '/auth/google',
|
url: '/auth/google',
|
||||||
callbackURL: nconf.get('url') + '/auth/google/callback',
|
callbackURL: '/auth/google/callback',
|
||||||
icon: 'google-plus',
|
icon: 'google-plus',
|
||||||
scope: 'https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email'
|
scope: 'https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email'
|
||||||
});
|
});
|
||||||
@@ -95,7 +95,7 @@
|
|||||||
login_strategies.push({
|
login_strategies.push({
|
||||||
name: 'facebook',
|
name: 'facebook',
|
||||||
url: '/auth/facebook',
|
url: '/auth/facebook',
|
||||||
callbackURL: nconf.get('url') + '/auth/facebook/callback',
|
callbackURL: '/auth/facebook/callback',
|
||||||
icon: 'facebook',
|
icon: 'facebook',
|
||||||
scope: 'email'
|
scope: 'email'
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -393,18 +393,24 @@ var fs = require('fs'),
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get('/api/user/:userslug', function (req, res) {
|
app.get('/api/user/:userslug', function (req, res, next) {
|
||||||
var callerUID = req.user ? req.user.uid : '0';
|
var callerUID = req.user ? req.user.uid : '0';
|
||||||
|
|
||||||
getUserDataByUserSlug(req.params.userslug, callerUID, function (userData) {
|
getUserDataByUserSlug(req.params.userslug, callerUID, function (userData) {
|
||||||
if (userData) {
|
if (userData) {
|
||||||
user.isFollowing(callerUID, userData.theirid, function (isFollowing) {
|
user.isFollowing(callerUID, userData.theirid, function (isFollowing) {
|
||||||
posts.getPostsByUid(userData.theirid, 0, 9, function (posts) {
|
posts.getPostsByUid(userData.theirid, 0, 9, function (err, posts) {
|
||||||
|
|
||||||
|
if(err) {
|
||||||
|
return next(err);
|
||||||
|
}
|
||||||
|
|
||||||
userData.posts = posts.filter(function (p) {
|
userData.posts = posts.filter(function (p) {
|
||||||
return p && parseInt(p.deleted, 10) !== 1;
|
return p && parseInt(p.deleted, 10) !== 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
userData.isFollowing = isFollowing;
|
userData.isFollowing = isFollowing;
|
||||||
|
|
||||||
if (!userData.profileviews) {
|
if (!userData.profileviews) {
|
||||||
userData.profileviews = 1;
|
userData.profileviews = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
17
src/user.js
17
src/user.js
@@ -444,21 +444,18 @@ var bcrypt = require('bcrypt'),
|
|||||||
|
|
||||||
User.getPostIds = function(uid, start, stop, callback) {
|
User.getPostIds = function(uid, start, stop, callback) {
|
||||||
db.getListRange('uid:' + uid + ':posts', start, stop, function(err, pids) {
|
db.getListRange('uid:' + uid + ':posts', start, stop, function(err, pids) {
|
||||||
if (!err) {
|
if(err) {
|
||||||
if (pids && pids.length) {
|
return callback(err);
|
||||||
callback(pids);
|
}
|
||||||
} else {
|
|
||||||
callback([]);
|
if (pids && pids.length) {
|
||||||
}
|
callback(null, pids);
|
||||||
} else {
|
} else {
|
||||||
console.log(err);
|
callback(null, []);
|
||||||
callback([]);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
User.follow = function(uid, followid, callback) {
|
User.follow = function(uid, followid, callback) {
|
||||||
db.setAdd('following:' + uid, followid, function(err, data) {
|
db.setAdd('following:' + uid, followid, function(err, data) {
|
||||||
if (!err) {
|
if (!err) {
|
||||||
|
|||||||
@@ -591,9 +591,9 @@ websockets.init = function(io) {
|
|||||||
threadTools.move(data.tid, data.cid, socket);
|
threadTools.move(data.tid, data.cid, socket);
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('api:categories.get', function() {
|
socket.on('api:categories.get', function(callback) {
|
||||||
categories.getAllCategories(0, function(err, categories) {
|
categories.getAllCategories(0, function(err, categories) {
|
||||||
socket.emit('api:categories.get', categories);
|
callback(categories);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -714,10 +714,10 @@ websockets.init = function(io) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var finalMessage = username + ' : ' + msg,
|
var username = usersData[0].username,
|
||||||
notifText = 'New message from <strong>' + username + '</strong>',
|
toUsername = usersData[1].username,
|
||||||
username = usersData[0].username,
|
finalMessage = username + ' : ' + msg,
|
||||||
toUsername = usersData[1].username;
|
notifText = 'New message from <strong>' + username + '</strong>';
|
||||||
|
|
||||||
if (!isUserOnline(touid)) {
|
if (!isUserOnline(touid)) {
|
||||||
notifications.create(notifText, 'javascript:app.openChat('' + username + '', ' + uid + ');', 'notification_' + uid + '_' + touid, function(nid) {
|
notifications.create(notifText, 'javascript:app.openChat('' + username + '', ' + uid + ');', 'notification_' + uid + '_' + touid, function(nid) {
|
||||||
@@ -1084,6 +1084,37 @@ websockets.init = function(io) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
socket.on('api:admin.categories.setGroupPrivilege', function(cid, gid, privilege, set, callback) {
|
||||||
|
var cb = function(err) {
|
||||||
|
CategoryTools.groupPrivileges(cid, gid, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (set) {
|
||||||
|
groups.joinByGroupName('cid:' + cid + ':privileges:' + privilege, gid, cb);
|
||||||
|
} else {
|
||||||
|
groups.leaveByGroupName('cid:' + cid + ':privileges:' + privilege, gid, cb);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('api:admin.categories.groupsearch', function(cid, callback) {
|
||||||
|
groups.list({expand:false}, function(err, data){
|
||||||
|
async.map(data, function(groupObj, next) {
|
||||||
|
CategoryTools.groupPrivileges(cid, groupObj.gid, function(err, privileges) {
|
||||||
|
if (!err) {
|
||||||
|
groupObj.privileges = privileges;
|
||||||
|
} else {
|
||||||
|
winston.error('[socket api:admin.categories.groupsearch] Could not retrieve permissions');
|
||||||
|
}
|
||||||
|
|
||||||
|
next(null, groupObj);
|
||||||
|
});
|
||||||
|
}, function(err, data) {
|
||||||
|
if (!callback) socket.emit('api:admin.categories.groupsearch', data);
|
||||||
|
else callback(null, data);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
socket.on('api:admin.themes.getInstalled', function(callback) {
|
socket.on('api:admin.themes.getInstalled', function(callback) {
|
||||||
meta.themes.get(function(err, themeArr) {
|
meta.themes.get(function(err, themeArr) {
|
||||||
callback(themeArr);
|
callback(themeArr);
|
||||||
|
|||||||
Reference in New Issue
Block a user