diff --git a/caosdb-proto b/caosdb-proto
index 4e0552f3bd0e40c96ec534f605f38ed7650bcdf1..9c22dfb9fbaf32d4072f84e4e04aae891aff5919 160000
--- a/caosdb-proto
+++ b/caosdb-proto
@@ -1 +1 @@
-Subproject commit 4e0552f3bd0e40c96ec534f605f38ed7650bcdf1
+Subproject commit 9c22dfb9fbaf32d4072f84e4e04aae891aff5919
diff --git a/src/main/java/org/caosdb/server/accessControl/Role.java b/src/main/java/org/caosdb/server/accessControl/Role.java
index 1938d9f18926601a9eb4a0fb081c9738d5c7f501..32ffb4476dff71cf5b6250ade9968da5346e4a7e 100644
--- a/src/main/java/org/caosdb/server/accessControl/Role.java
+++ b/src/main/java/org/caosdb/server/accessControl/Role.java
@@ -24,15 +24,17 @@ package org.caosdb.server.accessControl;
 
 import java.io.Serializable;
 import java.util.LinkedList;
+import org.caosdb.server.database.proto.ProtoUser;
 import org.caosdb.server.permissions.PermissionRule;
 import org.jdom2.Element;
 
 public class Role implements Serializable {
 
-  private static final long serialVersionUID = 8968219504349206982L;
+  private static final long serialVersionUID = -243913823L;
   public String name = null;
   public String description = null;
   public LinkedList<PermissionRule> permission_rules = null;
+  public LinkedList<ProtoUser> users = null;
 
   public Element toElement() {
     final Element ret = new Element("Role");
diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLDeleteRole.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLDeleteRole.java
index 8fd8d35fda6b99f7d79b245a10ace4ed9521e0ce..006e8d4eb266dd895eb3b2b6b717ab3606e978c7 100644
--- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLDeleteRole.java
+++ b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLDeleteRole.java
@@ -24,9 +24,11 @@ package org.caosdb.server.database.backend.implementation.MySQL;
 
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
+import java.sql.SQLIntegrityConstraintViolationException;
 import org.caosdb.server.database.access.Access;
 import org.caosdb.server.database.backend.interfaces.DeleteRoleImpl;
 import org.caosdb.server.database.exceptions.TransactionException;
+import org.caosdb.server.utils.ServerMessages;
 
 public class MySQLDeleteRole extends MySQLTransaction implements DeleteRoleImpl {
 
@@ -42,6 +44,8 @@ public class MySQLDeleteRole extends MySQLTransaction implements DeleteRoleImpl
       final PreparedStatement stmt = prepareStatement(STMT_DELETE_ROLE);
       stmt.setString(1, role);
       stmt.execute();
+    } catch (final SQLIntegrityConstraintViolationException e) {
+      throw new TransactionException(ServerMessages.ROLE_CANNOT_BE_DELETED);
     } catch (final SQLException e) {
       throw new TransactionException(e);
     } catch (final ConnectionException e) {
diff --git a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveRole.java b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveRole.java
index 95dfd2cfeecceb6d3751cba876484c7f5d7a66f9..b622967516cea869483a74f7fd39a7bd779f5f06 100644
--- a/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveRole.java
+++ b/src/main/java/org/caosdb/server/database/backend/implementation/MySQL/MySQLRetrieveRole.java
@@ -31,6 +31,7 @@ import org.caosdb.server.accessControl.Role;
 import org.caosdb.server.database.access.Access;
 import org.caosdb.server.database.backend.interfaces.RetrieveRoleImpl;
 import org.caosdb.server.database.exceptions.TransactionException;
+import org.caosdb.server.database.proto.ProtoUser;
 import org.caosdb.server.permissions.PermissionRule;
 import org.eclipse.jetty.util.ajax.JSON;
 
@@ -42,31 +43,53 @@ public class MySQLRetrieveRole extends MySQLTransaction implements RetrieveRoleI
 
   public static final String STMT_RETRIEVE_ROLE =
       "SELECT r.description AS description, p.permissions AS permissions FROM roles AS r LEFT JOIN permissions AS p ON (r.name = p.role) WHERE r.name=?";
+  public static final String STMT_RETRIEVE_USERS =
+      "SELECT u.realm, u.user FROM user_roles AS u WHERE u.role = ?";
 
   @Override
   public Role retrieve(final String role) throws TransactionException {
-    try {
-      final PreparedStatement stmt = prepareStatement(STMT_RETRIEVE_ROLE);
+    Role ret = null;
+    try (final PreparedStatement stmt = prepareStatement(STMT_RETRIEVE_ROLE)) {
       stmt.setString(1, role);
       final ResultSet rs = stmt.executeQuery();
-      try {
-        if (rs.next()) {
-          final Role ret = new Role();
-          ret.name = role;
-          ret.description = rs.getString("description");
-          ret.permission_rules = parse(rs.getString("permissions"));
-          return ret;
-        } else {
-          return null;
+      if (rs.next()) {
+        ret = new Role();
+        ret.name = role;
+        ret.description = rs.getString("description");
+        ret.permission_rules = parse(rs.getString("permissions"));
+      } else {
+        return null;
+      }
+    } catch (final SQLException e) {
+      throw new TransactionException(e);
+    } catch (final ConnectionException e) {
+      throw new TransactionException(e);
+    }
+
+    try (final PreparedStatement stmt = prepareStatement(STMT_RETRIEVE_USERS)) {
+      stmt.setString(1, role);
+      final ResultSet rs = stmt.executeQuery();
+      if (rs.next()) {
+        ret.users = new LinkedList<>();
+
+        ret.users.add(nextUser(rs));
+        while (rs.next()) {
+          ret.users.add(nextUser(rs));
         }
-      } finally {
-        rs.close();
       }
     } catch (final SQLException e) {
       throw new TransactionException(e);
     } catch (final ConnectionException e) {
       throw new TransactionException(e);
     }
+    return ret;
+  }
+
+  private ProtoUser nextUser(ResultSet rs) throws SQLException {
+    ProtoUser nextUser = new ProtoUser();
+    nextUser.realm = rs.getString("realm");
+    nextUser.name = rs.getString("user");
+    return nextUser;
   }
 
   @SuppressWarnings("unchecked")
diff --git a/src/main/java/org/caosdb/server/database/proto/ProtoUser.java b/src/main/java/org/caosdb/server/database/proto/ProtoUser.java
index cafa32d2580c8a09a97e1cd3ee48c2ec59a454cf..91dfe9aa63f4f3e04581e068bb1494543c504bff 100644
--- a/src/main/java/org/caosdb/server/database/proto/ProtoUser.java
+++ b/src/main/java/org/caosdb/server/database/proto/ProtoUser.java
@@ -23,19 +23,19 @@
 package org.caosdb.server.database.proto;
 
 import java.io.Serializable;
-import java.util.Set;
+import java.util.HashSet;
 import org.caosdb.server.accessControl.UserStatus;
 
 public class ProtoUser implements Serializable {
 
   public ProtoUser() {}
 
-  private static final long serialVersionUID = -2704114543883567439L;
+  private static final long serialVersionUID = 5381234723597234L;
 
   public UserStatus status = null;
   public String name = null;
   public String email = null;
   public Integer entity = null;
   public String realm = null;
-  public Set<String> roles = null;
+  public HashSet<String> roles = null;
 }
diff --git a/src/main/java/org/caosdb/server/entity/Message.java b/src/main/java/org/caosdb/server/entity/Message.java
index 4c89e1ee23839483f7bed1099c52e8c24a56a6a2..e206137e177cc761bf26b34790985b43b2a7e64a 100644
--- a/src/main/java/org/caosdb/server/entity/Message.java
+++ b/src/main/java/org/caosdb/server/entity/Message.java
@@ -35,6 +35,11 @@ public class Message extends Exception implements Comparable<Message>, ToElement
   private final String description;
   private final String body;
 
+  @Override
+  public String getMessage() {
+    return description;
+  }
+
   @Deprecated private static final Map<String, String> legacy_codes_mapping = new HashMap<>();
 
   static void init() {
diff --git a/src/main/java/org/caosdb/server/grpc/AccessControlManagementServiceImpl.java b/src/main/java/org/caosdb/server/grpc/AccessControlManagementServiceImpl.java
index 182d5cb5dd194db4475f3a923a9bf207eb7ab498..dbfa1512aa14bfd1652eefb5065498e654435294 100644
--- a/src/main/java/org/caosdb/server/grpc/AccessControlManagementServiceImpl.java
+++ b/src/main/java/org/caosdb/server/grpc/AccessControlManagementServiceImpl.java
@@ -1,14 +1,21 @@
 package org.caosdb.server.grpc;
 
+import io.grpc.Status;
+import io.grpc.StatusException;
 import io.grpc.stub.StreamObserver;
 import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.authz.UnauthorizedException;
+import org.apache.shiro.subject.Subject;
 import org.caosdb.api.acm.v1alpha1.AccessControlManagementServiceGrpc.AccessControlManagementServiceImplBase;
 import org.caosdb.api.acm.v1alpha1.CreateSingleRoleRequest;
 import org.caosdb.api.acm.v1alpha1.CreateSingleRoleResponse;
 import org.caosdb.api.acm.v1alpha1.CreateSingleUserRequest;
 import org.caosdb.api.acm.v1alpha1.CreateSingleUserResponse;
+import org.caosdb.api.acm.v1alpha1.DeleteSingleRoleRequest;
+import org.caosdb.api.acm.v1alpha1.DeleteSingleRoleResponse;
 import org.caosdb.api.acm.v1alpha1.ListRolesRequest;
 import org.caosdb.api.acm.v1alpha1.ListRolesResponse;
 import org.caosdb.api.acm.v1alpha1.ListUsersRequest;
@@ -18,16 +25,22 @@ import org.caosdb.api.acm.v1alpha1.RetrieveSingleRoleRequest;
 import org.caosdb.api.acm.v1alpha1.RetrieveSingleRoleResponse;
 import org.caosdb.api.acm.v1alpha1.RetrieveSingleUserRequest;
 import org.caosdb.api.acm.v1alpha1.RetrieveSingleUserResponse;
+import org.caosdb.api.acm.v1alpha1.UpdateSingleRoleRequest;
+import org.caosdb.api.acm.v1alpha1.UpdateSingleRoleResponse;
 import org.caosdb.api.acm.v1alpha1.User;
 import org.caosdb.api.acm.v1alpha1.UserStatus;
+import org.caosdb.server.accessControl.AuthenticationUtils;
 import org.caosdb.server.accessControl.Role;
 import org.caosdb.server.database.proto.ProtoUser;
+import org.caosdb.server.transaction.DeleteRoleTransaction;
 import org.caosdb.server.transaction.InsertRoleTransaction;
 import org.caosdb.server.transaction.InsertUserTransaction;
 import org.caosdb.server.transaction.ListRolesTransaction;
 import org.caosdb.server.transaction.ListUsersTransaction;
 import org.caosdb.server.transaction.RetrieveRoleTransaction;
 import org.caosdb.server.transaction.RetrieveUserTransaction;
+import org.caosdb.server.transaction.UpdateRoleTransaction;
+import org.caosdb.server.utils.ServerMessages;
 
 public class AccessControlManagementServiceImpl extends AccessControlManagementServiceImplBase {
 
@@ -70,16 +83,16 @@ public class AccessControlManagementServiceImpl extends AccessControlManagementS
 
   private User.Builder convert(ProtoUser user) {
     User.Builder result = User.newBuilder();
-    result.setStatus(convert(user.status));
     result.setRealm(user.realm);
     result.setName(user.name);
+    if (user.status != null) result.setStatus(convert(user.status));
     if (user.email != null) {
       result.setEmail(user.email);
     }
     if (user.entity != null) {
       result.setEntityId(Integer.toString(user.entity));
     }
-    if (user.roles != null) {
+    if (user.roles != null && !user.roles.isEmpty()) {
       result.addAllRoles(user.roles);
     }
     return result;
@@ -167,7 +180,31 @@ public class AccessControlManagementServiceImpl extends AccessControlManagementS
     RetrieveRoleTransaction transaction = new RetrieveRoleTransaction(request.getName());
     transaction.execute();
 
-    return RetrieveSingleRoleResponse.newBuilder().setRole(convert(transaction.getRole())).build();
+    Role role = transaction.getRole();
+    RetrieveSingleRoleResponse.Builder builder =
+        RetrieveSingleRoleResponse.newBuilder().setRole(convert(transaction.getRole()));
+    if (role.users != null && !role.users.isEmpty())
+      role.users.forEach(
+          (u) -> {
+            builder.addUsers(convert(u));
+          });
+    return builder.build();
+  }
+
+  private DeleteSingleRoleResponse deleteSingleRoleTransaction(DeleteSingleRoleRequest request)
+      throws Exception {
+    DeleteRoleTransaction transaction = new DeleteRoleTransaction(request.getName());
+    transaction.execute();
+
+    return DeleteSingleRoleResponse.newBuilder().build();
+  }
+
+  private UpdateSingleRoleResponse updateSingleRoleTransaction(UpdateSingleRoleRequest request)
+      throws Exception {
+    Role role = convert(request.getRole());
+    UpdateRoleTransaction transaction = new UpdateRoleTransaction(role);
+    transaction.execute();
+    return UpdateSingleRoleResponse.newBuilder().build();
   }
 
   ////////////////// ... for users
@@ -208,8 +245,7 @@ public class AccessControlManagementServiceImpl extends AccessControlManagementS
       responseObserver.onCompleted();
 
     } catch (final Exception e) {
-      e.printStackTrace();
-      responseObserver.onError(e);
+      handleException(responseObserver, e);
     }
   }
 
@@ -222,8 +258,7 @@ public class AccessControlManagementServiceImpl extends AccessControlManagementS
       responseObserver.onCompleted();
 
     } catch (final Exception e) {
-      e.printStackTrace();
-      responseObserver.onError(e);
+      handleException(responseObserver, e);
     }
   }
 
@@ -236,8 +271,7 @@ public class AccessControlManagementServiceImpl extends AccessControlManagementS
       responseObserver.onCompleted();
 
     } catch (final Exception e) {
-      e.printStackTrace();
-      responseObserver.onError(e);
+      handleException(responseObserver, e);
     }
   }
 
@@ -251,8 +285,7 @@ public class AccessControlManagementServiceImpl extends AccessControlManagementS
       responseObserver.onCompleted();
 
     } catch (final Exception e) {
-      e.printStackTrace();
-      responseObserver.onError(e);
+      handleException(responseObserver, e);
     }
   }
 
@@ -265,8 +298,7 @@ public class AccessControlManagementServiceImpl extends AccessControlManagementS
       responseObserver.onCompleted();
 
     } catch (final Exception e) {
-      e.printStackTrace();
-      responseObserver.onError(e);
+      handleException(responseObserver, e);
     }
   }
 
@@ -280,8 +312,57 @@ public class AccessControlManagementServiceImpl extends AccessControlManagementS
       responseObserver.onCompleted();
 
     } catch (final Exception e) {
-      e.printStackTrace();
-      responseObserver.onError(e);
+      handleException(responseObserver, e);
+    }
+  }
+
+  @Override
+  public void deleteSingleRole(
+      DeleteSingleRoleRequest request, StreamObserver<DeleteSingleRoleResponse> responseObserver) {
+    try {
+      final DeleteSingleRoleResponse response = deleteSingleRoleTransaction(request);
+      responseObserver.onNext(response);
+      responseObserver.onCompleted();
+
+    } catch (final Exception e) {
+      handleException(responseObserver, e);
+    }
+  }
+
+  @Override
+  public void updateSingleRole(
+      UpdateSingleRoleRequest request, StreamObserver<UpdateSingleRoleResponse> responseObserver) {
+    try {
+      final UpdateSingleRoleResponse response = updateSingleRoleTransaction(request);
+      responseObserver.onNext(response);
+      responseObserver.onCompleted();
+
+    } catch (final Exception e) {
+      handleException(responseObserver, e);
+    }
+  }
+
+  private void handleException(StreamObserver<?> responseObserver, Exception e) {
+    if (e instanceof UnauthorizedException) {
+      Subject subject = SecurityUtils.getSubject();
+      if (AuthenticationUtils.isAnonymous(subject)) {
+        responseObserver.onError(
+            new StatusException(Status.UNAUTHENTICATED.withDescription("Please login!")));
+        return;
+      } else {
+        responseObserver.onError(
+            new StatusException(
+                Status.PERMISSION_DENIED.withCause(e).withDescription(e.getMessage())));
+        return;
+      }
+    } else if (e == ServerMessages.ROLE_DOES_NOT_EXIST
+        || e == ServerMessages.ACCOUNT_DOES_NOT_EXIST) {
+      responseObserver.onError(
+          new StatusException(Status.NOT_FOUND.withDescription(e.getMessage()).withCause(e)));
+      return;
     }
+    e.printStackTrace();
+    responseObserver.onError(
+        new StatusException(Status.UNKNOWN.withDescription(e.getMessage()).withCause(e)));
   }
 }
diff --git a/src/main/java/org/caosdb/server/transaction/DeleteRoleTransaction.java b/src/main/java/org/caosdb/server/transaction/DeleteRoleTransaction.java
index ad9a9925f8bed2ef03a1bcf9cd6b8c79adca6345..23c3126108de6f5a03039adb2459d91c4d1bf22a 100644
--- a/src/main/java/org/caosdb/server/transaction/DeleteRoleTransaction.java
+++ b/src/main/java/org/caosdb/server/transaction/DeleteRoleTransaction.java
@@ -27,6 +27,8 @@ import org.caosdb.server.accessControl.ACMPermissions;
 import org.caosdb.server.database.backend.transaction.DeleteRole;
 import org.caosdb.server.database.backend.transaction.RetrieveRole;
 import org.caosdb.server.database.backend.transaction.SetPermissionRules;
+import org.caosdb.server.database.exceptions.TransactionException;
+import org.caosdb.server.entity.Message;
 import org.caosdb.server.utils.ServerMessages;
 
 public class DeleteRoleTransaction extends AccessControlTransaction {
@@ -41,10 +43,19 @@ public class DeleteRoleTransaction extends AccessControlTransaction {
   protected void transaction() throws Exception {
     SecurityUtils.getSubject().checkPermission(ACMPermissions.PERMISSION_DELETE_ROLE(this.name));
 
+    if (this.name == "administration" || this.name == "anonymous") {
+      throw ServerMessages.SPECIAL_ROLE_CANNOT_BE_DELETED;
+    }
     if (execute(new RetrieveRole(this.name), getAccess()).getRole() == null) {
       throw ServerMessages.ROLE_DOES_NOT_EXIST;
     }
     execute(new SetPermissionRules(this.name, null), getAccess());
-    execute(new DeleteRole(this.name), getAccess());
+    try {
+      execute(new DeleteRole(this.name), getAccess());
+    } catch (TransactionException e) {
+      if (e.getCause() == ServerMessages.ROLE_CANNOT_BE_DELETED) {
+        throw (Message) e.getCause();
+      }
+    }
   }
 }
diff --git a/src/main/java/org/caosdb/server/utils/ServerMessages.java b/src/main/java/org/caosdb/server/utils/ServerMessages.java
index 4197f2cf78cedb3fcf9dc0ea6648b6c3335a9da8..cc844fee1399cb03e893efd6adbc7bde6b64dcc9 100644
--- a/src/main/java/org/caosdb/server/utils/ServerMessages.java
+++ b/src/main/java/org/caosdb/server/utils/ServerMessages.java
@@ -267,6 +267,18 @@ public class ServerMessages {
           MessageCode.MESSAGE_CODE_UNKNOWN,
           "Role name is already in use. Choose a different name.");
 
+  public static final Message ROLE_CANNOT_BE_DELETED =
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_UNKNOWN,
+          "Role cannot be deleted because there are still users with this role.");
+
+  public static final Message SPECIAL_ROLE_CANNOT_BE_DELETED =
+      new Message(
+          MessageType.Error,
+          MessageCode.MESSAGE_CODE_UNKNOWN,
+          "This special role cannot be deleted. Ever.");
+
   public static final Message QUERY_EXCEPTION =
       new Message(
           MessageType.Error,