Bug 513834 - Prevent different users from linking the same github/google account
Signed-off-by: Alston Lin <alston@ca.ibm.com>
diff --git a/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/javascript/manageExternalIds.js b/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/javascript/manageExternalIds.js
index 7bdf987..060d924 100644
--- a/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/javascript/manageExternalIds.js
+++ b/bundles/org.eclipse.orion.client.ui/web/mixloginstatic/javascript/manageExternalIds.js
@@ -162,7 +162,11 @@
 		}).then(function(xhrResult) {
 			loadUserData(jsonData.Location);
 		}, function(xhrResult) {
-			console.error(xhrResult.error);
+			if (xhrResult.status === 409){
+				alert(messages["AccountAlreadyConnected"]);
+			} else {	
+				console.error(xhrResult.error);
+			}
 		});
 	};
 
diff --git a/bundles/org.eclipse.orion.client.ui/web/orion/mixloginstatic/nls/root/messages.js b/bundles/org.eclipse.orion.client.ui/web/orion/mixloginstatic/nls/root/messages.js
index 7c69a91..5bed757 100644
--- a/bundles/org.eclipse.orion.client.ui/web/orion/mixloginstatic/nls/root/messages.js
+++ b/bundles/org.eclipse.orion.client.ui/web/orion/mixloginstatic/nls/root/messages.js
@@ -14,4 +14,5 @@
 	"ConfirmRemove" : "Are you sure you want to remove ${0} from the list of your external accounts?",
 	"Remove" : "Remove",
 	"RemoveExternalAccount" : "Remove ${0}",
+	'AccountAlreadyConnected': 'This account is already connected to another user',
 });
diff --git a/modules/orionode/lib/user.js b/modules/orionode/lib/user.js
index c312781..31e83a3 100644
--- a/modules/orionode/lib/user.js
+++ b/modules/orionode/lib/user.js
@@ -337,10 +337,11 @@
 		orionAccount.findByUsername(req.params.id, function(err, user) {
 			if (err) return res.status(404).end();
 			if (!user) {
-				res.writeHead(400, "User not fount: " + req.params.id);
+				res.writeHead(400, "User not found: " + req.params.id);
 				return res.end();
 			}
 			var hasNewPassword = typeof req.body.Password !== "undefined";
+			var promiseChain = Promise.resolve();
 			// users other than admin have to know the old password to set a new one
 			if (!isAdmin(req.params.id)) {
 				//TODO
@@ -348,19 +349,46 @@
 			if (typeof req.body.UserName !== "undefined") user.username = req.body.UserName;
 			if (typeof req.body.FullName !== "undefined") user.fullname = req.body.FullName;
 			if (typeof req.body.Email !== "undefined") user.email = req.body.Email;
-			if (typeof req.body.OAuth !== "undefined") user.oauth = req.body.OAuth;
+			if (typeof req.body.OAuth !== "undefined") {
+				promiseChain = promiseChain.then(function(){
+					return new Promise(function(resolve, reject){
+						orionAccount.find({oauth: new RegExp("^" + req.body.OAuth + "$", "m")}, function(err, existing) {
+							if (err) {
+								reject(err);
+								return;
+							}
+							if (existing && existing.length) {
+								res.writeHead(409, "This account is already linked to someone else");
+								res.end();
+								reject();
+								return;
+							}
+							user.oauth = req.body.OAuth;
+							resolve();
+						});
+					});
+				});
+			}
 			function save(err) {
 				if (err) res.writeHead(400, "Failed to update: " + req.params.id);
 				return res.status(200).end();
 			}
-			if (hasNewPassword) {
-				user.setPassword(req.body.Password, function(err, user) {
-					if (err) res.writeHead(400, "Failed to update: " + req.params.id);
+			promiseChain.then(function(){
+				if (hasNewPassword) {
+					user.setPassword(req.body.Password, function(err, user) {
+						if (err) res.writeHead(400, "Failed to update: " + req.params.id);
+						user.save(save);
+					});
+				} else {
 					user.save(save);
-				});
-			} else {
-				user.save(save);
-			}
+				}
+			}).catch(function(err){
+				if (err) {
+					// Indicated unhandled error
+					res.writeHead(500, "An internal error has occured");
+					res.send();
+				}
+			});
 		});
 	});
 
@@ -510,4 +538,4 @@
 	});
 	
 	return app;
-};
\ No newline at end of file
+};