This is an automated email from the ASF dual-hosted git repository.
jshao 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 912a42469 [#3346] feat(core,server): Supports to list roles operations
(#4894)
912a42469 is described below
commit 912a42469583a88e31a777a9357eaae4afe83e76
Author: roryqi <[email protected]>
AuthorDate: Thu Sep 26 09:27:54 2024 +0800
[#3346] feat(core,server): Supports to list roles operations (#4894)
### What changes were proposed in this pull request?
Supports to list roles operations
### Why are the changes needed?
Fix: #3346
### Does this PR introduce _any_ user-facing change?
Yes, will add the document later.
### How was this patch tested?
Add UTs.
---
.../org/apache/gravitino/authorization/Role.java | 3 +-
.../apache/gravitino/client/GravitinoClient.java | 10 +++
.../apache/gravitino/client/GravitinoMetalake.java | 30 +++++--
.../java/org/apache/gravitino/client/TestRole.java | 24 ++++++
.../test/authorization/AccessControlIT.java | 28 +++++++
.../gravitino/dto/authorization/RoleDTO.java | 6 +-
.../gravitino/dto/responses/RoleResponse.java | 3 +-
.../java/org/apache/gravitino/EntityStore.java | 13 ++-
.../authorization/AccessControlDispatcher.java | 11 ++-
.../authorization/AccessControlManager.java | 5 ++
.../gravitino/authorization/RoleManager.java | 21 ++++-
.../gravitino/authorization/UserGroupManager.java | 14 +---
.../hook/AccessControlHookDispatcher.java | 5 ++
.../java/org/apache/gravitino/meta/RoleEntity.java | 15 +---
.../java/org/apache/gravitino/meta/UserEntity.java | 18 -----
.../gravitino/storage/relational/JDBCBackend.java | 10 +--
.../storage/relational/RelationalBackend.java | 11 ++-
.../storage/relational/RelationalEntityStore.java | 9 +--
.../storage/relational/mapper/RoleMetaMapper.java | 3 +
.../mapper/RoleMetaSQLProviderFactory.java | 4 +
.../provider/base/RoleMetaBaseSQLProvider.java | 15 ++++
.../relational/service/RoleMetaService.java | 18 +++++
.../relational/service/SupportsDesiredFields.java | 40 ---------
.../service/SupportsDesiredFieldsHandlers.java | 50 ------------
.../relational/service/UserMetaService.java | 94 ++++++----------------
.../authorization/TestAccessControlManager.java | 26 ++++++
.../java/org/apache/gravitino/meta/TestEntity.java | 2 +-
.../storage/relational/TestJDBCBackend.java | 19 ++---
.../relational/service/TestRoleMetaService.java | 49 +++++++++++
.../relational/service/TestUserMetaService.java | 3 +-
.../gravitino/server/web/rest/RoleOperations.java | 22 +++++
.../server/web/rest/TestRoleOperations.java | 48 +++++++++++
32 files changed, 374 insertions(+), 255 deletions(-)
diff --git a/api/src/main/java/org/apache/gravitino/authorization/Role.java
b/api/src/main/java/org/apache/gravitino/authorization/Role.java
index c7441a920..9b8453f80 100644
--- a/api/src/main/java/org/apache/gravitino/authorization/Role.java
+++ b/api/src/main/java/org/apache/gravitino/authorization/Role.java
@@ -25,8 +25,7 @@ import org.apache.gravitino.annotation.Evolving;
/**
* The interface of a role. The role is the entity which has kinds of
privileges. One role can have
- * multiple privileges of one securable object. Gravitino chooses to bind one
securable object to
- * one role to avoid granting too many privileges to one role.
+ * multiple privileges of multiple securable objects.
*/
@Evolving
public interface Role extends Auditable {
diff --git
a/clients/client-java/src/main/java/org/apache/gravitino/client/GravitinoClient.java
b/clients/client-java/src/main/java/org/apache/gravitino/client/GravitinoClient.java
index e074770e8..a7656fd02 100644
---
a/clients/client-java/src/main/java/org/apache/gravitino/client/GravitinoClient.java
+++
b/clients/client-java/src/main/java/org/apache/gravitino/client/GravitinoClient.java
@@ -359,6 +359,16 @@ public class GravitinoClient extends GravitinoClientBase
getMetalake().setOwner(object, ownerName, ownerType);
}
+ /**
+ * Lists the role names.
+ *
+ * @return The role name list.
+ * @throws NoSuchMetalakeException If the Metalake with the given name does
not exist.
+ */
+ public String[] listRoleNames() throws NoSuchMetalakeException {
+ return getMetalake().listRoleNames();
+ }
+
/**
* Creates a new builder for constructing a GravitinoClient.
*
diff --git
a/clients/client-java/src/main/java/org/apache/gravitino/client/GravitinoMetalake.java
b/clients/client-java/src/main/java/org/apache/gravitino/client/GravitinoMetalake.java
index 9a13a9dd1..58973b4cf 100644
---
a/clients/client-java/src/main/java/org/apache/gravitino/client/GravitinoMetalake.java
+++
b/clients/client-java/src/main/java/org/apache/gravitino/client/GravitinoMetalake.java
@@ -100,9 +100,9 @@ public class GravitinoMetalake extends MetalakeDTO
implements SupportsCatalogs,
private static final String API_METALAKES_GROUPS_PATH =
"api/metalakes/%s/groups/%s";
private static final String API_METALAKES_ROLES_PATH =
"api/metalakes/%s/roles/%s";
private static final String API_METALAKES_OWNERS_PATH =
"api/metalakes/%s/owners/%s";
- private static final String BLANK_PLACE_HOLDER = "";
private static final String API_METALAKES_TAGS_PATH =
"api/metalakes/%s/tags";
+ private static final String BLANK_PLACEHOLDER = "";
private final RESTClient restClient;
@@ -464,7 +464,7 @@ public class GravitinoMetalake extends MetalakeDTO
implements SupportsCatalogs,
UserResponse resp =
restClient.post(
- String.format(API_METALAKES_USERS_PATH, this.name(),
BLANK_PLACE_HOLDER),
+ String.format(API_METALAKES_USERS_PATH, this.name(),
BLANK_PLACEHOLDER),
req,
UserResponse.class,
Collections.emptyMap(),
@@ -528,7 +528,7 @@ public class GravitinoMetalake extends MetalakeDTO
implements SupportsCatalogs,
UserListResponse resp =
restClient.get(
- String.format(API_METALAKES_USERS_PATH, name(),
BLANK_PLACE_HOLDER),
+ String.format(API_METALAKES_USERS_PATH, name(), BLANK_PLACEHOLDER),
params,
UserListResponse.class,
Collections.emptyMap(),
@@ -547,7 +547,7 @@ public class GravitinoMetalake extends MetalakeDTO
implements SupportsCatalogs,
public String[] listUserNames() throws NoSuchMetalakeException {
NameListResponse resp =
restClient.get(
- String.format(API_METALAKES_USERS_PATH, name(),
BLANK_PLACE_HOLDER),
+ String.format(API_METALAKES_USERS_PATH, name(), BLANK_PLACEHOLDER),
NameListResponse.class,
Collections.emptyMap(),
ErrorHandlers.userErrorHandler());
@@ -571,7 +571,7 @@ public class GravitinoMetalake extends MetalakeDTO
implements SupportsCatalogs,
GroupResponse resp =
restClient.post(
- String.format(API_METALAKES_GROUPS_PATH, this.name(),
BLANK_PLACE_HOLDER),
+ String.format(API_METALAKES_GROUPS_PATH, this.name(),
BLANK_PLACEHOLDER),
req,
GroupResponse.class,
Collections.emptyMap(),
@@ -691,7 +691,7 @@ public class GravitinoMetalake extends MetalakeDTO
implements SupportsCatalogs,
RoleResponse resp =
restClient.post(
- String.format(API_METALAKES_ROLES_PATH, this.name(),
BLANK_PLACE_HOLDER),
+ String.format(API_METALAKES_ROLES_PATH, this.name(),
BLANK_PLACEHOLDER),
req,
RoleResponse.class,
Collections.emptyMap(),
@@ -701,6 +701,24 @@ public class GravitinoMetalake extends MetalakeDTO
implements SupportsCatalogs,
return resp.getRole();
}
+ /**
+ * Lists the role names.
+ *
+ * @return The role name list.
+ * @throws NoSuchMetalakeException If the Metalake with the given name does
not exist.
+ */
+ public String[] listRoleNames() {
+ NameListResponse resp =
+ restClient.get(
+ String.format(API_METALAKES_ROLES_PATH, this.name(),
BLANK_PLACEHOLDER),
+ NameListResponse.class,
+ Collections.emptyMap(),
+ ErrorHandlers.roleErrorHandler());
+ resp.validate();
+
+ return resp.getNames();
+ }
+
/**
* Grant roles to a user.
*
diff --git
a/clients/client-java/src/test/java/org/apache/gravitino/client/TestRole.java
b/clients/client-java/src/test/java/org/apache/gravitino/client/TestRole.java
index 370f1941d..3d0771fc5 100644
---
a/clients/client-java/src/test/java/org/apache/gravitino/client/TestRole.java
+++
b/clients/client-java/src/test/java/org/apache/gravitino/client/TestRole.java
@@ -40,6 +40,7 @@ import org.apache.gravitino.dto.requests.RoleCreateRequest;
import org.apache.gravitino.dto.responses.DeleteResponse;
import org.apache.gravitino.dto.responses.ErrorResponse;
import org.apache.gravitino.dto.responses.MetalakeResponse;
+import org.apache.gravitino.dto.responses.NameListResponse;
import org.apache.gravitino.dto.responses.RoleResponse;
import org.apache.gravitino.exceptions.NoSuchMetalakeException;
import org.apache.gravitino.exceptions.NoSuchRoleException;
@@ -211,6 +212,29 @@ public class TestRole extends TestBase {
Assertions.assertThrows(RuntimeException.class, () ->
gravitinoClient.deleteRole(roleName));
}
+ @Test
+ public void testListRoleNames() throws Exception {
+ String rolePath = withSlash(String.format(API_METALAKES_ROLES_PATH,
metalakeName, ""));
+
+ NameListResponse listResponse = new NameListResponse(new String[]
{"role1", "role2"});
+ buildMockResource(Method.GET, rolePath, null, listResponse, SC_OK);
+
+ Assertions.assertArrayEquals(new String[] {"role1", "role2"},
gravitinoClient.listRoleNames());
+
+ ErrorResponse errRespNoMetalake =
+ ErrorResponse.notFound(NoSuchMetalakeException.class.getSimpleName(),
"metalake not found");
+ buildMockResource(Method.GET, rolePath, null, errRespNoMetalake,
SC_NOT_FOUND);
+ Exception ex =
+ Assertions.assertThrows(
+ NoSuchMetalakeException.class, () ->
gravitinoClient.listRoleNames());
+ Assertions.assertEquals("metalake not found", ex.getMessage());
+
+ // Test RuntimeException
+ ErrorResponse errResp = ErrorResponse.internalError("internal error");
+ buildMockResource(Method.GET, rolePath, null, errResp, SC_SERVER_ERROR);
+ Assertions.assertThrows(RuntimeException.class, () ->
gravitinoClient.listRoleNames());
+ }
+
private RoleDTO mockRoleDTO(String name) {
SecurableObject securableObject =
SecurableObjects.ofCatalog("catalog",
Lists.newArrayList(Privileges.UseCatalog.allow()));
diff --git
a/clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/authorization/AccessControlIT.java
b/clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/authorization/AccessControlIT.java
index 662e2c159..965c31fdf 100644
---
a/clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/authorization/AccessControlIT.java
+++
b/clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/authorization/AccessControlIT.java
@@ -176,6 +176,16 @@ public class AccessControlIT extends AbstractIT {
Assertions.assertEquals(roleName, role.name());
Assertions.assertEquals(properties, role.properties());
+ assertSecurableObjects(Lists.newArrayList(metalakeObject),
role.securableObjects());
+
+ // List roles
+ String anotherRoleName = "another-role";
+ metalake.createRole(anotherRoleName, properties,
Lists.newArrayList(metalakeObject));
+ String[] roleNames = metalake.listRoleNames();
+ Arrays.sort(roleNames);
+
+ Assertions.assertEquals(
+ Lists.newArrayList(anotherRoleName, roleName),
Arrays.asList(roleNames));
// Verify the object
Assertions.assertEquals(1, role.securableObjects().size());
@@ -303,4 +313,22 @@ public class AccessControlIT extends AbstractIT {
metalake.removeGroup(groupName);
metalake.deleteRole(roleName);
}
+
+ private static void assertSecurableObjects(
+ List<SecurableObject> expect, List<SecurableObject> actual) {
+ Assertions.assertEquals(expect.size(), actual.size());
+ for (int index = 0; index < expect.size(); index++) {
+ Assertions.assertEquals(expect.get(index).fullName(),
actual.get(index).fullName());
+ Assertions.assertEquals(expect.get(index).type(),
actual.get(index).type());
+ List<Privilege> expectPrivileges = expect.get(index).privileges();
+ List<Privilege> actualPrivileges = actual.get(index).privileges();
+ Assertions.assertEquals(expectPrivileges.size(),
actualPrivileges.size());
+ for (int priIndex = 0; priIndex < expectPrivileges.size(); priIndex++) {
+ Assertions.assertEquals(
+ expectPrivileges.get(priIndex).name(),
actualPrivileges.get(priIndex).name());
+ Assertions.assertEquals(
+ actualPrivileges.get(priIndex).condition(),
actualPrivileges.get(priIndex).condition());
+ }
+ }
+ }
}
diff --git
a/common/src/main/java/org/apache/gravitino/dto/authorization/RoleDTO.java
b/common/src/main/java/org/apache/gravitino/dto/authorization/RoleDTO.java
index 9ce0b0da0..d0c51753e 100644
--- a/common/src/main/java/org/apache/gravitino/dto/authorization/RoleDTO.java
+++ b/common/src/main/java/org/apache/gravitino/dto/authorization/RoleDTO.java
@@ -158,7 +158,7 @@ public class RoleDTO implements Role {
/**
* Sets the securable objects of the role.
*
- * @param securableObjects The securableObjects of the role.
+ * @param securableObjects The securable objects of the role.
* @return The builder instance.
*/
public S withSecurableObjects(SecurableObjectDTO[] securableObjects) {
@@ -186,9 +186,7 @@ public class RoleDTO implements Role {
public RoleDTO build() {
Preconditions.checkArgument(StringUtils.isNotBlank(name), "name cannot
be null or empty");
Preconditions.checkArgument(audit != null, "audit cannot be null");
- Preconditions.checkArgument(
- securableObjects != null && securableObjects.length != 0,
- "securable objects can't null or empty");
+ Preconditions.checkArgument(securableObjects != null, "securable objects
can't null");
return new RoleDTO(name, properties, securableObjects, audit);
}
diff --git
a/common/src/main/java/org/apache/gravitino/dto/responses/RoleResponse.java
b/common/src/main/java/org/apache/gravitino/dto/responses/RoleResponse.java
index ca9c3960e..d200a24c8 100644
--- a/common/src/main/java/org/apache/gravitino/dto/responses/RoleResponse.java
+++ b/common/src/main/java/org/apache/gravitino/dto/responses/RoleResponse.java
@@ -65,7 +65,6 @@ public class RoleResponse extends BaseResponse {
StringUtils.isNotBlank(role.name()), "role 'name' must not be null and
empty");
Preconditions.checkArgument(role.auditInfo() != null, "role 'auditInfo'
must not be null");
Preconditions.checkArgument(
- role.securableObjects() != null && !role.securableObjects().isEmpty(),
- "role 'securableObjects' can't null or empty");
+ role.securableObjects() != null, "role 'securable objects' can't
null");
}
}
diff --git a/core/src/main/java/org/apache/gravitino/EntityStore.java
b/core/src/main/java/org/apache/gravitino/EntityStore.java
index dcb27f022..d26dbf13b 100644
--- a/core/src/main/java/org/apache/gravitino/EntityStore.java
+++ b/core/src/main/java/org/apache/gravitino/EntityStore.java
@@ -20,9 +20,7 @@ package org.apache.gravitino;
import java.io.Closeable;
import java.io.IOException;
-import java.util.Collections;
import java.util.List;
-import java.util.Set;
import java.util.function.Function;
import org.apache.gravitino.Entity.EntityType;
import org.apache.gravitino.exceptions.NoSuchEntityException;
@@ -66,7 +64,7 @@ public interface EntityStore extends Closeable {
*/
default <E extends Entity & HasIdentifier> List<E> list(
Namespace namespace, Class<E> type, EntityType entityType) throws
IOException {
- return list(namespace, type, entityType, Collections.emptySet());
+ return list(namespace, type, entityType, true /* allFields */);
}
/**
@@ -80,14 +78,15 @@ public interface EntityStore extends Closeable {
* @param namespace the namespace of the entities
* @param type the detailed type of the entity
* @param entityType the general type of the entity
- * @param skippingFields Some fields may have a relatively high acquisition
cost, EntityStore
- * provides an optional setting to avoid fetching these high-cost fields
to improve the
- * performance.
+ * @param allFields Some fields may have a relatively high acquisition cost,
EntityStore provides
+ * an optional setting to avoid fetching these high-cost fields to
improve the performance. If
+ * true, the method will fetch all the fields, Otherwise, the method
will fetch all the fields
+ * except for high-cost fields.
* @return the list of entities
* @throws IOException if the list operation fails
*/
default <E extends Entity & HasIdentifier> List<E> list(
- Namespace namespace, Class<E> type, EntityType entityType, Set<Field>
skippingFields)
+ Namespace namespace, Class<E> type, EntityType entityType, boolean
allFields)
throws IOException {
throw new UnsupportedOperationException("Don't support to skip fields");
}
diff --git
a/core/src/main/java/org/apache/gravitino/authorization/AccessControlDispatcher.java
b/core/src/main/java/org/apache/gravitino/authorization/AccessControlDispatcher.java
index fbeebd944..95cb304de 100644
---
a/core/src/main/java/org/apache/gravitino/authorization/AccessControlDispatcher.java
+++
b/core/src/main/java/org/apache/gravitino/authorization/AccessControlDispatcher.java
@@ -236,5 +236,14 @@ public interface AccessControlDispatcher {
* @throws NoSuchMetalakeException If the Metalake with the given name does
not exist.
* @throws RuntimeException If deleting the Role encounters storage issues.
*/
- public boolean deleteRole(String metalake, String role) throws
NoSuchMetalakeException;
+ boolean deleteRole(String metalake, String role) throws
NoSuchMetalakeException;
+
+ /**
+ * Lists the role names.
+ *
+ * @param metalake The Metalake of the Role.
+ * @return The role name list.
+ * @throws NoSuchMetalakeException If the Metalake with the given name does
not exist.
+ */
+ String[] listRoleNames(String metalake) throws NoSuchMetalakeException;
}
diff --git
a/core/src/main/java/org/apache/gravitino/authorization/AccessControlManager.java
b/core/src/main/java/org/apache/gravitino/authorization/AccessControlManager.java
index 222b1ffb5..8872afade 100644
---
a/core/src/main/java/org/apache/gravitino/authorization/AccessControlManager.java
+++
b/core/src/main/java/org/apache/gravitino/authorization/AccessControlManager.java
@@ -143,6 +143,11 @@ public class AccessControlManager implements
AccessControlDispatcher {
return roleManager.deleteRole(metalake, role);
}
+ @Override
+ public String[] listRoleNames(String metalake) throws
NoSuchMetalakeException {
+ return roleManager.listRoleNames(metalake);
+ }
+
@VisibleForTesting
RoleManager getRoleManager() {
return roleManager;
diff --git
a/core/src/main/java/org/apache/gravitino/authorization/RoleManager.java
b/core/src/main/java/org/apache/gravitino/authorization/RoleManager.java
index 457a7f5ff..8b195894f 100644
--- a/core/src/main/java/org/apache/gravitino/authorization/RoleManager.java
+++ b/core/src/main/java/org/apache/gravitino/authorization/RoleManager.java
@@ -19,6 +19,7 @@
package org.apache.gravitino.authorization;
+import com.google.common.collect.Sets;
import java.io.IOException;
import java.time.Instant;
import java.util.List;
@@ -27,14 +28,15 @@ import org.apache.gravitino.Entity;
import org.apache.gravitino.EntityAlreadyExistsException;
import org.apache.gravitino.EntityStore;
import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.Namespace;
import org.apache.gravitino.exceptions.NoSuchEntityException;
+import org.apache.gravitino.exceptions.NoSuchMetalakeException;
import org.apache.gravitino.exceptions.NoSuchRoleException;
import org.apache.gravitino.exceptions.RoleAlreadyExistsException;
import org.apache.gravitino.meta.AuditInfo;
import org.apache.gravitino.meta.RoleEntity;
import org.apache.gravitino.storage.IdGenerator;
import org.apache.gravitino.utils.PrincipalUtils;
-import org.glassfish.jersey.internal.guava.Sets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -46,6 +48,7 @@ import org.slf4j.LoggerFactory;
class RoleManager {
private static final Logger LOG = LoggerFactory.getLogger(RoleManager.class);
+ private static final String METALAKE_DOES_NOT_EXIST_MSG = "Metalake %s does
not exist";
private final EntityStore store;
private final IdGenerator idGenerator;
@@ -129,6 +132,22 @@ class RoleManager {
}
}
+ String[] listRoleNames(String metalake) {
+ try {
+ AuthorizationUtils.checkMetalakeExists(metalake);
+ Namespace namespace = AuthorizationUtils.ofRoleNamespace(metalake);
+ return store.list(namespace, RoleEntity.class,
Entity.EntityType.ROLE).stream()
+ .map(Role::name)
+ .toArray(String[]::new);
+ } catch (NoSuchEntityException e) {
+ LOG.warn("Metalake {} does not exist", metalake, e);
+ throw new NoSuchMetalakeException(METALAKE_DOES_NOT_EXIST_MSG, metalake);
+ } catch (IOException ioe) {
+ LOG.error("Listing user under metalake {} failed due to storage issues",
metalake, ioe);
+ throw new RuntimeException(ioe);
+ }
+ }
+
private RoleEntity getRoleEntity(NameIdentifier identifier) {
try {
return store.get(identifier, Entity.EntityType.ROLE, RoleEntity.class);
diff --git
a/core/src/main/java/org/apache/gravitino/authorization/UserGroupManager.java
b/core/src/main/java/org/apache/gravitino/authorization/UserGroupManager.java
index 4b7b4f2d8..be1b687f3 100644
---
a/core/src/main/java/org/apache/gravitino/authorization/UserGroupManager.java
+++
b/core/src/main/java/org/apache/gravitino/authorization/UserGroupManager.java
@@ -23,11 +23,9 @@ import java.io.IOException;
import java.time.Instant;
import java.util.Arrays;
import java.util.Collections;
-import java.util.Set;
import org.apache.gravitino.Entity;
import org.apache.gravitino.EntityAlreadyExistsException;
import org.apache.gravitino.EntityStore;
-import org.apache.gravitino.Field;
import org.apache.gravitino.Namespace;
import org.apache.gravitino.exceptions.GroupAlreadyExistsException;
import org.apache.gravitino.exceptions.NoSuchEntityException;
@@ -40,7 +38,6 @@ import org.apache.gravitino.meta.GroupEntity;
import org.apache.gravitino.meta.UserEntity;
import org.apache.gravitino.storage.IdGenerator;
import org.apache.gravitino.utils.PrincipalUtils;
-import org.glassfish.jersey.internal.guava.Sets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -117,26 +114,23 @@ class UserGroupManager {
}
String[] listUserNames(String metalake) {
- Set<Field> skippingFields = Sets.newHashSet();
- skippingFields.add(UserEntity.ROLE_NAMES);
- skippingFields.add(UserEntity.ROLE_IDS);
- return Arrays.stream(listUsersInternal(metalake, skippingFields))
+ return Arrays.stream(listUsersInternal(metalake, false /* allFields */))
.map(User::name)
.toArray(String[]::new);
}
User[] listUsers(String metalake) {
- return listUsersInternal(metalake, Collections.emptySet());
+ return listUsersInternal(metalake, true /* allFields */);
}
- private User[] listUsersInternal(String metalake, Set<Field> skippingFields)
{
+ private User[] listUsersInternal(String metalake, boolean allFields) {
try {
AuthorizationUtils.checkMetalakeExists(metalake);
Namespace namespace = AuthorizationUtils.ofUserNamespace(metalake);
return store
- .list(namespace, UserEntity.class, Entity.EntityType.USER,
skippingFields)
+ .list(namespace, UserEntity.class, Entity.EntityType.USER, allFields)
.toArray(new User[0]);
} catch (NoSuchEntityException e) {
LOG.error("Metalake {} does not exist", metalake, e);
diff --git
a/core/src/main/java/org/apache/gravitino/hook/AccessControlHookDispatcher.java
b/core/src/main/java/org/apache/gravitino/hook/AccessControlHookDispatcher.java
index 730563862..7882e9c8a 100644
---
a/core/src/main/java/org/apache/gravitino/hook/AccessControlHookDispatcher.java
+++
b/core/src/main/java/org/apache/gravitino/hook/AccessControlHookDispatcher.java
@@ -157,4 +157,9 @@ public class AccessControlHookDispatcher implements
AccessControlDispatcher {
public boolean deleteRole(String metalake, String role) throws
NoSuchMetalakeException {
return dispatcher.deleteRole(metalake, role);
}
+
+ @Override
+ public String[] listRoleNames(String metalake) throws
NoSuchMetalakeException {
+ return dispatcher.listRoleNames(metalake);
+ }
}
diff --git a/core/src/main/java/org/apache/gravitino/meta/RoleEntity.java
b/core/src/main/java/org/apache/gravitino/meta/RoleEntity.java
index d1b3bbfe9..a96f6e0f5 100644
--- a/core/src/main/java/org/apache/gravitino/meta/RoleEntity.java
+++ b/core/src/main/java/org/apache/gravitino/meta/RoleEntity.java
@@ -46,8 +46,8 @@ public class RoleEntity implements Role, Entity, Auditable,
HasIdentifier {
public static final Field AUDIT_INFO =
Field.required("audit_info", AuditInfo.class, "The audit details of the
role entity.");
- public static final Field SECURABLE_OBJECT =
- Field.required("securable_objects", List.class, "The securable objects
of the role entity.");
+ public static final Field SECURABLE_OBJECTS =
+ Field.optional("securable_objects", List.class, "The securable objects
of the role entity.");
private Long id;
private String name;
@@ -91,15 +91,6 @@ public class RoleEntity implements Role, Entity, Auditable,
HasIdentifier {
*/
@Override
public List<SecurableObject> securableObjects() {
- // The securable object is a special kind of entities. Some entity types
aren't the securable
- // object, such as
- // User, Role, etc.
- // The securable object identifier must be unique.
- // Gravitino assumes that the identifiers of the entities may be the same
if they have different
- // types.
- // So one type of them can't be the securable object at least if there are
the two same
- // identifier
- // entities .
return securableObjects;
}
@@ -115,7 +106,7 @@ public class RoleEntity implements Role, Entity, Auditable,
HasIdentifier {
fields.put(NAME, name);
fields.put(AUDIT_INFO, auditInfo);
fields.put(PROPERTIES, properties);
- fields.put(SECURABLE_OBJECT, securableObjects);
+ fields.put(SECURABLE_OBJECTS, securableObjects);
return Collections.unmodifiableMap(fields);
}
diff --git a/core/src/main/java/org/apache/gravitino/meta/UserEntity.java
b/core/src/main/java/org/apache/gravitino/meta/UserEntity.java
index df47215b4..c71d731a9 100644
--- a/core/src/main/java/org/apache/gravitino/meta/UserEntity.java
+++ b/core/src/main/java/org/apache/gravitino/meta/UserEntity.java
@@ -23,7 +23,6 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
-import java.util.Set;
import lombok.ToString;
import org.apache.gravitino.Auditable;
import org.apache.gravitino.Entity;
@@ -31,7 +30,6 @@ import org.apache.gravitino.Field;
import org.apache.gravitino.HasIdentifier;
import org.apache.gravitino.Namespace;
import org.apache.gravitino.authorization.User;
-import org.glassfish.jersey.internal.guava.Sets;
/** A class representing a user metadata entity in Apache Gravitino. */
@ToString
@@ -156,22 +154,6 @@ public class UserEntity implements User, Entity,
Auditable, HasIdentifier {
return roleIds;
}
- /**
- * Get the set of all the fields.
- *
- * @return The set of all the fields.
- */
- public static Set<Field> fieldSet() {
- Set<Field> fields = Sets.newHashSet();
- fields.add(ID);
- fields.add(NAME);
- fields.add(AUDIT_INFO);
- fields.add(ROLE_IDS);
- fields.add(ROLE_NAMES);
-
- return Collections.unmodifiableSet(fields);
- }
-
@Override
public boolean equals(Object o) {
if (this == o) return true;
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/JDBCBackend.java
b/core/src/main/java/org/apache/gravitino/storage/relational/JDBCBackend.java
index 549c5fec2..2b9a6d0e4 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/JDBCBackend.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/JDBCBackend.java
@@ -26,13 +26,11 @@ import com.google.common.collect.Lists;
import java.io.IOException;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import java.util.function.Function;
import org.apache.gravitino.Config;
import org.apache.gravitino.Configs;
import org.apache.gravitino.Entity;
import org.apache.gravitino.EntityAlreadyExistsException;
-import org.apache.gravitino.Field;
import org.apache.gravitino.HasIdentifier;
import org.apache.gravitino.MetadataObject;
import org.apache.gravitino.NameIdentifier;
@@ -90,8 +88,7 @@ public class JDBCBackend implements RelationalBackend {
@Override
public <E extends Entity & HasIdentifier> List<E> list(
- Namespace namespace, Entity.EntityType entityType, Set<Field>
skippingFields)
- throws IOException {
+ Namespace namespace, Entity.EntityType entityType, boolean allFields)
throws IOException {
switch (entityType) {
case METALAKE:
return (List<E>) MetalakeMetaService.getInstance().listMetalakes();
@@ -108,8 +105,9 @@ public class JDBCBackend implements RelationalBackend {
case TAG:
return (List<E>)
TagMetaService.getInstance().listTagsByNamespace(namespace);
case USER:
- return (List<E>)
- UserMetaService.getInstance().listUsersByNamespace(namespace,
skippingFields);
+ return (List<E>)
UserMetaService.getInstance().listUsersByNamespace(namespace, allFields);
+ case ROLE:
+ return (List<E>)
RoleMetaService.getInstance().listRolesByNamespace(namespace);
default:
throw new UnsupportedEntityTypeException(
"Unsupported entity type: %s for list operation", entityType);
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/RelationalBackend.java
b/core/src/main/java/org/apache/gravitino/storage/relational/RelationalBackend.java
index fe85754b4..cae0c7b4d 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/RelationalBackend.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/RelationalBackend.java
@@ -21,12 +21,10 @@ package org.apache.gravitino.storage.relational;
import java.io.Closeable;
import java.io.IOException;
import java.util.List;
-import java.util.Set;
import java.util.function.Function;
import org.apache.gravitino.Config;
import org.apache.gravitino.Entity;
import org.apache.gravitino.EntityAlreadyExistsException;
-import org.apache.gravitino.Field;
import org.apache.gravitino.HasIdentifier;
import org.apache.gravitino.NameIdentifier;
import org.apache.gravitino.Namespace;
@@ -50,9 +48,10 @@ public interface RelationalBackend
*
* @param namespace The parent namespace of these entities.
* @param entityType The type of these entities.
- * @param skippingFields Some fields may have a relatively high acquisition
cost, EntityStore
- * provide an optional setting to avoid fetching these high-cost fields
to improve the
- * performance.
+ * @param allFields Some fields may have a relatively high acquisition cost,
EntityStore provide
+ * an optional setting to avoid fetching these high-cost fields to
improve the performance. If
+ * true, the method will fetch all the fields, Otherwise, the method
will fetch all the fields
+ * except for high-cost fields.
* @return The list of entities associated with the given parent namespace
and entityType, or null
* if the entities does not exist.
* @throws NoSuchEntityException If the corresponding parent entity of these
list entities cannot
@@ -60,7 +59,7 @@ public interface RelationalBackend
* @throws IOException If the store operation fails
*/
<E extends Entity & HasIdentifier> List<E> list(
- Namespace namespace, Entity.EntityType entityType, Set<Field>
skippingFields)
+ Namespace namespace, Entity.EntityType entityType, boolean allFields)
throws NoSuchEntityException, IOException;
/**
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/RelationalEntityStore.java
b/core/src/main/java/org/apache/gravitino/storage/relational/RelationalEntityStore.java
index d7403729f..c95db1a07 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/RelationalEntityStore.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/RelationalEntityStore.java
@@ -22,9 +22,7 @@ import static
org.apache.gravitino.Configs.ENTITY_RELATIONAL_STORE;
import com.google.common.collect.ImmutableMap;
import java.io.IOException;
-import java.util.Collections;
import java.util.List;
-import java.util.Set;
import java.util.function.Function;
import org.apache.gravitino.Config;
import org.apache.gravitino.Configs;
@@ -32,7 +30,6 @@ import org.apache.gravitino.Entity;
import org.apache.gravitino.EntityAlreadyExistsException;
import org.apache.gravitino.EntitySerDe;
import org.apache.gravitino.EntityStore;
-import org.apache.gravitino.Field;
import org.apache.gravitino.HasIdentifier;
import org.apache.gravitino.MetadataObject;
import org.apache.gravitino.NameIdentifier;
@@ -92,14 +89,14 @@ public class RelationalEntityStore
@Override
public <E extends Entity & HasIdentifier> List<E> list(
Namespace namespace, Class<E> type, Entity.EntityType entityType) throws
IOException {
- return backend.list(namespace, entityType, Collections.emptySet());
+ return backend.list(namespace, entityType, false);
}
@Override
public <E extends Entity & HasIdentifier> List<E> list(
- Namespace namespace, Class<E> type, Entity.EntityType entityType,
Set<Field> skippingFields)
+ Namespace namespace, Class<E> type, Entity.EntityType entityType,
boolean allFields)
throws IOException {
- return backend.list(namespace, entityType, skippingFields);
+ return backend.list(namespace, entityType, allFields);
}
@Override
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/RoleMetaMapper.java
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/RoleMetaMapper.java
index d7478c3b7..6b155f498 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/RoleMetaMapper.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/RoleMetaMapper.java
@@ -65,6 +65,9 @@ public interface RoleMetaMapper {
@Param("metadataObjectId") Long metadataObjectId,
@Param("metadataObjectType") String metadataObjectType);
+ @SelectProvider(type = RoleMetaSQLProviderFactory.class, method =
"listRolePOsByMetalake")
+ List<RolePO> listRolePOsByMetalake(@Param("metalakeName") String
metalakeName);
+
@InsertProvider(type = RoleMetaSQLProviderFactory.class, method =
"insertRoleMeta")
void insertRoleMeta(@Param("roleMeta") RolePO rolePO);
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/RoleMetaSQLProviderFactory.java
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/RoleMetaSQLProviderFactory.java
index 156631845..65e68975d 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/RoleMetaSQLProviderFactory.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/RoleMetaSQLProviderFactory.java
@@ -72,6 +72,10 @@ public class RoleMetaSQLProviderFactory {
return getProvider().listRolesByMetadataObjectIdAndType(metadataObjectId,
type);
}
+ public static String listRolePOsByMetalake(@Param("metalakeName") String
metalakeName) {
+ return getProvider().listRolePOsByMetalake(metalakeName);
+ }
+
public static String insertRoleMeta(@Param("roleMeta") RolePO rolePO) {
return getProvider().insertRoleMeta(rolePO);
}
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/RoleMetaBaseSQLProvider.java
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/RoleMetaBaseSQLProvider.java
index 95749ab65..b2dc12137 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/RoleMetaBaseSQLProvider.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/RoleMetaBaseSQLProvider.java
@@ -22,6 +22,7 @@ import static
org.apache.gravitino.storage.relational.mapper.RoleMetaMapper.GROU
import static
org.apache.gravitino.storage.relational.mapper.RoleMetaMapper.ROLE_TABLE_NAME;
import static
org.apache.gravitino.storage.relational.mapper.RoleMetaMapper.USER_ROLE_RELATION_TABLE_NAME;
+import org.apache.gravitino.storage.relational.mapper.MetalakeMetaMapper;
import org.apache.gravitino.storage.relational.mapper.SecurableObjectMapper;
import org.apache.gravitino.storage.relational.po.RolePO;
import org.apache.ibatis.annotations.Param;
@@ -93,6 +94,20 @@ public class RoleMetaBaseSQLProvider {
+ " AND ro.deleted_at = 0 AND se.deleted_at = 0";
}
+ public String listRolePOsByMetalake(@Param("metalakeName") String
metalakeName) {
+ return "SELECT rt.role_id as roleId, rt.role_name as roleName,"
+ + " rt.metalake_id as metalakeId, rt.properties as properties,"
+ + " rt.audit_info as auditInfo, rt.current_version as currentVersion,"
+ + " rt.last_version as lastVersion, rt.deleted_at as deletedAt"
+ + " FROM "
+ + ROLE_TABLE_NAME
+ + " rt JOIN "
+ + MetalakeMetaMapper.TABLE_NAME
+ + " mt ON rt.metalake_id = mt.metalake_id"
+ + " WHERE mt.metalake_name = #{metalakeName}"
+ + " AND rt.deleted_at = 0 AND mt.deleted_at = 0";
+ }
+
public String insertRoleMeta(@Param("roleMeta") RolePO rolePO) {
return "INSERT INTO "
+ ROLE_TABLE_NAME
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/service/RoleMetaService.java
b/core/src/main/java/org/apache/gravitino/storage/relational/service/RoleMetaService.java
index 4560b74e0..1e914f59a 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/service/RoleMetaService.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/service/RoleMetaService.java
@@ -20,11 +20,13 @@ package org.apache.gravitino.storage.relational.service;
import com.google.common.collect.Lists;
import java.io.IOException;
+import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.gravitino.Entity;
import org.apache.gravitino.MetadataObject;
import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.Namespace;
import org.apache.gravitino.authorization.AuthorizationUtils;
import org.apache.gravitino.authorization.SecurableObject;
import org.apache.gravitino.exceptions.NoSuchEntityException;
@@ -237,6 +239,22 @@ public class RoleMetaService {
SecurableObjectMapper.class, mapper ->
mapper.listSecurableObjectsByRoleId(roleId));
}
+ public List<RoleEntity> listRolesByNamespace(Namespace namespace) {
+ AuthorizationUtils.checkRoleNamespace(namespace);
+ String metalakeName = namespace.level(0);
+
+ List<RolePO> rolePOs =
+ SessionUtils.getWithoutCommit(
+ RoleMetaMapper.class, mapper ->
mapper.listRolePOsByMetalake(metalakeName));
+
+ return rolePOs.stream()
+ .map(
+ po ->
+ POConverters.fromRolePO(
+ po, Collections.emptyList(),
AuthorizationUtils.ofRoleNamespace(metalakeName)))
+ .collect(Collectors.toList());
+ }
+
public int deleteRoleMetasByLegacyTimeline(long legacyTimeline, int limit) {
int[] roleDeletedCount = new int[] {0};
int[] userRoleRelDeletedCount = new int[] {0};
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/service/SupportsDesiredFields.java
b/core/src/main/java/org/apache/gravitino/storage/relational/service/SupportsDesiredFields.java
deleted file mode 100644
index 42978fa50..000000000
---
a/core/src/main/java/org/apache/gravitino/storage/relational/service/SupportsDesiredFields.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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.storage.relational.service;
-
-import java.util.Set;
-import org.apache.gravitino.Field;
-
-/** The handler supports to skip fields to acquire part desired fields. */
-interface SupportsDesiredFields<R> {
-
- /**
- * The fields which could be desired.
- *
- * @return The fields which are desired.
- */
- Set<Field> desiredFields();
-
- /**
- * The return value of the handler.
- *
- * @return The return value of the handler.
- */
- R execute();
-}
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/service/SupportsDesiredFieldsHandlers.java
b/core/src/main/java/org/apache/gravitino/storage/relational/service/SupportsDesiredFieldsHandlers.java
deleted file mode 100644
index b5b10a7b6..000000000
---
a/core/src/main/java/org/apache/gravitino/storage/relational/service/SupportsDesiredFieldsHandlers.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.storage.relational.service;
-
-import com.google.common.collect.Lists;
-import java.util.List;
-import java.util.Set;
-import org.apache.gravitino.Field;
-
-/**
- * This class is the collection wrapper of SupportsDesiredFields handler. The
class will contain all
- * the handlers can proceed the data. We can choose different handlers
according to the desired
- * fields to acquire better performance.
- *
- * @param <T> The value type which the handler will return.
- */
-class SupportsDesiredFieldsHandlers<T> {
- private final List<SupportsDesiredFields<T>> methods = Lists.newArrayList();
-
- // We should put the low-cost handler into the front of the list.
- void addHandler(SupportsDesiredFields<T> supportsSkippingFields) {
- methods.add(supportsSkippingFields);
- }
-
- T execute(Set<Field> desiredFields) {
- for (SupportsDesiredFields<T> method : methods) {
- if (method.desiredFields().containsAll(desiredFields)) {
- return method.execute();
- }
- }
-
- throw new IllegalArgumentException("Don't support skip fields");
- }
-}
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/service/UserMetaService.java
b/core/src/main/java/org/apache/gravitino/storage/relational/service/UserMetaService.java
index f64b4ab40..a8991da14 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/service/UserMetaService.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/service/UserMetaService.java
@@ -30,7 +30,6 @@ import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.gravitino.Entity;
-import org.apache.gravitino.Field;
import org.apache.gravitino.HasIdentifier;
import org.apache.gravitino.NameIdentifier;
import org.apache.gravitino.Namespace;
@@ -249,18 +248,34 @@ public class UserMetaService {
return newEntity;
}
- public List<UserEntity> listUsersByNamespace(Namespace namespace, Set<Field>
skippingFields) {
+ public List<UserEntity> listUsersByNamespace(Namespace namespace, boolean
allFields) {
AuthorizationUtils.checkUserNamespace(namespace);
String metalakeName = namespace.level(0);
- SupportsDesiredFieldsHandlers<List<UserEntity>> handlers =
- new SupportsDesiredFieldsHandlers<>();
- handlers.addHandler(new ListDesiredRolesHandler(metalakeName));
- handlers.addHandler(new ListAllFieldsHandler(metalakeName));
-
- Set<Field> desiredFields = Sets.newHashSet(UserEntity.fieldSet());
- desiredFields.removeAll(skippingFields);
- return handlers.execute(desiredFields);
+ if (allFields) {
+ Long metalakeId =
MetalakeMetaService.getInstance().getMetalakeIdByName(metalakeName);
+ List<ExtendedUserPO> userPOs =
+ SessionUtils.getWithoutCommit(
+ UserMetaMapper.class, mapper ->
mapper.listExtendedUserPOsByMetalakeId(metalakeId));
+ return userPOs.stream()
+ .map(
+ po ->
+ POConverters.fromExtendedUserPO(
+ po, AuthorizationUtils.ofUserNamespace(metalakeName)))
+ .collect(Collectors.toList());
+ } else {
+ List<UserPO> userPOs =
+ SessionUtils.getWithoutCommit(
+ UserMetaMapper.class, mapper ->
mapper.listUserPOsByMetalake(metalakeName));
+ return userPOs.stream()
+ .map(
+ po ->
+ POConverters.fromUserPO(
+ po,
+ Collections.emptyList(),
+ AuthorizationUtils.ofUserNamespace(metalakeName)))
+ .collect(Collectors.toList());
+ }
}
public int deleteUserMetasByLegacyTimeline(long legacyTimeline, int limit) {
@@ -282,63 +297,4 @@ public class UserMetaService {
return userDeletedCount[0] + userRoleRelDeletedCount[0];
}
-
- private static class ListDesiredRolesHandler implements
SupportsDesiredFields<List<UserEntity>> {
- private final String metalakeName;
-
- ListDesiredRolesHandler(String metalakeName) {
- this.metalakeName = metalakeName;
- }
-
- @Override
- public Set<Field> desiredFields() {
- Set<Field> requiredFields = Sets.newHashSet(UserEntity.fieldSet());
- requiredFields.remove(UserEntity.ROLE_IDS);
- requiredFields.remove(UserEntity.ROLE_NAMES);
-
- return requiredFields;
- }
-
- @Override
- public List<UserEntity> execute() {
- List<UserPO> userPOs =
- SessionUtils.getWithoutCommit(
- UserMetaMapper.class, mapper ->
mapper.listUserPOsByMetalake(metalakeName));
- return userPOs.stream()
- .map(
- po ->
- POConverters.fromUserPO(
- po,
- Collections.emptyList(),
- AuthorizationUtils.ofUserNamespace(metalakeName)))
- .collect(Collectors.toList());
- }
- }
-
- private static class ListAllFieldsHandler implements
SupportsDesiredFields<List<UserEntity>> {
- final String metalakeName;
-
- ListAllFieldsHandler(String metalakeName) {
- this.metalakeName = metalakeName;
- }
-
- @Override
- public Set<Field> desiredFields() {
- return UserEntity.fieldSet();
- }
-
- @Override
- public List<UserEntity> execute() {
- Long metalakeId =
MetalakeMetaService.getInstance().getMetalakeIdByName(metalakeName);
- List<ExtendedUserPO> userPOs =
- SessionUtils.getWithoutCommit(
- UserMetaMapper.class, mapper ->
mapper.listExtendedUserPOsByMetalakeId(metalakeId));
- return userPOs.stream()
- .map(
- po ->
- POConverters.fromExtendedUserPO(
- po, AuthorizationUtils.ofUserNamespace(metalakeName)))
- .collect(Collectors.toList());
- }
- }
}
diff --git
a/core/src/test/java/org/apache/gravitino/authorization/TestAccessControlManager.java
b/core/src/test/java/org/apache/gravitino/authorization/TestAccessControlManager.java
index 1c7a26dec..6dfaf54fe 100644
---
a/core/src/test/java/org/apache/gravitino/authorization/TestAccessControlManager.java
+++
b/core/src/test/java/org/apache/gravitino/authorization/TestAccessControlManager.java
@@ -397,6 +397,32 @@ public class TestAccessControlManager {
Assertions.assertFalse(dropped1);
}
+ @Test
+ public void testListRoles() {
+ Map<String, String> props = ImmutableMap.of("k1", "v1");
+
+ accessControlManager.createRole(
+ "metalake_list",
+ "testList1",
+ props,
+ Lists.newArrayList(
+ SecurableObjects.ofCatalog(
+ "catalog",
Lists.newArrayList(Privileges.UseCatalog.allow()))));
+
+ accessControlManager.createRole(
+ "metalake_list",
+ "testList2",
+ props,
+ Lists.newArrayList(
+ SecurableObjects.ofCatalog(
+ "catalog",
Lists.newArrayList(Privileges.UseCatalog.allow()))));
+
+ // Test to list roles
+ String[] actualRoles = accessControlManager.listRoleNames("metalake_list");
+ Arrays.sort(actualRoles);
+ Assertions.assertArrayEquals(new String[] {"testList1", "testList2"},
actualRoles);
+ }
+
private void testProperties(Map<String, String> expectedProps, Map<String,
String> testProps) {
expectedProps.forEach(
(k, v) -> {
diff --git a/core/src/test/java/org/apache/gravitino/meta/TestEntity.java
b/core/src/test/java/org/apache/gravitino/meta/TestEntity.java
index f4c32dca7..f657f01a9 100644
--- a/core/src/test/java/org/apache/gravitino/meta/TestEntity.java
+++ b/core/src/test/java/org/apache/gravitino/meta/TestEntity.java
@@ -296,7 +296,7 @@ public class TestEntity {
Lists.newArrayList(
SecurableObjects.ofCatalog(
catalogName,
Lists.newArrayList(Privileges.UseCatalog.allow()))),
- fields.get(RoleEntity.SECURABLE_OBJECT));
+ fields.get(RoleEntity.SECURABLE_OBJECTS));
RoleEntity roleWithoutFields =
RoleEntity.builder()
diff --git
a/core/src/test/java/org/apache/gravitino/storage/relational/TestJDBCBackend.java
b/core/src/test/java/org/apache/gravitino/storage/relational/TestJDBCBackend.java
index b141eb696..c67c9697a 100644
---
a/core/src/test/java/org/apache/gravitino/storage/relational/TestJDBCBackend.java
+++
b/core/src/test/java/org/apache/gravitino/storage/relational/TestJDBCBackend.java
@@ -45,7 +45,6 @@ import java.sql.SQLException;
import java.sql.Statement;
import java.time.Instant;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -715,29 +714,26 @@ public class TestJDBCBackend {
// meta data list
List<BaseMetalake> metaLakes =
- backend.list(metalake.namespace(), Entity.EntityType.METALAKE,
Collections.emptySet());
+ backend.list(metalake.namespace(), Entity.EntityType.METALAKE, true);
assertTrue(metaLakes.contains(metalake));
List<CatalogEntity> catalogs =
- backend.list(catalog.namespace(), Entity.EntityType.CATALOG,
Collections.emptySet());
+ backend.list(catalog.namespace(), Entity.EntityType.CATALOG, true);
assertTrue(catalogs.contains(catalog));
- List<SchemaEntity> schemas =
- backend.list(schema.namespace(), Entity.EntityType.SCHEMA,
Collections.emptySet());
+ List<SchemaEntity> schemas = backend.list(schema.namespace(),
Entity.EntityType.SCHEMA, true);
assertTrue(schemas.contains(schema));
- List<TableEntity> tables =
- backend.list(table.namespace(), Entity.EntityType.TABLE,
Collections.emptySet());
+ List<TableEntity> tables = backend.list(table.namespace(),
Entity.EntityType.TABLE, true);
assertTrue(tables.contains(table));
List<FilesetEntity> filesets =
- backend.list(fileset.namespace(), Entity.EntityType.FILESET,
Collections.emptySet());
+ backend.list(fileset.namespace(), Entity.EntityType.FILESET, true);
assertFalse(filesets.contains(fileset));
assertTrue(filesets.contains(filesetV2));
assertEquals("2",
filesets.get(filesets.indexOf(filesetV2)).properties().get("version"));
- List<TopicEntity> topics =
- backend.list(topic.namespace(), Entity.EntityType.TOPIC,
Collections.emptySet());
+ List<TopicEntity> topics = backend.list(topic.namespace(),
Entity.EntityType.TOPIC, true);
assertTrue(topics.contains(topic));
RoleEntity roleEntity = backend.get(role.nameIdentifier(),
Entity.EntityType.ROLE);
@@ -763,8 +759,7 @@ public class TestJDBCBackend {
TagEntity tagEntity = backend.get(tag.nameIdentifier(),
Entity.EntityType.TAG);
assertEquals(tag, tagEntity);
- List<TagEntity> tags =
- backend.list(tag.namespace(), Entity.EntityType.TAG,
Collections.emptySet());
+ List<TagEntity> tags = backend.list(tag.namespace(),
Entity.EntityType.TAG, true);
assertTrue(tags.contains(tag));
assertEquals(1, tags.size());
diff --git
a/core/src/test/java/org/apache/gravitino/storage/relational/service/TestRoleMetaService.java
b/core/src/test/java/org/apache/gravitino/storage/relational/service/TestRoleMetaService.java
index d811b8b59..4a781f018 100644
---
a/core/src/test/java/org/apache/gravitino/storage/relational/service/TestRoleMetaService.java
+++
b/core/src/test/java/org/apache/gravitino/storage/relational/service/TestRoleMetaService.java
@@ -106,6 +106,55 @@ class TestRoleMetaService extends TestJDBCBackend {
Assertions.assertEquals(role1,
roleMetaService.getRoleByIdentifier(role1.nameIdentifier()));
}
+ @Test
+ void testListRoles() throws IOException {
+ AuditInfo auditInfo =
+
AuditInfo.builder().withCreator("creator").withCreateTime(Instant.now()).build();
+ BaseMetalake metalake =
+ createBaseMakeLake(RandomIdGenerator.INSTANCE.nextId(), metalakeName,
auditInfo);
+ backend.insert(metalake, false);
+
+ CatalogEntity catalog =
+ createCatalog(
+ RandomIdGenerator.INSTANCE.nextId(), Namespace.of("metalake"),
"catalog", auditInfo);
+ backend.insert(catalog, false);
+
+ RoleEntity role1 =
+ createRoleEntity(
+ RandomIdGenerator.INSTANCE.nextId(),
+ AuthorizationUtils.ofRoleNamespace(metalakeName),
+ "role1",
+ auditInfo,
+ SecurableObjects.ofCatalog(
+ "catalog", Lists.newArrayList(Privileges.UseCatalog.allow())),
+ ImmutableMap.of("k1", "v1"));
+
+ RoleEntity role2 =
+ createRoleEntity(
+ RandomIdGenerator.INSTANCE.nextId(),
+ AuthorizationUtils.ofRoleNamespace(metalakeName),
+ "role2",
+ auditInfo,
+ SecurableObjects.ofCatalog(
+ "catalog", Lists.newArrayList(Privileges.UseCatalog.allow())),
+ ImmutableMap.of("k1", "v1"));
+
+ backend.insert(role1, false);
+ backend.insert(role2, false);
+
+ RoleMetaService roleMetaService = RoleMetaService.getInstance();
+ List<RoleEntity> actualRoles =
+
roleMetaService.listRolesByNamespace(AuthorizationUtils.ofRoleNamespace(metalakeName));
+ actualRoles.sort(Comparator.comparing(RoleEntity::name));
+ List<RoleEntity> expectRoles = Lists.newArrayList(role1, role2);
+ Assertions.assertEquals(expectRoles.size(), actualRoles.size());
+ for (int index = 0; index < expectRoles.size(); index++) {
+ RoleEntity expectRole = expectRoles.get(index);
+ RoleEntity actualRole = actualRoles.get(index);
+ Assertions.assertEquals(expectRole.name(), actualRole.name());
+ }
+ }
+
@Test
void insertRole() throws IOException {
AuditInfo auditInfo =
diff --git
a/core/src/test/java/org/apache/gravitino/storage/relational/service/TestUserMetaService.java
b/core/src/test/java/org/apache/gravitino/storage/relational/service/TestUserMetaService.java
index 0d037317d..0efd886ee 100644
---
a/core/src/test/java/org/apache/gravitino/storage/relational/service/TestUserMetaService.java
+++
b/core/src/test/java/org/apache/gravitino/storage/relational/service/TestUserMetaService.java
@@ -27,7 +27,6 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.Instant;
-import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
@@ -173,7 +172,7 @@ class TestUserMetaService extends TestJDBCBackend {
UserMetaService userMetaService = UserMetaService.getInstance();
List<UserEntity> actualUsers =
userMetaService.listUsersByNamespace(
- AuthorizationUtils.ofUserNamespace(metalakeName),
Collections.emptySet());
+ AuthorizationUtils.ofUserNamespace(metalakeName), true);
actualUsers.sort(Comparator.comparing(UserEntity::name));
List<UserEntity> expectUsers = Lists.newArrayList(user1, user2);
Assertions.assertEquals(expectUsers.size(), actualUsers.size());
diff --git
a/server/src/main/java/org/apache/gravitino/server/web/rest/RoleOperations.java
b/server/src/main/java/org/apache/gravitino/server/web/rest/RoleOperations.java
index 1fa8a443f..b006471e3 100644
---
a/server/src/main/java/org/apache/gravitino/server/web/rest/RoleOperations.java
+++
b/server/src/main/java/org/apache/gravitino/server/web/rest/RoleOperations.java
@@ -44,6 +44,7 @@ import org.apache.gravitino.authorization.SecurableObjects;
import org.apache.gravitino.dto.authorization.SecurableObjectDTO;
import org.apache.gravitino.dto.requests.RoleCreateRequest;
import org.apache.gravitino.dto.responses.DeleteResponse;
+import org.apache.gravitino.dto.responses.NameListResponse;
import org.apache.gravitino.dto.responses.RoleResponse;
import org.apache.gravitino.dto.util.DTOConverters;
import org.apache.gravitino.exceptions.NoSuchMetadataObjectException;
@@ -68,6 +69,27 @@ public class RoleOperations {
this.accessControlManager =
GravitinoEnv.getInstance().accessControlDispatcher();
}
+ @GET
+ @Produces("application/vnd.gravitino.v1+json")
+ @Timed(name = "list-role." + MetricNames.HTTP_PROCESS_DURATION, absolute =
true)
+ @ResponseMetered(name = "list-role", absolute = true)
+ public Response listRoles(@PathParam("metalake") String metalake) {
+ try {
+ return Utils.doAs(
+ httpRequest,
+ () ->
+ TreeLockUtils.doWithTreeLock(
+ NameIdentifier.of(metalake),
+ LockType.READ,
+ () -> {
+ String[] names =
accessControlManager.listRoleNames(metalake);
+ return Utils.ok(new NameListResponse(names));
+ }));
+ } catch (Exception e) {
+ return ExceptionHandlers.handleRoleException(OperationType.LIST, "",
metalake, e);
+ }
+ }
+
@GET
@Path("{role}")
@Produces("application/vnd.gravitino.v1+json")
diff --git
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestRoleOperations.java
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestRoleOperations.java
index a00f91b4d..eb365d1ac 100644
---
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestRoleOperations.java
+++
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestRoleOperations.java
@@ -54,6 +54,7 @@ import org.apache.gravitino.dto.requests.RoleCreateRequest;
import org.apache.gravitino.dto.responses.DeleteResponse;
import org.apache.gravitino.dto.responses.ErrorConstants;
import org.apache.gravitino.dto.responses.ErrorResponse;
+import org.apache.gravitino.dto.responses.NameListResponse;
import org.apache.gravitino.dto.responses.RoleResponse;
import org.apache.gravitino.dto.util.DTOConverters;
import org.apache.gravitino.exceptions.NoSuchMetadataObjectException;
@@ -454,4 +455,51 @@ public class TestRoleOperations extends JerseyTest {
NoSuchMetadataObjectException.class,
() -> RoleOperations.checkSecurableObject("metalake",
DTOConverters.toDTO(fileset)));
}
+
+ @Test
+ public void testListRoleNames() {
+ when(manager.listRoleNames(any())).thenReturn(new String[] {"role"});
+
+ Response resp =
+ target("/metalakes/metalake1/roles/")
+ .request(MediaType.APPLICATION_JSON_TYPE)
+ .accept("application/vnd.gravitino.v1+json")
+ .get();
+ Assertions.assertEquals(Response.Status.OK.getStatusCode(),
resp.getStatus());
+
+ NameListResponse listResponse = resp.readEntity(NameListResponse.class);
+ Assertions.assertEquals(0, listResponse.getCode());
+
+ Assertions.assertEquals(1, listResponse.getNames().length);
+ Assertions.assertEquals("role", listResponse.getNames()[0]);
+
+ // Test to throw NoSuchMetalakeException
+ doThrow(new NoSuchMetalakeException("mock
error")).when(manager).listRoleNames(any());
+ Response resp1 =
+ target("/metalakes/metalake1/roles/")
+ .request(MediaType.APPLICATION_JSON_TYPE)
+ .accept("application/vnd.gravitino.v1+json")
+ .get();
+
+ Assertions.assertEquals(Response.Status.NOT_FOUND.getStatusCode(),
resp1.getStatus());
+
+ ErrorResponse errorResponse = resp1.readEntity(ErrorResponse.class);
+ Assertions.assertEquals(ErrorConstants.NOT_FOUND_CODE,
errorResponse.getCode());
+ Assertions.assertEquals(NoSuchMetalakeException.class.getSimpleName(),
errorResponse.getType());
+
+ // Test to throw internal RuntimeException
+ doThrow(new RuntimeException("mock
error")).when(manager).listRoleNames(any());
+ Response resp3 =
+ target("/metalakes/metalake1/roles")
+ .request(MediaType.APPLICATION_JSON_TYPE)
+ .accept("application/vnd.gravitino.v1+json")
+ .get();
+
+ Assertions.assertEquals(
+ Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(),
resp3.getStatus());
+
+ ErrorResponse errorResponse2 = resp3.readEntity(ErrorResponse.class);
+ Assertions.assertEquals(ErrorConstants.INTERNAL_ERROR_CODE,
errorResponse2.getCode());
+ Assertions.assertEquals(RuntimeException.class.getSimpleName(),
errorResponse2.getType());
+ }
}