This is an automated email from the ASF dual-hosted git repository.

fanng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/main by this push:
     new b6a61bafb5 [#6760] test(core): Support role failure event to Gravitino 
server (#6866)
b6a61bafb5 is described below

commit b6a61bafb5d1e7f15c8336ac3e7d523dbdfd5831
Author: Lord of Abyss <103809695+abyss-l...@users.noreply.github.com>
AuthorDate: Fri Apr 11 08:33:22 2025 +0800

    [#6760] test(core): Support role failure event to Gravitino server (#6866)
    
    ### What changes were proposed in this pull request?
    
    Support role failure event to Gravitino server
    1. Support role failure event to Gravitino server
    2. Refactor the `EventBus#dispatchEvent` method using the Visitor design
    pattern to eliminate `instanceof` checks, improve extensibility, and
    ensure that unhandled event types can be detected at compile time.
    
    ### Why are the changes needed?
    
    Fix: #6760
    
    ### Does this PR introduce _any_ user-facing change?
    
    No.
    
    ### How was this patch tested?
    
    local test.
---
 .../api/event/AccessControlEventDispatcher.java    |  26 ++-
 .../listener/api/event/CreateRoleFailureEvent.java |  66 +++++++
 .../listener/api/event/DeleteRoleFailureEvent.java |  66 +++++++
 .../listener/api/event/GetRoleFailureEvent.java    |  65 +++++++
 .../api/event/GrantPrivilegesFailureEvent.java     | 100 ++++++++++
 .../api/event/ListRoleNamesFailureEvent.java       |  82 +++++++++
 .../api/event/RevokePrivilegesFailureEvent.java    |  99 ++++++++++
 .../listener/api/event/RoleFailureEvent.java       |  43 +++++
 .../gravitino/listener/api/info/RoleInfo.java      |  15 ++
 .../listener/api/event/TestRoleEvent.java          | 202 ++++++++++++++++++++-
 docs/gravitino-server-config.md                    |  26 +--
 11 files changed, 762 insertions(+), 28 deletions(-)

diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/AccessControlEventDispatcher.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/AccessControlEventDispatcher.java
index cd5d1613f3..cecf20de50 100644
--- 
a/core/src/main/java/org/apache/gravitino/listener/api/event/AccessControlEventDispatcher.java
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/AccessControlEventDispatcher.java
@@ -319,13 +319,7 @@ public class AccessControlEventDispatcher implements 
AccessControlDispatcher {
   /** {@inheritDoc} */
   @Override
   public boolean isServiceAdmin(String user) {
-    try {
-      // TODO: add Event
-      return dispatcher.isServiceAdmin(user);
-    } catch (Exception e) {
-      // TODO: add failure event
-      throw e;
-    }
+    return dispatcher.isServiceAdmin(user);
   }
 
   /** {@inheritDoc} */
@@ -346,7 +340,9 @@ public class AccessControlEventDispatcher implements 
AccessControlDispatcher {
 
       return roleObject;
     } catch (Exception e) {
-      // TODO: add failure event
+      eventBus.dispatchEvent(
+          new CreateRoleFailureEvent(
+              initiator, metalake, e, new RoleInfo(role, properties, 
securableObjects)));
       throw e;
     }
   }
@@ -364,7 +360,7 @@ public class AccessControlEventDispatcher implements 
AccessControlDispatcher {
 
       return roleObject;
     } catch (Exception e) {
-      // TODO: add failure event
+      eventBus.dispatchEvent(new GetRoleFailureEvent(initiator, metalake, e, 
role));
       throw e;
     }
   }
@@ -381,7 +377,7 @@ public class AccessControlEventDispatcher implements 
AccessControlDispatcher {
 
       return isExists;
     } catch (Exception e) {
-      // TODO: add failure event
+      eventBus.dispatchEvent(new DeleteRoleFailureEvent(initiator, metalake, 
e, role));
       throw e;
     }
   }
@@ -398,7 +394,7 @@ public class AccessControlEventDispatcher implements 
AccessControlDispatcher {
 
       return roleNames;
     } catch (Exception e) {
-      // TODO: add failure event
+      eventBus.dispatchEvent(new ListRoleNamesFailureEvent(initiator, 
metalake, e));
       throw e;
     }
   }
@@ -416,7 +412,7 @@ public class AccessControlEventDispatcher implements 
AccessControlDispatcher {
 
       return roleNames;
     } catch (Exception e) {
-      // TODO: add failure event
+      eventBus.dispatchEvent(new ListRoleNamesFailureEvent(initiator, 
metalake, e, object));
       throw e;
     }
   }
@@ -438,7 +434,8 @@ public class AccessControlEventDispatcher implements 
AccessControlDispatcher {
 
       return roleObject;
     } catch (Exception e) {
-      // TODO: add failure event
+      eventBus.dispatchEvent(
+          new GrantPrivilegesFailureEvent(initiator, metalake, e, role, 
object, privileges));
       throw e;
     }
   }
@@ -460,7 +457,8 @@ public class AccessControlEventDispatcher implements 
AccessControlDispatcher {
 
       return roleObject;
     } catch (Exception e) {
-      // TODO: add failure event
+      eventBus.dispatchEvent(
+          new RevokePrivilegesFailureEvent(initiator, metalake, e, role, 
object, privileges));
       throw e;
     }
   }
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/CreateRoleFailureEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/CreateRoleFailureEvent.java
new file mode 100644
index 0000000000..d3080bed62
--- /dev/null
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/CreateRoleFailureEvent.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.gravitino.listener.api.event;
+
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.info.RoleInfo;
+import org.apache.gravitino.utils.NameIdentifierUtil;
+
+/**
+ * Represents an event triggered when an attempt to create a role in a 
metalake fails due to an
+ * exception.
+ */
+@DeveloperApi
+public class CreateRoleFailureEvent extends RoleFailureEvent {
+  private final RoleInfo createRoleRequest;
+  /**
+   * Constructs a new {@code CreateRoleFailureEvent} instance.
+   *
+   * @param initiator the user who initiated the event.
+   * @param metalake the target metalake context for the role creation
+   * @param exception the exception that caused the failure
+   * @param createRoleRequest the role information that failed to be created
+   */
+  public CreateRoleFailureEvent(
+      String initiator, String metalake, Exception exception, RoleInfo 
createRoleRequest) {
+    super(initiator, NameIdentifierUtil.ofRole(metalake, 
createRoleRequest.roleName()), exception);
+
+    this.createRoleRequest = createRoleRequest;
+  }
+
+  /**
+   * Returns the role information that failed to be created.
+   *
+   * @return The {@link RoleInfo} instance.
+   */
+  public RoleInfo createRoleRequest() {
+    return createRoleRequest;
+  }
+
+  /**
+   * Returns the operation type of this event.
+   *
+   * @return the operation type.
+   */
+  @Override
+  public OperationType operationType() {
+    return OperationType.CREATE_ROLE;
+  }
+}
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/DeleteRoleFailureEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/DeleteRoleFailureEvent.java
new file mode 100644
index 0000000000..a020030a2e
--- /dev/null
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/DeleteRoleFailureEvent.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.gravitino.listener.api.event;
+
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.utils.NameIdentifierUtil;
+
+/**
+ * Represents an event triggered when an attempt to delete a role from a 
metalake fails due to an
+ * exception.
+ */
+@DeveloperApi
+public class DeleteRoleFailureEvent extends RoleFailureEvent {
+  private final String roleName;
+
+  /**
+   * Constructs a new {@code DeleteRoleFailureEvent} instance.
+   *
+   * @param user the user who initiated the deletion attempt
+   * @param metalake the target metalake from which the role is to be deleted
+   * @param exception the exception that caused the failure
+   * @param roleName the name of the role intended for deletion
+   */
+  protected DeleteRoleFailureEvent(
+      String user, String metalake, Exception exception, String roleName) {
+    super(user, NameIdentifierUtil.ofRole(metalake, roleName), exception);
+
+    this.roleName = roleName;
+  }
+
+  /**
+   * Returns the name of the role that was intended for deletion.
+   *
+   * @return the name of the role
+   */
+  public String roleName() {
+    return roleName;
+  }
+
+  /**
+   * Returns the operation type of this event.
+   *
+   * @return the operation type.
+   */
+  @Override
+  public OperationType operationType() {
+    return OperationType.DELETE_ROLE;
+  }
+}
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/GetRoleFailureEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/GetRoleFailureEvent.java
new file mode 100644
index 0000000000..87eb60ff74
--- /dev/null
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/GetRoleFailureEvent.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.gravitino.listener.api.event;
+
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.utils.NameIdentifierUtil;
+
+/**
+ * Represents an event triggered when an attempt to retrieve a role from a 
metalake fails due to an
+ * exception.
+ */
+@DeveloperApi
+public class GetRoleFailureEvent extends RoleFailureEvent {
+  private final String roleName;
+
+  /**
+   * Constructs a new {@code GetRoleFailureEvent} instance.
+   *
+   * @param user the user who initiated the retrieval attempt
+   * @param metalake the metalake from which the role is being retrieved
+   * @param exception the exception that occurred during role retrieval
+   * @param roleName the name of the role being retrieved
+   */
+  public GetRoleFailureEvent(String user, String metalake, Exception 
exception, String roleName) {
+    super(user, NameIdentifierUtil.ofRole(metalake, roleName), exception);
+
+    this.roleName = roleName;
+  }
+
+  /**
+   * Returns the name of the role that was attempted to be retrieved.
+   *
+   * @return the role name
+   */
+  public String roleName() {
+    return roleName;
+  }
+
+  /**
+   * Returns the operation type of this event.
+   *
+   * @return the operation type.
+   */
+  @Override
+  public OperationType operationType() {
+    return OperationType.GET_ROLE;
+  }
+}
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/GrantPrivilegesFailureEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/GrantPrivilegesFailureEvent.java
new file mode 100644
index 0000000000..fab59eb065
--- /dev/null
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/GrantPrivilegesFailureEvent.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.gravitino.listener.api.event;
+
+import com.google.common.collect.ImmutableSet;
+import java.util.Set;
+import org.apache.gravitino.MetadataObject;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.authorization.Privilege;
+import org.apache.gravitino.utils.NameIdentifierUtil;
+
+/**
+ * Represents an event triggered when an attempt to grant privileges to a role 
fails due to an
+ * exception.
+ */
+@DeveloperApi
+public class GrantPrivilegesFailureEvent extends RoleFailureEvent {
+
+  private final String roleName;
+  private final MetadataObject metadataObject;
+  private final Set<Privilege> privileges;
+
+  /**
+   * Constructs a new {@code GrantPrivilegesFailureEvent} instance.
+   *
+   * @param user the name of the user who triggered the event
+   * @param metalake the name of the metalake
+   * @param exception the exception that occurred while granting privileges
+   * @param roleName the name of the role to which privileges were being 
granted
+   * @param metadataObject the {@code MetadataObject} instance associated with 
the role
+   * @param privileges the set of privileges intended to be granted; if {@code 
null}, an empty set
+   *     is used
+   */
+  public GrantPrivilegesFailureEvent(
+      String user,
+      String metalake,
+      Exception exception,
+      String roleName,
+      MetadataObject metadataObject,
+      Set<Privilege> privileges) {
+    super(user, NameIdentifierUtil.ofRole(metalake, roleName), exception);
+    this.roleName = roleName;
+    this.metadataObject = metadataObject;
+    this.privileges = privileges == null ? ImmutableSet.of() : 
ImmutableSet.copyOf(privileges);
+  }
+
+  /**
+   * Returns the name of the role.
+   *
+   * @return the name of the role to which privileges were intended to be 
granted
+   */
+  public String roleName() {
+    return roleName;
+  }
+
+  /**
+   * Returns the associated {@code MetadataObject} instance.
+   *
+   * @return the {@code MetadataObject} instance related to the role
+   */
+  public MetadataObject object() {
+    return metadataObject;
+  }
+
+  /**
+   * Returns the set of privileges intended to be granted.
+   *
+   * @return an immutable set of privileges
+   */
+  public Set<Privilege> privileges() {
+    return privileges;
+  }
+
+  /**
+   * Returns the operation type of this event.
+   *
+   * @return the operation type.
+   */
+  @Override
+  public OperationType operationType() {
+    return OperationType.GRANT_PRIVILEGES;
+  }
+}
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListRoleNamesFailureEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListRoleNamesFailureEvent.java
new file mode 100644
index 0000000000..e95c63ac0b
--- /dev/null
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListRoleNamesFailureEvent.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.gravitino.listener.api.event;
+
+import java.util.Optional;
+import org.apache.gravitino.MetadataObject;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.utils.NameIdentifierUtil;
+
+/**
+ * Represents an event triggered when an attempt to list role names for a 
metalake fails due to an
+ * exception.
+ */
+@DeveloperApi
+public class ListRoleNamesFailureEvent extends RoleFailureEvent {
+  private final Optional<MetadataObject> metadataObject;
+
+  /**
+   * Constructs a new {@code ListRoleNamesFailureEvent} instance with no 
associated {@code
+   * MetadataObject}.
+   *
+   * @param user the user who initiated the operation
+   * @param metalake the name of the metalake for which role names were being 
listed
+   * @param exception the exception that occurred during the operation
+   */
+  public ListRoleNamesFailureEvent(String user, String metalake, Exception 
exception) {
+    super(user, NameIdentifierUtil.ofMetalake(metalake), exception);
+
+    this.metadataObject = Optional.empty();
+  }
+
+  /**
+   * Construct a new {@link ListRoleNamesFailureEvent} instance with the 
specified arguments.
+   *
+   * @param user The user who initiated the event.
+   * @param metalake The name of the metalake for which role names are being 
listed.
+   * @param exception The exception that occurred while listing role names.
+   * @param metadataObject The {@link MetadataObject} instance related to the 
role names being
+   *     listed, if present.
+   */
+  public ListRoleNamesFailureEvent(
+      String user, String metalake, Exception exception, MetadataObject 
metadataObject) {
+    super(user, NameIdentifierUtil.ofMetalake(metalake), exception);
+    this.metadataObject = Optional.of(metadataObject);
+  }
+
+  /**
+   * Returns the associated {@code MetadataObject} instance.
+   *
+   * @return an {@code Optional} containing the {@code MetadataObject} if 
present, otherwise empty
+   */
+  public Optional<MetadataObject> metadataObject() {
+    return metadataObject;
+  }
+
+  /**
+   * Returns the operation type of this event.
+   *
+   * @return the operation type.
+   */
+  @Override
+  public OperationType operationType() {
+    return OperationType.LIST_ROLE_NAMES;
+  }
+}
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/RevokePrivilegesFailureEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/RevokePrivilegesFailureEvent.java
new file mode 100644
index 0000000000..d934614d62
--- /dev/null
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/RevokePrivilegesFailureEvent.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.gravitino.listener.api.event;
+
+import com.google.common.collect.ImmutableSet;
+import java.util.Set;
+import org.apache.gravitino.MetadataObject;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.authorization.Privilege;
+import org.apache.gravitino.utils.NameIdentifierUtil;
+
+/**
+ * Represents an event triggered when an attempt to revoke privileges from a 
role fails due to an
+ * exception.
+ */
+@DeveloperApi
+public class RevokePrivilegesFailureEvent extends RoleFailureEvent {
+  private final String roleName;
+  private final MetadataObject metadataObject;
+  private final Set<Privilege> privileges;
+
+  /**
+   * Constructs a new {@code RevokePrivilegesFailureEvent} instance.
+   *
+   * @param user the user who initiated the event
+   * @param metalake the name of the metalake
+   * @param exception the exception that occurred during the revocation attempt
+   * @param roleName the name of the role from which privileges were attempted 
to be revoked
+   * @param metadataObject the {@code MetadataObject} instance associated with 
the role
+   * @param privileges the set of privileges intended to be revoked; if {@code 
null}, an empty set
+   *     is used
+   */
+  public RevokePrivilegesFailureEvent(
+      String user,
+      String metalake,
+      Exception exception,
+      String roleName,
+      MetadataObject metadataObject,
+      Set<Privilege> privileges) {
+    super(user, NameIdentifierUtil.ofRole(metalake, roleName), exception);
+    this.roleName = roleName;
+    this.metadataObject = metadataObject;
+    this.privileges = privileges == null ? ImmutableSet.of() : 
ImmutableSet.copyOf(privileges);
+  }
+
+  /**
+   * Returns the name of the role from which privileges were attempted to be 
revoked.
+   *
+   * @return the role name
+   */
+  public String roleName() {
+    return roleName;
+  }
+
+  /**
+   * Returns the associated {@code MetadataObject} instance.
+   *
+   * @return the {@code MetadataObject} instance linked to the role
+   */
+  public MetadataObject metadataObject() {
+    return metadataObject;
+  }
+
+  /**
+   * Returns the set of privileges intended to be revoked.
+   *
+   * @return an immutable set of privileges
+   */
+  public Set<Privilege> privileges() {
+    return privileges;
+  }
+
+  /**
+   * Returns the operation type of this event.
+   *
+   * @return the operation type.
+   */
+  @Override
+  public OperationType operationType() {
+    return OperationType.REVOKE_PRIVILEGES;
+  }
+}
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/event/RoleFailureEvent.java
 
b/core/src/main/java/org/apache/gravitino/listener/api/event/RoleFailureEvent.java
new file mode 100644
index 0000000000..359e68e435
--- /dev/null
+++ 
b/core/src/main/java/org/apache/gravitino/listener/api/event/RoleFailureEvent.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.gravitino.listener.api.event;
+
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.annotation.DeveloperApi;
+
+/**
+ * Represents an event that occurs when a role operation fails due to an 
exception. This event
+ * contains the role information, a unique identifier for the operation, and 
the exception that
+ * caused the failure.
+ */
+@DeveloperApi
+public abstract class RoleFailureEvent extends FailureEvent {
+
+  /**
+   * Constructs a new {@code RoleFailureEvent} instance.
+   *
+   * @param user the user who initiated the operation
+   * @param identifier the unique identifier associated with the operation
+   * @param exception the exception that caused the failure
+   */
+  protected RoleFailureEvent(String user, NameIdentifier identifier, Exception 
exception) {
+    super(user, identifier, exception);
+  }
+}
diff --git 
a/core/src/main/java/org/apache/gravitino/listener/api/info/RoleInfo.java 
b/core/src/main/java/org/apache/gravitino/listener/api/info/RoleInfo.java
index c89fd5233d..59865dcec6 100644
--- a/core/src/main/java/org/apache/gravitino/listener/api/info/RoleInfo.java
+++ b/core/src/main/java/org/apache/gravitino/listener/api/info/RoleInfo.java
@@ -51,6 +51,21 @@ public class RoleInfo {
             : ImmutableList.copyOf(roleObject.securableObjects());
   }
 
+  /**
+   * Constructs a new {@code RoleInfo} instance using the given arguments.
+   *
+   * @param roleName The role name.
+   * @param properties The properties associated with the role.
+   * @param securableObjects The securable objects that belong to the role.
+   */
+  public RoleInfo(
+      String roleName, Map<String, String> properties, List<SecurableObject> 
securableObjects) {
+    this.roleName = roleName;
+    this.properties = properties == null ? ImmutableMap.of() : 
ImmutableMap.copyOf(properties);
+    this.securableObjects =
+        securableObjects == null ? ImmutableList.of() : 
ImmutableList.copyOf(securableObjects);
+  }
+
   /**
    * Returns the role name.
    *
diff --git 
a/core/src/test/java/org/apache/gravitino/listener/api/event/TestRoleEvent.java 
b/core/src/test/java/org/apache/gravitino/listener/api/event/TestRoleEvent.java
index c4d63ffbfa..697c3836bd 100644
--- 
a/core/src/test/java/org/apache/gravitino/listener/api/event/TestRoleEvent.java
+++ 
b/core/src/test/java/org/apache/gravitino/listener/api/event/TestRoleEvent.java
@@ -101,6 +101,24 @@ public class TestRoleEvent {
     Assertions.assertEquals(roleName, roleInfo.roleName());
     Assertions.assertEquals(properties, roleInfo.properties());
     Assertions.assertEquals(securableObjects, roleInfo.securableObjects());
+
+    Assertions.assertThrows(
+        UnsupportedOperationException.class, () -> 
roleInfo.securableObjects().add(null));
+
+    Assertions.assertThrows(
+        UnsupportedOperationException.class, () -> 
roleInfo.properties().put("test", "test"));
+  }
+
+  @Test
+  void testRoleInfoWithNullSecurableObjects() {
+    RoleInfo roleInfo = new RoleInfo("test_role", ImmutableMap.of("comment", 
"test comment"), null);
+    Assertions.assertEquals("test_role", roleInfo.roleName());
+    Assertions.assertEquals(ImmutableMap.of("comment", "test comment"), 
roleInfo.properties());
+    Assertions.assertThrows(
+        UnsupportedOperationException.class, () -> 
roleInfo.properties().put("testKey", "testVal"));
+    Assertions.assertEquals(Collections.emptyList(), 
roleInfo.securableObjects());
+    Assertions.assertThrows(
+        UnsupportedOperationException.class, () -> 
roleInfo.securableObjects().add(null));
   }
 
   @Test
@@ -142,6 +160,50 @@ public class TestRoleEvent {
     validateRoleInfo(roleInfo, roleObject);
   }
 
+  @Test
+  void testCreateRoleFailureEvent() {
+    Assertions.assertThrowsExactly(
+        GravitinoRuntimeException.class,
+        () -> failureDispatcher.createRole(METALAKE, roleName, properties, 
securableObjects));
+
+    // validate event
+    Event event = dummyEventListener.popPostEvent();
+    Assertions.assertEquals(CreateRoleFailureEvent.class, event.getClass());
+    Assertions.assertEquals(OperationStatus.FAILURE, event.operationStatus());
+    Assertions.assertEquals(OperationType.CREATE_ROLE, event.operationType());
+
+    CreateRoleFailureEvent createRoleFailureEvent = (CreateRoleFailureEvent) 
event;
+    Assertions.assertEquals(
+        NameIdentifierUtil.ofRole(METALAKE, roleName), 
createRoleFailureEvent.identifier());
+    RoleInfo roleInfo = createRoleFailureEvent.createRoleRequest();
+    Assertions.assertEquals(roleName, roleInfo.roleName());
+    Assertions.assertEquals(properties, roleInfo.properties());
+    Assertions.assertEquals(securableObjects, roleInfo.securableObjects());
+  }
+
+  @Test
+  void testCreateRoleFailureEventWithNullSecurableObjects() {
+    Assertions.assertThrowsExactly(
+        GravitinoRuntimeException.class,
+        () -> failureDispatcher.createRole(METALAKE, roleName, properties, 
null));
+
+    // Validate event
+    Event event = dummyEventListener.popPostEvent();
+    Assertions.assertEquals(CreateRoleFailureEvent.class, event.getClass());
+    Assertions.assertEquals(OperationStatus.FAILURE, event.operationStatus());
+    CreateRoleFailureEvent createRoleFailureEvent = (CreateRoleFailureEvent) 
event;
+    Assertions.assertEquals(
+        NameIdentifierUtil.ofRole(METALAKE, roleName), 
createRoleFailureEvent.identifier());
+
+    RoleInfo roleInfo = createRoleFailureEvent.createRoleRequest();
+    Assertions.assertEquals(roleName, roleInfo.roleName());
+    Assertions.assertEquals(properties, roleInfo.properties());
+    Assertions.assertNotNull(roleInfo.securableObjects());
+    Assertions.assertTrue(roleInfo.securableObjects().isEmpty());
+    Assertions.assertThrows(
+        UnsupportedOperationException.class, () -> 
roleInfo.securableObjects().add(null));
+  }
+
   @Test
   void testDeleteRolePreEvent() {
     dispatcher.deleteRole(METALAKE, roleName);
@@ -191,6 +253,23 @@ public class TestRoleEvent {
     Assertions.assertEquals(otherRoleName, deleteRoleEvent.roleName());
   }
 
+  @Test
+  void testDeleteRoleFailureEvent() {
+    Assertions.assertThrowsExactly(
+        GravitinoRuntimeException.class, () -> 
failureDispatcher.deleteRole(METALAKE, roleName));
+
+    // validate event
+    Event event = dummyEventListener.popPostEvent();
+    Assertions.assertEquals(DeleteRoleFailureEvent.class, event.getClass());
+    Assertions.assertEquals(OperationStatus.FAILURE, event.operationStatus());
+    Assertions.assertEquals(OperationType.DELETE_ROLE, event.operationType());
+
+    DeleteRoleFailureEvent deleteRoleFailureEvent = (DeleteRoleFailureEvent) 
event;
+    Assertions.assertEquals(
+        NameIdentifierUtil.ofRole(METALAKE, roleName), 
deleteRoleFailureEvent.identifier());
+    Assertions.assertEquals(roleName, deleteRoleFailureEvent.roleName());
+  }
+
   @Test
   void testGetRolePreEvent() {
     dispatcher.getRole(METALAKE, roleName);
@@ -225,6 +304,23 @@ public class TestRoleEvent {
     validateRoleInfo(roleInfo, roleName, properties, securableObjects);
   }
 
+  @Test
+  void testGetRoleFailureEvent() {
+    Assertions.assertThrowsExactly(
+        GravitinoRuntimeException.class, () -> 
failureDispatcher.getRole(METALAKE, roleName));
+
+    // validate event
+    Event event = dummyEventListener.popPostEvent();
+    Assertions.assertEquals(GetRoleFailureEvent.class, event.getClass());
+    Assertions.assertEquals(OperationStatus.FAILURE, event.operationStatus());
+    Assertions.assertEquals(OperationType.GET_ROLE, event.operationType());
+
+    GetRoleFailureEvent getRoleFailureEvent = (GetRoleFailureEvent) event;
+    Assertions.assertEquals(
+        NameIdentifierUtil.ofRole(METALAKE, roleName), 
getRoleFailureEvent.identifier());
+    Assertions.assertEquals(roleName, getRoleFailureEvent.roleName());
+  }
+
   @Test
   void testListRolesPreEvent() {
     dispatcher.listRoleNames(METALAKE);
@@ -255,6 +351,22 @@ public class TestRoleEvent {
     Assertions.assertFalse(listRoleNamesEvent.object().isPresent());
   }
 
+  @Test
+  void testListRolesFailureEvent() {
+    Assertions.assertThrowsExactly(
+        GravitinoRuntimeException.class, () -> 
failureDispatcher.listRoleNames(METALAKE));
+
+    // validate event
+    Event event = dummyEventListener.popPostEvent();
+    Assertions.assertEquals(ListRoleNamesFailureEvent.class, event.getClass());
+    Assertions.assertEquals(OperationStatus.FAILURE, event.operationStatus());
+    Assertions.assertEquals(OperationType.LIST_ROLE_NAMES, 
event.operationType());
+
+    ListRoleNamesFailureEvent listRoleNamesFailureEvent = 
(ListRoleNamesFailureEvent) event;
+    Assertions.assertEquals(identifier, 
listRoleNamesFailureEvent.identifier());
+    
Assertions.assertFalse(listRoleNamesFailureEvent.metadataObject().isPresent());
+  }
+
   @Test
   void testListRolesFromObjectPreEvent() {
     dispatcher.listRoleNamesByObject(METALAKE, securableObjects.get(0));
@@ -288,7 +400,26 @@ public class TestRoleEvent {
   }
 
   @Test
-  void testGrantPrivilegesToRole() {
+  void testListRoleFromObjectFailureEvent() {
+    Assertions.assertThrowsExactly(
+        GravitinoRuntimeException.class,
+        () -> failureDispatcher.listRoleNamesByObject(METALAKE, 
securableObjects.get(0)));
+
+    // validate event
+    Event event = dummyEventListener.popPostEvent();
+    Assertions.assertEquals(ListRoleNamesFailureEvent.class, event.getClass());
+    Assertions.assertEquals(OperationStatus.FAILURE, event.operationStatus());
+    Assertions.assertEquals(OperationType.LIST_ROLE_NAMES, 
event.operationType());
+
+    ListRoleNamesFailureEvent listRoleNamesFailureEvent = 
(ListRoleNamesFailureEvent) event;
+    Assertions.assertEquals(identifier, 
listRoleNamesFailureEvent.identifier());
+    
Assertions.assertTrue(listRoleNamesFailureEvent.metadataObject().isPresent());
+    Assertions.assertEquals(
+        securableObjects.get(0), 
listRoleNamesFailureEvent.metadataObject().get());
+  }
+
+  @Test
+  void testGrantPrivilegesToRolePreEvent() {
     dispatcher.grantPrivilegeToRole(METALAKE, roleName, metadataObject, 
privileges);
 
     // validate pre-event
@@ -322,6 +453,52 @@ public class TestRoleEvent {
     validateRoleInfo(roleInfo, roleName, properties, securableObjects);
   }
 
+  @Test
+  void testGrantPrivilegesToRoleFailureEvent() {
+    Assertions.assertThrowsExactly(
+        GravitinoRuntimeException.class,
+        () ->
+            failureDispatcher.grantPrivilegeToRole(METALAKE, roleName, 
metadataObject, privileges));
+
+    // validate event
+    Event event = dummyEventListener.popPostEvent();
+    Assertions.assertEquals(GrantPrivilegesFailureEvent.class, 
event.getClass());
+    Assertions.assertEquals(OperationStatus.FAILURE, event.operationStatus());
+    Assertions.assertEquals(OperationType.GRANT_PRIVILEGES, 
event.operationType());
+
+    GrantPrivilegesFailureEvent grantPrivilegesFailureEvent = 
(GrantPrivilegesFailureEvent) event;
+    Assertions.assertEquals(
+        NameIdentifierUtil.ofRole(METALAKE, roleName), 
grantPrivilegesFailureEvent.identifier());
+    Assertions.assertEquals(roleName, grantPrivilegesFailureEvent.roleName());
+    Assertions.assertEquals(metadataObject, 
grantPrivilegesFailureEvent.object());
+    Assertions.assertEquals(privileges, 
grantPrivilegesFailureEvent.privileges());
+  }
+
+  @Test
+  void testGrantPrivilegesFailureEventWithNullPrivileges() {
+    Assertions.assertThrowsExactly(
+        GravitinoRuntimeException.class,
+        () -> failureDispatcher.grantPrivilegeToRole(METALAKE, roleName, 
metadataObject, null));
+
+    // validate event
+    Event event = dummyEventListener.popPostEvent();
+    Assertions.assertEquals(GrantPrivilegesFailureEvent.class, 
event.getClass());
+    Assertions.assertEquals(OperationStatus.FAILURE, event.operationStatus());
+    Assertions.assertEquals(OperationType.GRANT_PRIVILEGES, 
event.operationType());
+
+    GrantPrivilegesFailureEvent grantPrivilegesFailureEvent = 
(GrantPrivilegesFailureEvent) event;
+    Assertions.assertEquals(
+        NameIdentifierUtil.ofRole(METALAKE, roleName), 
grantPrivilegesFailureEvent.identifier());
+    Assertions.assertEquals(roleName, grantPrivilegesFailureEvent.roleName());
+    Assertions.assertEquals(metadataObject, 
grantPrivilegesFailureEvent.object());
+    Assertions.assertNotNull(grantPrivilegesFailureEvent.privileges());
+    Assertions.assertTrue(grantPrivilegesFailureEvent.privileges().isEmpty());
+
+    Assertions.assertThrows(
+        UnsupportedOperationException.class,
+        () -> grantPrivilegesFailureEvent.privileges().add(null));
+  }
+
   @Test
   void testRevokePrivilegesFromRolePreEvent() {
     dispatcher.revokePrivilegesFromRole(METALAKE, roleName, metadataObject, 
privileges);
@@ -357,6 +534,29 @@ public class TestRoleEvent {
     validateRoleInfo(roleInfo, roleName, properties, securableObjects);
   }
 
+  @Test
+  void testRevokePrivilegesFromRoleFailureEvent() {
+    Assertions.assertThrowsExactly(
+        GravitinoRuntimeException.class,
+        () ->
+            failureDispatcher.revokePrivilegesFromRole(
+                METALAKE, roleName, metadataObject, privileges));
+
+    // validate event
+    Event event = dummyEventListener.popPostEvent();
+    Assertions.assertEquals(RevokePrivilegesFailureEvent.class, 
event.getClass());
+    Assertions.assertEquals(OperationStatus.FAILURE, event.operationStatus());
+    Assertions.assertEquals(OperationType.REVOKE_PRIVILEGES, 
event.operationType());
+
+    RevokePrivilegesFailureEvent revokePrivilegesFailureEvent =
+        (RevokePrivilegesFailureEvent) event;
+    Assertions.assertEquals(
+        NameIdentifierUtil.ofRole(METALAKE, roleName), 
revokePrivilegesFailureEvent.identifier());
+    Assertions.assertEquals(roleName, revokePrivilegesFailureEvent.roleName());
+    Assertions.assertEquals(metadataObject, 
revokePrivilegesFailureEvent.metadataObject());
+    Assertions.assertEquals(privileges, 
revokePrivilegesFailureEvent.privileges());
+  }
+
   private AccessControlEventDispatcher mockRoleDispatcher() {
     AccessControlEventDispatcher dispatcher = 
mock(AccessControlEventDispatcher.class);
     Group mockGroup = getMockGroup(groupName, ImmutableList.of(roleName, 
otherRoleName));
diff --git a/docs/gravitino-server-config.md b/docs/gravitino-server-config.md
index de56789997..5c41b8aa3c 100644
--- a/docs/gravitino-server-config.md
+++ b/docs/gravitino-server-config.md
@@ -118,20 +118,20 @@ Gravitino triggers a pre-event before the operation, a 
post-event after the comp
 
 ##### Post-event
 
-| Operation type                      | Post-event                             
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
              [...]
-|-------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 [...]
-| table operation                     | `CreateTableEvent`, `AlterTableEvent`, 
`DropTableEvent`, `LoadTableEvent`, `ListTableEvent`, `PurgeTableFailureEvent`, 
`CreateTableFailureEvent`, `AlterTableFailureEvent`, `DropTableFailureEvent`, 
`LoadTableFailureEvent`, `ListTableFailureEvent`, `PurgeTableFailureEvent`      
                                                                                
                                                                                
                [...]
-| fileset operation                   | `CreateFileSetEvent`, 
`AlterFileSetEvent`, `DropFileSetEvent`, `LoadFileSetEvent`, 
`ListFileSetEvent`, `CreateFileSetFailureEvent`, `AlterFileSetFailureEvent`, 
`DropFileSetFailureEvent`, `LoadFileSetFailureEvent`, `ListFileSetFailureEvent` 
                                                                                
                                                                                
                                                     [...]
-| topic operation                     | `CreateTopicEvent`, `AlterTopicEvent`, 
`DropTopicEvent`, `LoadTopicEvent`, `ListTopicEvent`, 
`CreateTopicFailureEvent`, `AlterTopicFailureEvent`, `DropTopicFailureEvent`, 
`LoadTopicFailureEvent`, `ListTopicFailureEvent`                                
                                                                                
                                                                                
                                          [...]
-| schema operation                    | `CreateSchemaEvent`, 
`AlterSchemaEvent`, `DropSchemaEvent`, `LoadSchemaEvent`, `ListSchemaEvent`, 
`CreateSchemaFailureEvent`, `AlterSchemaFailureEvent`, 
`DropSchemaFailureEvent`, `LoadSchemaFailureEvent`, `ListSchemaFailureEvent`    
                                                                                
                                                                                
                                                            [...]
-| catalog operation                   | `CreateCatalogEvent`, 
`AlterCatalogEvent`, `DropCatalogEvent`, `LoadCatalogEvent`, 
`ListCatalogEvent`, `CreateCatalogFailureEvent`, `AlterCatalogFailureEvent`, 
`DropCatalogFailureEvent`, `LoadCatalogFailureEvent`, `ListCatalogFailureEvent` 
                                                                                
                                                                                
                                                     [...]
-| metalake operation                  | `CreateMetalakeEvent`, 
`AlterMetalakeEvent`, `DropMetalakeEvent`, `LoadMetalakeEvent`, 
`ListMetalakeEvent`, `CreateMetalakeFailureEvent`, `AlterMetalakeFailureEvent`, 
`DropMetalakeFailureEvent`, `LoadMetalakeFailureEvent`, 
`ListMetalakeFailureEvent`                                                      
                                                                                
                                                                      [...]
-| Iceberg REST server table operation | `IcebergCreateTableEvent`, 
`IcebergUpdateTableEvent`, `IcebergDropTableEvent`, `IcebergLoadTableEvent`, 
`IcebergListTableEvent`, `IcebergTableExistsEvent`, `IcebergRenameTableEvent`, 
`IcebergCreateTableFailureEvent`, `IcebergUpdateTableFailureEvent`, 
`IcebergDropTableFailureEvent`, `IcebergLoadTableFailureEvent`, 
`IcebergListTableFailureEvent`, `IcebergRenameTableFailureEvent`, 
`IcebergTableExistsFailureEvent`                                        [...]
+| Operation type                      | Post-event                             
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
              [...]
+|-------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 [...]
+| table operation                     | `CreateTableEvent`, `AlterTableEvent`, 
`DropTableEvent`, `LoadTableEvent`, `ListTableEvent`, `PurgeTableFailureEvent`, 
`CreateTableFailureEvent`, `AlterTableFailureEvent`, `DropTableFailureEvent`, 
`LoadTableFailureEvent`, `ListTableFailureEvent`, `PurgeTableFailureEvent`      
                                                                                
                                                                                
                [...]
+| fileset operation                   | `CreateFileSetEvent`, 
`AlterFileSetEvent`, `DropFileSetEvent`, `LoadFileSetEvent`, 
`ListFileSetEvent`, `CreateFileSetFailureEvent`, `AlterFileSetFailureEvent`, 
`DropFileSetFailureEvent`, `LoadFileSetFailureEvent`, `ListFileSetFailureEvent` 
                                                                                
                                                                                
                                                     [...]
+| topic operation                     | `CreateTopicEvent`, `AlterTopicEvent`, 
`DropTopicEvent`, `LoadTopicEvent`, `ListTopicEvent`, 
`CreateTopicFailureEvent`, `AlterTopicFailureEvent`, `DropTopicFailureEvent`, 
`LoadTopicFailureEvent`, `ListTopicFailureEvent`                                
                                                                                
                                                                                
                                          [...]
+| schema operation                    | `CreateSchemaEvent`, 
`AlterSchemaEvent`, `DropSchemaEvent`, `LoadSchemaEvent`, `ListSchemaEvent`, 
`CreateSchemaFailureEvent`, `AlterSchemaFailureEvent`, 
`DropSchemaFailureEvent`, `LoadSchemaFailureEvent`, `ListSchemaFailureEvent`    
                                                                                
                                                                                
                                                            [...]
+| catalog operation                   | `CreateCatalogEvent`, 
`AlterCatalogEvent`, `DropCatalogEvent`, `LoadCatalogEvent`, 
`ListCatalogEvent`, `CreateCatalogFailureEvent`, `AlterCatalogFailureEvent`, 
`DropCatalogFailureEvent`, `LoadCatalogFailureEvent`, `ListCatalogFailureEvent` 
                                                                                
                                                                                
                                                     [...]
+| metalake operation                  | `CreateMetalakeEvent`, 
`AlterMetalakeEvent`, `DropMetalakeEvent`, `LoadMetalakeEvent`, 
`ListMetalakeEvent`, `CreateMetalakeFailureEvent`, `AlterMetalakeFailureEvent`, 
`DropMetalakeFailureEvent`, `LoadMetalakeFailureEvent`, 
`ListMetalakeFailureEvent`                                                      
                                                                                
                                                                      [...]
+| Iceberg REST server table operation | `IcebergCreateTableEvent`, 
`IcebergUpdateTableEvent`, `IcebergDropTableEvent`, `IcebergLoadTableEvent`, 
`IcebergListTableEvent`, `IcebergTableExistsEvent`, `IcebergRenameTableEvent`, 
`IcebergCreateTableFailureEvent`, `IcebergUpdateTableFailureEvent`, 
`IcebergDropTableFailureEvent`, `IcebergLoadTableFailureEvent`, 
`IcebergListTableFailureEvent`, `IcebergRenameTableFailureEvent`, 
`IcebergTableExistsFailureEvent`                                        [...]
 | tag operation                       | `ListTagsEvent`, `ListTagsInfoEvent`, 
`CreateTagEvent`, `GetTagEvent`, `AlterTagEvent`, `DeleteTagEvent`, 
`ListMetadataObjectsForTagEvent`, `ListTagsForMetadataObjectEvent`, 
`ListTagsInfoForMetadataObjectEvent`, `AssociateTagsForMetadataObjectEvent`, 
`GetTagForMetadataObjectEvent`, `ListTagsFailureEvent`, 
`ListTagInfoFailureEvent`, `CreateTagFailureEvent`, `GetTagFailureEvent`, 
`AlterTagFailureEvent`, `DeleteTagFailureEvent`, `ListMetadataObjectsFo [...]
-| model operation                     | `DeleteModelEvent`,  
`DeleteModelVersionEvent`,  `GetModelEvent`, `GetModelVersionEvent`, 
`LinkModelVersionEvent`, `ListModelEvent`, `ListModelVersionsEvent`,  
`RegisterAndLinkModelEvent`, `RegisterModelEvent`,  `DeleteModelFailureEvent`, 
`DeleteModelVersionFailureEvent`, `GetModelFailureEvent`, 
`GetModelVersionFailureEvent`, `LinkModelVersionFailureEvent`, 
`ListModelFailureEvent`, `ListModelVersionFailureEvent`, 
`RegisterAndLinkModelFailureEvent`, [...]
-| user operation                      | `AddUserEvent`, `GetUserEvent`, 
`ListUserNamesEvent`, `ListUsersEvent`, `RemoveUserEvent`, 
`GrantUserRolesEvent`, `RevokeUserRolesEvent`, `AddUserFailureEvent`, 
`GetUserFailureEvent`, `GrantUserRolesFailureEvent`, 
`ListUserNamesFailureEvent`, `ListUsersFailureEvent`, `RemoveUserFailureEvent`, 
`RevokeUserRolesFailureEvent`                                                   
                                                                               
[...]
-| group operation                     | `AddGroupEvent`, `GetGroupEvent`, 
`ListGroupNamesEvent`, `ListGroupsEvent`, `RemoveGroupEvent`, 
`GrantGroupRolesEvent`, `RevokeGroupRolesEvent`, `AddGroupFailureEvent`, 
`GetGroupFailureEvent`, `GrantGroupRolesFailureEvent`, 
`ListGroupNamesFailureEvent`, `ListGroupsFailureEvent`, 
`RemoveGroupFailureEvent`, `RevokeGroupRolesFailureEvent`                       
                                                                                
             [...]
-| role operation                      | `CreateRoleEvent`, `DeleteRoleEvent`, 
`GetRoleEvent`, `GrantPrivilegesEvent`, `ListRoleNamesEvent`, 
`RevokePrivilegesEvent`                                                         
                                                                                
                                                                                
                                                                                
                                 [...]
+| model operation                     | `DeleteModelEvent`,  
`DeleteModelVersionEvent`,  `GetModelEvent`, `GetModelVersionEvent`, 
`LinkModelVersionEvent`, `ListModelEvent`, `ListModelVersionsEvent`,  
`RegisterAndLinkModelEvent`, `RegisterModelEvent`,  `DeleteModelFailureEvent`, 
`DeleteModelVersionFailureEvent`, `GetModelFailureEvent`, 
`GetModelVersionFailureEvent`, `LinkModelVersionFailureEvent`, 
`ListModelFailureEvent`, `ListModelVersionFailureEvent`, 
`RegisterAndLinkModelFailureEvent`, [...]
+| user operation                      | `AddUserEvent`, `GetUserEvent`, 
`ListUserNamesEvent`, `ListUsersEvent`, `RemoveUserEvent`, 
`GrantUserRolesEvent`, `RevokeUserRolesEvent`, `AddUserFailureEvent`, 
`GetUserFailureEvent`, `GrantUserRolesFailureEvent`, 
`ListUserNamesFailureEvent`, `ListUsersFailureEvent`, `RemoveUserFailureEvent`, 
`RevokeUserRolesFailureEvent`                                                   
                                                                               
[...]
+| group operation                     | `AddGroupEvent`, `GetGroupEvent`, 
`ListGroupNamesEvent`, `ListGroupsEvent`, `RemoveGroupEvent`, 
`GrantGroupRolesEvent`, `RevokeGroupRolesEvent`, `AddGroupFailureEvent`, 
`GetGroupFailureEvent`, `GrantGroupRolesFailureEvent`, 
`ListGroupNamesFailureEvent`, `ListGroupsFailureEvent`, 
`RemoveGroupFailureEvent`, `RevokeGroupRolesFailureEvent`                       
                                                                                
             [...]
+| role operation                      | `CreateRoleEvent`, `DeleteRoleEvent`, 
`GetRoleEvent`, `GrantPrivilegesEvent`, `ListRoleNamesEvent`, 
`RevokePrivilegesEvent`, `CreateRoleFailureEvent`, `DeleteRoleFailureEvent`, 
`GetRoleFailureEvent`, `GrantPrivilegesFailureEvent`, 
`ListRoleNamesFailureEvent`, `RevokePrivilegesFailureEvent`                     
                                                                                
                                                              [...]
 
 
 

Reply via email to