merged.. conflicted up the ass. registration looks gud again

v1.18.x
psychobunny 12 years ago
commit bb8f75b4be

@ -35,7 +35,8 @@
"request": "~2.25.0",
"reds": "~0.2.4",
"winston": "~0.7.2",
"nodebb-plugin-mentions": "~0.1.0"
"nodebb-plugin-mentions": "~0.1.0",
"nodebb-plugin-markdown": "~0.1.0"
},
"bugs": {
"url": "https://github.com/designcreateplay/NodeBB/issues"

@ -1,6 +1,8 @@
(function() {
var yourid = templates.get('yourid');
function initUsers() {
function isUserAdmin(element) {
@ -10,29 +12,32 @@
function isUserBanned(element) {
var parent = $(element).parents('.users-box');
return (parent.attr('data-banned') !== "" && parent.attr('data-banned') !== "0");
return (parent.attr('data-banned') !== "" && parent.attr('data-banned') !== "0");
}
function getUID(element) {
var parent = $(element).parents('.users-box');
return parent.attr('data-uid');
return parent.attr('data-uid');
}
jQuery('.admin-btn').each(function(index, element) {
var adminBtn = $(element);
var isAdmin = isUserAdmin(adminBtn);
var uid = getUID(adminBtn);
if(isAdmin)
adminBtn.addClass('btn-success');
else
adminBtn.removeClass('btn-success');
if(uid === yourid)
adminBtn.addClass('disabled');
});
jQuery('.delete-btn').each(function(index, element) {
var deleteBtn = $(element);
var isAdmin = isUserAdmin(deleteBtn);
if(isAdmin)
deleteBtn.addClass('disabled');
else
@ -43,12 +48,12 @@
var banBtn = $(element);
var isAdmin = isUserAdmin(banBtn);
var isBanned = isUserBanned(banBtn);
if(isAdmin)
banBtn.addClass('disabled');
else if(isBanned)
banBtn.addClass('btn-warning');
else
else
banBtn.removeClass('btn-warning');
});
@ -59,13 +64,12 @@
var parent = adminBtn.parents('.users-box');
var uid = getUID(adminBtn);
if(isAdmin) {
socket.emit('api:admin.user.removeAdmin', uid);
if(isAdmin && uid != yourid) {
socket.emit('api:admin.user.removeAdmin', uid);
adminBtn.removeClass('btn-success');
parent.find('.delete-btn').removeClass('disabled');
parent.attr('data-admin', 0);
}
else {
} else if(uid != yourid) {
bootbox.confirm('Do you really want to make "' + parent.attr('data-username') +'" an admin?', function(confirm) {
if(confirm) {
socket.emit('api:admin.user.makeAdmin', uid);
@ -75,7 +79,7 @@
}
});
}
return false;
});
@ -87,10 +91,10 @@
if(!isAdmin) {
bootbox.confirm('Do you really want to delete "' + parent.attr('data-username') +'"?', function(confirm) {
socket.emit('api:admin.user.deleteUser', uid);
socket.emit('api:admin.user.deleteUser', uid);
});
}
return false;
});
@ -108,13 +112,13 @@
parent.attr('data-banned', 0);
} else {
bootbox.confirm('Do you really want to ban "' + parent.attr('data-username') +'"?', function(confirm) {
socket.emit('api:admin.user.banUser', uid);
socket.emit('api:admin.user.banUser', uid);
banBtn.addClass('btn-warning');
parent.attr('data-banned', 1);
});
}
}
return false;
});
}
@ -122,8 +126,7 @@
jQuery('document').ready(function() {
var yourid = templates.get('yourid'),
timeoutId = 0,
var timeoutId = 0,
loadingMoreUsers = false;
var url = window.location.href,
@ -146,17 +149,17 @@
timeoutId = setTimeout(function() {
var username = $('#search-user').val();
jQuery('.icon-spinner').removeClass('none');
socket.emit('api:admin.user.search', username);
}, 250);
});
initUsers();
socket.removeAllListeners('api:admin.user.search');
socket.on('api:admin.user.search', function(data) {
var html = templates.prepare(templates['admin/users'].blocks['users']).parse({
users: data
@ -164,7 +167,7 @@
userListEl = document.querySelector('.users');
userListEl.innerHTML = html;
jQuery('.icon-spinner').addClass('none');
jQuery('.icon-spinner').addClass('none');
if(data && data.length === 0) {
$('#user-notfound-notify').html('User not found!')
@ -178,10 +181,10 @@
.addClass('label-success')
.removeClass('label-danger');
}
initUsers();
});
function onUsersLoaded(users) {
var html = templates.prepare(templates['admin/users'].blocks['users']).parse({ users: users });
$('#users-container').append(html);
@ -200,8 +203,8 @@
if(set) {
loadingMoreUsers = true;
socket.emit('api:users.loadMore', {
set: set,
after: $('#users-container').children().length
set: set,
after: $('#users-container').children().length
}, function(data) {
if(data.users.length) {
onUsersLoaded(data.users);

@ -132,6 +132,7 @@
});
}
});
notifList.addEventListener('click', function(e) {
var target;
switch(e.target.nodeName) {
@ -144,6 +145,7 @@
if (nid > 0) socket.emit('api:notifications.mark_read', nid);
}
});
socket.on('event:new_notification', function() {
document.querySelector('.notifications a i').className = 'icon-circle active';
app.alert({
@ -158,19 +160,26 @@
socket.on('chatMessage', function(data) {
var username = data.username;
var fromuid = data.fromuid;
var message = data.message;
require(['chat'], function(chat) {
var chatModal = chat.createModalIfDoesntExist(username, fromuid);
var chatModal = chat.createModalIfDoesntExist(data.username, data.fromuid, function(created, modal) {
if(!created)
chat.appendChatMessage(modal, data.message, data.timestamp);
});
chatModal.show();
chat.bringModalToTop(chatModal);
chat.appendChatMessage(chatModal, message);
});
});
socket.on('chatGoOffline', function(data) {
require(['chat'], function(chat) {
if(chat.modalOpen(data.uid)) {
var modal = chat.getModal(data.uid);
chat.appendChatMessage(modal, data.username + ' went offline\n', data.timestamp);
}
});
})
require(['mobileMenu'], function(mobileMenu) {
mobileMenu.init();

@ -1,161 +1,151 @@
(function() {
var username = document.getElementById('username'),
password = document.getElementById('password'),
password_confirm = document.getElementById('password-confirm'),
register = document.getElementById('register'),
emailEl = document.getElementById('email'),
username_notify = document.getElementById('username-notify'),
email_notify = document.getElementById('email-notify'),
password_notify = document.getElementById('password-notify'),
password_confirm_notify = document.getElementById('password-confirm-notify'),
usernamevalid = false;
emailexists = false,
emailvalid = false,
userexists = false,
passwordsmatch = false,
passwordvalid = false;
$(username).on('keyup change', function() {
usernamevalid = utils.isUserNameValid(username.value);
if(username.value.length < 3) {
username_notify.innerHTML = 'Username too short';
username_notify.parentNode.className = 'input-group-addon btn-warning label-warning';
} else if(username.value.length > 13) {
username_notify.innerHTML = 'Username too long';
username_notify.parentNode.className = 'input-group-addon btn-warning label-warning';
} else if(!usernamevalid) {
username_notify.innerHTML = 'Invalid username';
username_notify.parentNode.className = 'input-group-addon btn-warning label-warning';
} else {
socket.emit('user.exists', {username: username.value});
var username = $('#username'),
password = $('#password'),
password_confirm = $('#password-confirm'),
register = $('#register'),
emailEl = $('#email'),
username_notify = $('#username-notify'),
email_notify = $('#email-notify'),
password_notify = $('#password-notify'),
password_confirm_notify = $('#password-confirm-notify'),
validationError = false,
successIcon = '<i class="icon icon-ok"></i>';
function showError(element, msg) {
element.html(msg);
element.parent().removeClass('alert-success').addClass('alert-danger');
element.show();
validationError = true;
}
function showSuccess(element, msg) {
element.html(msg);
element.parent().removeClass('alert-danger').addClass('alert-success');
element.show();
}
function validateEmail() {
if(!emailEl.val()) {
validationError = true;
//email_notify.hide();
return;
}
if(!utils.isEmailValid(emailEl.val())) {
showError(email_notify, 'Invalid email address.');
}
else
socket.emit('user.email.exists', { email: emailEl.val() });
}
emailEl.on('blur', function() {
validateEmail();
});
$(emailEl).on('keyup change', function() {
emailvalid = utils.isEmailValid(email.value);
function validateUsername() {
if(!username.val()) {
validationError = true;
//username_notify.hide();
return;
}
if(!emailvalid) {
email_notify.innerHTML = 'Invalid email address';
email_notify.parentNode.className = 'input-group-addon btn-warning label-warning';
if(username.val().length < config.minimumUsernameLength) {
showError(username_notify, 'Username too short!');
} else if(username.val().length > config.maximumUsernameLength) {
showError(username_notify, 'Username too long!');
} else if(!utils.isUserNameValid(username.val())) {
showError(username_notify, 'Invalid username!');
} else {
socket.emit('user.exists', {username: username.val()});
}
else
socket.emit('user.email.exists', { email: emailEl.value });
}
username.on('keyup', function() {
jQuery('#yourUsername').html(this.value.length > 0 ? this.value : 'username');
});
$(password).on('keyup', function() {
passwordvalid = utils.isPasswordValid(password.value);
if (password.value.length < 6) {
password_notify.innerHTML = 'Password too short';
password_notify.parentNode.className = 'input-group-addon btn-warning label-warning';
} else if(!passwordvalid) {
password_notify.innerHTML = 'Invalid password';
password_notify.parentNode.className = 'input-group-addon btn-warning label-warning';
} else {
password_notify.innerHTML = '<i class="icon icon-ok"></i>';
password_notify.parentNode.className = 'input-group-addon btn-success label-success';
username.on('blur', function() {
validateUsername();
});
function validatePassword() {
if(!password.val()){
validationError = true;
//password_notify.hide();
return;
}
if(password.value !== password_confirm.value && password_confirm.value.length > 0) {
password_confirm_notify.innerHTML = 'Passwords must match!';
password_confirm_notify.parentNode.className = 'input-group-addon btn-warning label-warning';
passwordsmatch = false;
} else if (password.value === password_confirm.value && password_confirm.value.length > 0) {
password_confirm_notify.innerHTML = '<i class="icon icon-ok"></i>';
password_confirm_notify.parentNode.className = 'input-group-addon btn-success label-success';
passwordsmatch = true;
if (password.val().length < config.minimumPasswordLength) {
showError(password_notify, 'Password too short!');
} else if(password.val().length > config.maximumPasswordLength) {
showError(password_notify, 'Password too long!');
} else if(!utils.isPasswordValid(password.val())) {
showError(password_notify, 'Invalid password!');
} else {
showSuccess(password_notify, successIcon);
}
if(password.val() !== password_confirm.val() && password_confirm.val() !== '') {
showError(password_confirm_notify, 'Passwords must match!');
}
}
$(password).on('blur', function() {
validatePassword();
});
$(password_confirm).on('keyup', function() {
if(password.value !== password_confirm.value) {
password_confirm_notify.innerHTML = 'Passwords must match!';
password_confirm_notify.parentNode.className = 'input-group-addon btn-warning label-warning';
passwordsmatch = false;
function validatePasswordConfirm() {
if(!password.val() || password_notify.hasClass('alert-error')) {
//password_confirm_notify.hide();
return;
}
else {
password_confirm_notify.innerHTML = '<i class="icon icon-ok"></i>';
password_confirm_notify.parentNode.className = 'input-group-addon btn-success label-success';
passwordsmatch = true;
if(password.val() !== password_confirm.val()) {
showError(password_confirm_notify, 'Passwords must match!');
} else {
showSuccess(password_confirm_notify, successIcon);
}
}
$(password_confirm).on('blur', function() {
validatePasswordConfirm();
});
ajaxify.register_events(['user.exists', 'user.email.exists']);
socket.on('user.exists', function(data) {
userexists = data.exists;
if (data.exists === true) {
username_notify.innerHTML = 'Username exists';
username_notify.parentNode.className = 'input-group-addon btn-warning label-warning';
showError(username_notify, 'Username already taken!');
} else {
username_notify.innerHTML = '<i class="icon icon-ok"></i>';
username_notify.parentNode.className = 'input-group-addon btn-success label-success';
showSuccess(username_notify, successIcon);
}
});
socket.on('user.email.exists', function(data) {
emailexists = data.exists;
socket.on('user.email.exists', function(data) {
if (data.exists === true) {
email_notify.innerHTML = 'Email Address exists';
email_notify.className = 'label label-warning';
}
else {
email_notify.innerHTML = '<i class="icon icon-ok"></i>';
email_notify.parentNode.className = 'input-group-addon btn-success label-success';
showError(email_notify, 'Email address already taken!');
} else {
showSuccess(email_notify, successIcon);
}
});
// Alternate Logins
var altLoginEl = document.querySelector('.alt-logins');
altLoginEl.addEventListener('click', function(e) {
var target;
switch(e.target.nodeName) {
case 'LI': target = e.target; break;
case 'I': target = e.target.parentNode; break;
}
if (target) {
document.location.href = target.getAttribute('data-url');
}
$('.alt-logins li').on('click', function(e) {
document.location.href = $(this).attr('data-url');
});
function validateForm() {
var validated = true;
if (username.value.length < 2 || !usernamevalid) {
username_notify.innerHTML = 'Invalid username';
username_notify.className = 'label label-warning';
validated = false;
}
validationError = false;
if (password.value.length < 5) {
password_notify.innerHTML = 'Password too short';
validated = false;
}
if(password.value !== password_confirm.value) {
password_confirm_notify.innerHTML = 'Passwords must match!';
}
validateEmail();
validateUsername();
validatePassword();
validatePasswordConfirm();
if (!emailvalid) {
email_notify.innerHTML = 'Invalid email address';
validated = false;
}
if(emailexists) {
email_notify.innerHTML = 'Email Address exists';
validated = false;
}
return validationError;
}
if(userexists || !passwordsmatch || !passwordvalid)
validated = false;
register.on('click', function(e) {
if (validateForm()) e.preventDefault();
});
return validated;
}
register.addEventListener('click', function(e) {
if (!validateForm()) e.preventDefault();
}, false);
}());
}());

@ -13,12 +13,19 @@ define(['taskbar'], function(taskbar) {
chatModal.css('zIndex', topZ + 1);
}
module.createModalIfDoesntExist = function(username, touid) {
var chatModal = $('#chat-modal-'+touid);
module.getModal = function(touid) {
return $('#chat-modal-' + touid);
}
module.modalOpen = function(touid) {
return $('#chat-modal-' + touid).length !== 0;
}
module.createModalIfDoesntExist = function(username, touid, callback) {
var chatModal = $('#chat-modal-' + touid);
if(!chatModal.length) {
var chatModal = $('#chat-modal').clone();
chatModal.attr('id','chat-modal-'+touid);
chatModal.attr('id','chat-modal-' + touid);
var uuid = utils.generateUUID();
chatModal.attr('UUID', uuid);
chatModal.appendTo($('body'));
@ -29,7 +36,7 @@ define(['taskbar'], function(taskbar) {
});
chatModal.find('#chat-with-name').html(username);
chatModal.find('.close').on('click',function(e){
chatModal.find('.close').on('click', function(e) {
chatModal.hide();
taskbar.discard('chat', uuid);
});
@ -40,9 +47,15 @@ define(['taskbar'], function(taskbar) {
addSendHandler(chatModal, touid);
getChatMessages(chatModal, touid);
getChatMessages(chatModal, touid, callback);
taskbar.push('chat', chatModal.attr('UUID'), {title:'chat with '+username});
return chatModal;
}
if(callback)
callback(false, chatModal);
taskbar.push('chat', chatModal.attr('UUID'), {title:'chat with '+username});
return chatModal;
}
@ -59,11 +72,14 @@ define(['taskbar'], function(taskbar) {
taskbar.minimize('chat', uuid);
}
function getChatMessages(chatModal, touid) {
function getChatMessages(chatModal, touid, callback) {
socket.emit('getChatMessages', {touid:touid}, function(messages) {
for(var i = 0; i<messages.length; ++i) {
module.appendChatMessage(chatModal, messages[i].content);
module.appendChatMessage(chatModal, messages[i].content, messages[i].timestamp);
}
if(callback)
callback(true, chatModal);
});
}
@ -88,14 +104,15 @@ define(['taskbar'], function(taskbar) {
msg = msg +'\n';
socket.emit('sendChatMessage', { touid:touid, message:msg});
chatModal.find('#chat-message-input').val('');
module.appendChatMessage(chatModal, 'You : ' + msg);
}
}
module.appendChatMessage = function(chatModal, message){
module.appendChatMessage = function(chatModal, message, timestamp) {
var chatContent = chatModal.find('#chat-content');
chatContent.append(message);
var date = new Date(parseInt(timestamp, 10));
chatContent.append('[' + date.toLocaleTimeString() + '] ' + message);
chatContent.scrollTop(
chatContent[0].scrollHeight - chatContent.height()
);

@ -91,11 +91,11 @@
},
isUserNameValid: function(name) {
return (name && name !== "" && (/^[a-zA-Z0-9 _-]{3,14}$/.test(name)));
return (name && name !== "" && (/^[a-zA-Z0-9 _-]+$/.test(name)));
},
isPasswordValid: function(password) {
return password && password.indexOf(' ') === -1 && password.length > 5;
return password && password.indexOf(' ') === -1;
},
// Blatently stolen from: http://phpjs.org/functions/strip_tags/

@ -50,6 +50,14 @@
</div>
</form>
<form>
<h3>User Settings</h3>
<div class="alert alert-notify">
<strong>Minimum Username Length</strong><br /> <input type="text" class="" value="2" data-field="minimumUsernameLength"><br />
<strong>Maximum Username Length</strong><br /> <input type="text" class="" value="16" data-field="maximumUsernameLength"><br />
</div>
</form>
<form>
<h3>Post Settings</h3>
<div class="alert alert-warning">

@ -15,11 +15,12 @@
<label for="email" class="col-lg-4 control-label">Email Address</label>
<div class="col-lg-8">
<div class="input-group">
<input class="form-control" type="text" placeholder="Enter Email Address" name="email" id="email" />
<input class="form-control" type="text" placeholder="Enter Email Address" name="email" id="email" />
<span class="input-group-addon">
<span id="email-notify"><i class="icon icon-circle-blank"></i></span>
</span>
</div>
<span class="help-block">By default, your email will be hidden from the public.</span>
</div>
</div>
<div class="form-group">
@ -31,6 +32,7 @@
<span id="username-notify"><i class="icon icon-circle-blank"></i></span>
</span>
</div>
<span class="help-block">A unique username. {minimumUsernameLength}-{maximumUsernameLength} characters. Others can mention you with @<span id="yourUsername">username</span>.</span>
</div>
</div>
<div class="form-group">
@ -42,6 +44,7 @@
<span id="password-notify"><i class="icon icon-circle-blank"></i></span>
</span>
</div>
<span class="help-block">Your password's length must be {minimumPasswordLength}-{maximumPasswordLength} characters.</span>
</div>
</div>
<div class="form-group">
@ -57,7 +60,8 @@
</div>
<div class="form-group">
<div class="col-lg-offset-4 col-lg-8">
<button class="btn btn-primary" id="register" type="submit">Register Now</button>
<hr />
<button class="btn btn-primary btn-lg btn-block" id="register" type="submit">Register Now</button>
</div>
</div>
<input type="hidden" name="_csrf" value="{token}" />

@ -74,6 +74,7 @@ var RDB = require('./redis.js'),
categoryData.moderator_block_class = results[1].length > 0 ? '' : 'none';
categoryData.moderators = results[1];
categoryData.active_users = results[2];
categoryData.show_sidebar = categoryData.topics.length > 0 ? 'show':'hidden';
callback(null, categoryData);
});
}
@ -234,6 +235,26 @@ var RDB = require('./redis.js'),
});
}
Categories.moveActiveUsers = function(tid, oldCid, cid, callback) {
topics.getUids(tid, function(err, uids) {
if(!err && uids) {
function updateUser(uid) {
Categories.addActiveUser(cid, uid);
Categories.isUserActiveIn(oldCid, uid, function(err, active) {
if(!err && !active) {
Categories.removeActiveUser(oldCid, uid);
}
});
}
for(var i=0; i<uids.length; ++i) {
updateUser(uids[i]);
}
}
});
}
Categories.getCategoryData = function(cid, callback) {
RDB.exists('category:' + cid, function(err, exists) {
if (exists) RDB.hgetall('category:' + cid, callback);
@ -299,5 +320,58 @@ var RDB = require('./redis.js'),
};
Categories.isUserActiveIn = function(cid, uid, callback) {
RDB.lrange('uid:' + uid + ':posts', 0, -1, function(err, pids) {
if(err)
return callback(err, null);
function getPostCategory(pid, callback) {
posts.getPostField(pid, 'tid', function(tid) {
topics.getTopicField(tid, 'cid', function(err, postCid) {
if(err)
return callback(err, null);
return callback(null, postCid);
});
});
}
var index = 0,
active = false;
async.whilst(
function() {
return active === false && index < pids.length;
},
function(callback) {
getPostCategory(pids[index], function(err, postCid) {
if(err)
return callback(err);
if(postCid === cid)
active = true;
++index;
callback(null);
})
},
function(err) {
if(err)
return callback(err, null);
callback(null, active);
}
);
});
}
Categories.addActiveUser = function(cid, uid) {
RDB.sadd('cid:' + cid + ':active_users', uid);
}
Categories.removeActiveUser = function(cid, uid) {
RDB.srem('cid:' + cid + ':active_users', uid);
}
}(exports));

@ -88,6 +88,10 @@ var async = require('async'),
meta.configs.set('postDelay', 10000);
meta.configs.set('minimumPostLength', 8);
meta.configs.set('minimumTitleLength', 3);
meta.configs.set('minimumUsernameLength', 2);
meta.configs.set('maximumUsernameLength', 16);
meta.configs.set('minimumPasswordLength', 6);
meta.configs.set('maximumPasswordLength', 16);
meta.configs.set('imgurClientID', '');
install.save(server_conf, client_conf, callback);

@ -80,7 +80,7 @@ var fs = require('fs'),
hookList = this.loadedHooks[hook];
if (hookList && Array.isArray(hookList)) {
if (global.env === 'development') winston.info('[plugins] Firing hook: \'' + hook + '\'');
//if (global.env === 'development') winston.info('[plugins] Firing hook: \'' + hook + '\'');
var hookType = hook.split(':')[0];
switch(hookType) {
case 'filter':

@ -56,7 +56,6 @@ var RDB = require('./redis.js'),
}
PostTools.edit = function(uid, pid, title, content) {
var success = function() {
posts.setPostField(pid, 'content', content);
posts.setPostField(pid, 'edited', Date.now());
@ -66,27 +65,36 @@ var RDB = require('./redis.js'),
postSearch.index(content, pid);
});
posts.getPostField(pid, 'tid', function(tid) {
PostTools.isMain(pid, tid, function(isMainPost) {
if (isMainPost) {
topics.setTopicField(tid, 'title', title);
topicSearch.remove(tid, function() {
topicSearch.index(title, tid);
async.parallel([
function(next) {
posts.getPostField(pid, 'tid', function(tid) {
PostTools.isMain(pid, tid, function(isMainPost) {
if (isMainPost) {
topics.setTopicField(tid, 'title', title);
topicSearch.remove(tid, function() {
topicSearch.index(title, tid);
});
}
next(null, tid);
});
}
io.sockets.in('topic_' + tid).emit('event:post_edited', {
pid: pid,
title: title,
content: PostTools.markdownToHTML(content)
});
},
function(next) {
PostTools.toHTML(content, next);
}
], function(err, results) {
io.sockets.in('topic_' + results[0]).emit('event:post_edited', {
pid: pid,
title: title,
content: results[1]
});
});
};
PostTools.privileges(pid, uid, function(privileges) {
if (privileges.editable) {
plugins.fireHook('filter:save_post_content', content, function(parsedContent) {
plugins.fireHook('filter:post.save', content, function(parsedContent) {
content = parsedContent;
success();
});
@ -101,6 +109,7 @@ var RDB = require('./redis.js'),
postSearch.remove(pid);
posts.getPostFields(pid, ['tid', 'uid'], function(postData) {
RDB.hincrby('topic:'+postData.tid, 'postcount', -1);
user.decrementUserFieldBy(postData.uid, 'postcount', 1, function(err, postcount) {
RDB.zadd('users:postcount', postcount, postData.uid);
@ -134,25 +143,33 @@ var RDB = require('./redis.js'),
PostTools.restore = function(uid, pid) {
var success = function() {
posts.setPostField(pid, 'deleted', 0);
posts.setPostField(pid, 'deleted', 0);
posts.getPostFields(pid, ['tid', 'uid', 'content'], function(postData) {
posts.getPostFields(pid, ['tid', 'uid', 'content'], function(postData) {
RDB.hincrby('topic:'+postData.tid, 'postcount', 1);
user.incrementUserFieldBy(postData.uid, 'postcount', 1);
user.incrementUserFieldBy(postData.uid, 'postcount', 1);
io.sockets.in('topic_' + postData.tid).emit('event:post_restored', {
pid: pid
});
io.sockets.in('topic_' + postData.tid).emit('event:post_restored', {
pid: pid
});
threadTools.get_latest_undeleted_pid(postData.tid, function(err, pid) {
posts.getPostField(pid, 'timestamp', function(timestamp) {
topics.updateTimestamp(postData.tid, timestamp);
threadTools.get_latest_undeleted_pid(postData.tid, function(err, pid) {
posts.getPostField(pid, 'timestamp', function(timestamp) {
topics.updateTimestamp(postData.tid, timestamp);
});
});
});
postSearch.index(postData.content, pid);
});
};
// Restore topic if it is the only post
topics.getTopicField(postData.tid, 'postcount', function(err, count) {
if (count === '1') {
threadTools.restore(postData.tid, uid);
}
});
postSearch.index(postData.content, pid);
});
};
PostTools.privileges(pid, uid, function(privileges) {
if (privileges.editable) {
@ -161,35 +178,28 @@ var RDB = require('./redis.js'),
});
}
PostTools.markdownToHTML = function(md, isSignature) {
var marked = require('marked'),
cheerio = require('cheerio');
marked.setOptions({
breaks: true
});
if (md && md.length > 0) {
var parsedContentDOM = cheerio.load(marked(md));
var domain = nconf.get('url');
parsedContentDOM('a').each(function() {
this.attr('rel', 'nofollow');
var href = this.attr('href');
PostTools.toHTML = function(raw, callback) {
plugins.fireHook('filter:post.parse', raw, function(parsed) {
var cheerio = require('cheerio');
if (href && !href.match(domain) && !utils.isRelativeUrl(href)) {
this.attr('href', domain + 'outgoing?url=' + encodeURIComponent(href));
if (!isSignature) this.append(' <i class="icon-external-link"></i>');
}
});
if (parsed && parsed.length > 0) {
var parsedContentDOM = cheerio.load(parsed);
var domain = nconf.get('url');
parsedContentDOM('a').each(function() {
this.attr('rel', 'nofollow');
var href = this.attr('href');
html = parsedContentDOM.html();
} else {
html = '<p></p>';
}
if (href && !href.match(domain) && !utils.isRelativeUrl(href)) {
this.attr('href', domain + 'outgoing?url=' + encodeURIComponent(href));
}
});
return html;
callback(null, parsedContentDOM.html());
} else {
callback(null, '<p></p>');
}
});
}

@ -34,28 +34,29 @@ var RDB = require('./redis.js'),
Posts.addUserInfoToPost = function(post, callback) {
user.getUserFields(post.uid, ['username', 'userslug', 'reputation', 'postcount', 'picture', 'signature', 'banned'], function(err, userData) {
if(err)
return callback();
post.username = userData.username || 'anonymous';
post.userslug = userData.userslug || '';
post.user_rep = userData.reputation || 0;
post.user_postcount = userData.postcount || 0;
post.user_banned = userData.banned || '0';
post.picture = userData.picture || require('gravatar').url('', {}, https=nconf.get('https'));
post.signature = postTools.markdownToHTML(userData.signature, true);
if(post.editor !== '') {
user.getUserFields(post.editor, ['username', 'userslug'], function(err, editorData) {
if(err)
return callback();
post.editorname = editorData.username;
post.editorslug = editorData.userslug;
if(err) return callback();
postTools.toHTML(userData.signature, function(err, signature) {
post.username = userData.username || 'anonymous';
post.userslug = userData.userslug || '';
post.user_rep = userData.reputation || 0;
post.user_postcount = userData.postcount || 0;
post.user_banned = userData.banned || '0';
post.picture = userData.picture || require('gravatar').url('', {}, https=nconf.get('https'));
post.signature = signature;
if(post.editor !== '') {
user.getUserFields(post.editor, ['username', 'userslug'], function(err, editorData) {
if(err) return callback();
post.editorname = editorData.username;
post.editorslug = editorData.userslug;
callback();
});
} else {
callback();
});
} else {
callback();
}
}
});
});
}
@ -64,28 +65,41 @@ var RDB = require('./redis.js'),
var posts = [];
function getPostSummary(pid, callback) {
Posts.getPostFields(pid, ['pid', 'tid', 'content', 'uid', 'timestamp', 'deleted'], function(postData) {
if(postData.deleted === '1') {
return callback(null);
}
Posts.addUserInfoToPost(postData, function() {
async.waterfall([
function(next) {
Posts.getPostFields(pid, ['pid', 'tid', 'content', 'uid', 'timestamp', 'deleted'], function(postData) {
if (postData.deleted === '1') return callback(null);
else {
postData.relativeTime = utils.relativeTime(postData.timestamp);
next(null, postData);
}
});
},
function(postData, next) {
Posts.addUserInfoToPost(postData, function() {
next(null, postData);
});
},
function(postData, next) {
topics.getTopicFields(postData.tid, ['slug', 'deleted'], function(err, topicData) {
if(err)
return callback(err);
if(topicData.deleted === '1')
return callback(null);
if (err) return callback(err);
else if (topicData.deleted === '1') return callback(null);
if(postData.content)
postData.content = utils.strip_tags(postTools.markdownToHTML(postData.content));
postData.relativeTime = utils.relativeTime(postData.timestamp);
postData.topicSlug = topicData.slug;
posts.push(postData);
callback(null);
next(null, postData);
});
});
},
function(postData, next) {
if (postData.content) {
postTools.toHTML(postData.content, function(err, content) {
if (!err) postData.content = utils.strip_tags(content);
next(err, postData);
});
} else next(null, postData);
}
], function(err, postData) {
if (!err) posts.push(postData);
callback(err);
});
}
@ -144,7 +158,7 @@ var RDB = require('./redis.js'),
Posts.getPostsByPids = function(pids, callback) {
var posts = [];
function iterator(pid, callback) {
async.eachSeries(pids, function (pid, callback) {
Posts.getPostData(pid, function(postData) {
if(postData) {
postData.relativeTime = utils.relativeTime(postData.timestamp);
@ -152,8 +166,6 @@ var RDB = require('./redis.js'),
postData['edited-class'] = postData.editor !== '' ? '' : 'none';
postData['relativeEditTime'] = postData.edited !== '0' ? utils.relativeTime(postData.edited) : '';
postData.content = postTools.markdownToHTML(postData.content);
if(postData.uploadedImages) {
try {
postData.uploadedImages = JSON.parse(postData.uploadedImages);
@ -164,13 +176,15 @@ var RDB = require('./redis.js'),
} else {
postData.uploadedImages = [];
}
posts.push(postData);
postTools.toHTML(postData.content, function(err, content) {
postData.content = content;
posts.push(postData);
callback(null);
});
}
callback(null);
});
}
async.eachSeries(pids, iterator, function(err) {
}, function(err) {
if(!err) {
callback(null, posts);
} else {
@ -310,7 +324,7 @@ var RDB = require('./redis.js'),
RDB.spop('cid:' + cid + ':active_users');
}
RDB.sadd('cid:' + cid + ':active_users', uid);
categories.addActiveUser(cid, uid);
});
});
@ -329,8 +343,9 @@ var RDB = require('./redis.js'),
},
content: function(next) {
plugins.fireHook('filter:post.get', postData, function(postData) {
postData.content = postTools.markdownToHTML(postData.content, false);
next(null, postData.content);
postTools.toHTML(postData.content, function(err, content) {
next(null, content);
});
});
}
}, function(err, results) {

@ -22,6 +22,10 @@ var user = require('./../user.js'),
config['minimumTitleLength'] = meta.config['minimumTitleLength'];
config['minimumPostLength'] = meta.config['minimumPostLength'];
config['imgurClientIDSet'] = !!meta.config['imgurClientID'];
config['minimumUsernameLength'] = meta.config['minimumUsernameLength'];
config['maximumUsernameLength'] = meta.config['maximumUsernameLength'];
config['minimumPasswordLength'] = meta.config['minimumPasswordLength'];
config['maximumPasswordLength'] = meta.config['maximumPasswordLength'];
res.json(200, config);
});
@ -44,8 +48,7 @@ var user = require('./../user.js'),
require('async').each(data.categories, iterator, function(err) {
data.motd_class = (meta.config.show_motd === '1' || meta.config.show_motd === undefined) ? '' : 'none';
data.motd = marked(meta.config.motd || "# NodeBB <span>v " + pkg.version + "</span>\nWelcome to NodeBB, the discussion platform of the future.\n\n<div class='btn-group'><a target=\"_blank\" href=\"http://www.nodebb.org\" class=\"btn btn-default btn-lg\"><i class=\"icon-comment\"></i><span class='hidden-mobile'>&nbsp;Get NodeBB</span></a> <a target=\"_blank\" href=\"https://github.com/designcreateplay/NodeBB\" class=\"btn btn-default btn-lg\"><i class=\"icon-github-alt\"></i><span class='hidden-mobile'>&nbsp;Fork us on Github</span></a> <a target=\"_blank\" href=\"https://twitter.com/dcplabs\" class=\"btn btn-default btn-lg\"><i class=\"icon-twitter\"></i><span class='hidden-mobile'>&nbsp;@dcplabs</span></a></div>");
data.motd = require('marked')(meta.config.motd || "# NodeBB <span>v " + pkg.version + "</span>\nWelcome to NodeBB, the discussion platform of the future.\n\n<div class='btn-group'><a target=\"_blank\" href=\"http://www.nodebb.org\" class=\"btn btn-default btn-lg\"><i class=\"icon-comment\"></i><span class='hidden-mobile'>&nbsp;Get NodeBB</span></a> <a target=\"_blank\" href=\"https://github.com/designcreateplay/NodeBB\" class=\"btn btn-default btn-lg\"><i class=\"icon-github-alt\"></i><span class='hidden-mobile'>&nbsp;Fork us on Github</span></a> <a target=\"_blank\" href=\"https://twitter.com/dcplabs\" class=\"btn btn-default btn-lg\"><i class=\"icon-twitter\"></i><span class='hidden-mobile'>&nbsp;@dcplabs</span></a></div>");
res.json(data);
});
@ -98,7 +101,10 @@ var user = require('./../user.js'),
}
data.token = res.locals.csrf_token;
data.minimumUsernameLength = meta.config['minimumUsernameLength'];
data.maximumUsernameLength = meta.config['maximumUsernameLength'];
data.minimumPasswordLength = meta.config['minimumPasswordLength'];
data.maximumPasswordLength = meta.config['maximumPasswordLength'];
res.json(data);
});

@ -4,7 +4,6 @@ var user = require('./../user.js'),
fs = require('fs'),
utils = require('./../../public/src/utils.js'),
path = require('path'),
marked = require('marked'),
winston = require('winston');
(function(User) {
@ -353,12 +352,15 @@ var user = require('./../user.js'),
userData.posts = posts.filter(function(p) {return p.deleted !== "1";});
userData.isFollowing = isFollowing;
userData.signature = postTools.markdownToHTML(userData.signature, true);
if(!userData.profileviews)
userData.profileviews = 1;
if(callerUID !== userData.uid)
user.incrementUserFieldBy(userData.uid, 'profileviews', 1);
res.json(userData);
postTools.toHTML(userData.signature, function(err, signature) {
userData.signature = signature;
res.json(userData);
});
});
});
} else {

@ -20,11 +20,13 @@ var path = require('path'),
var categoryUrls = [];
categories.getAllCategories(function(data) {
data.categories.forEach(function(category) {
categoryUrls.push({
url: path.join('category', category.slug),
changefreq: 'weekly',
priority: '0.4'
});
if (!category.disabled) {
categoryUrls.push({
url: path.join('category', category.slug),
changefreq: 'weekly',
priority: '0.4'
});
}
});
next(null, categoryUrls);
@ -34,11 +36,13 @@ var path = require('path'),
var topicUrls = [];
topics.getAllTopics(null, null, function(topics) {
topics.forEach(function(topic) {
topicUrls.push({
url: path.join('topic', topic.slug),
changefreq: 'daily',
priority: '0.6'
});
if (topic.deleted !== '1') {
topicUrls.push({
url: path.join('topic', topic.slug),
changefreq: 'daily',
priority: '0.6'
});
}
});
next(null, topicUrls);

@ -199,12 +199,19 @@ var RDB = require('./redis.js'),
}
});
categories.moveActiveUsers(tid, oldCid, cid, function(err, data) {
if(err) {
winston.err(err);
}
});
categories.incrementCategoryFieldBy(oldCid, 'topic_count', -1);
categories.incrementCategoryFieldBy(cid, 'topic_count', 1);
socket.emit('api:topic.move', {
status: 'ok'
});
io.sockets.in('topic_' + tid).emit('event:topic_moved', {
tid: tid
});
@ -264,7 +271,7 @@ var RDB = require('./redis.js'),
topics.getTopicField(tid, 'title', function(err, title) {
topics.getTeaser(tid, function(err, teaser) {
if (!err) {
notifications.create(teaser.username + ' has posted a reply to: "' + title + '"', null, '/topic/' + tid, 'topic:' + tid, function(nid) {
notifications.create('<strong>' + teaser.username + '</strong> has posted a reply to: "<strong>' + title + '</strong>"', null, '/topic/' + tid, 'topic:' + tid, function(nid) {
next(null, nid);
});
} else next(err);

@ -5,7 +5,6 @@ var RDB = require('./redis.js')
user = require('./user.js'),
categories = require('./categories.js'),
posts = require('./posts.js'),
marked = require('marked'),
threadTools = require('./threadTools.js'),
postTools = require('./postTools'),
async = require('async'),
@ -14,9 +13,6 @@ var RDB = require('./redis.js')
reds = require('reds'),
topicSearch = reds.createSearch('nodebbtopicsearch');
marked.setOptions({
breaks: true
});
(function(Topics) {
@ -566,19 +562,23 @@ marked.setOptions({
return callback(err, null);
var stripped = postData.content,
timestamp = postData.timestamp;
if(postData.content) {
timestamp = postData.timestamp,
returnObj = {
"username": userData.username,
"picture": userData.picture,
"timestamp" : timestamp
};
if (postData.content) {
stripped = postData.content.replace(/>.+\n\n/, '');
stripped = utils.strip_tags(postTools.markdownToHTML(stripped));
postTools.toHTML(stripped, function(err, stripped) {
returnObj.text = utils.strip_tags(stripped);
callback(null, returnObj);
});
} else {
returnObj.text = '';
callback(null, returnObj);
}
callback(null, {
"text": stripped,
"username": userData.username,
"picture": userData.picture,
"timestamp" : timestamp
});
});
});
} else callback(new Error('no-teaser-found'));
@ -723,6 +723,28 @@ marked.setOptions({
RDB.lrange('tid:' + tid + ':posts', 0, -1, callback);
}
Topics.getUids = function(tid, callback) {
var uids = {};
Topics.getPids(tid, function(err, pids) {
function getUid(pid, next) {
posts.getPostField(pid, 'uid', function(uid) {
if(err)
return next(err);
uids[uid] = 1;
next(null);
});
}
async.each(pids, getUid, function(err) {
if(err)
return callback(err, null);
callback(null, Object.keys(uids));
});
});
}
Topics.delete = function(tid) {
Topics.setTopicField(tid, 'deleted', 1);
RDB.zrem('topics:recent', tid);

@ -3,9 +3,8 @@ var utils = require('./../public/src/utils.js'),
crypto = require('crypto'),
emailjs = require('emailjs'),
meta = require('./meta.js'),
emailjsServer = emailjs.server.connect(meta.config.mailer),
emailjsServer = emailjs.server.connect(meta.config.mailer || '127.0.0.1'),
bcrypt = require('bcrypt'),
marked = require('marked'),
notifications = require('./notifications.js'),
topics = require('./topics.js'),
async = require('async');
@ -581,7 +580,7 @@ var utils = require('./../public/src/utils.js'),
User.getUserField(uid, 'username', function(err, username) {
RDB.smembers('followers:' + uid, function(err, followers) {
topics.getTopicField(tid, 'slug', function(err, slug) {
var message = username + ' made a new post';
var message = '<strong>' + username + '</strong> made a new post';
notifications.create(message, 5, nconf.get('url') + 'topic/' + slug + '#' + pid, 'notification_'+ Date.now(), function(nid) {
notifications.push(nid, followers);

@ -6,7 +6,6 @@ var express = require('express'),
path = require('path'),
redis = require('redis'),
redisServer = redis.createClient(nconf.get('redis:port'), nconf.get('redis:host')),
marked = require('marked'),
utils = require('../public/src/utils.js'),
pkg = require('../package.json'),
fs = require('fs'),
@ -67,12 +66,12 @@ var express = require('express'),
app.use(express.session({
store: new RedisStore({
client: redisServer,
ttl: 60*60*24*14
ttl: 60*60*24*30
}),
secret: nconf.get('secret'),
key: 'express.sid',
cookie: {
maxAge: 60*60*24*30 // 30 days
maxAge: 60*60*24*30*1000 // 30 days
}
}));
app.use(express.csrf());

@ -32,7 +32,8 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
(function(io) {
var users = {},
userSockets = {},
rooms = {}
rooms = {},
chats = {};
global.io = io;
@ -55,7 +56,14 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
io.sockets.in('global').emit('api:user.isOnline', isUserOnline(uid));
user.getUserField(uid, 'username', function(err, username) {
socket.emit('event:connect', {status: 1, username:username});
socket.emit('event:connect', {status: 1, username:username, uid:uid});
if(chats[uid]) {
for(var i=0; i<chats[uid].length; ++i) {
io.sockets.in(chats[uid][i]).emit('chatMessage', {fromuid:uid, username:username, message: username+' came online\n', timestamp: Date.now()});
socket.join(chats[uid][i]);
}
}
});
}
});
@ -72,8 +80,21 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
if(userSockets[uid].length === 0) {
delete users[sessionID];
if(uid)
if(uid) {
io.sockets.in('global').emit('api:user.isOnline', isUserOnline(uid));
user.getUserField(uid, 'username', function(err, username) {
if(chats[uid] && chats[uid].length) {
for(var i=0; i<chats[uid].length; ++i) {
io.sockets.in(chats[uid][i]).emit('chatGoOffline', {uid:uid, username:username, timestamp:Date.now()});
socket.leave(chats[uid][i]);
}
}
});
}
}
for(var roomName in rooms) {
@ -196,9 +217,11 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
});
socket.on('user.exists', function(data) {
user.exists(utils.slugify(data.username), function(exists){
socket.emit('user.exists', {exists: exists});
});
if(data.username) {
user.exists(utils.slugify(data.username), function(exists){
socket.emit('user.exists', {exists: exists});
});
}
});
socket.on('user.count', function(data) {
@ -523,28 +546,54 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
return;
}
if(userSockets[touid]) {
var msg = utils.strip_tags(data.message),
numSockets = userSockets[touid].length;
var msg = utils.strip_tags(data.message);
user.getUserField(uid, 'username', function(err, username) {
var finalMessage = username + ' says : ' + msg;
var uids = [uid, touid].sort();
var chatroom = 'chatroom_'+uids[0]+'_'+uids[1];
for(var x=0;x<numSockets;x++) {
userSockets[touid][x].emit('chatMessage', {fromuid:uid, username:username, message:finalMessage});
}
user.getUserField(uid, 'username', function(err, username) {
var finalMessage = username + ': ' + msg,
notifText = 'New message from <strong>' + username + '</strong>';
notifications.create(finalMessage, 5, '#', 'notification_' + uid + '_' + touid, function(nid) {
if(!isUserOnline(touid)) {
notifications.create(notifText, 5, '#', 'notification_' + uid + '_' + touid, function(nid) {
notifications.push(nid, [touid], function(success) {
});
});
}
require('./messaging').addMessage(uid, touid, msg, function(err, message) {
require('./messaging').addMessage(uid, touid, msg, function(err, message) {
var numSockets = 0;
});
if(userSockets[touid]) {
numSockets = userSockets[touid].length;
for(var x=0; x<numSockets; ++x) {
userSockets[touid][x].join(chatroom);
userSockets[touid][x].emit('chatMessage', {fromuid:uid, username:username, message: finalMessage, timestamp: Date.now()});
}
chats[touid] = chats[touid] || [];
if(chats[touid].indexOf(chatroom) === -1)
chats[touid].push(chatroom);
}
if(userSockets[uid]) {
numSockets = userSockets[uid].length;
for(var x=0; x<numSockets; ++x) {
userSockets[uid][x].join(chatroom);
userSockets[uid][x].emit('chatMessage', {fromuid:touid, username:username, message:'You : ' + msg, timestamp: Date.now()});
}
chats[uid] = chats[uid] || [];
if(chats[uid].indexOf(chatroom) === -1)
chats[uid].push(chatroom);
}
});
}
});
});
socket.on('api:config.get', function(data) {

Loading…
Cancel
Save