From 86e1811bb22116e6c47cc8bb8b3e4f0d1804ffc4 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Thu, 27 Mar 2014 18:24:39 -0400
Subject: [PATCH] Refactored TPS profiles.

The TPS profile has been modified to use PATCH for update operation as
required by Backbone. The ProfileData class has been modified to accept
null properties to indicate that the properties are not being updated.
The ProfileModel class has been modified to use JSON data type for
enable and disable operations.

Ticket #654
---
 .../netscape/certsrv/tps/profile/ProfileData.java  | 29 +++---------
 .../certsrv/tps/profile/ProfileResource.java       |  4 +-
 .../netscape/cmstools/tps/profile/ProfileCLI.java  |  8 ++--
 .../src/com/netscape/cmscore/dbs/CSCfgRecord.java  |  1 +
 base/tps-tomcat/shared/webapps/tps/js/profile.js   | 53 +++++++++++-----------
 .../dogtagpki/server/tps/rest/ProfileService.java  | 32 +++++++++----
 6 files changed, 63 insertions(+), 64 deletions(-)

diff --git a/base/common/src/com/netscape/certsrv/tps/profile/ProfileData.java b/base/common/src/com/netscape/certsrv/tps/profile/ProfileData.java
index d733777aa3af6e854b8c6ea9a4beb0c59507b6d4..81e0dea3ac4860a74403c501e3c1dd95e4c3a842 100644
--- a/base/common/src/com/netscape/certsrv/tps/profile/ProfileData.java
+++ b/base/common/src/com/netscape/certsrv/tps/profile/ProfileData.java
@@ -21,7 +21,6 @@ package com.netscape.certsrv.tps.profile;
 import java.io.StringReader;
 import java.io.StringWriter;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -62,7 +61,7 @@ public class ProfileData {
 
     String id;
     String status;
-    Map<String, String> properties = new LinkedHashMap<String, String>();
+    Map<String, String> properties;
 
     Link link;
 
@@ -91,24 +90,7 @@ public class ProfileData {
     }
 
     public void setProperties(Map<String, String> properties) {
-        this.properties.clear();
-        this.properties.putAll(properties);
-    }
-
-    public Collection<String> getPropertyNames() {
-        return properties.keySet();
-    }
-
-    public String getProperty(String name) {
-        return properties.get(name);
-    }
-
-    public void setProperty(String name, String value) {
-        properties.put(name, value);
-    }
-
-    public String removeProperty(String name) {
-        return properties.remove(name);
+        this.properties = properties;
     }
 
     public static class MapAdapter extends XmlAdapter<PropertyList, Map<String, String>> {
@@ -223,8 +205,11 @@ public class ProfileData {
         ProfileData before = new ProfileData();
         before.setID("profile1");
         before.setStatus("ENABLED");
-        before.setProperty("param1", "value1");
-        before.setProperty("param2", "value2");
+
+        Map<String, String> properties = new LinkedHashMap<String, String>();
+        properties.put("param1", "value1");
+        properties.put("param2", "value2");
+        before.setProperties(properties);
 
         String string = before.toString();
         System.out.println(string);
diff --git a/base/common/src/com/netscape/certsrv/tps/profile/ProfileResource.java b/base/common/src/com/netscape/certsrv/tps/profile/ProfileResource.java
index 50a205cd7eb9331627856d52241c2902713ce4b7..48d3a8c4d57217ed4e9a0663eb130e3b1dda4f66 100644
--- a/base/common/src/com/netscape/certsrv/tps/profile/ProfileResource.java
+++ b/base/common/src/com/netscape/certsrv/tps/profile/ProfileResource.java
@@ -20,7 +20,6 @@ package com.netscape.certsrv.tps.profile;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.QueryParam;
@@ -30,6 +29,7 @@ import org.jboss.resteasy.annotations.ClientResponseType;
 
 import com.netscape.certsrv.acls.ACLMapping;
 import com.netscape.certsrv.authentication.AuthMethodMapping;
+import com.netscape.certsrv.base.PATCH;
 
 
 /**
@@ -57,7 +57,7 @@ public interface ProfileResource {
     @ClientResponseType(entityType=ProfileData.class)
     public Response addProfile(ProfileData profileData);
 
-    @PUT
+    @PATCH
     @Path("{profileID}")
     @ACLMapping("profiles.modify")
     @ClientResponseType(entityType=ProfileData.class)
diff --git a/base/java-tools/src/com/netscape/cmstools/tps/profile/ProfileCLI.java b/base/java-tools/src/com/netscape/cmstools/tps/profile/ProfileCLI.java
index 8b02f2e577979a94b435c60b0577fc08b455a3f2..b27578ffcaaae1afc0c932f0242c10cf2245dab2 100644
--- a/base/java-tools/src/com/netscape/cmstools/tps/profile/ProfileCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/tps/profile/ProfileCLI.java
@@ -61,9 +61,11 @@ public class ProfileCLI extends CLI {
         if (showProperties) {
             System.out.println("  Properties:");
             Map<String, String> properties = profileData.getProperties();
-            for (String name : properties.keySet()) {
-                String value = properties.get(name);
-                System.out.println("    " + name + ": " + value);
+            if (properties != null) {
+                for (String name : properties.keySet()) {
+                    String value = properties.get(name);
+                    System.out.println("    " + name + ": " + value);
+                }
             }
         }
 
diff --git a/base/server/cmscore/src/com/netscape/cmscore/dbs/CSCfgRecord.java b/base/server/cmscore/src/com/netscape/cmscore/dbs/CSCfgRecord.java
index f8e07b43e650cf72204ed232ddd1e9e8a0ca1981..854244150f1bf24e70089b83ad54f20ad4b642eb 100644
--- a/base/server/cmscore/src/com/netscape/cmscore/dbs/CSCfgRecord.java
+++ b/base/server/cmscore/src/com/netscape/cmscore/dbs/CSCfgRecord.java
@@ -54,6 +54,7 @@ public class CSCfgRecord {
 
     public void setProperties(Map<String, String> properties) {
         this.properties.clear();
+        if (properties == null) return;
         this.properties.putAll(properties);
     }
 
diff --git a/base/tps-tomcat/shared/webapps/tps/js/profile.js b/base/tps-tomcat/shared/webapps/tps/js/profile.js
index 6b496e56009c0459607e7fbb8ed8e9bed847adf1..410328ca8155fe8d8da1365cee1e968b3e867b8b 100644
--- a/base/tps-tomcat/shared/webapps/tps/js/profile.js
+++ b/base/tps-tomcat/shared/webapps/tps/js/profile.js
@@ -24,46 +24,45 @@ var ProfileModel = Model.extend({
     parseResponse: function(response) {
         return {
             id: response.id,
+            profileID: response.id,
             status: response.Status,
             properties: response.Properties.Property
         };
     },
-    parseXML: function(data) {
-        var xml = $(data);
-        var entry = $("Profile", xml);
-        var status = $("Status", entry);
-        return {
-            id: entry.attr("id"),
-            status: status.text()
-        };
-    },
     createRequest: function(attributes) {
         return {
-            id: attributes.id,
-            Status: attributes.status
+            id: attributes.profileID,
+            Status: attributes.status,
+            Properties: {
+                Property: attributes.properties
+            }
         };
     },
     enable: function(options) {
         var self = this;
-        $.post(self.url() + "?action=enable")
-            .done(function(data, textStatus, jqXHR) {
-                self.set(self.parseXML(data));
-                options.success.call(self, data, textStatus, jqXHR);
-            })
-            .fail(function(jqXHR, textStatus, errorThrown) {
-                options.error.call(self, jqXHR, textStatus, errorThrown);
-            });
+        $.ajax({
+            type: "POST",
+            url: self.url() + "?action=enable",
+            dataType: "json"
+        }).done(function(data, textStatus, jqXHR) {
+            self.set(self.parseResponse(data));
+            if (options.success) options.success.call(self, data, textStatus, jqXHR);
+        }).fail(function(jqXHR, textStatus, errorThrown) {
+            if (options.error) options.error.call(self, jqXHR, textStatus, errorThrown);
+        });
     },
     disable: function(options) {
         var self = this;
-        $.post(self.url() + "?action=disable")
-            .done(function(data, textStatus, jqXHR) {
-                self.set(self.parseXML(data));
-                options.success.call(self, data, textStatus, jqXHR);
-            })
-            .fail(function(jqXHR, textStatus, errorThrown) {
-                options.error.call(self, jqXHR, textStatus, errorThrown);
-            });
+        $.ajax({
+            type: "POST",
+            url: self.url() + "?action=disable",
+            dataType: "json"
+        }).done(function(data, textStatus, jqXHR) {
+            self.set(self.parseResponse(data));
+            if (options.success) options.success.call(self, data, textStatus, jqXHR);
+        }).fail(function(jqXHR, textStatus, errorThrown) {
+            if (options.error) options.error.call(self, jqXHR, textStatus, errorThrown);
+        });
     }
 });
 
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/rest/ProfileService.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/rest/ProfileService.java
index 723075a407473e0a78dd2d8d5f94e12dad0b8a01..d21b8939ecf411cf38bdebbeaf65e2989e3b1777 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/rest/ProfileService.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/rest/ProfileService.java
@@ -23,6 +23,7 @@ import java.net.URI;
 import java.net.URLEncoder;
 import java.security.Principal;
 import java.util.Iterator;
+import java.util.Map;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.core.Context;
@@ -206,23 +207,34 @@ public class ProfileService extends PKIService implements ProfileResource {
 
             ProfileRecord record = database.getRecord(profileID);
 
-            String status = record.getStatus();
-            if (!"Disabled".equals(status)) {
+            // only disabled profile can be updated
+            if (!"Disabled".equals(record.getStatus())) {
                 throw new ForbiddenException("Unable to update profile " + profileID);
             }
 
-            status = profileData.getStatus();
-            if (!"Enabled".equals(status)) {
-                throw new ForbiddenException("Invalid profile status: " + status);
+            // update status if specified
+            String status = profileData.getStatus();
+            if (status != null && !"Disabled".equals(status)) {
+                if (!"Enabled".equals(status)) {
+                    throw new ForbiddenException("Invalid profile status: " + status);
+                }
+
+                // if user doesn't have rights, set to pending
+                Principal principal = servletRequest.getUserPrincipal();
+                if (database.requiresApproval() && !database.canApprove(principal)) {
+                    status = "Pending_Approval";
+                }
+
+                // enable profile
+                record.setStatus(status);
             }
 
-            Principal principal = servletRequest.getUserPrincipal();
-            if (database.requiresApproval() && !database.canApprove(principal)) {
-                status = "Pending_Approval";
+            // update properties if specified
+            Map<String, String> properties = profileData.getProperties();
+            if (properties != null) {
+                record.setProperties(properties);
             }
 
-            record.setStatus(status);
-            record.setProperties(profileData.getProperties());
             database.updateRecord(profileID, record);
 
             profileData = createProfileData(database.getRecord(profileID));
-- 
1.8.4.2

