From 9f5fae5000035039b35306f6817725b0a0282dac Mon Sep 17 00:00:00 2001
From: Sonia Zorba <sonia.zorba@inaf.it>
Date: Sun, 23 Aug 2020 19:18:17 +0200
Subject: [PATCH] Changes in set permission and CLI

---
 README.md                                     | 11 -----
 .../main/java/it/inaf/ia2/gms/cli/CLI.java    |  8 ++++
 .../it/inaf/ia2/gms/client/GmsClient.java     |  5 +++
 .../gms/client/call/SetPermissionCall.java    | 39 +++++++++++++++++
 .../it/inaf/ia2/gms/authn/SessionData.java    |  2 +-
 .../controller/JWTWebServiceController.java   | 24 ++++-------
 .../ia2/gms/manager/PermissionsManager.java   |  5 +++
 .../ia2/gms/service/PermissionsService.java   | 11 +++++
 .../inaf/ia2/gms/authn/SessionDataTest.java   | 43 +++++++++++++++++++
 9 files changed, 121 insertions(+), 27 deletions(-)
 create mode 100644 gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/SetPermissionCall.java
 create mode 100644 gms/src/test/java/it/inaf/ia2/gms/authn/SessionDataTest.java

diff --git a/README.md b/README.md
index ca0046b..ec8ca07 100644
--- a/README.md
+++ b/README.md
@@ -28,17 +28,6 @@ The first super admin user must be added manually, then he/she will be able to a
 
 The value `user_id` is the RAP user id.
 
-## Command line clients
-
-To add a command line client first generate the sha256 of its password:
-
-    echo -n password | sha256sum
-
-Then insert the client line into the database:
-
-    INSERT INTO gms_client (client_id, client_secret, allowed_actions, ip_filter)
-    VALUES ('test', '9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08', '{"*"}', NULL);
-
 ## Developer notes
 
 Backend and frontend are 2 separate applications:
diff --git a/gms-client/gms-cli/src/main/java/it/inaf/ia2/gms/cli/CLI.java b/gms-client/gms-cli/src/main/java/it/inaf/ia2/gms/cli/CLI.java
index a237abc..4d4ff78 100644
--- a/gms-client/gms-cli/src/main/java/it/inaf/ia2/gms/cli/CLI.java
+++ b/gms-client/gms-cli/src/main/java/it/inaf/ia2/gms/cli/CLI.java
@@ -178,6 +178,13 @@ public class CLI {
                 client.removeMember(args[argIndex + 1], args[argIndex + 2]);
                 System.out.println("Member removed");
                 break;
+            case "set-permission":
+                if (argIndex + 3 >= args.length) {
+                    displayUsage();
+                }
+                client.setPermission(args[argIndex + 1], args[argIndex + 2], Permission.valueOf(args[argIndex + 3]));
+                System.out.println("Permission changed");
+                break;
             case "add-permission":
                 if (argIndex + 3 >= args.length) {
                     displayUsage();
@@ -220,6 +227,7 @@ public class CLI {
                 + "    delete-group <name1.name2.name3>\n"
                 + "    add-member <name1.name2.name3> <user_id>\n"
                 + "    remove-member <name1.name2.name3> <user_id>\n"
+                + "    set-permission <name1.name2.name3> <user_id> <permission>\n"
                 + "    add-permission <name1.name2.name3> <user_id> <permission>\n"
                 + "    delete-permission <name1.name2.name3> <user_id>\n"
                 + "    get-member-email-addresses <name1.name2.name3> [<permission>]");
diff --git a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/GmsClient.java b/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/GmsClient.java
index 86a9100..8dcf041 100644
--- a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/GmsClient.java
+++ b/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/GmsClient.java
@@ -13,6 +13,7 @@ import it.inaf.ia2.gms.client.call.GetUserPermissionsCall;
 import it.inaf.ia2.gms.client.call.ListGroupsCall;
 import it.inaf.ia2.gms.client.call.RemoveMemberCall;
 import it.inaf.ia2.gms.client.call.RemovePermissionCall;
+import it.inaf.ia2.gms.client.call.SetPermissionCall;
 import it.inaf.ia2.gms.client.model.GroupPermission;
 import it.inaf.ia2.gms.client.model.Permission;
 import it.inaf.ia2.gms.client.model.UserPermission;
@@ -64,6 +65,10 @@ public class GmsClient {
         new AddPermissionCall(httpClientWrapper).addPermission(completeGroupName, userId, permission);
     }
 
+    public void setPermission(String completeGroupName, String userId, Permission permission) {
+        new SetPermissionCall(httpClientWrapper).setPermission(completeGroupName, userId, permission);
+    }
+
     public void removePermission(String completeGroupName, String userId) {
         new RemovePermissionCall(httpClientWrapper).removePermission(completeGroupName, userId);
     }
diff --git a/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/SetPermissionCall.java b/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/SetPermissionCall.java
new file mode 100644
index 0000000..c7eee10
--- /dev/null
+++ b/gms-client/gms-client-lib/src/main/java/it/inaf/ia2/gms/client/call/SetPermissionCall.java
@@ -0,0 +1,39 @@
+package it.inaf.ia2.gms.client.call;
+
+import static it.inaf.ia2.gms.client.call.BaseGmsCall.logServerErrorInputStream;
+import it.inaf.ia2.gms.client.model.Permission;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+
+public class SetPermissionCall extends BaseGmsCall {
+
+    public SetPermissionCall(HttpClientWrapper clientWrapper) {
+        super(clientWrapper);
+    }
+
+    public boolean setPermission(String completeGroupName, String userId, Permission permission) {
+
+        String endpoint = "permission";
+        if (completeGroupName != null && !completeGroupName.isBlank()) {
+            endpoint += "/" + completeGroupName;
+        }
+
+        HttpRequest.BodyPublisher requestBody = HttpRequest.BodyPublishers.ofString(
+                "user_id=" + userId + "&permission=" + permission);
+
+        HttpRequest groupsRequest = newHttpRequest(endpoint)
+                .header("Accept", "text/plain")
+                .header("Content-Type", "application/x-www-form-urlencoded")
+                .PUT(requestBody)
+                .build();
+
+        return getClient().sendAsync(groupsRequest, HttpResponse.BodyHandlers.ofInputStream())
+                .thenApply(response -> {
+                    if (response.statusCode() == 200) {
+                        return true;
+                    }
+                    logServerErrorInputStream(groupsRequest, response);
+                    throw new IllegalStateException("Unable to set permission");
+                }).join();
+    }
+}
diff --git a/gms/src/main/java/it/inaf/ia2/gms/authn/SessionData.java b/gms/src/main/java/it/inaf/ia2/gms/authn/SessionData.java
index 289bb55..2084e79 100644
--- a/gms/src/main/java/it/inaf/ia2/gms/authn/SessionData.java
+++ b/gms/src/main/java/it/inaf/ia2/gms/authn/SessionData.java
@@ -59,6 +59,6 @@ public class SessionData {
     }
 
     public long getExpiresIn() {
-        return (System.currentTimeMillis() - expiration) / 1000;
+        return (expiration - System.currentTimeMillis()) / 1000;
     }
 }
diff --git a/gms/src/main/java/it/inaf/ia2/gms/controller/JWTWebServiceController.java b/gms/src/main/java/it/inaf/ia2/gms/controller/JWTWebServiceController.java
index 9677cdf..fc11b09 100644
--- a/gms/src/main/java/it/inaf/ia2/gms/controller/JWTWebServiceController.java
+++ b/gms/src/main/java/it/inaf/ia2/gms/controller/JWTWebServiceController.java
@@ -37,6 +37,7 @@ import org.springframework.web.bind.annotation.DeleteMapping;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
@@ -254,23 +255,16 @@ public class JWTWebServiceController {
         }
     }
 
-    @PostMapping(value = {"/permission/{group:.+}", "/permission/"}, produces = MediaType.TEXT_PLAIN_VALUE)
-    public void addPermission(@PathVariable("group") Optional<String> groupNames, HttpServletRequest request, HttpServletResponse response) throws IOException {
-
-        String targetUserId = request.getParameter("user_id");
-        if (targetUserId == null) {
-            response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Missing user_id parameter");
-            return;
-        }
-        String permissionParam = request.getParameter("permission");
-        if (permissionParam == null) {
-            response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Missing permission parameter");
-            return;
-        }
-
+    @PostMapping(value = {"/permission/{group:.+}", "/permission/"}, produces = MediaType.TEXT_PLAIN_VALUE, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
+    public void addPermission(@PathVariable("group") Optional<String> groupNames, @RequestParam("user_id") String targetUserId, @RequestParam("permission") Permission permission) throws IOException {
         GroupEntity groupEntity = getGroupFromNames(extractGroupNames(groupNames));
+        permissionsManager.addPermission(groupEntity, targetUserId, permission);
+    }
 
-        permissionsManager.addPermission(groupEntity, targetUserId, Permission.valueOf(permissionParam));
+    @PutMapping(value = {"/permission/{group:.+}", "/permission/"}, produces = MediaType.TEXT_PLAIN_VALUE, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
+    public void setPermission(@PathVariable("group") Optional<String> groupNames, @RequestParam("user_id") String targetUserId, @RequestParam("permission") Permission permission) throws IOException {
+        GroupEntity groupEntity = getGroupFromNames(extractGroupNames(groupNames));
+        permissionsManager.createOrUpdatePermission(groupEntity, targetUserId, permission);
     }
 
     @DeleteMapping(value = {"/permission/{group:.+}", "/permission/"}, produces = MediaType.TEXT_PLAIN_VALUE)
diff --git a/gms/src/main/java/it/inaf/ia2/gms/manager/PermissionsManager.java b/gms/src/main/java/it/inaf/ia2/gms/manager/PermissionsManager.java
index 1a22842..e6a6551 100644
--- a/gms/src/main/java/it/inaf/ia2/gms/manager/PermissionsManager.java
+++ b/gms/src/main/java/it/inaf/ia2/gms/manager/PermissionsManager.java
@@ -87,6 +87,11 @@ public class PermissionsManager extends UserAwareComponent {
         throw unauthorizedExceptionSupplier(group).get();
     }
 
+    public PermissionEntity createOrUpdatePermission(GroupEntity group, String userId, Permission permission) {
+        verifyUserCanManagePermissions(group);
+        return permissionsService.createOrUpdatePermission(group, userId, permission);
+    }
+
     public PermissionEntity updatePermission(GroupEntity group, String userId, Permission permission) {
         verifyUserCanManagePermissions(group);
         return permissionsService.updatePermission(group, userId, permission);
diff --git a/gms/src/main/java/it/inaf/ia2/gms/service/PermissionsService.java b/gms/src/main/java/it/inaf/ia2/gms/service/PermissionsService.java
index b0525e4..e00f47b 100644
--- a/gms/src/main/java/it/inaf/ia2/gms/service/PermissionsService.java
+++ b/gms/src/main/java/it/inaf/ia2/gms/service/PermissionsService.java
@@ -62,6 +62,17 @@ public class PermissionsService {
         return permissionEntity;
     }
 
+    public PermissionEntity createOrUpdatePermission(GroupEntity group, String userId, Permission permission) {
+
+        PermissionEntity permissionEntity = new PermissionEntity();
+        permissionEntity.setGroupId(group.getId());
+        permissionEntity.setUserId(userId);
+        permissionEntity.setPermission(permission);
+        permissionEntity.setGroupPath(group.getPath());
+
+        return permissionsDAO.createOrUpdatePermission(permissionEntity);
+    }
+
     public PermissionEntity updatePermission(GroupEntity group, String userId, Permission permission) {
 
         PermissionEntity permissionEntity = permissionsDAO.findPermissionEntity(group.getId(), userId)
diff --git a/gms/src/test/java/it/inaf/ia2/gms/authn/SessionDataTest.java b/gms/src/test/java/it/inaf/ia2/gms/authn/SessionDataTest.java
new file mode 100644
index 0000000..d525b88
--- /dev/null
+++ b/gms/src/test/java/it/inaf/ia2/gms/authn/SessionDataTest.java
@@ -0,0 +1,43 @@
+package it.inaf.ia2.gms.authn;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import javax.servlet.http.HttpServletRequest;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.springframework.security.oauth2.common.OAuth2AccessToken;
+import org.springframework.security.oauth2.provider.OAuth2Authentication;
+
+@RunWith(MockitoJUnitRunner.class)
+public class SessionDataTest {
+
+    @Mock
+    private HttpServletRequest request;
+
+    @InjectMocks
+    private SessionData sessionData;
+
+    @Test
+    public void testExpired() {
+
+        OAuth2AccessToken accessToken = mock(OAuth2AccessToken.class);
+        when(accessToken.getExpiresIn()).thenReturn(3600);
+
+        CustomAuthenticationData data = new CustomAuthenticationData("user",
+                new HashMap<>(), new ArrayList<>(), accessToken, "refresh_token");
+
+        OAuth2Authentication auth = mock(OAuth2Authentication.class);
+        when(auth.getUserAuthentication()).thenReturn(data);
+        when(request.getUserPrincipal()).thenReturn(auth);
+
+        sessionData.init();
+
+        assertTrue(sessionData.getExpiresIn() > 0);
+    }
+}
-- 
GitLab