diff --git a/src/main/java/org/caosdb/server/accessControl/AuthenticationUtils.java b/src/main/java/org/caosdb/server/accessControl/AuthenticationUtils.java
index e6907f40b57b5ef44dc9c4772327ddf8920df173..dc40e72e44ffdd6fca21824c6f3dd036f0b6f9ed 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 17637b010a1ddcd7ed88e3ba448e3fa68b894b43..5bc711e17b60309f851e55bf249a22beeec56d61 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 050b5367832e98e6b7c1136bfe47f4daa2b17871..de7b698792f2660848d1bf93196a7dc9174ee703 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 f33400099a951aa8fbcf1975208988085813a8b8..57474da515418745ed0457962596dfce233bff48 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 3affdfd21421961edc4721c25d80f392d914d1bb..0ef0ac143428eaddaf857f063b7953a620f47ee6 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 bfbb7eb2e8515f71bb2d611d4fd75916cfae50e7..615b4d1a9c26c1addb955506ab1debddb729db9c 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 876b43a160f673b96a7220a746c9a7dcd4951388..0fa5b4b405f254fa9e8aa4ab2609eb9da7b3d766 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 ff71d984b2c6651b7ba02695a1d37ffc8e9e8c43..1047e1f60143bd6ab3ebbc8ae7c9a7ebb93f2a15 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();
+        }
       }
     }
   }