From c1fea52a93a011de80af695fc3ac4f099b3316ad Mon Sep 17 00:00:00 2001
From: MrWaffle <mrwafflewaffle@aim.com>
Date: Sun, 19 Jan 2014 22:38:44 +0100
Subject: [PATCH 1/4] Only alternate title when not focused

---
 public/src/app.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/public/src/app.js b/public/src/app.js
index 99b4b29615..7c78e6e26f 100644
--- a/public/src/app.js
+++ b/public/src/app.js
@@ -407,7 +407,7 @@ var socket,
 			return;
 		}
 
-		if (title.length > 0) {
+		if (title.length > 0 && !app.isFocused) {
 			titleObj.titles[1] = title;
 			if (titleObj.interval) {
 				clearInterval(titleObj.interval);

From 189e69284e13cda35a4b79279259938a028e283f Mon Sep 17 00:00:00 2001
From: Baris Soner Usakli <barisusakli@gmail.com>
Date: Sun, 19 Jan 2014 17:28:08 -0500
Subject: [PATCH 2/4] fixes for post privileges

---
 public/templates/topic.tpl |  4 ++--
 src/categoryTools.js       |  4 +++-
 src/postTools.js           |  3 ++-
 src/socket.io/topics.js    | 12 +++++++++++-
 src/threadTools.js         |  4 +++-
 src/topics.js              | 31 +++++++++++++++++++++++--------
 6 files changed, 44 insertions(+), 14 deletions(-)

diff --git a/public/templates/topic.tpl b/public/templates/topic.tpl
index a67e7b1b8c..16a8016e46 100644
--- a/public/templates/topic.tpl
+++ b/public/templates/topic.tpl
@@ -106,9 +106,9 @@
 										<ul class="dropdown-menu text-center pull-right" role="menu" aria-labelledby="dLabel">
 											<button class="btn btn-sm btn-default edit" type="button" title="[[topic:edit]]"><i class="fa fa-pencil"></i></button>
 											<button class="btn btn-sm btn-default delete" type="button" title="[[topic:delete]]"><i class="fa fa-trash-o"></i></button>
-											<!-- IF !@first -->
+											<!-- IF posts.display_move_tools -->
 											<button class="btn btn-sm btn-default move" type="button" title="[[topic:move]]"><i class="fa fa-arrows"></i></button>
-											<!-- ENDIF !@first -->
+											<!-- ENDIF posts.display_move_tools -->
 										</ul>
 									</div>
 								</div>
diff --git a/src/categoryTools.js b/src/categoryTools.js
index bdce420460..853b9c049f 100644
--- a/src/categoryTools.js
+++ b/src/categoryTools.js
@@ -116,7 +116,9 @@ CategoryTools.privileges = function(cid, uid, callback) {
 				privileges.admin
 			),
 			editable: privileges.moderator || privileges.admin,
-			view_deleted: privileges.moderator || privileges.admin
+			view_deleted: privileges.moderator || privileges.admin,
+			moderator: privileges.moderator,
+			admin: privileges.moderator
 		});
 	});
 };
diff --git a/src/postTools.js b/src/postTools.js
index aca3214ded..13f7963f36 100644
--- a/src/postTools.js
+++ b/src/postTools.js
@@ -58,7 +58,8 @@ var winston = require('winston'),
 			callback(null, {
 				read: results.topicPrivs.read,
 				editable: results.topicPrivs.editable || results.isOwner || results.hasEnoughRep,
-				view_deleted: results.topicPrivs.view_deleted || results.isOwner || results.hasEnoughRep
+				view_deleted: results.topicPrivs.view_deleted || results.isOwner || results.hasEnoughRep,
+				move: results.topicPrivs.admin || results.topicPrivs.moderator
 			});
 		});
 	}
diff --git a/src/socket.io/topics.js b/src/socket.io/topics.js
index 4b8496287a..8dd19299ed 100644
--- a/src/socket.io/topics.js
+++ b/src/socket.io/topics.js
@@ -170,7 +170,17 @@ SocketTopics.movePost = function(socket, data, callback) {
 		return callback(new Error('invalid data'));
 	}
 
-	topics.movePostToTopic(data.pid, data.tid, callback);
+	threadTools.privileges(data.tid, socket.uid, function(err, privileges) {
+		if(err) {
+			return callback(err);
+		}
+
+		if(!(privileges.admin || privileges.moderator)) {
+			return callback(new Error('not allowed'));
+		}
+
+		topics.movePostToTopic(data.pid, data.tid, callback);
+	});
 };
 
 SocketTopics.move = function(socket, data, callback) {
diff --git a/src/threadTools.js b/src/threadTools.js
index dfcdb72fab..e7fa9a5854 100644
--- a/src/threadTools.js
+++ b/src/threadTools.js
@@ -50,7 +50,9 @@ var winston = require('winston'),
 				read: results.categoryPrivs.read,
 				write: results.categoryPrivs.write,
 				editable: results.categoryPrivs.editable || results.hasEnoughRep,
-				view_deleted: results.categoryPrivs.view_deleted || results.hasEnoughRep
+				view_deleted: results.categoryPrivs.view_deleted || results.hasEnoughRep,
+				moderator: results.categoryPrivs.moderator,
+				admin: results.categoryPrivs.admin
 			});
 		});
 	}
diff --git a/src/topics.js b/src/topics.js
index 9a57648702..131e1962e7 100644
--- a/src/topics.js
+++ b/src/topics.js
@@ -211,6 +211,7 @@ var async = require('async'),
 
 						postData.favourited = false;
 						postData.display_moderator_tools = true;
+						postData.display_move_tools = privileges.admin || privileges.moderator;
 						postData.relativeTime = utils.toISOString(postData.timestamp);
 
 						callback(null, postData);
@@ -358,12 +359,11 @@ var async = require('async'),
 				return parseInt(current_user, 10) !== 0 || parseInt(post.deleted, 10) === 0;
 			});
 
-			function getFavouritesData(next) {
-				var pids = [];
-				for (var i = 0; i < postData.length; ++i) {
-					pids.push(postData[i].pid);
-				}
+			pids = postData.map(function(post) {
+				return post.pid;
+			});
 
+			function getFavouritesData(next) {
 				favourites.getFavouritesByPostIDs(pids, current_user, function(fav_data) {
 					next(null, fav_data);
 				});
@@ -382,7 +382,20 @@ var async = require('async'),
 			}
 
 			function getPrivileges(next) {
-				postTools.privileges(tid, current_user, next);
+				var privs = {};
+				async.each(pids, getPostPrivileges, function(err) {
+					next(err, privs);
+				});
+
+				function getPostPrivileges(pid, next) {
+					postTools.privileges(pid, current_user, function(err, postPrivileges) {
+						if(err) {
+							return next(err);
+						}
+						privs[pid] = postPrivileges;
+						next();
+					});
+				}
 			}
 
 			async.parallel([getFavouritesData, addUserInfoToPosts, getPrivileges], function(err, results) {
@@ -394,8 +407,10 @@ var async = require('async'),
 					privileges = results[2];
 
 				for (var i = 0; i < postData.length; ++i) {
-					postData[i].favourited = fav_data[postData[i].pid];
-					postData[i].display_moderator_tools = ((current_user != 0) && (postData[i].uid == current_user || privileges.editable));
+					var pid = postData[i].pid;
+					postData[i].favourited = fav_data[pid];
+					postData[i].display_moderator_tools = (current_user != 0) && privileges[pid].editable;
+					postData[i].display_move_tools = privileges[pid].move;
 				}
 
 				callback(null, postData);

From 32adbc8c777eb4b7753c78fa99a9a0af3425a58f Mon Sep 17 00:00:00 2001
From: Baris Soner Usakli <barisusakli@gmail.com>
Date: Sun, 19 Jan 2014 17:49:16 -0500
Subject: [PATCH 3/4] close modal on error

---
 public/src/forum/topic.js | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/public/src/forum/topic.js b/public/src/forum/topic.js
index 7bead051dd..90e5ea0cb0 100644
--- a/public/src/forum/topic.js
+++ b/public/src/forum/topic.js
@@ -503,6 +503,8 @@ define(['composer'], function(composer) {
 			moveBtn.on('click', function() {
 				socket.emit('topics.movePost', {pid: pid, tid: topicId.val()}, function(err) {
 					if(err) {
+						$('#topicId').val('');
+						moveModal.addClass('hide');
 						return app.alertError(err.message);
 					}
 

From 4273fc4d23bda732308b269b40e4af699cd73cd6 Mon Sep 17 00:00:00 2001
From: Baris Soner Usakli <barisusakli@gmail.com>
Date: Sun, 19 Jan 2014 18:02:01 -0500
Subject: [PATCH 4/4] added check for valid field

---
 src/meta.js | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/meta.js b/src/meta.js
index 1fdf24bf5b..dd272bd796 100644
--- a/src/meta.js
+++ b/src/meta.js
@@ -44,6 +44,10 @@ var fs = require('fs'),
 			db.getObjectFields('config', fields, callback);
 		},
 		set: function (field, value, callback) {
+			if(!field) {
+				return callback(new Error('invalid config field'));
+			}
+
 			db.setObjectField('config', field, value, function(err, res) {
 				if (callback) {
 					if(!err && Meta.config) {