>From e90bcdbe1b9e05f6224d88cdc005480003c20308 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Thu, 20 Oct 2016 00:54:47 +0200
Subject: [PATCH] Fixed TPS UI system menu.

The TPS UI has been modified to adjust the system menu based
on the list of accessible components obtained during login.

The TPSApplication has been modified to use TPSAccountService
which returns the list of accessible components based on the
following properties in the CS.cfg:
* admin: target.configure.list
* agent: target.agent_approve.list

The AccountInfo has been changed to extend the ResourceMessage
such that it can be used to pass the list of accessible
components as an attribute.

https://fedorahosted.org/pki/ticket/2523
---
 .../com/netscape/certsrv/account/AccountInfo.java  |  8 ++-
 .../com/netscape/certsrv/base/ResourceMessage.java | 11 ++-
 .../org/dogtagpki/server/rest/AccountService.java  | 46 +++++--------
 base/tps/shared/webapps/tps/ui/index.html          | 56 +++++++++++++--
 .../dogtagpki/server/tps/TPSAccountService.java    | 80 ++++++++++++++++++++++
 .../dogtagpki/server/tps/rest/TPSApplication.java  |  4 +-
 6 files changed, 163 insertions(+), 42 deletions(-)
 create mode 100644 base/tps/src/org/dogtagpki/server/tps/TPSAccountService.java

diff --git a/base/common/src/com/netscape/certsrv/account/AccountInfo.java b/base/common/src/com/netscape/certsrv/account/AccountInfo.java
index 7943d229a23198771d06d288cf31c78604995f77..3310bf0d07d69f14dd1fb1b1d2bb8abee4a8ec36 100644
--- a/base/common/src/com/netscape/certsrv/account/AccountInfo.java
+++ b/base/common/src/com/netscape/certsrv/account/AccountInfo.java
@@ -33,11 +33,13 @@ import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.adapters.XmlAdapter;
 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 
+import com.netscape.certsrv.base.ResourceMessage;
+
 /**
  * @author Endi S. Dewata
  */
 @XmlRootElement(name="Account")
-public class AccountInfo {
+public class AccountInfo extends ResourceMessage {
 
     public static Marshaller marshaller;
     public static Unmarshaller unmarshaller;
@@ -98,7 +100,7 @@ public class AccountInfo {
     @Override
     public int hashCode() {
         final int prime = 31;
-        int result = 1;
+        int result = super.hashCode();
         result = prime * result + ((email == null) ? 0 : email.hashCode());
         result = prime * result + ((fullName == null) ? 0 : fullName.hashCode());
         result = prime * result + ((id == null) ? 0 : id.hashCode());
@@ -110,7 +112,7 @@ public class AccountInfo {
     public boolean equals(Object obj) {
         if (this == obj)
             return true;
-        if (obj == null)
+        if (!super.equals(obj))
             return false;
         if (getClass() != obj.getClass())
             return false;
diff --git a/base/common/src/com/netscape/certsrv/base/ResourceMessage.java b/base/common/src/com/netscape/certsrv/base/ResourceMessage.java
index 1214b45fbf59341f4c515116071361835c59a119..85d0d07a434e6c62f8a45a4a1b7895c70d524c8c 100644
--- a/base/common/src/com/netscape/certsrv/base/ResourceMessage.java
+++ b/base/common/src/com/netscape/certsrv/base/ResourceMessage.java
@@ -26,6 +26,7 @@ import javax.xml.bind.annotation.XmlValue;
 import javax.xml.bind.annotation.adapters.XmlAdapter;
 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 
+import com.netscape.certsrv.account.AccountInfo;
 import com.netscape.certsrv.key.AsymKeyGenerationRequest;
 import com.netscape.certsrv.key.KeyArchivalRequest;
 import com.netscape.certsrv.key.KeyRecoveryRequest;
@@ -35,8 +36,14 @@ import com.netscape.certsrv.key.SymKeyGenerationRequest;
  * @author Ade Lee
  */
 @XmlRootElement(name = "ResourceMessage")
-@XmlSeeAlso({ KeyArchivalRequest.class, KeyRecoveryRequest.class, SymKeyGenerationRequest.class,
-        PKIException.Data.class, AsymKeyGenerationRequest.class })
+@XmlSeeAlso({
+    AccountInfo.class,
+    KeyArchivalRequest.class,
+    KeyRecoveryRequest.class,
+    SymKeyGenerationRequest.class,
+    PKIException.Data.class,
+    AsymKeyGenerationRequest.class
+})
 @XmlAccessorType(XmlAccessType.NONE)
 public class ResourceMessage {
 
diff --git a/base/server/cms/src/org/dogtagpki/server/rest/AccountService.java b/base/server/cms/src/org/dogtagpki/server/rest/AccountService.java
index 827e99e076585d0732bfde8ae795d6ae63648d5f..673db45b6513f081efa4c8b1c65bb81fd5e378bc 100644
--- a/base/server/cms/src/org/dogtagpki/server/rest/AccountService.java
+++ b/base/server/cms/src/org/dogtagpki/server/rest/AccountService.java
@@ -21,13 +21,8 @@ package org.dogtagpki.server.rest;
 import java.security.Principal;
 import java.util.Arrays;
 
-import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpSession;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.Request;
 import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
 
 import org.apache.catalina.realm.GenericPrincipal;
 import org.apache.commons.lang.StringUtils;
@@ -43,47 +38,40 @@ import com.netscape.cms.servlet.base.PKIService;
  */
 public class AccountService extends PKIService implements AccountResource {
 
-    @Context
-    private UriInfo uriInfo;
-
-    @Context
-    private HttpHeaders headers;
-
-    @Context
-    private Request request;
-
-    @Context
-    private HttpServletRequest servletRequest;
-
-    @Override
-    public Response login() {
-        HttpSession session = servletRequest.getSession();
-        System.out.println("Creating session "+session.getId());
-
+    protected AccountInfo createAccountInfo() {
         Principal principal = servletRequest.getUserPrincipal();
-        System.out.println("Principal: "+principal);
+        System.out.println("Principal: " + principal);
 
-        AccountInfo response = new AccountInfo();
+        AccountInfo accountInfo = new AccountInfo();
         String name = principal.getName();
-        response.setID(name);
+        accountInfo.setID(name);
 
         if (principal instanceof PKIPrincipal) {
             PKIPrincipal pkiPrincipal = (PKIPrincipal)principal;
             IUser user = pkiPrincipal.getUser();
 
             String fullName = user.getFullName();
-            if (!StringUtils.isEmpty(fullName)) response.setFullName(fullName);
+            if (!StringUtils.isEmpty(fullName)) accountInfo.setFullName(fullName);
 
             String email = user.getEmail();
-            if (!StringUtils.isEmpty(email)) response.setEmail(email);
+            if (!StringUtils.isEmpty(email)) accountInfo.setEmail(email);
         }
 
         if (principal instanceof GenericPrincipal) {
             String[] roles = ((GenericPrincipal) principal).getRoles();
-            response.setRoles(Arrays.asList(roles));
+            accountInfo.setRoles(Arrays.asList(roles));
         }
 
-        return createOKResponse(response);
+        return accountInfo;
+    }
+
+    @Override
+    public Response login() {
+        HttpSession session = servletRequest.getSession();
+        System.out.println("Creating session " + session.getId());
+
+        AccountInfo accountInfo = createAccountInfo();
+        return createOKResponse(accountInfo);
     }
 
     @Override
diff --git a/base/tps/shared/webapps/tps/ui/index.html b/base/tps/shared/webapps/tps/ui/index.html
index 63baf3e27bbc5e4267d91fc1c3f5586991b3abb8..93d3af0b0837b95a6bf4e26c3c5bc2a2ed3b9806 100644
--- a/base/tps/shared/webapps/tps/ui/index.html
+++ b/base/tps/shared/webapps/tps/ui/index.html
@@ -46,6 +46,40 @@
     <script>
 $(function() {
 
+    function getAttribute(attributes, name) {
+        for (var i=0; i<attributes.length; i++) {
+            var attribute = attributes[i];
+            if (name != attribute.name) continue;
+            return attribute.value;
+        }
+        return null;
+    }
+
+    function getElementName(component) {
+
+        if (component == "Generals") {
+            return "config";
+
+        } else if (component == "Authentication_Sources") {
+            return "authenticators";
+
+        } else if (component == "Subsystem_Connections") {
+            return "connectors";
+
+        } else if (component == "Profiles") {
+            return "profiles";
+
+        } else if (component == "Profile_Mappings") {
+            return "profile-mappings";
+
+        } else if (component == "Audit_Logging") {
+            return "audit";
+
+        } else {
+            return null;
+        }
+    }
+
     var account = new Account();
     account.login({
         success: function(data, textStatus, jqXHR) {
@@ -64,14 +98,24 @@ $(function() {
                 accounts_menu.hide();
             }
 
-            if (_.contains(roles, "Administrators")) {
-                system_menu.show();
-                $("li", system_menu).show();
+            var attributes = tps.user.Attributes.Attribute;
+            var values = getAttribute(attributes, "components");
+
+            var components;
+            if (values) {
+                components = values.split(",");
+            } else {
+                components = [];
+            }
 
-            } else if (_.contains(roles, "TPS Agents")) {
+            if (components.length > 0) {
+                // display menu items for accessible components
                 system_menu.show();
-                $("li", system_menu).hide();
-                $("[name=profiles]", system_menu).show();
+                for (var i=0; i<components.length; i++) {
+                    var name = getElementName(components[i]);
+                    if (!name) continue;
+                    $("[name=" + name + "]", system_menu).show();
+                }
 
             } else {
                 system_menu.hide();
diff --git a/base/tps/src/org/dogtagpki/server/tps/TPSAccountService.java b/base/tps/src/org/dogtagpki/server/tps/TPSAccountService.java
new file mode 100644
index 0000000000000000000000000000000000000000..73f3c5e3f8ccd7d66d93ebc7b3e95ecf136cbeec
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/TPSAccountService.java
@@ -0,0 +1,80 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2016 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+
+import org.apache.commons.lang.StringUtils;
+import org.dogtagpki.server.rest.AccountService;
+
+import com.netscape.certsrv.account.AccountInfo;
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.PKIException;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class TPSAccountService extends AccountService {
+
+    IConfigStore configStore = CMS.getConfigStore();
+
+    @Override
+    public AccountInfo createAccountInfo() {
+
+        AccountInfo accountInfo = super.createAccountInfo();
+
+        try {
+            // determine accessible components based on roles
+            Collection<String> components = new HashSet<String>();
+
+            Collection<String> roles = accountInfo.getRoles();
+
+            if (roles.contains("Administrators")) {
+                String values = configStore.getString("target.configure.list", "");
+                if (!StringUtils.isEmpty(values)) {
+                    components.addAll(Arrays.asList(values.split(",")));
+                }
+
+                // admin always has access to general configuration and audit logging
+                components.add("Generals");
+                components.add("Audit_Logging");
+
+            }
+
+            if (roles.contains("TPS Agents")) {
+                String values = configStore.getString("target.agent_approve.list", "");
+                if (!StringUtils.isEmpty(values)) {
+                    components.addAll(Arrays.asList(values.split(",")));
+                }
+            }
+
+            accountInfo.setAttribute("components", StringUtils.join(components, ","));
+
+        } catch (EBaseException e) {
+            CMS.debug(e);
+            throw new PKIException(e);
+        }
+
+        return accountInfo;
+    }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/rest/TPSApplication.java b/base/tps/src/org/dogtagpki/server/tps/rest/TPSApplication.java
index b63af83442d7c51d92a282f8e8cb182208cb1e9b..09f5025f77afb902b6d20b067440b5c48111c049 100644
--- a/base/tps/src/org/dogtagpki/server/tps/rest/TPSApplication.java
+++ b/base/tps/src/org/dogtagpki/server/tps/rest/TPSApplication.java
@@ -23,7 +23,6 @@ import java.util.Set;
 import javax.ws.rs.core.Application;
 
 import org.dogtagpki.server.rest.ACLInterceptor;
-import org.dogtagpki.server.rest.AccountService;
 import org.dogtagpki.server.rest.AuditService;
 import org.dogtagpki.server.rest.AuthMethodInterceptor;
 import org.dogtagpki.server.rest.GroupService;
@@ -33,6 +32,7 @@ import org.dogtagpki.server.rest.SelfTestService;
 import org.dogtagpki.server.rest.SessionContextInterceptor;
 import org.dogtagpki.server.rest.SystemCertService;
 import org.dogtagpki.server.rest.UserService;
+import org.dogtagpki.server.tps.TPSAccountService;
 import org.dogtagpki.server.tps.config.ConfigService;
 
 /**
@@ -46,7 +46,7 @@ public class TPSApplication extends Application {
     public TPSApplication() {
 
         // account
-        classes.add(AccountService.class);
+        classes.add(TPSAccountService.class);
 
         // audit
         classes.add(AuditService.class);
-- 
2.5.5

