From b70075a7bb6203642b4355bf9a76be9ec56508c1 Mon Sep 17 00:00:00 2001
From: Timm Fitschen <t.fitschen@indiscale.com>
Date: Thu, 9 Dec 2021 12:42:40 +0100
Subject: [PATCH] WIP: acm grpc

---
 .../accessControl/AuthenticationUtils.java    |  5 +++
 .../CaosDBRolePermissionResolver.java         |  1 +
 .../server/grpc/GeneralInfoServiceImpl.java   | 24 +++++++++++++
 .../java/org/caosdb/server/jobs/Schedule.java |  4 +--
 .../org/caosdb/server/jobs/ScheduledJob.java  | 13 +++++--
 .../server/permissions/CaosPermission.java    | 36 +++++++++++++------
 .../AbstractCaosDBServerResource.java         |  1 +
 .../transaction/RetrieveRoleTransaction.java  | 14 ++++----
 8 files changed, 77 insertions(+), 21 deletions(-)

diff --git a/src/main/java/org/caosdb/server/accessControl/AuthenticationUtils.java b/src/main/java/org/caosdb/server/accessControl/AuthenticationUtils.java
index e6907f40..dc40e72e 100644
--- a/src/main/java/org/caosdb/server/accessControl/AuthenticationUtils.java
+++ b/src/main/java/org/caosdb/server/accessControl/AuthenticationUtils.java
@@ -29,6 +29,7 @@ import static org.caosdb.server.utils.Utils.URLDecodeWithUTF8;
 import java.sql.Timestamp;
 import java.util.Collection;
 import java.util.LinkedList;
+import org.apache.shiro.authz.AuthorizationInfo;
 import org.apache.shiro.subject.Subject;
 import org.caosdb.server.CaosDBServer;
 import org.caosdb.server.ServerProperties;
@@ -199,4 +200,8 @@ public class AuthenticationUtils {
         .getRealm()
         .equals(OneTimeAuthenticationToken.REALM_NAME);
   }
+
+  public static AuthorizationInfo getAuthorizationInfo(Subject user) {
+    return new CaosDBAuthorizingRealm().doGetAuthorizationInfo(user.getPrincipals());
+  }
 }
diff --git a/src/main/java/org/caosdb/server/accessControl/CaosDBRolePermissionResolver.java b/src/main/java/org/caosdb/server/accessControl/CaosDBRolePermissionResolver.java
index 17637b01..5bc711e1 100644
--- a/src/main/java/org/caosdb/server/accessControl/CaosDBRolePermissionResolver.java
+++ b/src/main/java/org/caosdb/server/accessControl/CaosDBRolePermissionResolver.java
@@ -49,6 +49,7 @@ public class CaosDBRolePermissionResolver {
         throw new AuthenticationException(e);
       }
     }
+
     return new CaosPermission(rules);
   }
 }
diff --git a/src/main/java/org/caosdb/server/grpc/GeneralInfoServiceImpl.java b/src/main/java/org/caosdb/server/grpc/GeneralInfoServiceImpl.java
index 050b5367..de7b6987 100644
--- a/src/main/java/org/caosdb/server/grpc/GeneralInfoServiceImpl.java
+++ b/src/main/java/org/caosdb/server/grpc/GeneralInfoServiceImpl.java
@@ -21,7 +21,11 @@
 package org.caosdb.server.grpc;
 
 import io.grpc.stub.StreamObserver;
+import java.util.Collection;
+import java.util.LinkedList;
 import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.authz.AuthorizationInfo;
+import org.apache.shiro.authz.Permission;
 import org.apache.shiro.subject.Subject;
 import org.caosdb.api.info.v1.GeneralInfoServiceGrpc.GeneralInfoServiceImplBase;
 import org.caosdb.api.info.v1.GetSessionInfoRequest;
@@ -31,7 +35,9 @@ import org.caosdb.api.info.v1.GetVersionInfoResponse;
 import org.caosdb.api.info.v1.VersionInfo;
 import org.caosdb.server.CaosDBServer;
 import org.caosdb.server.ServerProperties;
+import org.caosdb.server.accessControl.AuthenticationUtils;
 import org.caosdb.server.accessControl.Principal;
+import org.caosdb.server.permissions.CaosPermission;
 
 /**
  * Implementation of the GeneralInfoService.
@@ -83,6 +89,24 @@ public class GeneralInfoServiceImpl extends GeneralInfoServiceImplBase {
     response.setUsername(principal.getUsername());
     response.setRealm(principal.getRealm());
 
+    AuthorizationInfo authorizationInfo = AuthenticationUtils.getAuthorizationInfo(user);
+    Collection<String> roles = authorizationInfo.getRoles();
+    if (roles != null && !roles.isEmpty()) {
+      response.addAllRoles(roles);
+    }
+    Collection<String> permissions =
+        new LinkedList<String>(authorizationInfo.getStringPermissions());
+    for (Permission p : authorizationInfo.getObjectPermissions()) {
+      if (p instanceof CaosPermission) {
+        permissions.addAll(((CaosPermission) p).getStringPermissions(user));
+      } else {
+        permissions.add(p.toString());
+      }
+    }
+    if (permissions != null && !permissions.isEmpty()) {
+      response.addAllPermissions(permissions);
+    }
+
     responseObserver.onNext(response.build());
     responseObserver.onCompleted();
   }
diff --git a/src/main/java/org/caosdb/server/jobs/Schedule.java b/src/main/java/org/caosdb/server/jobs/Schedule.java
index f3340009..57474da5 100644
--- a/src/main/java/org/caosdb/server/jobs/Schedule.java
+++ b/src/main/java/org/caosdb/server/jobs/Schedule.java
@@ -97,8 +97,8 @@ public class Schedule {
             ? this.jobLists.get(jobclass.getAnnotation(JobAnnotation.class).stage().ordinal())
             : this.jobLists.get(TransactionStage.CHECK.ordinal());
     for (final ScheduledJob scheduledJob : jobs) {
-      if (jobclass.isInstance(scheduledJob.job)) {
-        if (scheduledJob.job.getEntity() == entity) {
+      if (jobclass.isInstance(scheduledJob.getJob())) {
+        if (scheduledJob.getJob().getEntity() == entity) {
           runJob(scheduledJob);
         }
       }
diff --git a/src/main/java/org/caosdb/server/jobs/ScheduledJob.java b/src/main/java/org/caosdb/server/jobs/ScheduledJob.java
index 3affdfd2..0ef0ac14 100644
--- a/src/main/java/org/caosdb/server/jobs/ScheduledJob.java
+++ b/src/main/java/org/caosdb/server/jobs/ScheduledJob.java
@@ -31,11 +31,14 @@ package org.caosdb.server.jobs;
 public class ScheduledJob {
 
   long runtime = 0;
-  final Job job;
+  private final Job job;
   private long startTime = -1;
 
-  ScheduledJob(final Job j) {
-    this.job = j;
+  ScheduledJob(final Job job) {
+    if (job == null) {
+      throw new NullPointerException("job was null.");
+    }
+    this.job = job;
   }
 
   void run() {
@@ -85,4 +88,8 @@ public class ScheduledJob {
   public boolean skip() {
     return this.job.getTarget().skipJob();
   }
+
+  public Job getJob() {
+    return job;
+  }
 }
diff --git a/src/main/java/org/caosdb/server/permissions/CaosPermission.java b/src/main/java/org/caosdb/server/permissions/CaosPermission.java
index bfbb7eb2..615b4d1a 100644
--- a/src/main/java/org/caosdb/server/permissions/CaosPermission.java
+++ b/src/main/java/org/caosdb/server/permissions/CaosPermission.java
@@ -22,12 +22,11 @@
  */
 package org.caosdb.server.permissions;
 
+import java.util.Collection;
 import java.util.HashSet;
-import java.util.Map;
 import org.apache.shiro.SecurityUtils;
 import org.apache.shiro.authz.Permission;
 import org.apache.shiro.subject.Subject;
-import org.eclipse.jetty.util.ajax.JSON;
 
 public class CaosPermission extends HashSet<PermissionRule> implements Permission {
 
@@ -35,16 +34,33 @@ public class CaosPermission extends HashSet<PermissionRule> implements Permissio
     super(rules);
   }
 
-  public CaosPermission() {}
+  public Collection<String> getStringPermissions(Subject subject) {
+    HashSet<String> grant = new HashSet<>();
+    HashSet<String> prio_grant = new HashSet<>();
+    HashSet<String> deny = new HashSet<>();
+    HashSet<String> prio_deny = new HashSet<>();
 
-  public static CaosPermission parseJSON(final String json) {
-    final CaosPermission ret = new CaosPermission();
-    @SuppressWarnings("unchecked")
-    final Map<String, String>[] rules = (Map<String, String>[]) JSON.parse(json);
-    for (final Map<String, String> rule : rules) {
-      ret.add(PermissionRule.parse(rule));
+    for (PermissionRule r : this) {
+      String p = subject == null ? r.getPermission() : r.getPermission(subject).toString();
+      if (r.isGrant()) {
+        if (r.isPriority()) {
+          prio_grant.add(p);
+        } else {
+          grant.add(p);
+        }
+      } else {
+        if (r.isPriority()) {
+          prio_deny.add(p);
+        } else {
+          deny.add(p);
+        }
+      }
     }
-    return ret;
+
+    grant.removeAll(deny);
+    grant.addAll(prio_grant);
+    grant.removeAll(prio_deny);
+    return grant;
   }
 
   private static final long serialVersionUID = 2136265443788256009L;
diff --git a/src/main/java/org/caosdb/server/resource/AbstractCaosDBServerResource.java b/src/main/java/org/caosdb/server/resource/AbstractCaosDBServerResource.java
index 876b43a1..0fa5b4b4 100644
--- a/src/main/java/org/caosdb/server/resource/AbstractCaosDBServerResource.java
+++ b/src/main/java/org/caosdb/server/resource/AbstractCaosDBServerResource.java
@@ -251,6 +251,7 @@ public abstract class AbstractCaosDBServerResource extends ServerResource {
     try {
       return httpPostInChildClass(entity);
     } catch (final Throwable t) {
+      t.printStackTrace();
       return handleThrowable(t);
     }
   }
diff --git a/src/main/java/org/caosdb/server/transaction/RetrieveRoleTransaction.java b/src/main/java/org/caosdb/server/transaction/RetrieveRoleTransaction.java
index ff71d984..1047e1f6 100644
--- a/src/main/java/org/caosdb/server/transaction/RetrieveRoleTransaction.java
+++ b/src/main/java/org/caosdb/server/transaction/RetrieveRoleTransaction.java
@@ -51,12 +51,14 @@ public class RetrieveRoleTransaction extends AccessControlTransaction {
     if (this.role == null) {
       throw ServerMessages.ROLE_DOES_NOT_EXIST;
     }
-    Iterator<ProtoUser> iterator = this.role.users.iterator();
-    while (iterator.hasNext()) {
-      ProtoUser user = iterator.next();
-      if (!currentUser.isPermitted(
-          ACMPermissions.PERMISSION_RETRIEVE_USER_ROLES(user.realm, user.name))) {
-        iterator.remove();
+    if (this.role.users != null) {
+      Iterator<ProtoUser> iterator = this.role.users.iterator();
+      while (iterator.hasNext()) {
+        ProtoUser user = iterator.next();
+        if (!currentUser.isPermitted(
+            ACMPermissions.PERMISSION_RETRIEVE_USER_ROLES(user.realm, user.name))) {
+          iterator.remove();
+        }
       }
     }
   }
-- 
GitLab