From f5298cbaf659ffc52d49649490c60b376f7ada87 Mon Sep 17 00:00:00 2001
From: Piotr Gawron <piotr.gawron@uni.lu>
Date: Thu, 12 Oct 2017 12:43:06 +0200
Subject: [PATCH] editing of user privileges implemented

---
 .../main/js/gui/admin/EditProjectDialog.js    |  44 ++---
 .../src/main/js/gui/admin/EditUserDialog.js   | 157 +++++++++++++++++-
 frontend-js/src/main/js/map/data/User.js      |  37 ++++-
 .../test/js/gui/admin/EditUserDialog-test.js  |  62 ++++++-
 frontend-js/src/test/js/map/data/User-test.js |  58 +++++++
 5 files changed, 325 insertions(+), 33 deletions(-)
 create mode 100644 frontend-js/src/test/js/map/data/User-test.js

diff --git a/frontend-js/src/main/js/gui/admin/EditProjectDialog.js b/frontend-js/src/main/js/gui/admin/EditProjectDialog.js
index cb84fb6740..971eabefe3 100644
--- a/frontend-js/src/main/js/gui/admin/EditProjectDialog.js
+++ b/frontend-js/src/main/js/gui/admin/EditProjectDialog.js
@@ -59,7 +59,7 @@ EditProjectDialog.prototype.createGeneralTab = function (tabMenuDiv, tabContentD
     tabContentDiv: tabContentDiv,
     name: "GENERAL",
     id: self.getProject().getProjectId() + "_general_tab",
-    content: self.createGeneralTabContent(),
+    content: self.createGeneralTabContent()
   });
 
 };
@@ -90,7 +90,7 @@ EditProjectDialog.prototype.createGeneralTabContent = function () {
   var project = self.getProject();
 
   var result = new Functions.createElement({
-    type: "div",
+    type: "div"
   });
 
   var table = new Functions.createElement({
@@ -107,12 +107,12 @@ EditProjectDialog.prototype.createGeneralTabContent = function () {
   projectIdRow.appendChild(new Functions.createElement({
     type: "div",
     style: "display:table-cell",
-    content: "ProjectId",
+    content: "ProjectId"
   }));
   projectIdRow.appendChild(new Functions.createElement({
     type: "div",
     style: "display:table-cell",
-    content: project.getProjectId(),
+    content: project.getProjectId()
   }));
 
   var nameRow = new Functions.createElement({
@@ -128,7 +128,7 @@ EditProjectDialog.prototype.createGeneralTabContent = function () {
   nameRow.appendChild(new Functions.createElement({
     type: "div",
     style: "display:table-cell",
-    content: "<input name='projectName' value='" + project.getName() + "'/>",
+    content: "<input name='projectName' value='" + project.getName() + "'/>"
   }));
 
   var versionRow = new Functions.createElement({
@@ -144,7 +144,7 @@ EditProjectDialog.prototype.createGeneralTabContent = function () {
   versionRow.appendChild(new Functions.createElement({
     type: "div",
     style: "display:table-cell",
-    content: "<input name='projectVersion' value='" + project.getVersion() + "'/>",
+    content: "<input name='projectVersion' value='" + project.getVersion() + "'/>"
   }));
 
   var diseaseRow = new Functions.createElement({
@@ -155,7 +155,7 @@ EditProjectDialog.prototype.createGeneralTabContent = function () {
   diseaseRow.appendChild(new Functions.createElement({
     type: "div",
     style: "display:table-cell",
-    content: "Disease",
+    content: "Disease"
   }));
   var disease = "";
   if (project.getDisease() !== undefined) {
@@ -164,7 +164,7 @@ EditProjectDialog.prototype.createGeneralTabContent = function () {
   diseaseRow.appendChild(new Functions.createElement({
     type: "div",
     style: "display:table-cell",
-    content: "<input name='projectDisease' value='" + disease + "'/>",
+    content: "<input name='projectDisease' value='" + disease + "'/>"
   }));
 
   var organismRow = new Functions.createElement({
@@ -175,7 +175,7 @@ EditProjectDialog.prototype.createGeneralTabContent = function () {
   organismRow.appendChild(new Functions.createElement({
     type: "div",
     style: "display:table-cell",
-    content: "Organism",
+    content: "Organism"
   }));
   var organism = "";
   if (project.getOrganism() !== undefined) {
@@ -184,7 +184,7 @@ EditProjectDialog.prototype.createGeneralTabContent = function () {
   organismRow.appendChild(new Functions.createElement({
     type: "div",
     style: "display:table-cell",
-    content: "<input name='projectOrganism' value='" + organism + "'/>",
+    content: "<input name='projectOrganism' value='" + organism + "'/>"
   }));
 
   var emailRow = new Functions.createElement({
@@ -204,7 +204,7 @@ EditProjectDialog.prototype.createGeneralTabContent = function () {
   emailRow.appendChild(new Functions.createElement({
     type: "div",
     style: "display:table-cell",
-    content: "<input name='projectNotifyEmail' value='" + email + "'/>",
+    content: "<input name='projectNotifyEmail' value='" + email + "'/>"
   }));
 
   var menuRow = Functions.createElement({
@@ -230,7 +230,7 @@ EditProjectDialog.prototype.createGeneralTabContent = function () {
     content: '<span class="ui-icon ui-icon-cancel"></span>&nbsp;CANCEL',
     onclick: function () {
       return self.close();
-    },
+    }
   });
   menuRow.appendChild(saveProjectButton);
   menuRow.appendChild(cancelButton);
@@ -246,14 +246,14 @@ EditProjectDialog.prototype.createOverlaysTab = function (tabMenuDiv, tabContent
     tabContentDiv: tabContentDiv,
     name: "OVERLAYS",
     id: self.getProject().getProjectId() + "_overlays_tab",
-    content: self.createOverlaysTabContent(),
+    content: self.createOverlaysTabContent()
   });
 };
 
 EditProjectDialog.prototype.createOverlaysTabContent = function () {
   var self = this;
   var result = Functions.createElement({
-    type: "div",
+    type: "div"
   });
   result.appendChild(self._createOverlayTable());
   return result;
@@ -264,14 +264,14 @@ EditProjectDialog.prototype._createOverlayTable = function () {
 
   var result = Functions.createElement({
     type: "div",
-    style: "margin-top:10px;",
+    style: "margin-top:10px;"
   });
 
   var overlaysTable = Functions.createElement({
     type: "table",
     name: "overlaysTable",
     className: "display",
-    style: "width:100%",
+    style: "width:100%"
   });
   result.appendChild(overlaysTable);
 
@@ -343,7 +343,7 @@ EditProjectDialog.prototype.createUsersTab = function (tabMenuDiv, tabContentDiv
     tabContentDiv: tabContentDiv,
     name: "USERS",
     id: self.getProject().getProjectId() + "_users_tab",
-    content: self.createUsersTabContent(),
+    content: self.createUsersTabContent()
   });
 };
 
@@ -352,14 +352,14 @@ EditProjectDialog.prototype.createUsersTabContent = function () {
 
   var result = Functions.createElement({
     type: "div",
-    style: "margin-top:10px;",
+    style: "margin-top:10px;"
   });
 
   var usersTable = Functions.createElement({
     type: "table",
     name: "usersTable",
     className: "display",
-    style: "width:100%",
+    style: "width:100%"
   });
   result.appendChild(usersTable);
 
@@ -425,7 +425,7 @@ EditProjectDialog.prototype.initUsersTab = function () {
 
   return self.createUserPrivilegeColumns().then(function (columns) {
     $(usersTable).DataTable({
-      columns: columns,
+      columns: columns
     });
   });
 };
@@ -584,7 +584,7 @@ EditProjectDialog.prototype.open = function () {
     $(div).dialog({
       title: self.getProject().getProjectId(),
       width: window.innerWidth / 2,
-      height: window.innerHeight / 2,
+      height: window.innerHeight / 2
     });
   }
   $(div).dialog("open");
@@ -664,7 +664,7 @@ EditProjectDialog.prototype.openAddOverlayDialog = function () {
   self._addOverlayDialog = new AddOverlayDialog({
     project: self.getProject(),
     customMap: null,
-    element: document.createElement("div"),
+    element: document.createElement("div")
   });
   self._addOverlayDialog.addListener("onAddOverlay", function () {
     return self.refreshOverlays();
diff --git a/frontend-js/src/main/js/gui/admin/EditUserDialog.js b/frontend-js/src/main/js/gui/admin/EditUserDialog.js
index 21c1c09333..58f3c3ef8e 100644
--- a/frontend-js/src/main/js/gui/admin/EditUserDialog.js
+++ b/frontend-js/src/main/js/gui/admin/EditUserDialog.js
@@ -55,6 +55,7 @@ EditUserDialog.prototype.createGui = function () {
   tabDiv.appendChild(tabContentDiv);
 
   self.createGeneralTab(tabMenuDiv, tabContentDiv);
+  self.createPrivilegesTab(tabMenuDiv, tabContentDiv);
   self.createProjectsTab(tabMenuDiv, tabContentDiv);
 };
 
@@ -64,22 +65,45 @@ EditUserDialog.prototype.createGeneralTab = function (tabMenuDiv, tabContentDiv)
     tabMenuDiv: tabMenuDiv,
     tabContentDiv: tabContentDiv,
     name: "GENERAL",
-    id: self.getUser().getLogin() + "_general_tab",
     content: self.createGeneralTabContent()
   });
 
 };
 
+var login_counter = 0;
+
+EditUserDialog.prototype.generateTabId = function (tab_name) {
+  var self = this;
+  var login = self.getUser().getLogin();
+  if (login === undefined) {
+    login = "new_user_" + (login_counter++);
+  }
+  return login.replace(".", "_") + tab_name + "_TAB";
+};
+
+EditUserDialog.prototype.createPrivilegesTab = function (tabMenuDiv, tabContentDiv) {
+  var self = this;
+  self.addTab({
+    tabMenuDiv: tabMenuDiv,
+    tabContentDiv: tabContentDiv,
+    name: "PRIVILEGES",
+    content: self.createPrivilegesTabContent()
+  });
+
+};
+
 EditUserDialog.prototype.addTab = function (params) {
+  var id = this.generateTabId(params.name);
+
   var navLi = guiUtils.createTabMenuObject({
-    id: params.id,
+    id: id,
     name: params.name,
     navigationBar: params.tabMenuDiv
   });
   params.tabMenuDiv.appendChild(navLi);
 
   var contentDiv = guiUtils.createTabContentObject({
-    id: params.id,
+    id: id,
     navigationObject: navLi,
     navigationBar: params.tabMenuDiv
   });
@@ -242,13 +266,39 @@ EditUserDialog.prototype.createGeneralTabContent = function () {
 
 };
 
+EditUserDialog.prototype.createPrivilegesTabContent = function () {
+  var self = this;
+  var result = Functions.createElement({
+    type: "div"
+  });
+  result.appendChild(self._createPrivilegesTable());
+  return result;
+};
+
+EditUserDialog.prototype._createPrivilegesTable = function () {
+  var result = Functions.createElement({
+    type: "div",
+    style: "margin-top:10px;"
+  });
+
+  var privilegesTable = Functions.createElement({
+    type: "table",
+    name: "privilegesTable",
+    className: "display",
+    style: "width:100%"
+  });
+  result.appendChild(privilegesTable);
+
+  return result;
+};
+
+
 EditUserDialog.prototype.createProjectsTab = function (tabMenuDiv, tabContentDiv) {
   var self = this;
   self.addTab({
     tabMenuDiv: tabMenuDiv,
     tabContentDiv: tabContentDiv,
     name: "PROJECTS",
-    id: self.getProject().getProjectId() + "_projects_tab",
     content: self.createProjectsTabContent()
   });
 };
@@ -283,6 +333,8 @@ EditUserDialog.prototype.init = function () {
   var self = this;
   return self.initProjectsTab().then(function () {
     return self.refreshProjects();
+  }).then(function () {
+    return self.initPrivilegesTab();
   }).then(function () {
     $(window).trigger('resize');
   });
@@ -293,10 +345,90 @@ EditUserDialog.prototype.initProjectsTab = function () {
 
   var usersTable = $("[name=projectsTable]", self.getElement())[0];
 
-  return self.createUserPrivilegeColumns().then(function (columns) {
+  var configuration;
+  return ServerConnector.getConfiguration().then(function (result) {
+    configuration = result;
+    return self.createUserPrivilegeColumns()
+  }).then(function (columns) {
     $(usersTable).DataTable({
       columns: columns
     });
+    $(usersTable).on("click", "[name='project-privilege-checkbox']", function () {
+      var data = $(this).attr("data").split("-");
+      var privilegeType = data[0];
+      var objectId = data[1];
+      var value = $(this).is(":checked");
+      for (var i = 0; i < configuration.getPrivilegeTypes().length; i++) {
+        var privilege = configuration.getPrivilegeTypes()[i];
+        if (privilege.getName() === privilegeType) {
+          self.getUser().setPrivilege({type: privilege, value: value, objectId: objectId});
+        }
+      }
+    });
+
+  });
+};
+
+EditUserDialog.prototype.initPrivilegesTab = function () {
+  var self = this;
+
+  var usersTable = $("[name=privilegesTable]", self.getElement())[0];
+
+  return ServerConnector.getConfiguration().then(function (configuration) {
+    var columns = [{
+      title: "Name"
+    }, {
+      title: "Value"
+    }];
+    var dataTable = $(usersTable).DataTable({
+      columns: columns
+    });
+    var data = [];
+
+    for (var i = 0; i < configuration.getPrivilegeTypes().length; i++) {
+      var privilege = configuration.getPrivilegeTypes()[i];
+      if (privilege.getObjectType() === null) {
+        if (privilege.getValueType() === "boolean") {
+          var checked = "";
+          if (self.getUser().hasPrivilege(privilege)) {
+            checked = "checked"
+          }
+          data.push([
+            "<span>" + privilege.getCommonName() + "</span>",
+            "<input type='checkbox' name='privilege-checkbox' data='" + privilege.getName() + "' " + checked + " />"
+          ]);
+        } else if (privilege.getValueType() === "int") {
+          data.push([
+            "<span>" + privilege.getCommonName() + "</span>",
+            "<input name='privilege-int' data='" + privilege.getName() + "' value='" + self.getUser().getPrivilegeValue(privilege) + "' />"
+          ]);
+
+        }
+      }
+    }
+    dataTable.clear().rows.add(data).draw();
+    $(usersTable).on("click", "[name='privilege-checkbox']", function () {
+      var privilegeType = $(this).attr("data");
+      for (var i = 0; i < configuration.getPrivilegeTypes().length; i++) {
+        var privilege = configuration.getPrivilegeTypes()[i];
+        if (privilege.getName() === privilegeType) {
+          self.getUser().setPrivilege({type: privilege, value: $(this).is(":checked")});
+        }
+      }
+    });
+    $(usersTable).on("change", "[name='privilege-int']", function () {
+      var privilegeType = $(this).attr("data");
+      var value = $(this).val();
+      value = parseInt(value);
+      if (Functions.isInt(value)) {
+        for (var i = 0; i < configuration.getPrivilegeTypes().length; i++) {
+          var privilege = configuration.getPrivilegeTypes()[i];
+          if (privilege.getName() === privilegeType) {
+            self.getUser().setPrivilege({type: privilege, value: value});
+          }
+        }
+      }
+    });
   });
 };
 
@@ -323,12 +455,18 @@ EditUserDialog.prototype.setProjects = function (projects) {
 };
 
 EditUserDialog.prototype.projectToTableRow = function (project, columns) {
+  var user = this.getUser();
   var row = [];
 
-  row[0] = project.getProjectId();
+  row[0] = "<span data='" + project.getId() + "'>" + project.getProjectId() + "</span>";
 
   for (var i = 1; i < columns.length; i++) {
-    row.push("");
+    var privilege = columns[i].privilegeType;
+    var checked = "";
+    if (user.hasPrivilege(privilege, project.getId())) {
+      checked = "checked";
+    }
+    row.push("<input type='checkbox' name='project-privilege-checkbox' data='" + privilege.getName() + "-" + project.getId() + "' " + checked + " />");
   }
 
   return row;
@@ -342,6 +480,11 @@ EditUserDialog.prototype.destroy = function () {
   if ($.fn.DataTable.isDataTable(usersTable)) {
     $(usersTable).DataTable().destroy();
   }
+  var privilegesTable = $("[name=privilegesTable]", self.getElement())[0];
+  if ($.fn.DataTable.isDataTable(privilegesTable)) {
+    $(privilegesTable).DataTable().destroy();
+  }
+
 
   if ($(div).hasClass("ui-dialog-content")) {
     $(div).dialog("destroy");
diff --git a/frontend-js/src/main/js/map/data/User.js b/frontend-js/src/main/js/map/data/User.js
index 09fc261d6e..b60a37cb38 100644
--- a/frontend-js/src/main/js/map/data/User.js
+++ b/frontend-js/src/main/js/map/data/User.js
@@ -104,6 +104,9 @@ User.prototype.getPassword = function () {
 
 User.prototype.setPrivileges = function (privileges) {
   this._privileges = privileges;
+  if (this._privileges === undefined) {
+    this._privileges = [];
+  }
 };
 
 User.prototype.getPrivileges = function () {
@@ -122,17 +125,47 @@ User.prototype.getPreferences = function () {
 };
 
 User.prototype.hasPrivilege = function (type, objectId) {
+  return this.getPrivilegeValue(type, objectId) > 0;
+};
+
+User.prototype.setPrivilege = function (params) {
+  var objectId = params.objectId;
+  var type = params.type;
+  var value = params.value;
+  if (value === undefined) {
+    value = 1;
+  } else if (value === true) {
+    value = 1;
+  } else if (value === false) {
+    value = 0;
+  }
   for (var i = 0; i < this._privileges.length; i++) {
     var privilege = this._privileges[i];
     if (privilege.type === type.getName()) {
       if (objectId === privilege.objectId) {
-        return privilege.value > 0;
+        privilege.value = value;
+        return;
       }
     }
   }
-  return false;
+  this._privileges.push({
+    type: type.getName(),
+    value: value,
+    objectId: objectId
+  });
 };
 
+User.prototype.getPrivilegeValue = function (type, objectId) {
+  for (var i = 0; i < this._privileges.length; i++) {
+    var privilege = this._privileges[i];
+    if (privilege.type === type.getName()) {
+      if (objectId === privilege.objectId) {
+        return privilege.value;
+      }
+    }
+  }
+  return 0;
+}
 User.prototype.privilegesToExport = function (configuration) {
   var self = this;
   var result = {};
diff --git a/frontend-js/src/test/js/gui/admin/EditUserDialog-test.js b/frontend-js/src/test/js/gui/admin/EditUserDialog-test.js
index afbb5f8dd6..9c50e955d6 100644
--- a/frontend-js/src/test/js/gui/admin/EditUserDialog-test.js
+++ b/frontend-js/src/test/js/gui/admin/EditUserDialog-test.js
@@ -12,8 +12,9 @@ var ValidationError = require('../../../../main/js/ValidationError');
 // noinspection JSUnusedLocalSymbols
 var logger = require('../../logger');
 
-// noinspection JSUnusedLocalSymbols
-var assert = require('assert');
+var chai = require('chai');
+var assert = chai.assert;
+var expect = chai.expect;
 
 describe('EditUserDialog', function () {
 
@@ -113,4 +114,61 @@ describe('EditUserDialog', function () {
     });
 
   });
+  describe('click privilege checkbox', function () {
+    it('existing user', function () {
+      var dialog;
+      var project;
+      var user;
+      var serializedPrivileges;
+      return ServerConnector.getUser("anonymous").then(function (result) {
+        user = result;
+        serializedPrivileges = user.privilegesToExport(helper.getConfiguration());
+        return ServerConnector.getProject();
+      }).then(function (result) {
+        project = result;
+        dialog = new EditUserDialog({
+          element: testDiv,
+          project: project,
+          user: user,
+          customMap: null
+        });
+        return dialog.init();
+      }).then(function () {
+        return $("[name=privilege-checkbox]", dialog.getElement()).click();
+      }).then(function () {
+        expect(serializedPrivileges).not.to.deep.equal(user.privilegesToExport(helper.getConfiguration()));
+        dialog.destroy();
+      });
+    });
+
+  });
+  describe('change privilege int value', function () {
+    it('existing user', function () {
+      var dialog;
+      var project;
+      var user;
+      var serializedPrivileges;
+      return ServerConnector.getUser("anonymous").then(function (result) {
+        user = result;
+        serializedPrivileges = user.privilegesToExport(helper.getConfiguration());
+        return ServerConnector.getProject();
+      }).then(function (result) {
+        project = result;
+        dialog = new EditUserDialog({
+          element: testDiv,
+          project: project,
+          user: user,
+          customMap: null
+        });
+        return dialog.init();
+      }).then(function () {
+        $("[name=privilege-int]", dialog.getElement()).val("101010");
+        $("[name=privilege-int]", dialog.getElement()).trigger("change");
+      }).then(function () {
+        expect(serializedPrivileges).not.to.deep.equal(user.privilegesToExport(helper.getConfiguration()));
+        dialog.destroy();
+      });
+    });
+
+  });
 });
diff --git a/frontend-js/src/test/js/map/data/User-test.js b/frontend-js/src/test/js/map/data/User-test.js
new file mode 100644
index 0000000000..a8ec996794
--- /dev/null
+++ b/frontend-js/src/test/js/map/data/User-test.js
@@ -0,0 +1,58 @@
+"use strict";
+
+require("../../mocha-config");
+
+var User = require('../../../../main/js/map/data/User');
+
+var logger = require('../../logger');
+
+var chai = require('chai');
+var assert = chai.assert;
+
+describe('Project', function () {
+  describe("constructor", function () {
+    it("empty data", function () {
+      var user = new User({});
+      assert.ok(user);
+
+      assert.equal(logger.getWarnings().length, 0);
+    });
+  });
+
+  describe("setPrivilege", function () {
+    it("non existing data", function () {
+      var user = new User({});
+      assert.ok(user);
+
+      return ServerConnector.getConfiguration().then(function (configuration) {
+        var privilegeType = configuration.getPrivilegeTypes()[0];
+        user.setPrivilege({type: privilegeType, value: true});
+        assert.ok(user.hasPrivilege(privilegeType));
+      });
+    });
+
+    it("existing data", function () {
+      var user = new User({});
+      assert.ok(user);
+
+      return ServerConnector.getConfiguration().then(function (configuration) {
+        var privilegeType = configuration.getPrivilegeTypes()[0];
+        user.setPrivilege({type: privilegeType, value: false});
+        user.setPrivilege({type: privilegeType, value: true});
+        assert.ok(user.hasPrivilege(privilegeType));
+      });
+    });
+
+    it("undefined value", function () {
+      var user = new User({});
+      assert.ok(user);
+
+      return ServerConnector.getConfiguration().then(function (configuration) {
+        var privilegeType = configuration.getPrivilegeTypes()[0];
+        user.setPrivilege({type: privilegeType, value: false});
+        user.setPrivilege({type: privilegeType});
+        assert.ok(user.hasPrivilege(privilegeType));
+      });
+    });
+  });
+});
-- 
GitLab