azkaban-aplcache

XmlPermission seeming to work.

8/2/2012 3:40:15 PM

Details

diff --git a/src/java/azkaban/project/FileProjectManager.java b/src/java/azkaban/project/FileProjectManager.java
index fcd6499..6bb7074 100644
--- a/src/java/azkaban/project/FileProjectManager.java
+++ b/src/java/azkaban/project/FileProjectManager.java
@@ -169,7 +169,8 @@ public class FileProjectManager implements ProjectManager {
 		ArrayList<Project> array = new ArrayList<Project>();
 		for(Project project : projects.values()) {
 			Permission perm = project.getUserPermission(user);
-			if (perm.isPermissionSet(Type.ADMIN) || perm.isPermissionSet(Type.READ)) {
+
+			if (perm != null && (perm.isPermissionSet(Type.ADMIN) || perm.isPermissionSet(Type.READ))) {
 				array.add(project);
 			}
 		}
diff --git a/src/java/azkaban/project/Project.java b/src/java/azkaban/project/Project.java
index 9daa603..5b81b33 100644
--- a/src/java/azkaban/project/Project.java
+++ b/src/java/azkaban/project/Project.java
@@ -2,6 +2,7 @@ package azkaban.project;
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -18,7 +19,7 @@ public class Project {
 	private long lastModifiedTimestamp;
 	private String lastModifiedUser;
 	private String source;
-	private HashMap<String, Permission> userToPermission = new HashMap<String, Permission>();
+	private LinkedHashMap<String, Permission> userToPermission = new LinkedHashMap<String, Permission>();
 	private Map<String, Flow> flows = null;
 	
 	public Project(String name) {
@@ -102,6 +103,10 @@ public class Project {
 		return userToPermission.get(user.getUserId());
 	}
 
+	public Permission getUserPermission(String userID) {
+		return userToPermission.get(userID);
+	}
+	
 	public long getCreateTimestamp() {
 		return createTimestamp;
 	}
@@ -169,7 +174,7 @@ public class Project {
 			String userid = (String) user.get("userid");
 			Permission perm = new Permission();
 			List<String> list = (List<String>) user.get("permissions");
-			perm.setPermissionsByName(list);
+			perm.addPermissionsByName(list);
 
 			project.setUserPermission(userid, perm);
 		}
diff --git a/src/java/azkaban/user/Permission.java b/src/java/azkaban/user/Permission.java
index df4adac..01b0645 100644
--- a/src/java/azkaban/user/Permission.java
+++ b/src/java/azkaban/user/Permission.java
@@ -23,46 +23,63 @@ public class Permission {
 	}
 	
 	public Permission(Type ... list) {
-		setPermission(list);
+		addPermission(list);
 	}
 	
-	public void setPermission(Type ... list) {
-		for (Type perm: list) {
-			permissions.add(perm);
+	public void setPermission(Type type, boolean set) {
+		if (set) {
+			addPermission(type);
+		}
+		else {
+			removePermissions(type);
+		}
+	}
+	
+	public void addPermission(Type ... list) {
+		// Admin is all encompassing permission. No need to add other types
+		if (!permissions.contains(Type.ADMIN)) {
+			for (Type perm: list) {
+				permissions.add(perm);
+			}
+			// We add everything, and if there's Admin left, we make sure that only Admin is remaining.
+			if (permissions.contains(Type.ADMIN)) {
+				permissions.clear();
+				permissions.add(Type.ADMIN);
+			}
 		}
 	}
 	
-	public void setPermissionsByName(String ... list) {
+	public void addPermissionsByName(String ... list) {
 		for (String perm: list) {
 			Type type = Type.valueOf(perm);
 			if (type != null) {
-				permissions.add(type);
+				addPermission(type);
 			};
 		}
 	}
 	
-	public void setPermissions(Collection<Type> list) {
+	public void addPermissions(Collection<Type> list) {
 		for (Type perm: list) {
-			permissions.add(perm);
+			addPermission(perm);
 		}
 	}
 	
-	public void setPermissionsByName(Collection<String> list) {
+	public void addPermissionsByName(Collection<String> list) {
 		for (String perm: list) {
 			Type type = Type.valueOf(perm);
 			if (type != null) {
-				permissions.add(type);
+				addPermission(type);
 			};
 		}
 	}
 	
-	public void unsetPermissions(Type ... list) {
+	public void removePermissions(Type ... list) {
 		for (Type perm: list) {
 			permissions.remove(perm);
 		}
 	}
 	
-	public void unsetPermissionsByName(String ... list) {
+	public void removePermissionsByName(String ... list) {
 		for (String perm: list) {
 			Type type = Type.valueOf(perm);
 			if (type != null) {
diff --git a/src/java/azkaban/user/UserManager.java b/src/java/azkaban/user/UserManager.java
index 3af5e5e..3f9cb99 100644
--- a/src/java/azkaban/user/UserManager.java
+++ b/src/java/azkaban/user/UserManager.java
@@ -18,4 +18,6 @@ public interface UserManager {
 	 * @throws UserManagerException If the username/password combination doesn't exist.
 	 */
 	public User getUser(String username, String password) throws UserManagerException;
+	
+	public boolean validateUser(String username);
 }
diff --git a/src/java/azkaban/user/XmlUserManager.java b/src/java/azkaban/user/XmlUserManager.java
index 21968a4..b952a2f 100644
--- a/src/java/azkaban/user/XmlUserManager.java
+++ b/src/java/azkaban/user/XmlUserManager.java
@@ -186,4 +186,9 @@ public class XmlUserManager implements UserManager {
 		}
 		return user;
 	}
+
+	@Override
+	public boolean validateUser(String username) {
+		return users.containsKey(username);
+	}
 }
diff --git a/src/java/azkaban/webapp/servlet/ProjectManagerServlet.java b/src/java/azkaban/webapp/servlet/ProjectManagerServlet.java
index 325fdbf..8baf2cd 100644
--- a/src/java/azkaban/webapp/servlet/ProjectManagerServlet.java
+++ b/src/java/azkaban/webapp/servlet/ProjectManagerServlet.java
@@ -36,6 +36,8 @@ import azkaban.flow.Node;
 import azkaban.project.Project;
 import azkaban.project.ProjectManager;
 import azkaban.project.ProjectManagerException;
+import azkaban.user.Permission;
+import azkaban.user.UserManager;
 import azkaban.user.Permission.Type;
 import azkaban.user.User;
 import azkaban.utils.Pair;
@@ -151,6 +153,21 @@ public class ProjectManagerServlet extends LoginAbstractAzkabanServlet {
 				jsonChangeDescription(project, ret, req, resp);
 			}
 		}
+		else if (jsonName.equals("getPermissions")) {
+			if (handleJsonPermission(project, user, Type.READ, ret)) {
+				jsonGetPermissions(project, ret);
+			}
+		}
+		else if (jsonName.equals("changeUserPermission")) {
+			if (handleJsonPermission(project, user, Type.ADMIN, ret)) {
+				jsonChangePermissions(project, ret, req);
+			}
+		}
+		else if (jsonName.equals("addUserPermission")) {
+			if (handleJsonPermission(project, user, Type.ADMIN, ret)) {
+				jsonAddUserPermission(project, ret, req);
+			}
+		}
 		
 		this.writeJSON(resp, ret);
 	}
@@ -274,6 +291,88 @@ public class ProjectManagerServlet extends LoginAbstractAzkabanServlet {
 		ret.put("nodes", nodeList);
 	}
 	
+	private void jsonAddUserPermission(Project project, HashMap<String, Object> ret, HttpServletRequest req) throws ServletException {
+		String username = getParam(req, "username");
+		UserManager userManager = getApplication().getUserManager();
+		if (!userManager.validateUser(username)) {
+			ret.put("error", "User is invalid.");
+			return;
+		}
+		if (project.getUserPermission(username) != null) {
+			ret.put("error", "User permission already exists.");
+			return;
+		}
+		
+		boolean admin = Boolean.parseBoolean(getParam(req, "permissions[admin]"));
+		boolean read = Boolean.parseBoolean(getParam(req, "permissions[read]"));
+		boolean write = Boolean.parseBoolean(getParam(req, "permissions[write]"));
+		boolean execute = Boolean.parseBoolean(getParam(req, "permissions[execute]"));
+		boolean schedule = Boolean.parseBoolean(getParam(req, "permissions[schedule]"));
+		
+		Permission perm = new Permission();
+		if (admin) {
+			perm.setPermission(Type.ADMIN, true);
+		}
+		else {
+			perm.setPermission(Type.READ, read);
+			perm.setPermission(Type.WRITE, write);
+			perm.setPermission(Type.EXECUTE, execute);
+			perm.setPermission(Type.SCHEDULE, schedule);
+		}
+		
+		project.setUserPermission(username, perm);
+		try {
+			manager.commitProject(project.getName());
+		} catch (ProjectManagerException e) {
+			ret.put("error", e.getMessage());
+		}
+	}
+
+	
+	private void jsonChangePermissions(Project project, HashMap<String, Object> ret, HttpServletRequest req) throws ServletException {
+		boolean admin = Boolean.parseBoolean(getParam(req, "permissions[admin]"));
+		boolean read = Boolean.parseBoolean(getParam(req, "permissions[read]"));
+		boolean write = Boolean.parseBoolean(getParam(req, "permissions[write]"));
+		boolean execute = Boolean.parseBoolean(getParam(req, "permissions[execute]"));
+		boolean schedule = Boolean.parseBoolean(getParam(req, "permissions[schedule]"));
+		
+		String username = getParam(req, "username");
+		Permission perm = project.getUserPermission(username);
+		if (perm == null) {
+			ret.put("error", "Permissions for " + username + " cannot be found.");
+			return;
+		}
+		
+		if (admin) {
+			perm.setPermission(Type.ADMIN, true);
+		}
+		else {
+			perm.setPermission(Type.READ, read);
+			perm.setPermission(Type.WRITE, write);
+			perm.setPermission(Type.EXECUTE, execute);
+			perm.setPermission(Type.SCHEDULE, schedule);
+		}
+		try {
+			manager.commitProject(project.getName());
+		} catch (ProjectManagerException e) {
+			ret.put("error", e.getMessage());
+		}
+	}
+	
+	private void jsonGetPermissions(Project project, HashMap<String, Object> ret) {
+		ArrayList<HashMap<String, Object>> permissions = new ArrayList<HashMap<String, Object>>();
+		for(Pair<String, Permission> perm: project.getUserPermissions()) {
+			HashMap<String, Object> permObj = new HashMap<String, Object>();
+			String userId = perm.getFirst();
+			permObj.put("username", userId);
+			permObj.put("permission", perm.getSecond().toStringArray());
+			
+			permissions.add(permObj);
+		}
+		
+		ret.put("permissions", permissions);
+	}
+	
 	private void handlePermissionPage(HttpServletRequest req, HttpServletResponse resp, Session session) throws ServletException {
 		Page page = newPage(req, resp, session, "azkaban/webapp/servlet/velocity/permissionspage.vm");
 		String projectName = getParam(req, "project");
@@ -287,10 +386,14 @@ public class ProjectManagerServlet extends LoginAbstractAzkabanServlet {
 			}
 			else {
 				page.add("project", project);
-				
+				page.add("username", user.getUserId());
 				page.add("admins", Utils.flattenToString(project.getUsersWithPermission(Type.ADMIN), ","));
 				page.add("userpermission", project.getUserPermission(user));
 				page.add("permissions", project.getUserPermissions());
+				
+				if(project.hasPermission(user, Type.ADMIN)) {
+					page.add("isAdmin", true);
+				}
 			}
 		}
 		catch(AccessControlException e) {
diff --git a/src/java/azkaban/webapp/servlet/velocity/permissionspage.vm b/src/java/azkaban/webapp/servlet/velocity/permissionspage.vm
index c84ca08..ff11bed 100644
--- a/src/java/azkaban/webapp/servlet/velocity/permissionspage.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/permissionspage.vm
@@ -9,13 +9,14 @@
 		<script type="text/javascript" src="${context}/js/backbone-0.5.3-min.js"></script>
 		<script type="text/javascript" src="${context}/js/jquery.simplemodal.js"></script>
 		<script type="text/javascript" src="${context}/js/azkaban.nav.js"></script>
+		<script type="text/javascript" src="${context}/js/azkaban.permission.view.js"></script>
 		<script type="text/javascript">
 			var contextURL = "${context}";
 			var currentTime = ${currentTime};
 			var timezone = "${timezone}";
 			var errorMessage = "${error_message}";
 			var successMessage = "${success_message}";
-			
+			var userId = "$username";
 			var projectId = "$project.name";
 		</script>
 	</head>
@@ -47,7 +48,13 @@
 					<table class="user-table">
 						<tr><td class="first">Project Admins:</td><td>$admins</td></tr>
 						<tr><td class="first">Your Permissions:</td><td>$userpermission.toString()</td></tr>
+						
+						<tr><td class="first"></td></tr>
 					</table>
+					
+					#if($isAdmin)
+						<button id="addUser" class="btn1">Add User</button>
+					#end
 				</div>
 
 				<div id="project-summary">
@@ -57,14 +64,11 @@
 						<tr><td class="first">Modified Date:</td><td>$utils.formatDate($project.createTimestamp)</td></tr>
 						<tr><td class="first">Last Modified by:</td><td>$project.lastModifiedUser</td></tr>
 						<tr><td class="first">Description:</td><td id="pdescription">$project.description</td>
-							#if($admin)
-								<td><div id="edit" class="btn5">Edit</div></td>
-							#end
 						</tr>
 					</table>
 				</div>
 
-		<table id="all-jobs" class="all-jobs permission-table">
+		<table id="permissions-table" class="all-jobs permission-table">
 			<thead>
 				<tr>
 					<th class="tb-username">User</th>
@@ -73,35 +77,75 @@
 					<th class="tb-write">Write</th>
 					<th class="tb-execute">Execute</th>
 					<th class="tb-schedule">Schedule</th>
+					#if($isAdmin)
+						<th class="tb-action"></th>
+					#end
 				</tr>
 			</thead>
 			<tbody>
 #if($permissions)
 #foreach($perm in $permissions)
-	<tr>
-		<td class="tb-name">$perm.first</td>
-		#if ($perm.second.isPermissionNameSet('ADMIN'))
-			<td><input type="checkbox" name="admin" disabled="disabled" checked></input></td>
-			<td><input type="checkbox" name="read" disabled="disabled" checked></input></td>
-			<td><input type="checkbox" name="write" disabled="disabled" checked></input></td>
-			<td><input type="checkbox" name="execute" disabled="disabled" checked></input></td>
-			<td><input type="checkbox" name="scheduled" disabled="disabled" checked></input></td>
+	<tr id="${perm.first}-row" >
+		<td class="tb-name">#if($perm.first == $username) ${perm.first} <span class="sublabel">(you)</span> #else $perm.first #end</td>
+		#if ($perm.second.isPermissionNameSet("ADMIN")) 
+			<td><input id="${perm.first}-admin-checkbox" type="checkbox" name="admin" disabled="disabled" checked="true"></input></td>
+			<td><input id="${perm.first}-read-checkbox" type="checkbox" name="read" disabled="disabled" checked="true"></input></td>
+			<td><input id="${perm.first}-write-checkbox" type="checkbox" name="write" disabled="disabled" checked="true"></input></td>
+			<td><input id="${perm.first}-execute-checkbox" type="checkbox" name="execute" disabled="disabled" checked="true"></input></td>
+			<td><input id="${perm.first}-schedule-checkbox" type="checkbox" name="schedule" disabled="disabled" checked="true"></input></td>
 		#else
-			<td><input type="checkbox" name="admin" disabled="disabled"> </input></td>
-			<td><input type="checkbox" name="read" disabled="disabled" #if ($perm.second.isPermissionNameSet('READ')) checked#end > </input></td>
-			<td><input type="checkbox" name="write" disabled="disabled" #if ($perm.second.isPermissionNameSet('WRITE')) checked#end > </input></td>
-			<td><input type="checkbox" name="execute" disabled="disabled" #if ($perm.second.isPermissionNameSet('EXECUTE')) checked#end > </input></td>
-			<td><input type="checkbox" name="scheduled" disabled="disabled" #if ($perm.second.isPermissionNameSet('SCHEDULE')) checked#end > </input></td>
+			<td><input id="${perm.first}-admin-checkbox" type="checkbox" name="admin" disabled="disabled"></input></td>
+			<td><input id="${perm.first}-read-checkbox" type="checkbox" name="read" disabled="disabled"  #if ($perm.second.isPermissionNameSet("READ")) checked="true" #end></input></td>
+			<td><input id="${perm.first}-write-checkbox" type="checkbox" name="write" disabled="disabled" #if ($perm.second.isPermissionNameSet("WRITE")) checked="true" #end></input></td>
+			<td><input id="${perm.first}-execute-checkbox" type="checkbox" name="execute" disabled="disabled" #if ($perm.second.isPermissionNameSet("EXECUTE")) checked="true" #end></input></td>
+			<td><input id="${perm.first}-schedule-checkbox" type="checkbox" name="schedule" disabled="disabled" #if ($perm.second.isPermissionNameSet("SCHEDULE")) checked="true" #end></input></td>
+		#end
+
+		#if($isAdmin)
+			<td><button id="$perm.first" #if($perm.first == $username) disabled="disabled" class="change-btn btn-disabled" #else class="change-btn btn2" #end >Change</button></td>
 		#end
 	</tr>
 #end
 #else
-						<tr><td class="last">No Users Found.</td></tr>
+	<tr><td class="last">No Users Found.</td></tr>
 #end
 			</tbody>
 		</table>
 #end
 		</div>
 	
+		<div id="change-permission" class="modal">
+			<h3 id="change-title">Change User Permissions</h3>
+			<div id="errorMsg" class="box-error-message"></div>
+			<div class="message">
+				<fieldset>
+					<dl>
+						<dt>User</dt>
+						<dd><input id="user-box" name="userid" type="text" /></dd>
+						<dt class="nextline">Admin</dt>
+						<dd><input id="admin-change" name="admin" type="checkbox" /></dd>
+						<dt>Read</dt>
+					    <dd><input id="read-change" name="read" type="checkbox" /></dd>
+					    <dt>Write</dt>
+					    <dd><input id="write-change" name="write" type="checkbox" /></dd>
+					    <dt>Execute</dt>
+					    <dd><input id="execute-change" name="execute" type="checkbox" /></dd>
+					    <dt>Schedule</dt>
+					    <dd><input id="schedule-change" name="schedule" type="checkbox" /></dd>
+					</dl>
+				</fieldset>
+			</div>
+			<div class="actions">
+				<a class="yes btn2" id="change-btn" href="#">Commit</a>
+				<a class="no simplemodal-close btn3" href="#">Cancel</a>
+			</div>
+			<div id="invalid-session" class="modal">
+				<h3>Invalid Session</h3>
+				<p>Session has expired. Please re-login.</p>
+				<div class="actions">
+					<a class="yes btn2" id="login-btn" href="#">Re-login</a>
+				</div>
+			</div>
+		</div>
 	</body>
 </html>
\ No newline at end of file
diff --git a/src/web/css/azkaban.css b/src/web/css/azkaban.css
index 366438c..0cad317 100644
--- a/src/web/css/azkaban.css
+++ b/src/web/css/azkaban.css
@@ -311,7 +311,8 @@ tr:hover td {
 .btn2,
 .btn3,
 .btn4,
-.btn5 {
+.btn5,
+.btn-disabled {
   -moz-border-radius: 3px;
   -webkit-border-radius: 3px;
   border-radius: 3px;
@@ -396,11 +397,20 @@ tr:hover td {
   border-color: #999;
   color: #666;
 }
-.btn5:hover {
+.btn3:hover {
   background: -moz-linear-gradient(center top , white 0pt, #ECECEC 100%) repeat scroll 0 0 transparent;
   background: -webkit-gradient(linear, center top, center bottom, from(#FFF), to(#ECECEC));
 }
 
+.btn-disabled {
+  background: #CECECE;
+  background: -moz-linear-gradient(top, #F2F2F2 0, #F2F2F2 1px, #E4E4E4 1px, #CECECE 100%);
+  background: -o-linear-gradient(top, #F2F2F2 0, #F2F2F2 1px, #E4E4E4 1px, #CECECE 100%);
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(0,#F2F2F2), color-stop(5%,#F2F2F2), color-stop(5%,#E4E4E4), color-stop(100%,#CECECE));
+  background: linear-gradient(top, #F2F2F2 0, #F2F2F2 1px, #E4E4E4 1px, #CECECE 100%);
+  color: #EEE;
+}
+
 /* confirm modal */
 .modal {
   display: none;
@@ -519,6 +529,12 @@ tr:hover td {
   padding-bottom: 8px; 
 }
 
+.modal h4 {
+  font-weight: bold;
+  margin: 20px 20px 10px 40px;
+  padding-bottom: 8px;
+}
+
 .modal .message {
   font-size: 81.25%;
   padding: 20px;
@@ -559,6 +575,24 @@ tr:hover td {
   padding-bottom: 6px;
 }
 
+#change-permission dt {
+  clear: none;
+  width: 75px;
+  padding: 0 0 0 0;
+}
+
+#change-permission dt.nextline {
+	clear: both;
+}
+
+#user-box {
+	background-color: #FFF;
+	border-width: 1px;
+	border-color: #CCC;
+	width: 300px;
+	margin-left: 10px;
+}
+
 #create-project #overwrite {
   width: 12px;
 }
@@ -1187,6 +1221,17 @@ svg .selected circle {
 	fill: #444;
 }
 
+span.sublabel {
+	font-size: 8pt;
+	margin-left: 12px;
+	color: #333;
+}
+
+#td-adduser {
+	text-align: left;
+	padding-left: 12px;
+}
+
 /* old styles */
 
 .azkaban-charts .hitarea {
diff --git a/src/web/js/azkaban.main.view.js b/src/web/js/azkaban.main.view.js
index a614a4a..49b9d25 100644
--- a/src/web/js/azkaban.main.view.js
+++ b/src/web/js/azkaban.main.view.js
@@ -83,7 +83,6 @@ azkaban.ProjectTableView= Backbone.View.extend({
   }
 });
 
-
 var projectHeaderView;
 azkaban.ProjectHeaderView= Backbone.View.extend({
   events : {
diff --git a/src/web/js/azkaban.permission.view.js b/src/web/js/azkaban.permission.view.js
new file mode 100644
index 0000000..d86bf1c
--- /dev/null
+++ b/src/web/js/azkaban.permission.view.js
@@ -0,0 +1,165 @@
+$.namespace('azkaban');
+
+var permissionTableView;
+azkaban.PermissionTableView= Backbone.View.extend({
+  events : {
+	"click button": "handleChangePermission"
+  },
+  initialize : function(settings) {
+  },
+  render: function() {
+  },
+  handleChangePermission: function(evt) {
+  	  var currentTarget = evt.currentTarget;
+  	  changePermissionView.display(currentTarget.id, false);
+  }
+});
+
+
+var changePermissionView;
+azkaban.ChangePermissionView= Backbone.View.extend({
+  events : {
+  	"click input['checkbox']": "handleCheckboxClick",
+  	"click #change-btn": "handleChangePermissions"
+  },
+  initialize : function(settings) {
+  	$('#errorMsg').hide();
+  },
+  display: function(userid, newUser) {
+  	this.userid = userid;
+  	this.permission = {};
+	$('#user-box').val(userid);
+	this.newUser = newUser;
+	
+	var adminInput = $("#" + userid + "-admin-checkbox");
+	var readInput = $("#" + userid + "-read-checkbox");
+	var writeInput = $("#" + userid + "-write-checkbox");
+	var executeInput = $("#" + userid + "-execute-checkbox");
+	var scheduleInput = $("#" + userid + "-schedule-checkbox");
+	
+	if (newUser) {
+		$('#change-title').text("Add New User");
+		$('#user-box').attr("disabled", null);
+		
+		// default
+		this.permission.admin = false;
+		this.permission.read = true;
+		this.permission.write = false;
+		this.permission.execute = false;
+		this.permission.schedule = false;
+	}
+	else {
+		$('#change-title').text("Change Permissions");
+		$('#user-box').attr("disabled", "disabled");
+		
+		this.permission.admin = $(adminInput).attr("checked");
+		this.permission.read = $(readInput).attr("checked");
+		this.permission.write = $(writeInput).attr("checked");
+		this.permission.execute = $(executeInput).attr("checked");
+		this.permission.schedule = $(scheduleInput).attr("checked");
+	}
+	
+	this.changeCheckbox();
+	
+	changePermissionView.render();
+  	 $('#change-permission').modal({
+          closeHTML: "<a href='#' title='Close' class='modal-close'>x</a>",
+          position: ["20%",],
+          containerId: 'confirm-container',
+          containerCss: {
+            'height': '220px',
+            'width': '565px'
+          },
+          onShow: function (dialog) {
+            var modal = this;
+            $("#errorMsg").hide();
+          }
+        });
+  },
+  render: function() {
+  },
+  handleCheckboxClick : function(evt) {
+  	console.log("click");
+  	var targetName = evt.currentTarget.name;
+  	this.permission[targetName] = evt.currentTarget.checked;
+  	this.changeCheckbox(evt);
+  },
+  changeCheckbox : function(evt) {
+    var perm = this.permission;
+  	if (perm.admin) {
+  		$("#admin-change").attr("checked", true);
+  		$("#read-change").attr("checked", true);
+  		$("#read-change").attr("disabled", "disabled");
+  		
+  		$("#write-change").attr("checked", true);
+  		$("#write-change").attr("disabled", "disabled");
+
+  		$("#execute-change").attr("checked", true);
+  		$("#execute-change").attr("disabled", "disabled"); 
+  		
+  		$("#schedule-change").attr("checked", true);
+  		$("#schedule-change").attr("disabled", "disabled");
+  	}
+  	else {
+  		$("#admin-change").attr("checked", false);
+  		$("#read-change").attr("checked", perm.read);
+  		$("#read-change").attr("disabled", null);
+  		  		
+  		$("#write-change").attr("checked", perm.write);
+  		$("#write-change").attr("disabled", null);
+  		
+  		$("#execute-change").attr("checked", perm.execute);
+  		$("#execute-change").attr("disabled", null);
+  		
+  		$("#schedule-change").attr("checked", perm.schedule);
+		$("#schedule-change").attr("disabled", null);
+  	}
+  	
+  	$("#change-btn").removeClass("btn-disabled");
+  	$("#change-btn").attr("disabled", null);
+  	
+  	if (perm.admin || perm.read || perm.write || perm.execute || perm.schedule) {
+  		$("#change-btn").text("Commit");
+  	}
+  	else {
+  		if(	this.newUser) {
+  			$("#change-btn").disabled = true;
+  			$("#change-btn").addClass("btn-disabled");
+  		}
+  		else {
+  			$("#change-btn").text("Remove");
+  		}
+  	}
+  },
+  handleChangePermissions : function(evt) {
+  	var requestURL = contextURL + "/manager";
+  	var userID = $('#user-box').val();
+	var command = this.newUser ? "addUserPermission" : "changeUserPermission";
+
+  	$.get(
+	      requestURL,
+	      {"project": projectId, "username": userID, "json":command, "permissions": this.permission},
+	      function(data) {
+	      	  console.log("Output");
+	      	  if (data.error) {
+	      	  	$("#errorMsg").text(data.error);
+	      	  	$("#errorMsg").show();
+	      	  	return;
+	      	  }
+	      	  
+	      	  var replaceURL = requestURL + "?project=" + projectId +"&permissions";
+	          window.location.replace(replaceURL);
+	      },
+	      "json"
+	    );
+  }
+});
+
+$(function() {
+	permissionTableView = new azkaban.PermissionTableView({el:$('#permissions-table')});
+	changePermissionView = new azkaban.ChangePermissionView({el:$('#change-permission')});
+	
+	$('#addUser').bind('click', function() {
+		changePermissionView.display("", true);
+	});
+});
diff --git a/unit/java/azkaban/test/user/PermissionTest.java b/unit/java/azkaban/test/user/PermissionTest.java
index df1dd72..0350379 100644
--- a/unit/java/azkaban/test/user/PermissionTest.java
+++ b/unit/java/azkaban/test/user/PermissionTest.java
@@ -21,16 +21,16 @@ public class PermissionTest {
     @Test
     public void testEmptyPermissionCreation() throws Exception {
     	Permission permission = new Permission();
-    	permission.setPermissionsByName(new String[]{});
+    	permission.addPermissionsByName(new String[]{});
     }
     
     @Test
     public void testSinglePermissionCreation() throws Exception {
     	Permission perm1 = new Permission();
-    	perm1.setPermissionsByName("READ");
+    	perm1.addPermissionsByName("READ");
     	
     	Permission perm2 = new Permission();
-    	perm2.setPermission(Type.READ);
+    	perm2.addPermission(Type.READ);
     	info("Compare " + perm1.toString() + " and " + perm2.toString());
     	assertTrue(perm1.equals(perm2));
     }
@@ -38,10 +38,10 @@ public class PermissionTest {
     @Test
     public void testListPermissionCreation() throws Exception {
     	Permission perm1 = new Permission();
-    	perm1.setPermissionsByName(new String[]{"READ", "EXECUTE"});
+    	perm1.addPermissionsByName(new String[]{"READ", "EXECUTE"});
     	
     	Permission perm2 = new Permission();
-    	perm2.setPermission(new Type[]{Type.EXECUTE, Type.READ});
+    	perm2.addPermission(new Type[]{Type.EXECUTE, Type.READ});
     	info("Compare " + perm1.toString() + " and " + perm2.toString());
     	assertTrue(perm1.equals(perm2));
     }
@@ -49,11 +49,11 @@ public class PermissionTest {
     @Test
     public void testRemovePermission() throws Exception {
     	Permission perm1 = new Permission();
-    	perm1.setPermissionsByName(new String[]{"READ", "EXECUTE", "WRITE"});
-    	perm1.unsetPermissions(Type.EXECUTE);
+    	perm1.addPermissionsByName(new String[]{"READ", "EXECUTE", "WRITE"});
+    	perm1.removePermissions(Type.EXECUTE);
     	
     	Permission perm2 = new Permission();
-    	perm2.setPermission(new Type[]{Type.READ, Type.WRITE});
+    	perm2.addPermission(new Type[]{Type.READ, Type.WRITE});
     	info("Compare " + perm1.toString() + " and " + perm2.toString());
     	assertTrue(perm1.equals(perm2));
     }
@@ -61,11 +61,11 @@ public class PermissionTest {
     @Test
     public void testRemovePermissionByName() throws Exception {
     	Permission perm1 = new Permission();
-    	perm1.setPermissionsByName(new String[]{"READ", "EXECUTE", "WRITE"});
-    	perm1.unsetPermissionsByName("EXECUTE");
+    	perm1.addPermissionsByName(new String[]{"READ", "EXECUTE", "WRITE"});
+    	perm1.removePermissionsByName("EXECUTE");
     	
     	Permission perm2 = new Permission();
-    	perm2.setPermission(new Type[]{Type.READ, Type.WRITE});
+    	perm2.addPermission(new Type[]{Type.READ, Type.WRITE});
     	info("Compare " + perm1.toString() + " and " + perm2.toString());
     	assertTrue(perm1.equals(perm2));
     }
@@ -73,11 +73,11 @@ public class PermissionTest {
     @Test
     public void testToAndFromObject() throws Exception {
     	Permission permission = new Permission();
-    	permission.setPermissionsByName(new String[]{"READ", "EXECUTE", "WRITE"});
+    	permission.addPermissionsByName(new String[]{"READ", "EXECUTE", "WRITE"});
     	
     	String[] array = permission.toStringArray();
     	Permission permission2 = new Permission();
-    	permission2.setPermissionsByName(array);
+    	permission2.addPermissionsByName(array);
     	assertTrue(permission.equals(permission2));
     }