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 6cbf907e9a [#6741] feat(core): Support group event to Gravitino server
(#6801)
6cbf907e9a is described below
commit 6cbf907e9ac2c32349208ab1bd6c2ed36c29abe9
Author: Lord of Abyss <[email protected]>
AuthorDate: Wed Apr 2 08:39:06 2025 +0800
[#6741] feat(core): Support group event to Gravitino server (#6801)
### What changes were proposed in this pull request?
Support group event to Gravitino server.
### Why are the changes needed?
Fix: #6741
### Does this PR introduce _any_ user-facing change?
Users can now listen for the User Event.
### How was this patch tested?
local test.
---
.../api/event/AccessControlEventDispatcher.java | 64 +++++--
.../{AddGroupPreEvent.java => AddGroupEvent.java} | 35 ++--
.../listener/api/event/AddGroupPreEvent.java | 18 +-
.../{GetGroupPreEvent.java => GetGroupEvent.java} | 35 ++--
.../listener/api/event/GetGroupPreEvent.java | 18 +-
.../listener/api/event/GrantGroupRolesEvent.java | 77 ++++++++
...pPreEvent.java => GrantGroupRolesPreEvent.java} | 40 ++--
.../{ListGroupsPreEvent.java => GroupEvent.java} | 30 +--
...NamesPreEvent.java => ListGroupNamesEvent.java} | 16 +-
.../listener/api/event/ListGroupNamesPreEvent.java | 12 +-
...istGroupsPreEvent.java => ListGroupsEvent.java} | 17 +-
.../listener/api/event/ListGroupsPreEvent.java | 14 +-
.../listener/api/event/OperationType.java | 2 +
.../listener/api/event/RemoveGroupEvent.java | 77 ++++++++
.../listener/api/event/RemoveGroupPreEvent.java | 19 +-
.../listener/api/event/RevokeGroupRolesEvent.java | 78 ++++++++
.../api/event/RevokeGroupRolesPreEvent.java | 75 ++++++++
.../GroupInfo.java} | 40 ++--
.../apache/gravitino/utils/NameIdentifierUtil.java | 11 ++
.../org/apache/gravitino/utils/NamespaceUtil.java | 10 +
.../listener/api/event/TestGroupEvent.java | 212 ++++++++++++++++++++-
.../gravitino/utils/TestNameIdentifierUtil.java | 19 +-
.../apache/gravitino/utils/TestNamespaceUtil.java | 24 +++
docs/gravitino-server-config.md | 8 +-
24 files changed, 795 insertions(+), 156 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 9004f7fa70..2cb3bcd8fb 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
@@ -23,7 +23,6 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.gravitino.MetadataObject;
-import org.apache.gravitino.NameIdentifier;
import org.apache.gravitino.authorization.AccessControlDispatcher;
import org.apache.gravitino.authorization.Group;
import org.apache.gravitino.authorization.Privilege;
@@ -40,6 +39,7 @@ import org.apache.gravitino.exceptions.NoSuchUserException;
import org.apache.gravitino.exceptions.RoleAlreadyExistsException;
import org.apache.gravitino.exceptions.UserAlreadyExistsException;
import org.apache.gravitino.listener.EventBus;
+import org.apache.gravitino.listener.api.info.GroupInfo;
import org.apache.gravitino.listener.api.info.UserInfo;
import org.apache.gravitino.utils.PrincipalUtils;
@@ -155,11 +155,14 @@ public class AccessControlEventDispatcher implements
AccessControlDispatcher {
@Override
public Group addGroup(String metalake, String group)
throws GroupAlreadyExistsException, NoSuchMetalakeException {
+ String initiator = PrincipalUtils.getCurrentUserName();
+
+ eventBus.dispatchEvent(new AddGroupPreEvent(initiator, metalake, group));
try {
- String initiator = PrincipalUtils.getCurrentUserName();
+ Group groupObject = dispatcher.addGroup(metalake, group);
+ eventBus.dispatchEvent(new AddGroupEvent(initiator, metalake, new
GroupInfo(groupObject)));
- eventBus.dispatchEvent(new AddGroupPreEvent(initiator,
NameIdentifier.of(metalake), group));
- return dispatcher.addGroup(metalake, group);
+ return groupObject;
} catch (Exception e) {
// TODO: add failure event
throw e;
@@ -169,12 +172,14 @@ public class AccessControlEventDispatcher implements
AccessControlDispatcher {
/** {@inheritDoc} */
@Override
public boolean removeGroup(String metalake, String group) throws
NoSuchMetalakeException {
+ String initiator = PrincipalUtils.getCurrentUserName();
+
+ eventBus.dispatchEvent(new RemoveGroupPreEvent(initiator, metalake,
group));
try {
- String initiator = PrincipalUtils.getCurrentUserName();
+ boolean isExists = dispatcher.removeGroup(metalake, group);
+ eventBus.dispatchEvent(new RemoveGroupEvent(initiator, metalake, group,
isExists));
- eventBus.dispatchEvent(
- new RemoveGroupPreEvent(initiator, NameIdentifier.of(metalake),
group));
- return dispatcher.removeGroup(metalake, group);
+ return isExists;
} catch (Exception e) {
// TODO: add failure event
throw e;
@@ -187,9 +192,12 @@ public class AccessControlEventDispatcher implements
AccessControlDispatcher {
throws NoSuchGroupException, NoSuchMetalakeException {
String initiator = PrincipalUtils.getCurrentUserName();
- eventBus.dispatchEvent(new GetGroupPreEvent(initiator,
NameIdentifier.of(metalake), group));
+ eventBus.dispatchEvent(new GetGroupPreEvent(initiator, metalake, group));
try {
- return dispatcher.getGroup(metalake, group);
+ Group groupObject = dispatcher.getGroup(metalake, group);
+ eventBus.dispatchEvent(new GetGroupEvent(initiator, metalake, new
GroupInfo(groupObject)));
+
+ return groupObject;
} catch (Exception e) {
// TODO: add failure event
throw e;
@@ -201,10 +209,12 @@ public class AccessControlEventDispatcher implements
AccessControlDispatcher {
public Group[] listGroups(String metalake) {
String initiator = PrincipalUtils.getCurrentUserName();
- eventBus.dispatchEvent(new ListGroupsPreEvent(initiator,
NameIdentifier.of(metalake)));
+ eventBus.dispatchEvent(new ListGroupsPreEvent(initiator, metalake));
try {
- // TODO: add Event
- return dispatcher.listGroups(metalake);
+ Group[] groups = dispatcher.listGroups(metalake);
+ eventBus.dispatchEvent(new ListGroupsEvent(initiator, metalake));
+
+ return groups;
} catch (Exception e) {
// TODO: add failure event
throw e;
@@ -216,10 +226,12 @@ public class AccessControlEventDispatcher implements
AccessControlDispatcher {
public String[] listGroupNames(String metalake) {
String initiator = PrincipalUtils.getCurrentUserName();
- eventBus.dispatchEvent(new ListGroupNamesPreEvent(initiator,
NameIdentifier.of(metalake)));
+ eventBus.dispatchEvent(new ListGroupNamesPreEvent(initiator, metalake));
try {
- // TODO: add Event
- return dispatcher.listGroupNames(metalake);
+ String[] groupNames = dispatcher.listGroupNames(metalake);
+ eventBus.dispatchEvent(new ListGroupNamesEvent(initiator, metalake));
+
+ return groupNames;
} catch (Exception e) {
// TODO: add failure event
throw e;
@@ -249,9 +261,15 @@ public class AccessControlEventDispatcher implements
AccessControlDispatcher {
@Override
public Group grantRolesToGroup(String metalake, List<String> roles, String
group)
throws NoSuchGroupException, IllegalRoleException,
NoSuchMetalakeException {
+ String initiator = PrincipalUtils.getCurrentUserName();
+
+ eventBus.dispatchEvent(new GrantGroupRolesPreEvent(initiator, metalake,
group, roles));
try {
- // TODO: add Event
- return dispatcher.grantRolesToGroup(metalake, roles, group);
+ Group groupObject = dispatcher.grantRolesToGroup(metalake, roles, group);
+ eventBus.dispatchEvent(
+ new GrantGroupRolesEvent(initiator, metalake, new
GroupInfo(groupObject), roles));
+
+ return groupObject;
} catch (Exception e) {
// TODO: add failure event
throw e;
@@ -262,9 +280,15 @@ public class AccessControlEventDispatcher implements
AccessControlDispatcher {
@Override
public Group revokeRolesFromGroup(String metalake, List<String> roles,
String group)
throws NoSuchGroupException, IllegalRoleException,
NoSuchMetalakeException {
+ String initiator = PrincipalUtils.getCurrentUserName();
+
+ eventBus.dispatchEvent(new RevokeGroupRolesPreEvent(initiator, metalake,
group, roles));
try {
- // TODO: add Event
- return dispatcher.revokeRolesFromGroup(metalake, roles, group);
+ Group groupObject = dispatcher.revokeRolesFromGroup(metalake, roles,
group);
+ eventBus.dispatchEvent(
+ new RevokeGroupRolesEvent(initiator, metalake, new
GroupInfo(groupObject), roles));
+
+ return groupObject;
} catch (Exception e) {
// TODO: add failure event
throw e;
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/AddGroupPreEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/AddGroupEvent.java
similarity index 51%
copy from
core/src/main/java/org/apache/gravitino/listener/api/event/AddGroupPreEvent.java
copy to
core/src/main/java/org/apache/gravitino/listener/api/event/AddGroupEvent.java
index 85594ef31a..248111915f 100644
---
a/core/src/main/java/org/apache/gravitino/listener/api/event/AddGroupPreEvent.java
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/AddGroupEvent.java
@@ -19,41 +19,42 @@
package org.apache.gravitino.listener.api.event;
-import org.apache.gravitino.NameIdentifier;
import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.info.GroupInfo;
+import org.apache.gravitino.utils.NameIdentifierUtil;
-/** Represents an event triggered before add a group to a metalake. */
+/** Represents an event triggered when a group is successfully added to a
metalake. */
@DeveloperApi
-public class AddGroupPreEvent extends GroupPreEvent {
- private final String groupName;
+public class AddGroupEvent extends GroupEvent {
+ private final GroupInfo addedGroupInfo;
/**
- * Construct a new {@link AddGroupPreEvent} instance with the given
initiator, identifier and
- * group name.
+ * Constructs a new {@link AddGroupEvent} with the specified initiator,
metalake name, and group
+ * information.
*
* @param initiator the user who initiated the add-group request.
- * @param identifier the identifier of the metalake which the group is being
added to.
- * @param groupName the group name which is requested to be added to the
metalake.
+ * @param metalake the name of the metalake where the group was added.
+ * @param addedGroupInfo the information about the group that was added.
*/
- protected AddGroupPreEvent(String initiator, NameIdentifier identifier,
String groupName) {
- super(initiator, identifier);
+ protected AddGroupEvent(String initiator, String metalake, GroupInfo
addedGroupInfo) {
+ super(initiator, NameIdentifierUtil.ofGroup(metalake,
addedGroupInfo.name()));
- this.groupName = groupName;
+ this.addedGroupInfo = addedGroupInfo;
}
/**
- * Returns the group information which is being added to the metalake.
+ * Retrieves the {@link GroupInfo} of the group that was added to the
metalake.
*
- * @return the group name which is requested to be added to the metalake.
+ * @return the {@link GroupInfo} object containing details of the added
group.
*/
- public String groupName() {
- return groupName;
+ public GroupInfo addedGroupInfo() {
+ return addedGroupInfo;
}
/**
- * Returns the operation type of this event.
+ * Returns the operation type for this event.
*
- * @return the operation type.
+ * @return the operation type for this event.
*/
@Override
public OperationType operationType() {
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/AddGroupPreEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/AddGroupPreEvent.java
index 85594ef31a..f0a8df36ee 100644
---
a/core/src/main/java/org/apache/gravitino/listener/api/event/AddGroupPreEvent.java
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/AddGroupPreEvent.java
@@ -19,32 +19,32 @@
package org.apache.gravitino.listener.api.event;
-import org.apache.gravitino.NameIdentifier;
import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.utils.NameIdentifierUtil;
-/** Represents an event triggered before add a group to a metalake. */
+/** Represents an event triggered before a group is added to a metalake. */
@DeveloperApi
public class AddGroupPreEvent extends GroupPreEvent {
private final String groupName;
/**
- * Construct a new {@link AddGroupPreEvent} instance with the given
initiator, identifier and
+ * Constructs a new {@link AddGroupPreEvent} with the specified initiator,
metalake name, and
* group name.
*
* @param initiator the user who initiated the add-group request.
- * @param identifier the identifier of the metalake which the group is being
added to.
- * @param groupName the group name which is requested to be added to the
metalake.
+ * @param metalake the name of the metalake where the group is to be added.
+ * @param groupName the name of the group that is requested to be added to
the metalake.
*/
- protected AddGroupPreEvent(String initiator, NameIdentifier identifier,
String groupName) {
- super(initiator, identifier);
+ protected AddGroupPreEvent(String initiator, String metalake, String
groupName) {
+ super(initiator, NameIdentifierUtil.ofGroup(metalake, groupName));
this.groupName = groupName;
}
/**
- * Returns the group information which is being added to the metalake.
+ * Retrieves the name of the group that is being requested to be added to
the metalake.
*
- * @return the group name which is requested to be added to the metalake.
+ * @return the name of the group to be added.
*/
public String groupName() {
return groupName;
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/GetGroupPreEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/GetGroupEvent.java
similarity index 51%
copy from
core/src/main/java/org/apache/gravitino/listener/api/event/GetGroupPreEvent.java
copy to
core/src/main/java/org/apache/gravitino/listener/api/event/GetGroupEvent.java
index ea09c34d85..05c7d54e43 100644
---
a/core/src/main/java/org/apache/gravitino/listener/api/event/GetGroupPreEvent.java
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/GetGroupEvent.java
@@ -19,35 +19,38 @@
package org.apache.gravitino.listener.api.event;
-import org.apache.gravitino.NameIdentifier;
import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.info.GroupInfo;
+import org.apache.gravitino.utils.NameIdentifierUtil;
-/** Represents an event triggered before get a group from specific metalake */
+/**
+ * Represents an event triggered after a group is successfully retrieved from
a specific metalake.
+ */
@DeveloperApi
-public class GetGroupPreEvent extends GroupPreEvent {
- private final String groupName;
+public class GetGroupEvent extends GroupEvent {
+ private final GroupInfo loadedGroupInfo;
/**
- * Construct a new {@link GetGroupPreEvent} instance with the given
initiator and identifier and
- * group name.
+ * Constructs a new {@link GetGroupEvent} with the specified initiator,
metalake name, and group
+ * information.
*
- * @param initiator the user who initiated the get-group request.
- * @param identifier the identifier of the metalake which the group is
getting retrieved from.
- * @param groupName the group name which is requested to be retrieved.
+ * @param initiator the user who initiated the group retrieval request.
+ * @param metalake the name of the metalake from which the group is
retrieved.
+ * @param loadedGroupInfo the information of the group that was retrieved.
*/
- protected GetGroupPreEvent(String initiator, NameIdentifier identifier,
String groupName) {
- super(initiator, identifier);
+ protected GetGroupEvent(String initiator, String metalake, GroupInfo
loadedGroupInfo) {
+ super(initiator, NameIdentifierUtil.ofGroup(metalake,
loadedGroupInfo.name()));
- this.groupName = groupName;
+ this.loadedGroupInfo = loadedGroupInfo;
}
/**
- * Returns the group info for the group which is getting retrieved.
+ * Retrieves the {@link GroupInfo} of the group that was successfully
retrieved from the metalake.
*
- * @return the group name which is requested to be retrieved.
+ * @return the {@link GroupInfo} object containing details of the retrieved
group.
*/
- public String groupName() {
- return groupName;
+ public GroupInfo loadedGroupInfo() {
+ return loadedGroupInfo;
}
/**
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/GetGroupPreEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/GetGroupPreEvent.java
index ea09c34d85..fbc67fc0ea 100644
---
a/core/src/main/java/org/apache/gravitino/listener/api/event/GetGroupPreEvent.java
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/GetGroupPreEvent.java
@@ -19,32 +19,32 @@
package org.apache.gravitino.listener.api.event;
-import org.apache.gravitino.NameIdentifier;
import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.utils.NameIdentifierUtil;
-/** Represents an event triggered before get a group from specific metalake */
+/** Represents an event triggered before a group is retrieved from a specific
metalake. */
@DeveloperApi
public class GetGroupPreEvent extends GroupPreEvent {
private final String groupName;
/**
- * Construct a new {@link GetGroupPreEvent} instance with the given
initiator and identifier and
+ * Constructs a new {@link GetGroupPreEvent} with the specified initiator,
metalake name, and
* group name.
*
* @param initiator the user who initiated the get-group request.
- * @param identifier the identifier of the metalake which the group is
getting retrieved from.
- * @param groupName the group name which is requested to be retrieved.
+ * @param metalake the name of the metalake from which the group is being
retrieved.
+ * @param groupName the name of the group that is requested to be retrieved.
*/
- protected GetGroupPreEvent(String initiator, NameIdentifier identifier,
String groupName) {
- super(initiator, identifier);
+ protected GetGroupPreEvent(String initiator, String metalake, String
groupName) {
+ super(initiator, NameIdentifierUtil.ofGroup(metalake, groupName));
this.groupName = groupName;
}
/**
- * Returns the group info for the group which is getting retrieved.
+ * Retrieves the name of the group that is being requested to be retrieved.
*
- * @return the group name which is requested to be retrieved.
+ * @return the name of the group to be retrieved.
*/
public String groupName() {
return groupName;
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/GrantGroupRolesEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/GrantGroupRolesEvent.java
new file mode 100644
index 0000000000..04c754ed02
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/GrantGroupRolesEvent.java
@@ -0,0 +1,77 @@
+/*
+ * 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.ImmutableList;
+import java.util.List;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.info.GroupInfo;
+import org.apache.gravitino.utils.NameIdentifierUtil;
+
+/** Represents an event triggered after roles are granted to a group. */
+@DeveloperApi
+public class GrantGroupRolesEvent extends GroupEvent {
+ private final GroupInfo grantedGroupInfo;
+ private final List<String> roles;
+
+ /**
+ * Constructs a new {@link GrantGroupRolesEvent} with the specified
initiator, metalake name,
+ * group information, and granted roles.
+ *
+ * @param initiator the user who initiated the role-granting operation.
+ * @param metalake the name of the metalake where the operation takes place.
+ * @param grantedGroupInfo the group information of the group to which roles
are granted.
+ * @param roles the list of roles granted to the group.
+ */
+ public GrantGroupRolesEvent(
+ String initiator, String metalake, GroupInfo grantedGroupInfo,
List<String> roles) {
+ super(initiator, NameIdentifierUtil.ofGroup(metalake,
grantedGroupInfo.name()));
+ this.grantedGroupInfo = grantedGroupInfo;
+ this.roles = roles == null ? null : ImmutableList.copyOf(roles);
+ }
+
+ /**
+ * Retrieves the {@link GroupInfo} of the group to which roles have been
granted.
+ *
+ * @return the {@link GroupInfo} instance containing the details of the
granted group.
+ */
+ public GroupInfo grantedGroupInfo() {
+ return grantedGroupInfo;
+ }
+
+ /**
+ * Returns the list of roles that have been granted to the group.
+ *
+ * @return the list of roles granted to the group.
+ */
+ public List<String> roles() {
+ return roles;
+ }
+
+ /**
+ * Returns the operation type of this event.
+ *
+ * @return the operation type.
+ */
+ @Override
+ public OperationType operationType() {
+ return OperationType.GRANT_GROUP_ROLES;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/AddGroupPreEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/GrantGroupRolesPreEvent.java
similarity index 50%
copy from
core/src/main/java/org/apache/gravitino/listener/api/event/AddGroupPreEvent.java
copy to
core/src/main/java/org/apache/gravitino/listener/api/event/GrantGroupRolesPreEvent.java
index 85594ef31a..3777d1695c 100644
---
a/core/src/main/java/org/apache/gravitino/listener/api/event/AddGroupPreEvent.java
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/GrantGroupRolesPreEvent.java
@@ -19,37 +19,51 @@
package org.apache.gravitino.listener.api.event;
-import org.apache.gravitino.NameIdentifier;
+import java.util.List;
import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.utils.NameIdentifierUtil;
-/** Represents an event triggered before add a group to a metalake. */
+/** Represents an event triggered before roles are granted to a group. */
@DeveloperApi
-public class AddGroupPreEvent extends GroupPreEvent {
+public class GrantGroupRolesPreEvent extends GroupPreEvent {
private final String groupName;
+ private final List<String> roles;
/**
- * Construct a new {@link AddGroupPreEvent} instance with the given
initiator, identifier and
- * group name.
+ * Constructs a new {@link GrantGroupRolesPreEvent} with the specified
initiator, metalake name,
+ * group name, and roles to be granted.
*
- * @param initiator the user who initiated the add-group request.
- * @param identifier the identifier of the metalake which the group is being
added to.
- * @param groupName the group name which is requested to be added to the
metalake.
+ * @param initiator the user who initiated the role-granting event.
+ * @param metalake the name of the metalake where the operation will be
performed.
+ * @param groupName the name of the group to which roles will be granted.
+ * @param roles the list of roles to be granted to the group.
*/
- protected AddGroupPreEvent(String initiator, NameIdentifier identifier,
String groupName) {
- super(initiator, identifier);
+ public GrantGroupRolesPreEvent(
+ String initiator, String metalake, String groupName, List<String> roles)
{
+ super(initiator, NameIdentifierUtil.ofGroup(metalake, groupName));
this.groupName = groupName;
+ this.roles = roles;
}
/**
- * Returns the group information which is being added to the metalake.
+ * Retrieves the name of the group to which roles will be granted.
*
- * @return the group name which is requested to be added to the metalake.
+ * @return the name of the group.
*/
public String groupName() {
return groupName;
}
+ /**
+ * Returns the list of roles that are being granted to the group.
+ *
+ * @return the list of roles to be granted.
+ */
+ public List<String> roles() {
+ return roles;
+ }
+
/**
* Returns the operation type of this event.
*
@@ -57,6 +71,6 @@ public class AddGroupPreEvent extends GroupPreEvent {
*/
@Override
public OperationType operationType() {
- return OperationType.ADD_GROUP;
+ return OperationType.GRANT_GROUP_ROLES;
}
}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupsPreEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/GroupEvent.java
similarity index 52%
copy from
core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupsPreEvent.java
copy to
core/src/main/java/org/apache/gravitino/listener/api/event/GroupEvent.java
index 4461a04a03..1d9e2e2410 100644
---
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupsPreEvent.java
+++ b/core/src/main/java/org/apache/gravitino/listener/api/event/GroupEvent.java
@@ -22,26 +22,30 @@ package org.apache.gravitino.listener.api.event;
import org.apache.gravitino.NameIdentifier;
import org.apache.gravitino.annotation.DeveloperApi;
-/** Represents an event triggered before list groups from specific metalake */
+/**
+ * Represents an abstract base class for events related to group operations.
This class extends
+ * {@link Event} to provide a more specific context involving operations
performed by groups. It
+ * captures essential information including the user performing the operation
and the identifier of
+ * the metalake being operated on.
+ *
+ * <p>Concrete implementations of this class should provide additional details
pertinent to the
+ * specific type of group operation being represented.
+ */
@DeveloperApi
-public class ListGroupsPreEvent extends GroupPreEvent {
+public abstract class GroupEvent extends Event {
/**
- * Construct a new {@code ListGroupPreEvent} instance with the given
initiator and identifier.
+ * Construct a new {@link GroupEvent} instance with the given initiator and
identifier.
*
- * @param initiator the user who initiated the list group operation.
- * @param identifier the identifier of the metalake which is being listed.
+ * @param initiator the user who triggered the event.
+ * @param identifier the identifier of the metalake being operated on.
*/
- protected ListGroupsPreEvent(String initiator, NameIdentifier identifier) {
+ protected GroupEvent(String initiator, NameIdentifier identifier) {
super(initiator, identifier);
}
- /**
- * Returns the operation type for this event.
- *
- * @return the operation type for this event.
- */
+ /** {@inheritDoc} */
@Override
- public OperationType operationType() {
- return OperationType.LIST_GROUPS;
+ public OperationStatus operationStatus() {
+ return OperationStatus.SUCCESS;
}
}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupNamesPreEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupNamesEvent.java
similarity index 69%
copy from
core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupNamesPreEvent.java
copy to
core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupNamesEvent.java
index cf0e702e21..297df5cc0a 100644
---
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupNamesPreEvent.java
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupNamesEvent.java
@@ -19,19 +19,23 @@
package org.apache.gravitino.listener.api.event;
-import org.apache.gravitino.NameIdentifier;
import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.utils.NameIdentifierUtil;
-/** Represents an event triggered before list group name from specific
metalake */
+/**
+ * Represents an event triggered after successfully listing group names from a
specific metalake.
+ */
@DeveloperApi
-public class ListGroupNamesPreEvent extends GroupPreEvent {
+public class ListGroupNamesEvent extends GroupEvent {
/**
+ * Constructs a new {@link ListGroupNamesEvent} with the specified initiator
and metalake name.
+ *
* @param initiator the user who initiated the list-group-names request.
- * @param identifier the identifier of the metalake which is being listed.
+ * @param metalake the name of the metalake from which group names are
listed.
*/
- protected ListGroupNamesPreEvent(String initiator, NameIdentifier
identifier) {
- super(initiator, identifier);
+ protected ListGroupNamesEvent(String initiator, String metalake) {
+ super(initiator, NameIdentifierUtil.ofMetalake(metalake));
}
/**
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupNamesPreEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupNamesPreEvent.java
index cf0e702e21..b4c8886019 100644
---
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupNamesPreEvent.java
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupNamesPreEvent.java
@@ -19,19 +19,21 @@
package org.apache.gravitino.listener.api.event;
-import org.apache.gravitino.NameIdentifier;
import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.utils.NameIdentifierUtil;
-/** Represents an event triggered before list group name from specific
metalake */
+/** Represents an event triggered before listing group names from a specific
metalake. */
@DeveloperApi
public class ListGroupNamesPreEvent extends GroupPreEvent {
/**
+ * Constructs a new {@link ListGroupNamesPreEvent} with the specified
initiator and metalake name.
+ *
* @param initiator the user who initiated the list-group-names request.
- * @param identifier the identifier of the metalake which is being listed.
+ * @param metalake the name of the metalake from which group names will be
listed.
*/
- protected ListGroupNamesPreEvent(String initiator, NameIdentifier
identifier) {
- super(initiator, identifier);
+ protected ListGroupNamesPreEvent(String initiator, String metalake) {
+ super(initiator, NameIdentifierUtil.ofMetalake(metalake));
}
/**
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupsPreEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupsEvent.java
similarity index 66%
copy from
core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupsPreEvent.java
copy to
core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupsEvent.java
index 4461a04a03..e732cdff92 100644
---
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupsPreEvent.java
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupsEvent.java
@@ -19,20 +19,21 @@
package org.apache.gravitino.listener.api.event;
-import org.apache.gravitino.NameIdentifier;
import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.utils.NameIdentifierUtil;
-/** Represents an event triggered before list groups from specific metalake */
+/** Represents an event triggered after successfully listing groups from a
specific metalake. */
@DeveloperApi
-public class ListGroupsPreEvent extends GroupPreEvent {
+public class ListGroupsEvent extends GroupEvent {
+
/**
- * Construct a new {@code ListGroupPreEvent} instance with the given
initiator and identifier.
+ * Constructs a new {@link ListGroupsEvent} with the specified initiator and
metalake name.
*
- * @param initiator the user who initiated the list group operation.
- * @param identifier the identifier of the metalake which is being listed.
+ * @param initiator the user who initiated the list-groups request.
+ * @param metalake the name of the metalake from which the groups were
listed.
*/
- protected ListGroupsPreEvent(String initiator, NameIdentifier identifier) {
- super(initiator, identifier);
+ protected ListGroupsEvent(String initiator, String metalake) {
+ super(initiator, NameIdentifierUtil.ofMetalake(metalake));
}
/**
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupsPreEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupsPreEvent.java
index 4461a04a03..a709e83a57 100644
---
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupsPreEvent.java
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupsPreEvent.java
@@ -19,20 +19,20 @@
package org.apache.gravitino.listener.api.event;
-import org.apache.gravitino.NameIdentifier;
import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.utils.NameIdentifierUtil;
-/** Represents an event triggered before list groups from specific metalake */
+/** Represents an event triggered before listing groups from a specific
metalake. */
@DeveloperApi
public class ListGroupsPreEvent extends GroupPreEvent {
/**
- * Construct a new {@code ListGroupPreEvent} instance with the given
initiator and identifier.
+ * Constructs a new {@link ListGroupsPreEvent} with the specified initiator
and metalake name.
*
- * @param initiator the user who initiated the list group operation.
- * @param identifier the identifier of the metalake which is being listed.
+ * @param initiator the user who initiated the list-groups request.
+ * @param metalake the name of the metalake from which groups will be listed.
*/
- protected ListGroupsPreEvent(String initiator, NameIdentifier identifier) {
- super(initiator, identifier);
+ protected ListGroupsPreEvent(String initiator, String metalake) {
+ super(initiator, NameIdentifierUtil.ofMetalake(metalake));
}
/**
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/OperationType.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/OperationType.java
index a61d68dd6f..7905109421 100644
---
a/core/src/main/java/org/apache/gravitino/listener/api/event/OperationType.java
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/OperationType.java
@@ -128,6 +128,8 @@ public enum OperationType {
GET_GROUP,
LIST_GROUPS,
LIST_GROUP_NAMES,
+ GRANT_GROUP_ROLES,
+ REVOKE_GROUP_ROLES,
// TODO ROLE
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/RemoveGroupEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/RemoveGroupEvent.java
new file mode 100644
index 0000000000..417070cb5d
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/RemoveGroupEvent.java
@@ -0,0 +1,77 @@
+/*
+ * 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 that is triggered after a group is successfully
removed from a metalake. */
+@DeveloperApi
+public class RemoveGroupEvent extends GroupEvent {
+ private final String removedGroupName;
+ private final boolean isExists;
+
+ /**
+ * Constructs a new {@link RemoveGroupEvent} with the specified initiator,
metalake name, removed
+ * group name, and existence status.
+ *
+ * @param initiator the user who initiated the remove group operation.
+ * @param metalake the name of the metalake from which the group was removed.
+ * @param removedGroupName the name of the group that was removed.
+ * @param isExists {@code true} if the group was successfully removed,
{@code false} if there was
+ * no such group in the metalake.
+ */
+ protected RemoveGroupEvent(
+ String initiator, String metalake, String removedGroupName, boolean
isExists) {
+ super(initiator, NameIdentifierUtil.ofGroup(metalake, removedGroupName));
+
+ this.removedGroupName = removedGroupName;
+ this.isExists = isExists;
+ }
+
+ /**
+ * Returns the name of the group that was removed.
+ *
+ * @return the name of the removed group.
+ */
+ public String removedGroupName() {
+ return removedGroupName;
+ }
+
+ /**
+ * Returns whether the group was removed from the metalake.
+ *
+ * @return {@code true} if the group was removed, {@code false} if no such
group exists in the
+ * metalake.
+ */
+ public boolean isExists() {
+ return isExists;
+ }
+
+ /**
+ * Returns the operation type of this event.
+ *
+ * @return the operation type of this event.
+ */
+ @Override
+ public OperationType operationType() {
+ return OperationType.REMOVE_GROUP;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/RemoveGroupPreEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/RemoveGroupPreEvent.java
index b42b90d739..bafe80c126 100644
---
a/core/src/main/java/org/apache/gravitino/listener/api/event/RemoveGroupPreEvent.java
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/RemoveGroupPreEvent.java
@@ -19,31 +19,32 @@
package org.apache.gravitino.listener.api.event;
-import org.apache.gravitino.NameIdentifier;
import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.utils.NameIdentifierUtil;
-/** Represents an event triggered before remove a group from specific
metalake. */
+/** Represents an event triggered before removing a group from a specific
metalake. */
@DeveloperApi
public class RemoveGroupPreEvent extends GroupPreEvent {
private final String groupName;
/**
- * Construct a new {@link RemoveGroupPreEvent} instance with initiator,
identifier and group name.
+ * Constructs a new {@link RemoveGroupPreEvent} with the specified
initiator, metalake name, and
+ * group name.
*
* @param initiator the user who initiated the remove group operation.
- * @param identifier the identifier of the metalake where the group is
removed.
- * @param groupName the group name which is requested to be removed from the
metalake.
+ * @param metalake the name of the metalake from which the group will be
removed.
+ * @param groupName the name of the group that is requested to be removed
from the metalake.
*/
- protected RemoveGroupPreEvent(String initiator, NameIdentifier identifier,
String groupName) {
- super(initiator, identifier);
+ protected RemoveGroupPreEvent(String initiator, String metalake, String
groupName) {
+ super(initiator, NameIdentifierUtil.ofGroup(metalake, groupName));
this.groupName = groupName;
}
/**
- * Returns the group information which is being removed from the metalake.
+ * Returns the name of the group that is being removed from the metalake.
*
- * @return the group name which is requested to be removed from the metalake.
+ * @return the name of the group requested to be removed.
*/
public String groupName() {
return groupName;
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/RevokeGroupRolesEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/RevokeGroupRolesEvent.java
new file mode 100644
index 0000000000..48f928a821
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/RevokeGroupRolesEvent.java
@@ -0,0 +1,78 @@
+/*
+ * 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.ImmutableList;
+import java.util.List;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.info.GroupInfo;
+import org.apache.gravitino.utils.NameIdentifierUtil;
+
+/** Represents an event triggered after the operation of revoking roles from a
group. */
+@DeveloperApi
+public class RevokeGroupRolesEvent extends GroupEvent {
+ private final GroupInfo revokedGroupInfo;
+ private final List<String> roles;
+
+ /**
+ * Constructs a new {@link RevokeGroupRolesEvent} with the specified
initiator, metalake name,
+ * revoked group information, and the list of revoked roles.
+ *
+ * @param initiator the user who initiated the role-revocation operation.
+ * @param metalake the name of the metalake that the operation affects.
+ * @param revokedGroupInfo the group information of the group whose roles
are being revoked.
+ * @param roles the list of roles that have been revoked from the group.
+ */
+ public RevokeGroupRolesEvent(
+ String initiator, String metalake, GroupInfo revokedGroupInfo,
List<String> roles) {
+ super(initiator, NameIdentifierUtil.ofGroup(metalake,
revokedGroupInfo.name()));
+
+ this.revokedGroupInfo = revokedGroupInfo;
+ this.roles = roles == null ? null : ImmutableList.copyOf(roles);
+ }
+
+ /**
+ * Returns the group information of the group whose roles have been revoked.
+ *
+ * @return the {@link GroupInfo} instance containing the details of the
group.
+ */
+ public GroupInfo revokedGroupInfo() {
+ return revokedGroupInfo;
+ }
+
+ /**
+ * Returns the list of roles that have been revoked from the group.
+ *
+ * @return the list of revoked roles.
+ */
+ public List<String> roles() {
+ return roles;
+ }
+
+ /**
+ * Returns the operation type of this event.
+ *
+ * @return the operation type.
+ */
+ @Override
+ public OperationType operationType() {
+ return OperationType.REVOKE_GROUP_ROLES;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/RevokeGroupRolesPreEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/RevokeGroupRolesPreEvent.java
new file mode 100644
index 0000000000..5ac2405622
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/RevokeGroupRolesPreEvent.java
@@ -0,0 +1,75 @@
+/*
+ * 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.List;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.utils.NameIdentifierUtil;
+
+/** Represents an event triggered before revoking roles from a group. */
+@DeveloperApi
+public class RevokeGroupRolesPreEvent extends GroupPreEvent {
+ private final String groupName;
+ private final List<String> roles;
+
+ /**
+ * Constructs a new {@link RevokeGroupRolesPreEvent} instance with the
specified initiator,
+ * metalake, group name, and roles to be revoked.
+ *
+ * @param initiator the user who initiated the event to revoke roles.
+ * @param metalake the name of the metalake on which the operation is being
performed.
+ * @param groupName the name of the group whose roles are being revoked.
+ * @param roles the list of roles to be revoked from the group.
+ */
+ public RevokeGroupRolesPreEvent(
+ String initiator, String metalake, String groupName, List<String> roles)
{
+ super(initiator, NameIdentifierUtil.ofGroup(metalake, groupName));
+ this.groupName = groupName;
+ this.roles = roles;
+ }
+
+ /**
+ * Returns the name of the group whose roles are being revoked.
+ *
+ * @return the group name of the group.
+ */
+ public String groupName() {
+ return groupName;
+ }
+
+ /**
+ * Returns the list of roles that are being revoked from the group.
+ *
+ * @return the list of roles to be revoked.
+ */
+ public List<String> roles() {
+ return roles;
+ }
+
+ /**
+ * Returns the operation type of this event.
+ *
+ * @return the operation type.
+ */
+ @Override
+ public OperationType operationType() {
+ return OperationType.REVOKE_GROUP_ROLES;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupsPreEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/info/GroupInfo.java
similarity index 53%
copy from
core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupsPreEvent.java
copy to core/src/main/java/org/apache/gravitino/listener/api/info/GroupInfo.java
index 4461a04a03..a1479cc5ef 100644
---
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListGroupsPreEvent.java
+++ b/core/src/main/java/org/apache/gravitino/listener/api/info/GroupInfo.java
@@ -17,31 +17,43 @@
* under the License.
*/
-package org.apache.gravitino.listener.api.event;
+package org.apache.gravitino.listener.api.info;
-import org.apache.gravitino.NameIdentifier;
+import java.util.List;
import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.authorization.Group;
-/** Represents an event triggered before list groups from specific metalake */
+/** Provides read-only access to group information for event listeners. */
@DeveloperApi
-public class ListGroupsPreEvent extends GroupPreEvent {
+public class GroupInfo {
+ private final String name;
+ private List<String> roles;
+
+ /**
+ * Constructs a new {@link GroupInfo} instance from the specified {@link
Group} object.
+ *
+ * @param group the {@link Group} object from which to create the {@link
GroupInfo}.
+ */
+ public GroupInfo(Group group) {
+ this.name = group.name();
+ this.roles = group.roles();
+ }
+
/**
- * Construct a new {@code ListGroupPreEvent} instance with the given
initiator and identifier.
+ * Returns the name of the group.
*
- * @param initiator the user who initiated the list group operation.
- * @param identifier the identifier of the metalake which is being listed.
+ * @return The name of the group.
*/
- protected ListGroupsPreEvent(String initiator, NameIdentifier identifier) {
- super(initiator, identifier);
+ public String name() {
+ return name;
}
/**
- * Returns the operation type for this event.
+ * Returns the roles of the roles.
*
- * @return the operation type for this event.
+ * @return The roles of the group.
*/
- @Override
- public OperationType operationType() {
- return OperationType.LIST_GROUPS;
+ public List<String> roles() {
+ return roles;
}
}
diff --git
a/core/src/main/java/org/apache/gravitino/utils/NameIdentifierUtil.java
b/core/src/main/java/org/apache/gravitino/utils/NameIdentifierUtil.java
index ba2aa6fa89..b2b3d83bed 100644
--- a/core/src/main/java/org/apache/gravitino/utils/NameIdentifierUtil.java
+++ b/core/src/main/java/org/apache/gravitino/utils/NameIdentifierUtil.java
@@ -509,4 +509,15 @@ public class NameIdentifierUtil {
return identifier.name();
}
}
+
+ /**
+ * Create the group {@link NameIdentifier} with the given metalake and group
name.
+ *
+ * @param metalake The metalake name
+ * @param groupName The group name
+ * @return the created group {@link NameIdentifier}
+ */
+ public static NameIdentifier ofGroup(String metalake, String groupName) {
+ return NameIdentifier.of(NamespaceUtil.ofGroup(metalake), groupName);
+ }
}
diff --git a/core/src/main/java/org/apache/gravitino/utils/NamespaceUtil.java
b/core/src/main/java/org/apache/gravitino/utils/NamespaceUtil.java
index 3b9d56087d..76670b0066 100644
--- a/core/src/main/java/org/apache/gravitino/utils/NamespaceUtil.java
+++ b/core/src/main/java/org/apache/gravitino/utils/NamespaceUtil.java
@@ -92,6 +92,16 @@ public class NamespaceUtil {
return Namespace.of(metalake, Entity.SYSTEM_CATALOG_RESERVED_NAME,
Entity.USER_SCHEMA_NAME);
}
+ /**
+ * Create a namespace for group.
+ *
+ * @param metalake The metalake name
+ * @return A namespace for group
+ */
+ public static Namespace ofGroup(String metalake) {
+ return Namespace.of(metalake, Entity.SYSTEM_CATALOG_RESERVED_NAME,
Entity.GROUP_SCHEMA_NAME);
+ }
+
/**
* Create a namespace for column.
*
diff --git
a/core/src/test/java/org/apache/gravitino/listener/api/event/TestGroupEvent.java
b/core/src/test/java/org/apache/gravitino/listener/api/event/TestGroupEvent.java
index 22c6301362..44d7ae1936 100644
---
a/core/src/test/java/org/apache/gravitino/listener/api/event/TestGroupEvent.java
+++
b/core/src/test/java/org/apache/gravitino/listener/api/event/TestGroupEvent.java
@@ -32,6 +32,8 @@ import org.apache.gravitino.exceptions.NoSuchGroupException;
import org.apache.gravitino.exceptions.NoSuchMetalakeException;
import org.apache.gravitino.listener.DummyEventListener;
import org.apache.gravitino.listener.EventBus;
+import org.apache.gravitino.listener.api.info.GroupInfo;
+import org.apache.gravitino.utils.NameIdentifierUtil;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
@@ -51,6 +53,8 @@ public class TestGroupEvent {
private Group group;
private Group otherGroup;
private NameIdentifier identifier;
+ private List<String> grantedRoles;
+ private List<String> revokedRoles;
@BeforeAll
void init() {
@@ -60,6 +64,8 @@ public class TestGroupEvent {
this.group = getMockGroup(groupName, ImmutableList.of("test", "engineer"));
this.otherGroup = getMockGroup(otherGroupName, null);
this.identifier = NameIdentifier.of(METALAKE);
+ this.grantedRoles = ImmutableList.of("test", "engineer");
+ this.revokedRoles = ImmutableList.of("admin", "scientist");
this.dummyEventListener = new DummyEventListener();
EventBus eventBus = new
EventBus(Collections.singletonList(dummyEventListener));
@@ -70,6 +76,14 @@ public class TestGroupEvent {
System.out.println(failureDispatcher);
}
+ @Test
+ void testGroupInfo() {
+ Group mockGroup = getMockGroup("group_test", ImmutableList.of("test",
"engineer"));
+ GroupInfo groupInfo = new GroupInfo(mockGroup);
+
+ validateGroup(groupInfo, mockGroup);
+ }
+
@Test
void testAddGroupPreEvent() {
dispatcher.addGroup(METALAKE, groupName);
@@ -81,10 +95,28 @@ public class TestGroupEvent {
Assertions.assertEquals(OperationType.ADD_GROUP, preEvent.operationType());
AddGroupPreEvent addGroupPreEvent = (AddGroupPreEvent) preEvent;
- Assertions.assertEquals(identifier, addGroupPreEvent.identifier());
+ Assertions.assertEquals(
+ NameIdentifierUtil.ofGroup(METALAKE, groupName),
addGroupPreEvent.identifier());
Assertions.assertEquals(groupName, addGroupPreEvent.groupName());
}
+ @Test
+ void testAddGroupEvent() {
+ dispatcher.addGroup(METALAKE, groupName);
+
+ // validate event
+ Event event = dummyEventListener.popPostEvent();
+ Assertions.assertEquals(AddGroupEvent.class, event.getClass());
+ Assertions.assertEquals(OperationStatus.SUCCESS, event.operationStatus());
+ Assertions.assertEquals(OperationType.ADD_GROUP, event.operationType());
+
+ AddGroupEvent addGroupEvent = (AddGroupEvent) event;
+ Assertions.assertEquals(
+ NameIdentifierUtil.ofGroup(METALAKE, groupName),
addGroupEvent.identifier());
+
+ validateGroup(addGroupEvent.addedGroupInfo(), group);
+ }
+
@Test
void testGetGroupPreEventWithExistingGroup() {
dispatcher.getGroup(METALAKE, groupName);
@@ -96,7 +128,8 @@ public class TestGroupEvent {
Assertions.assertEquals(OperationType.GET_GROUP, preEvent.operationType());
GetGroupPreEvent getGroupPreEvent = (GetGroupPreEvent) preEvent;
- Assertions.assertEquals(identifier, getGroupPreEvent.identifier());
+ Assertions.assertEquals(
+ NameIdentifierUtil.ofGroup(METALAKE, groupName),
getGroupPreEvent.identifier());
Assertions.assertEquals(groupName, getGroupPreEvent.groupName());
}
@@ -112,6 +145,35 @@ public class TestGroupEvent {
NoSuchMetalakeException.class, () ->
dispatcher.getGroup(INEXIST_METALAKE, groupName));
}
+ @Test
+ void testGetGroupEventWithExistingGroup() {
+ dispatcher.getGroup(METALAKE, groupName);
+
+ // validate event
+ Event event = dummyEventListener.popPostEvent();
+ Assertions.assertEquals(GetGroupEvent.class, event.getClass());
+ Assertions.assertEquals(OperationStatus.SUCCESS, event.operationStatus());
+ Assertions.assertEquals(OperationType.GET_GROUP, event.operationType());
+
+ GetGroupEvent getGroupEvent = (GetGroupEvent) event;
+ Assertions.assertEquals(
+ NameIdentifierUtil.ofGroup(METALAKE, groupName),
getGroupEvent.identifier());
+
+ validateGroup(getGroupEvent.loadedGroupInfo(), group);
+ }
+
+ @Test
+ void testGetGroupEventWithInexistMetalake() {
+ Assertions.assertThrows(
+ NoSuchMetalakeException.class, () ->
dispatcher.getGroup(INEXIST_METALAKE, groupName));
+ }
+
+ @Test
+ void testGetGroupEventWithGroupNotFound() {
+ Assertions.assertThrows(
+ NoSuchGroupException.class, () -> dispatcher.getGroup(METALAKE,
inExistGroupName));
+ }
+
@Test
void testListGroupsPreEvent() {
dispatcher.listGroups(METALAKE);
@@ -126,6 +188,20 @@ public class TestGroupEvent {
Assertions.assertEquals(identifier, listGroupsPreEvent.identifier());
}
+ @Test
+ void testListGroupsEvent() {
+ dispatcher.listGroups(METALAKE);
+
+ // validate event
+ Event event = dummyEventListener.popPostEvent();
+ Assertions.assertEquals(ListGroupsEvent.class, event.getClass());
+ Assertions.assertEquals(OperationStatus.SUCCESS, event.operationStatus());
+ Assertions.assertEquals(OperationType.LIST_GROUPS, event.operationType());
+
+ ListGroupsEvent listGroupsEvent = (ListGroupsEvent) event;
+ Assertions.assertEquals(identifier, listGroupsEvent.identifier());
+ }
+
@Test
void testListGroupNamesPreEvent() {
dispatcher.listGroupNames(METALAKE);
@@ -140,6 +216,20 @@ public class TestGroupEvent {
Assertions.assertEquals(identifier, listGroupNamesPreEvent.identifier());
}
+ @Test
+ void testListGroupNamesEvent() {
+ dispatcher.listGroupNames(METALAKE);
+
+ // validate event
+ Event event = dummyEventListener.popPostEvent();
+ Assertions.assertEquals(ListGroupNamesEvent.class, event.getClass());
+ Assertions.assertEquals(OperationStatus.SUCCESS, event.operationStatus());
+ Assertions.assertEquals(OperationType.LIST_GROUP_NAMES,
event.operationType());
+
+ ListGroupNamesEvent listGroupNamesEvent = (ListGroupNamesEvent) event;
+ Assertions.assertEquals(identifier, listGroupNamesEvent.identifier());
+ }
+
@Test
void testRemoveGroupPreEvent() {
dispatcher.removeGroup(METALAKE, groupName);
@@ -151,10 +241,118 @@ public class TestGroupEvent {
Assertions.assertEquals(OperationType.REMOVE_GROUP,
preEvent.operationType());
RemoveGroupPreEvent removeGroupPreEvent = (RemoveGroupPreEvent) preEvent;
- Assertions.assertEquals(identifier, removeGroupPreEvent.identifier());
+ Assertions.assertEquals(
+ NameIdentifierUtil.ofGroup(METALAKE, groupName),
removeGroupPreEvent.identifier());
Assertions.assertEquals(groupName, removeGroupPreEvent.groupName());
}
+ @Test
+ void testRemoveGroupEventWithExistingGroup() {
+ dispatcher.removeGroup(METALAKE, groupName);
+
+ // validate event
+ Event event = dummyEventListener.popPostEvent();
+ Assertions.assertEquals(RemoveGroupEvent.class, event.getClass());
+ Assertions.assertEquals(OperationStatus.SUCCESS, event.operationStatus());
+ Assertions.assertEquals(OperationType.REMOVE_GROUP, event.operationType());
+
+ RemoveGroupEvent removeGroupEvent = (RemoveGroupEvent) event;
+ Assertions.assertEquals(
+ NameIdentifierUtil.ofGroup(METALAKE, groupName),
removeGroupEvent.identifier());
+ Assertions.assertTrue(removeGroupEvent.isExists());
+ Assertions.assertEquals(groupName, removeGroupEvent.removedGroupName());
+ }
+
+ @Test
+ void testRemoveGroupEventWithNonExistingGroup() {
+ dispatcher.removeGroup(METALAKE, inExistGroupName);
+
+ // validate event
+ Event event = dummyEventListener.popPostEvent();
+ Assertions.assertEquals(RemoveGroupEvent.class, event.getClass());
+ Assertions.assertEquals(OperationStatus.SUCCESS, event.operationStatus());
+ Assertions.assertEquals(OperationType.REMOVE_GROUP, event.operationType());
+
+ RemoveGroupEvent removeGroupEvent = (RemoveGroupEvent) event;
+ Assertions.assertEquals(
+ NameIdentifierUtil.ofGroup(METALAKE, inExistGroupName),
removeGroupEvent.identifier());
+ Assertions.assertFalse(removeGroupEvent.isExists());
+ Assertions.assertEquals(inExistGroupName,
removeGroupEvent.removedGroupName());
+ }
+
+ @Test
+ void testGrantRolesToGroupPreEvent() {
+ dispatcher.grantRolesToGroup(METALAKE, grantedRoles, groupName);
+
+ // validate pre-event
+ PreEvent preEvent = dummyEventListener.popPreEvent();
+ Assertions.assertEquals(GrantGroupRolesPreEvent.class,
preEvent.getClass());
+ Assertions.assertEquals(OperationStatus.UNPROCESSED,
preEvent.operationStatus());
+ Assertions.assertEquals(OperationType.GRANT_GROUP_ROLES,
preEvent.operationType());
+
+ GrantGroupRolesPreEvent grantGroupRolesPreEvent =
(GrantGroupRolesPreEvent) preEvent;
+ Assertions.assertEquals(
+ NameIdentifierUtil.ofGroup(METALAKE, groupName),
grantGroupRolesPreEvent.identifier());
+ String grantedUserName = grantGroupRolesPreEvent.groupName();
+ Assertions.assertEquals(groupName, grantedUserName);
+ Assertions.assertEquals(grantedRoles, grantGroupRolesPreEvent.roles());
+ }
+
+ @Test
+ void testGrantRolesToGroupEvent() {
+ dispatcher.grantRolesToGroup(METALAKE, grantedRoles, groupName);
+
+ // validate event
+ Event event = dummyEventListener.popPostEvent();
+ Assertions.assertEquals(GrantGroupRolesEvent.class, event.getClass());
+ Assertions.assertEquals(OperationStatus.SUCCESS, event.operationStatus());
+ Assertions.assertEquals(OperationType.GRANT_GROUP_ROLES,
event.operationType());
+
+ GrantGroupRolesEvent grantGroupRolesEvent = (GrantGroupRolesEvent) event;
+ Assertions.assertEquals(
+ NameIdentifierUtil.ofGroup(METALAKE, groupName),
grantGroupRolesEvent.identifier());
+ GroupInfo groupInfo = grantGroupRolesEvent.grantedGroupInfo();
+
+ validateGroup(groupInfo, group);
+ }
+
+ @Test
+ void testRevokeRolesFromGroupPreEvent() {
+ dispatcher.revokeRolesFromGroup(METALAKE, revokedRoles, otherGroupName);
+
+ // validate pre-event
+ PreEvent preEvent = dummyEventListener.popPreEvent();
+ Assertions.assertEquals(RevokeGroupRolesPreEvent.class,
preEvent.getClass());
+ Assertions.assertEquals(OperationStatus.UNPROCESSED,
preEvent.operationStatus());
+ Assertions.assertEquals(OperationType.REVOKE_GROUP_ROLES,
preEvent.operationType());
+
+ RevokeGroupRolesPreEvent revokeGroupRolesPreEvent =
(RevokeGroupRolesPreEvent) preEvent;
+ Assertions.assertEquals(
+ NameIdentifierUtil.ofGroup(METALAKE, otherGroupName),
+ revokeGroupRolesPreEvent.identifier());
+ String revokedUserName = revokeGroupRolesPreEvent.groupName();
+ Assertions.assertEquals(otherGroupName, revokedUserName);
+ Assertions.assertEquals(revokedRoles, revokeGroupRolesPreEvent.roles());
+ }
+
+ @Test
+ void testRevokeRolesFromGroupEvent() {
+ dispatcher.revokeRolesFromGroup(METALAKE, revokedRoles, otherGroupName);
+
+ // validate event
+ Event event = dummyEventListener.popPostEvent();
+ Assertions.assertEquals(RevokeGroupRolesEvent.class, event.getClass());
+ Assertions.assertEquals(OperationStatus.SUCCESS, event.operationStatus());
+ Assertions.assertEquals(OperationType.REVOKE_GROUP_ROLES,
event.operationType());
+
+ RevokeGroupRolesEvent revokeGroupRolesEvent = (RevokeGroupRolesEvent)
event;
+ Assertions.assertEquals(
+ NameIdentifierUtil.ofGroup(METALAKE, otherGroupName),
revokeGroupRolesEvent.identifier());
+ GroupInfo groupInfo = revokeGroupRolesEvent.revokedGroupInfo();
+
+ validateGroup(groupInfo, otherGroup);
+ }
+
private Group getMockGroup(String name, List<String> roles) {
Group mockGroup = mock(Group.class);
when(mockGroup.name()).thenReturn(name);
@@ -179,6 +377,9 @@ public class TestGroupEvent {
.thenThrow(new NoSuchGroupException("group not found"));
when(dispatcher.getGroup(INEXIST_METALAKE, groupName))
.thenThrow(new NoSuchMetalakeException("metalake not found"));
+ when(dispatcher.grantRolesToGroup(METALAKE, grantedRoles,
groupName)).thenReturn(group);
+ when(dispatcher.revokeRolesFromGroup(METALAKE, revokedRoles,
otherGroupName))
+ .thenReturn(otherGroup);
return dispatcher;
}
@@ -190,4 +391,9 @@ public class TestGroupEvent {
throw new GravitinoRuntimeException("Exception for all methods");
});
}
+
+ private void validateGroup(GroupInfo groupInfo, Group group) {
+ Assertions.assertEquals(group.name(), groupInfo.name());
+ Assertions.assertEquals(group.roles(), groupInfo.roles());
+ }
}
diff --git
a/core/src/test/java/org/apache/gravitino/utils/TestNameIdentifierUtil.java
b/core/src/test/java/org/apache/gravitino/utils/TestNameIdentifierUtil.java
index 8dc9170b9f..fcd7455f7c 100644
--- a/core/src/test/java/org/apache/gravitino/utils/TestNameIdentifierUtil.java
+++ b/core/src/test/java/org/apache/gravitino/utils/TestNameIdentifierUtil.java
@@ -165,11 +165,22 @@ public class TestNameIdentifierUtil {
Joiner.on(".")
.join(metalake, Entity.SYSTEM_CATALOG_RESERVED_NAME,
Entity.USER_SCHEMA_NAME, userName),
nameIdentifier.toString());
- Assertions.assertEquals(
- Joiner.on(".").join(metalake, Entity.SYSTEM_CATALOG_RESERVED_NAME,
Entity.USER_SCHEMA_NAME),
- NamespaceUtil.ofUser(metalake).toString());
Assertions.assertThrows(
IllegalArgumentException.class, () -> NameIdentifierUtil.ofUser(null,
userName));
- Assertions.assertThrows(IllegalArgumentException.class, () ->
NamespaceUtil.ofUser(null));
+ }
+
+ @Test
+ void testOfGroup() {
+ String groupName = "groupA";
+ String metalake = "demo_metalake";
+
+ NameIdentifier nameIdentifier = NameIdentifierUtil.ofGroup(metalake,
groupName);
+ Assertions.assertEquals(
+ Joiner.on(".")
+ .join(
+ metalake, Entity.SYSTEM_CATALOG_RESERVED_NAME,
Entity.GROUP_SCHEMA_NAME, groupName),
+ nameIdentifier.toString());
+ Assertions.assertThrows(
+ IllegalArgumentException.class, () -> NameIdentifierUtil.ofGroup(null,
groupName));
}
}
diff --git
a/core/src/test/java/org/apache/gravitino/utils/TestNamespaceUtil.java
b/core/src/test/java/org/apache/gravitino/utils/TestNamespaceUtil.java
index 71ba8e4c7d..9c26043a12 100644
--- a/core/src/test/java/org/apache/gravitino/utils/TestNamespaceUtil.java
+++ b/core/src/test/java/org/apache/gravitino/utils/TestNamespaceUtil.java
@@ -18,6 +18,8 @@
*/
package org.apache.gravitino.utils;
+import com.google.common.base.Joiner;
+import org.apache.gravitino.Entity;
import org.apache.gravitino.Namespace;
import org.apache.gravitino.exceptions.IllegalNamespaceException;
import org.junit.jupiter.api.Assertions;
@@ -82,4 +84,26 @@ public class TestNamespaceUtil {
Assertions.assertTrue(
excep5.getMessage().contains("Model version namespace must be non-null
and have 4 levels"));
}
+
+ @Test
+ void testOfUser() {
+ String metalake = "metalake";
+ Assertions.assertEquals(
+ Joiner.on(".").join(metalake, Entity.SYSTEM_CATALOG_RESERVED_NAME,
Entity.USER_SCHEMA_NAME),
+ NamespaceUtil.ofUser(metalake).toString());
+
+ Assertions.assertThrows(IllegalArgumentException.class, () ->
NamespaceUtil.ofUser(null));
+ }
+
+ @Test
+ void testOfGroup() {
+ String metalake = "metalake";
+ Namespace namespace = NamespaceUtil.ofGroup(metalake);
+
+ Assertions.assertEquals(
+ Joiner.on(".")
+ .join(metalake, Entity.SYSTEM_CATALOG_RESERVED_NAME,
Entity.GROUP_SCHEMA_NAME),
+ namespace.toString());
+ Assertions.assertThrows(IllegalArgumentException.class, () ->
NamespaceUtil.ofGroup(null));
+ }
}
diff --git a/docs/gravitino-server-config.md b/docs/gravitino-server-config.md
index 2a04ca2ce6..95ac479adf 100644
--- a/docs/gravitino-server-config.md
+++ b/docs/gravitino-server-config.md
@@ -129,7 +129,9 @@ Gravitino triggers a pre-event before the operation, a
post-event after the comp
| 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`
[...]
+| user operation | `AddUserEvent`, `GetUserEvent`,
`ListUserNamesEvent`, `ListUsersEvent`, `RemoveUserEvent`,
`GrantUserRolesEvent`, `RevokeUserRolesEvent`
[...]
+| group operation | `AddGroupEvent`, `GetGroupEvent`,
`ListGroupNamesEvent`, `ListGroupsEvent`, `RemoveGroupEvent`,
`GrantGroupRolesEvent`, `RevokeGroupRolesEvent`
[...]
+
##### Pre-event
@@ -145,8 +147,8 @@ Gravitino triggers a pre-event before the operation, a
post-event after the comp
| Gravitino server fileset operation | `CreateFilesetPreEvent`,
`AlterFilesetPreEvent`, `DropFilesetPreEvent`,
`LoadFilesetPreEvent`,`ListFilesetPreEvent`,`GetFileLocationPreEvent`
| 0.8.0-incubating |
| Gravitino server model operation | `DeleteModelPreEvent`,
`DeleteModelVersionPreEvent`,
`RegisterAndLinkModelPreEvent`,`GetModelPreEvent`,
`GetModelVersionPreEvent`,`LinkModelVersionPreEvent`,`ListModelPreEvent`,`RegisterModelPreEvent`
| 0.9.0-incubating |
| Gravitino server tag operation | `ListTagsPreEvent`,
`ListTagsInfoPreEvent`, `CreateTagPreEvent`, `GetTagPreEvent`,
`AlterTagPreEvent`, `DeleteTagPreEvent`, `ListMetadataObjectsForTagPreEvent`,
`ListTagsForMetadataObjectPreEvent`, `ListTagsInfoForMetadataObjectPreEvent`,
`AssociateTagsForMetadataObjectPreEvent`, `GetTagForMetadataObjectPreEvent` |
0.9.0-incubating |
-| Gravitino server user operation | `AddUserPreEvent`, `GetUserPreEvent`,
`ListUserNamesPreEvent`, `ListUsersPreEvent`, `RemoveUserPreEvent`
| 0.9.0-incubating |
-| Gravitino server group operation | `AddGroupPreEvent`,
`GetGroupPreEvent`, `ListGroupNamesPreEvent`, `ListGroupsPreEvent`,
`RemoveGroupPreEvent`
|
0.9.0-incubating |
+| Gravitino server user operation | `AddUserPreEvent`, `GetUserPreEvent`,
`ListUserNamesPreEvent`, `ListUsersPreEvent`, `RemoveUserPreEvent`,
`GrantUserRolesPreEvent`, `RevokeUserRolesPreEvent`
| 0.9.0-incubating |
+| Gravitino server group operation | `AddGroupPreEvent`,
`GetGroupPreEvent`, `ListGroupNamesPreEvent`, `ListGroupsPreEvent`,
`RemoveGroupPreEvent`, `GrantGroupRolesPreEvent`, `RevokeGroupRolesPreEvent`
|
0.9.0-incubating |
#### Event listener plugin