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 627e88ffb [#4126] improvement(core): Remove MetalakeAdmin API (#4127)
627e88ffb is described below
commit 627e88ffb9cbb8f5efe1b6e8af3a69f8e051d3e0
Author: roryqi <[email protected]>
AuthorDate: Tue Jul 16 18:21:18 2024 +0800
[#4126] improvement(core): Remove MetalakeAdmin API (#4127)
### What changes were proposed in this pull request?
Remove MetalakeAdmin API.
### Why are the changes needed?
Fix: #4126
### Does this PR introduce _any_ user-facing change?
Remove API. But this API isn't released.
### How was this patch tested?
Existing tests.
---
.../gravitino/client/GravitinoAdminClient.java | 45 -----
.../apache/gravitino/client/TestMetalakeAdmin.java | 110 -----------
.../authorization/AccessControlManager.java | 91 ++-------
.../gravitino/authorization/AdminManager.java | 122 ------------
.../authorization/TestAccessControlManager.java | 21 --
.../gravitino/server/web/rest/GroupOperations.java | 33 +++-
.../server/web/rest/MetalakeAdminOperations.java | 98 ----------
.../server/web/rest/PermissionOperations.java | 76 ++++++--
.../gravitino/server/web/rest/RoleOperations.java | 37 ++--
.../gravitino/server/web/rest/UserOperations.java | 32 +++-
.../web/rest/TestMetalakeAdminOperations.java | 213 ---------------------
11 files changed, 149 insertions(+), 729 deletions(-)
diff --git
a/clients/client-java/src/main/java/org/apache/gravitino/client/GravitinoAdminClient.java
b/clients/client-java/src/main/java/org/apache/gravitino/client/GravitinoAdminClient.java
index 67d32289f..b70839733 100644
---
a/clients/client-java/src/main/java/org/apache/gravitino/client/GravitinoAdminClient.java
+++
b/clients/client-java/src/main/java/org/apache/gravitino/client/GravitinoAdminClient.java
@@ -67,7 +67,6 @@ public class GravitinoAdminClient extends GravitinoClientBase
implements Support
private static final String API_METALAKES_USERS_PATH =
"api/metalakes/%s/users/%s";
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_ADMIN_PATH = "api/admins/%s";
private static final String API_PERMISSION_PATH =
"api/metalakes/%s/permissions/%s";
private static final String BLANK_PLACE_HOLDER = "";
@@ -334,50 +333,6 @@ public class GravitinoAdminClient extends
GravitinoClientBase implements Support
return resp.getGroup();
}
- /**
- * Adds a new metalake admin.
- *
- * @param user The name of the User.
- * @return The added User instance.
- * @throws UserAlreadyExistsException If a metalake admin with the same name
already exists.
- * @throws RuntimeException If adding the User encounters storage issues.
- */
- public User addMetalakeAdmin(String user) throws UserAlreadyExistsException {
- UserAddRequest req = new UserAddRequest(user);
- req.validate();
-
- UserResponse resp =
- restClient.post(
- String.format(API_ADMIN_PATH, BLANK_PLACE_HOLDER),
- req,
- UserResponse.class,
- Collections.emptyMap(),
- ErrorHandlers.userErrorHandler());
- resp.validate();
-
- return resp.getUser();
- }
-
- /**
- * Removes a metalake admin.
- *
- * @param user The name of the User.
- * @return True if the User was successfully removed, false only when
there's no such metalake
- * admin, otherwise it will throw an exception.
- * @throws RuntimeException If removing the User encounters storage issues.
- */
- public boolean removeMetalakeAdmin(String user) {
- RemoveResponse resp =
- restClient.delete(
- String.format(API_ADMIN_PATH, user),
- RemoveResponse.class,
- Collections.emptyMap(),
- ErrorHandlers.userErrorHandler());
- resp.validate();
-
- return resp.removed();
- }
-
/**
* Gets a Role.
*
diff --git
a/clients/client-java/src/test/java/org/apache/gravitino/client/TestMetalakeAdmin.java
b/clients/client-java/src/test/java/org/apache/gravitino/client/TestMetalakeAdmin.java
deleted file mode 100644
index 6dd10965d..000000000
---
a/clients/client-java/src/test/java/org/apache/gravitino/client/TestMetalakeAdmin.java
+++ /dev/null
@@ -1,110 +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.client;
-
-import static javax.servlet.http.HttpServletResponse.SC_CONFLICT;
-import static javax.servlet.http.HttpServletResponse.SC_OK;
-import static org.apache.hc.core5.http.HttpStatus.SC_SERVER_ERROR;
-
-import java.time.Instant;
-import org.apache.gravitino.authorization.User;
-import org.apache.gravitino.dto.AuditDTO;
-import org.apache.gravitino.dto.authorization.UserDTO;
-import org.apache.gravitino.dto.requests.UserAddRequest;
-import org.apache.gravitino.dto.responses.ErrorResponse;
-import org.apache.gravitino.dto.responses.RemoveResponse;
-import org.apache.gravitino.dto.responses.UserResponse;
-import org.apache.gravitino.exceptions.UserAlreadyExistsException;
-import org.apache.hc.core5.http.Method;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-
-public class TestMetalakeAdmin extends TestBase {
-
- private static final String API_ADMINS_PATH = "api/admins/%s";
-
- @BeforeAll
- public static void setUp() throws Exception {
- TestBase.setUp();
- }
-
- @Test
- public void testAddMetalakeAdmin() throws Exception {
- String username = "user";
- String userPath = withSlash(String.format(API_ADMINS_PATH, ""));
- UserAddRequest request = new UserAddRequest(username);
-
- UserDTO mockUser = mockUserDTO(username);
- UserResponse userResponse = new UserResponse(mockUser);
- buildMockResource(Method.POST, userPath, request, userResponse, SC_OK);
-
- User addedUser = client.addMetalakeAdmin(username);
- Assertions.assertNotNull(addedUser);
- assertUser(addedUser, mockUser);
-
- // test UserAlreadyExistsException
- ErrorResponse errResp1 =
- ErrorResponse.alreadyExists(
- UserAlreadyExistsException.class.getSimpleName(), "user already
exists");
- buildMockResource(Method.POST, userPath, request, errResp1, SC_CONFLICT);
- Exception ex =
- Assertions.assertThrows(
- UserAlreadyExistsException.class, () ->
client.addMetalakeAdmin(username));
- Assertions.assertEquals("user already exists", ex.getMessage());
-
- // test RuntimeException
- ErrorResponse errResp3 = ErrorResponse.internalError("internal error");
- buildMockResource(Method.POST, userPath, request, errResp3,
SC_SERVER_ERROR);
- Assertions.assertThrows(
- RuntimeException.class, () -> client.addMetalakeAdmin(username),
"internal error");
- }
-
- @Test
- public void testRemoveMetalakeAdmin() throws Exception {
- String username = "user";
- String rolePath = withSlash(String.format(API_ADMINS_PATH, username));
-
- RemoveResponse removeResponse = new RemoveResponse(true);
- buildMockResource(Method.DELETE, rolePath, null, removeResponse, SC_OK);
-
- Assertions.assertTrue(client.removeMetalakeAdmin(username));
-
- removeResponse = new RemoveResponse(false);
- buildMockResource(Method.DELETE, rolePath, null, removeResponse, SC_OK);
- Assertions.assertFalse(client.removeMetalakeAdmin(username));
-
- // test RuntimeException
- ErrorResponse errResp = ErrorResponse.internalError("internal error");
- buildMockResource(Method.DELETE, rolePath, null, errResp, SC_SERVER_ERROR);
- Assertions.assertThrows(RuntimeException.class, () ->
client.removeMetalakeAdmin(username));
- }
-
- private UserDTO mockUserDTO(String name) {
- return UserDTO.builder()
- .withName(name)
-
.withAudit(AuditDTO.builder().withCreator("creator").withCreateTime(Instant.now()).build())
- .build();
- }
-
- private void assertUser(User expected, User actual) {
- Assertions.assertEquals(expected.name(), actual.name());
- Assertions.assertEquals(expected.roles(), actual.roles());
- }
-}
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 2425f6d58..69ca26bb7 100644
---
a/core/src/main/java/org/apache/gravitino/authorization/AccessControlManager.java
+++
b/core/src/main/java/org/apache/gravitino/authorization/AccessControlManager.java
@@ -22,6 +22,7 @@ import com.google.common.annotations.VisibleForTesting;
import java.util.List;
import java.util.Map;
import org.apache.gravitino.Config;
+import org.apache.gravitino.Configs;
import org.apache.gravitino.EntityStore;
import org.apache.gravitino.exceptions.GroupAlreadyExistsException;
import org.apache.gravitino.exceptions.NoSuchGroupException;
@@ -31,30 +32,23 @@ import org.apache.gravitino.exceptions.NoSuchUserException;
import org.apache.gravitino.exceptions.RoleAlreadyExistsException;
import org.apache.gravitino.exceptions.UserAlreadyExistsException;
import org.apache.gravitino.storage.IdGenerator;
-import org.apache.gravitino.utils.Executable;
/**
- * AccessControlManager is used for manage users, roles, admin, grant
information, this class is an
- * entrance class for tenant management. This lock policy about this is as
follows: First, admin
- * operations are prevented by one lock. Then, other operations are prevented
by the other lock. For
- * non-admin operations, Apache Gravitino doesn't choose metalake level lock.
There are some reasons
- * mainly: First, the metalake can be renamed by users. It's hard to maintain
a map with metalake as
- * the key. Second, the lock will be couped with life cycle of the metalake.
+ * AccessControlManager is used for manage users, roles, grant information,
this class is an
+ * entrance class for tenant management. The operations will be protected by
one lock.
*/
public class AccessControlManager {
private final UserGroupManager userGroupManager;
- private final AdminManager adminManager;
private final RoleManager roleManager;
private final PermissionManager permissionManager;
- private final Object adminOperationLock = new Object();
- private final Object nonAdminOperationLock = new Object();
+ private final List<String> serviceAdmins;
public AccessControlManager(EntityStore store, IdGenerator idGenerator,
Config config) {
- this.adminManager = new AdminManager(store, idGenerator, config);
this.roleManager = new RoleManager(store, idGenerator, config);
this.userGroupManager = new UserGroupManager(store, idGenerator);
this.permissionManager = new PermissionManager(store, roleManager);
+ this.serviceAdmins = config.get(Configs.SERVICE_ADMINS);
}
/**
@@ -69,7 +63,7 @@ public class AccessControlManager {
*/
public User addUser(String metalake, String user)
throws UserAlreadyExistsException, NoSuchMetalakeException {
- return doWithNonAdminLock(() -> userGroupManager.addUser(metalake, user));
+ return userGroupManager.addUser(metalake, user);
}
/**
@@ -83,7 +77,7 @@ public class AccessControlManager {
* @throws RuntimeException If removing the User encounters storage issues.
*/
public boolean removeUser(String metalake, String user) throws
NoSuchMetalakeException {
- return doWithNonAdminLock(() -> userGroupManager.removeUser(metalake,
user));
+ return userGroupManager.removeUser(metalake, user);
}
/**
@@ -98,7 +92,7 @@ public class AccessControlManager {
*/
public User getUser(String metalake, String user)
throws NoSuchUserException, NoSuchMetalakeException {
- return doWithNonAdminLock(() -> userGroupManager.getUser(metalake, user));
+ return userGroupManager.getUser(metalake, user);
}
/**
@@ -113,7 +107,7 @@ public class AccessControlManager {
*/
public Group addGroup(String metalake, String group)
throws GroupAlreadyExistsException, NoSuchMetalakeException {
- return doWithNonAdminLock(() -> userGroupManager.addGroup(metalake,
group));
+ return userGroupManager.addGroup(metalake, group);
}
/**
@@ -127,7 +121,7 @@ public class AccessControlManager {
* @throws RuntimeException If removing the Group encounters storage issues.
*/
public boolean removeGroup(String metalake, String group) throws
NoSuchMetalakeException {
- return doWithNonAdminLock(() -> userGroupManager.removeGroup(metalake,
group));
+ return userGroupManager.removeGroup(metalake, group);
}
/**
@@ -142,7 +136,7 @@ public class AccessControlManager {
*/
public Group getGroup(String metalake, String group)
throws NoSuchGroupException, NoSuchMetalakeException {
- return doWithNonAdminLock(() -> userGroupManager.getGroup(metalake,
group));
+ return userGroupManager.getGroup(metalake, group);
}
/**
@@ -159,7 +153,7 @@ public class AccessControlManager {
*/
public User grantRolesToUser(String metalake, List<String> roles, String
user)
throws NoSuchUserException, NoSuchRoleException, NoSuchMetalakeException
{
- return doWithNonAdminLock(() ->
permissionManager.grantRolesToUser(metalake, roles, user));
+ return permissionManager.grantRolesToUser(metalake, roles, user);
}
/**
@@ -176,7 +170,7 @@ public class AccessControlManager {
*/
public Group grantRolesToGroup(String metalake, List<String> roles, String
group)
throws NoSuchGroupException, NoSuchRoleException,
NoSuchMetalakeException {
- return doWithNonAdminLock(() ->
permissionManager.grantRolesToGroup(metalake, roles, group));
+ return permissionManager.grantRolesToGroup(metalake, roles, group);
}
/**
@@ -193,7 +187,7 @@ public class AccessControlManager {
*/
public Group revokeRolesFromGroup(String metalake, List<String> roles,
String group)
throws NoSuchGroupException, NoSuchRoleException,
NoSuchMetalakeException {
- return doWithNonAdminLock(() ->
permissionManager.revokeRolesFromGroup(metalake, roles, group));
+ return permissionManager.revokeRolesFromGroup(metalake, roles, group);
}
/**
@@ -210,31 +204,7 @@ public class AccessControlManager {
*/
public User revokeRolesFromUser(String metalake, List<String> roles, String
user)
throws NoSuchUserException, NoSuchRoleException, NoSuchMetalakeException
{
- return doWithNonAdminLock(() ->
permissionManager.revokeRolesFromUser(metalake, roles, user));
- }
-
- /**
- * Adds a new metalake admin.
- *
- * @param user The name of the User.
- * @return The added User instance.
- * @throws UserAlreadyExistsException If a metalake admin with the same name
already exists.
- * @throws RuntimeException If adding the User encounters storage issues.
- */
- public User addMetalakeAdmin(String user) throws UserAlreadyExistsException {
- return doWithAdminLock(() -> adminManager.addMetalakeAdmin(user));
- }
-
- /**
- * Removes a metalake admin.
- *
- * @param user The name of the User.
- * @return True if the User was successfully removed, false only when
there's no such metalake
- * admin, otherwise it will throw an exception.
- * @throws RuntimeException If removing the User encounters storage issues.
- */
- public boolean removeMetalakeAdmin(String user) {
- return doWithAdminLock(() -> adminManager.removeMetalakeAdmin(user));
+ return permissionManager.revokeRolesFromUser(metalake, roles, user);
}
/**
@@ -244,17 +214,7 @@ public class AccessControlManager {
* @return True if the user is service admin, otherwise false.
*/
public boolean isServiceAdmin(String user) {
- return adminManager.isServiceAdmin(user);
- }
-
- /**
- * Judges whether the user is the metalake admin.
- *
- * @param user the name of the user
- * @return True if the user is metalake admin, otherwise false.
- */
- public boolean isMetalakeAdmin(String user) {
- return doWithAdminLock(() -> adminManager.isMetalakeAdmin(user));
+ return serviceAdmins.contains(user);
}
/**
@@ -275,8 +235,7 @@ public class AccessControlManager {
Map<String, String> properties,
List<SecurableObject> securableObjects)
throws RoleAlreadyExistsException, NoSuchMetalakeException {
- return doWithNonAdminLock(
- () -> roleManager.createRole(metalake, role, properties,
securableObjects));
+ return roleManager.createRole(metalake, role, properties,
securableObjects);
}
/**
@@ -291,7 +250,7 @@ public class AccessControlManager {
*/
public Role getRole(String metalake, String role)
throws NoSuchRoleException, NoSuchMetalakeException {
- return doWithNonAdminLock(() -> roleManager.getRole(metalake, role));
+ return roleManager.getRole(metalake, role);
}
/**
@@ -305,23 +264,11 @@ public class AccessControlManager {
* @throws RuntimeException If deleting the Role encounters storage issues.
*/
public boolean deleteRole(String metalake, String role) throws
NoSuchMetalakeException {
- return doWithNonAdminLock(() -> roleManager.deleteRole(metalake, role));
+ return roleManager.deleteRole(metalake, role);
}
@VisibleForTesting
RoleManager getRoleManager() {
return roleManager;
}
-
- private <R, E extends Exception> R doWithNonAdminLock(Executable<R, E>
executable) throws E {
- synchronized (nonAdminOperationLock) {
- return executable.execute();
- }
- }
-
- private <R, E extends Exception> R doWithAdminLock(Executable<R, E>
executable) throws E {
- synchronized (adminOperationLock) {
- return executable.execute();
- }
- }
}
diff --git
a/core/src/main/java/org/apache/gravitino/authorization/AdminManager.java
b/core/src/main/java/org/apache/gravitino/authorization/AdminManager.java
deleted file mode 100644
index f1a6f7036..000000000
--- a/core/src/main/java/org/apache/gravitino/authorization/AdminManager.java
+++ /dev/null
@@ -1,122 +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.authorization;
-
-import com.google.common.collect.Lists;
-import java.io.IOException;
-import java.time.Instant;
-import java.util.List;
-import org.apache.gravitino.Config;
-import org.apache.gravitino.Configs;
-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.UserAlreadyExistsException;
-import org.apache.gravitino.meta.AuditInfo;
-import org.apache.gravitino.meta.UserEntity;
-import org.apache.gravitino.storage.IdGenerator;
-import org.apache.gravitino.utils.PrincipalUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * There are two kinds of admin roles in the system: service admin and
metalake admin. The service
- * admin is configured instead of managing by APIs. It is responsible for
creating metalake admin.
- * If Gravitino enables authorization, service admin is required. Metalake
admin can create a
- * metalake or drops its metalake. The metalake admin will be responsible for
managing the access
- * control. AdminManager operates underlying store using the lock because kv
storage needs the lock.
- */
-class AdminManager {
-
- private static final Logger LOG =
LoggerFactory.getLogger(AdminManager.class);
-
- private final EntityStore store;
- private final IdGenerator idGenerator;
- private final List<String> serviceAdmins;
-
- AdminManager(EntityStore store, IdGenerator idGenerator, Config config) {
- this.store = store;
- this.idGenerator = idGenerator;
- this.serviceAdmins = config.get(Configs.SERVICE_ADMINS);
- }
-
- User addMetalakeAdmin(String user) {
-
- UserEntity userEntity =
- UserEntity.builder()
- .withId(idGenerator.nextId())
- .withName(user)
- .withNamespace(
- Namespace.of(
- Entity.SYSTEM_METALAKE_RESERVED_NAME,
- Entity.AUTHORIZATION_CATALOG_NAME,
- Entity.ADMIN_SCHEMA_NAME))
- .withRoleNames(Lists.newArrayList())
- .withAuditInfo(
- AuditInfo.builder()
-
.withCreator(PrincipalUtils.getCurrentPrincipal().getName())
- .withCreateTime(Instant.now())
- .build())
- .build();
- try {
- store.put(userEntity, false /* overwritten */);
- return userEntity;
- } catch (EntityAlreadyExistsException e) {
- LOG.warn("User {} in the metalake admin already exists", user, e);
- throw new UserAlreadyExistsException("User %s in the metalake admin
already exists", user);
- } catch (IOException ioe) {
- LOG.error("Adding user {} failed to the metalake admin due to storage
issues", user, ioe);
- throw new RuntimeException(ioe);
- }
- }
-
- boolean removeMetalakeAdmin(String user) {
- try {
- return store.delete(ofMetalakeAdmin(user), Entity.EntityType.USER);
- } catch (IOException ioe) {
- LOG.error(
- "Removing user {} from the metalake admin {} failed due to storage
issues", user, ioe);
- throw new RuntimeException(ioe);
- }
- }
-
- boolean isServiceAdmin(String user) {
- return serviceAdmins.contains(user);
- }
-
- boolean isMetalakeAdmin(String user) {
- try {
- return store.exists(ofMetalakeAdmin(user), Entity.EntityType.USER);
- } catch (IOException ioe) {
- LOG.error(
- "Fail to check whether {} is the metalake admin {} due to storage
issues", user, ioe);
- throw new RuntimeException(ioe);
- }
- }
-
- private NameIdentifier ofMetalakeAdmin(String user) {
- return NameIdentifier.of(
- Entity.SYSTEM_METALAKE_RESERVED_NAME,
- Entity.AUTHORIZATION_CATALOG_NAME,
- Entity.ADMIN_SCHEMA_NAME,
- user);
- }
-}
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 e0a6e3835..8035f303f 100644
---
a/core/src/test/java/org/apache/gravitino/authorization/TestAccessControlManager.java
+++
b/core/src/test/java/org/apache/gravitino/authorization/TestAccessControlManager.java
@@ -204,27 +204,6 @@ public class TestAccessControlManager {
Assertions.assertFalse(removed1);
}
- @Test
- public void testMetalakeAdmin() {
- User user = accessControlManager.addMetalakeAdmin("test");
- Assertions.assertEquals("test", user.name());
- Assertions.assertTrue(user.roles().isEmpty());
- Assertions.assertTrue(accessControlManager.isMetalakeAdmin("test"));
-
- // Test with UserAlreadyExistsException
- Assertions.assertThrows(
- UserAlreadyExistsException.class, () ->
accessControlManager.addMetalakeAdmin("test"));
-
- // Test to remove admin
- boolean removed = accessControlManager.removeMetalakeAdmin("test");
- Assertions.assertTrue(removed);
- Assertions.assertFalse(accessControlManager.isMetalakeAdmin("test"));
-
- // Test to remove non-existed admin
- boolean removed1 = accessControlManager.removeMetalakeAdmin("no-exist");
- Assertions.assertFalse(removed1);
- }
-
@Test
public void testServiceAdmin() {
Assertions.assertTrue(accessControlManager.isServiceAdmin("admin1"));
diff --git
a/server/src/main/java/org/apache/gravitino/server/web/rest/GroupOperations.java
b/server/src/main/java/org/apache/gravitino/server/web/rest/GroupOperations.java
index fb12c184b..d1ec13c7e 100644
---
a/server/src/main/java/org/apache/gravitino/server/web/rest/GroupOperations.java
+++
b/server/src/main/java/org/apache/gravitino/server/web/rest/GroupOperations.java
@@ -30,11 +30,15 @@ import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import org.apache.gravitino.GravitinoEnv;
+import org.apache.gravitino.NameIdentifier;
import org.apache.gravitino.authorization.AccessControlManager;
+import org.apache.gravitino.authorization.AuthorizationUtils;
import org.apache.gravitino.dto.requests.GroupAddRequest;
import org.apache.gravitino.dto.responses.GroupResponse;
import org.apache.gravitino.dto.responses.RemoveResponse;
import org.apache.gravitino.dto.util.DTOConverters;
+import org.apache.gravitino.lock.LockType;
+import org.apache.gravitino.lock.TreeLockUtils;
import org.apache.gravitino.metrics.MetricNames;
import org.apache.gravitino.server.authorization.NameBindings;
import org.apache.gravitino.server.web.Utils;
@@ -69,9 +73,14 @@ public class GroupOperations {
return Utils.doAs(
httpRequest,
() ->
- Utils.ok(
- new GroupResponse(
-
DTOConverters.toDTO(accessControlManager.getGroup(metalake, group)))));
+ TreeLockUtils.doWithTreeLock(
+ AuthorizationUtils.ofGroup(metalake, group),
+ LockType.READ,
+ () ->
+ Utils.ok(
+ new GroupResponse(
+ DTOConverters.toDTO(
+ accessControlManager.getGroup(metalake,
group))))));
} catch (Exception e) {
return ExceptionHandlers.handleGroupException(OperationType.GET, group,
metalake, e);
}
@@ -86,10 +95,14 @@ public class GroupOperations {
return Utils.doAs(
httpRequest,
() ->
- Utils.ok(
- new GroupResponse(
- DTOConverters.toDTO(
- accessControlManager.addGroup(metalake,
request.getName())))));
+ TreeLockUtils.doWithTreeLock(
+
NameIdentifier.of(AuthorizationUtils.ofGroupNamespace(metalake).levels()),
+ LockType.WRITE,
+ () ->
+ Utils.ok(
+ new GroupResponse(
+ DTOConverters.toDTO(
+ accessControlManager.addGroup(metalake,
request.getName()))))));
} catch (Exception e) {
return ExceptionHandlers.handleGroupException(
OperationType.ADD, request.getName(), metalake, e);
@@ -107,7 +120,11 @@ public class GroupOperations {
return Utils.doAs(
httpRequest,
() -> {
- boolean removed = accessControlManager.removeGroup(metalake,
group);
+ boolean removed =
+ TreeLockUtils.doWithTreeLock(
+
NameIdentifier.of(AuthorizationUtils.ofGroupNamespace(metalake).levels()),
+ LockType.WRITE,
+ () -> accessControlManager.removeGroup(metalake, group));
if (!removed) {
LOG.warn("Failed to remove group {} under metalake {}", group,
metalake);
}
diff --git
a/server/src/main/java/org/apache/gravitino/server/web/rest/MetalakeAdminOperations.java
b/server/src/main/java/org/apache/gravitino/server/web/rest/MetalakeAdminOperations.java
deleted file mode 100644
index 0b4aa1547..000000000
---
a/server/src/main/java/org/apache/gravitino/server/web/rest/MetalakeAdminOperations.java
+++ /dev/null
@@ -1,98 +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.server.web.rest;
-
-import com.codahale.metrics.annotation.ResponseMetered;
-import com.codahale.metrics.annotation.Timed;
-import javax.servlet.http.HttpServletRequest;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.Response;
-import org.apache.gravitino.GravitinoEnv;
-import org.apache.gravitino.authorization.AccessControlManager;
-import org.apache.gravitino.dto.requests.UserAddRequest;
-import org.apache.gravitino.dto.responses.RemoveResponse;
-import org.apache.gravitino.dto.responses.UserResponse;
-import org.apache.gravitino.dto.util.DTOConverters;
-import org.apache.gravitino.metrics.MetricNames;
-import org.apache.gravitino.server.authorization.NameBindings;
-import org.apache.gravitino.server.web.Utils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
[email protected]
-@Path("/admins")
-public class MetalakeAdminOperations {
- private static final Logger LOG =
LoggerFactory.getLogger(MetalakeAdminOperations.class);
-
- private final AccessControlManager accessControlManager;
-
- @Context private HttpServletRequest httpRequest;
-
- public MetalakeAdminOperations() {
- // Because accessManager may be null when Gravitino doesn't enable
authorization,
- // and Jersey injection doesn't support null value. So
MetalakeAdminOperations chooses to
- // retrieve accessControlManager from GravitinoEnv instead of injection
here.
- this.accessControlManager =
GravitinoEnv.getInstance().accessControlManager();
- }
-
- @POST
- @Produces("application/vnd.gravitino.v1+json")
- @Timed(name = "add-admin." + MetricNames.HTTP_PROCESS_DURATION, absolute =
true)
- @ResponseMetered(name = "add-admin", absolute = true)
- public Response addAdmin(UserAddRequest request) {
-
- try {
- return Utils.doAs(
- httpRequest,
- () ->
- Utils.ok(
- new UserResponse(
- DTOConverters.toDTO(
-
accessControlManager.addMetalakeAdmin(request.getName())))));
- } catch (Exception e) {
- return ExceptionHandlers.handleUserException(OperationType.ADD,
request.getName(), null, e);
- }
- }
-
- @DELETE
- @Path("{user}")
- @Produces("application/vnd.gravitino.v1+json")
- @Timed(name = "remove-admin." + MetricNames.HTTP_PROCESS_DURATION, absolute
= true)
- @ResponseMetered(name = "remove-admin", absolute = true)
- public Response removeAdmin(@PathParam("user") String user) {
- try {
- return Utils.doAs(
- httpRequest,
- () -> {
- boolean removed = accessControlManager.removeMetalakeAdmin(user);
- if (!removed) {
- LOG.warn("Failed to remove metalake admin user {}", user);
- }
- return Utils.ok(new RemoveResponse(removed));
- });
- } catch (Exception e) {
- return ExceptionHandlers.handleUserException(OperationType.REMOVE, user,
null, e);
- }
- }
-}
diff --git
a/server/src/main/java/org/apache/gravitino/server/web/rest/PermissionOperations.java
b/server/src/main/java/org/apache/gravitino/server/web/rest/PermissionOperations.java
index bc0decee9..c27791be5 100644
---
a/server/src/main/java/org/apache/gravitino/server/web/rest/PermissionOperations.java
+++
b/server/src/main/java/org/apache/gravitino/server/web/rest/PermissionOperations.java
@@ -29,12 +29,16 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import org.apache.commons.lang3.StringUtils;
import org.apache.gravitino.GravitinoEnv;
+import org.apache.gravitino.NameIdentifier;
import org.apache.gravitino.authorization.AccessControlManager;
+import org.apache.gravitino.authorization.AuthorizationUtils;
import org.apache.gravitino.dto.requests.RoleGrantRequest;
import org.apache.gravitino.dto.requests.RoleRevokeRequest;
import org.apache.gravitino.dto.responses.GroupResponse;
import org.apache.gravitino.dto.responses.UserResponse;
import org.apache.gravitino.dto.util.DTOConverters;
+import org.apache.gravitino.lock.LockType;
+import org.apache.gravitino.lock.TreeLockUtils;
import org.apache.gravitino.metrics.MetricNames;
import org.apache.gravitino.server.web.Utils;
@@ -65,11 +69,19 @@ public class PermissionOperations {
return Utils.doAs(
httpRequest,
() ->
- Utils.ok(
- new UserResponse(
- DTOConverters.toDTO(
- accessControlManager.grantRolesToUser(
- metalake, request.getRoleNames(), user)))));
+ TreeLockUtils.doWithTreeLock(
+ AuthorizationUtils.ofUser(metalake, user),
+ LockType.WRITE,
+ () ->
+ TreeLockUtils.doWithTreeLock(
+
NameIdentifier.of(AuthorizationUtils.ofRoleNamespace(metalake).levels()),
+ LockType.READ,
+ () ->
+ Utils.ok(
+ new UserResponse(
+ DTOConverters.toDTO(
+
accessControlManager.grantRolesToUser(
+ metalake,
request.getRoleNames(), user)))))));
} catch (Exception e) {
return ExceptionHandlers.handleUserPermissionOperationException(
OperationType.GRANT, StringUtils.join(request.getRoleNames(), ","),
user, e);
@@ -89,11 +101,19 @@ public class PermissionOperations {
return Utils.doAs(
httpRequest,
() ->
- Utils.ok(
- new GroupResponse(
- DTOConverters.toDTO(
- accessControlManager.grantRolesToGroup(
- metalake, request.getRoleNames(), group)))));
+ TreeLockUtils.doWithTreeLock(
+ AuthorizationUtils.ofGroup(metalake, group),
+ LockType.WRITE,
+ () ->
+ TreeLockUtils.doWithTreeLock(
+
NameIdentifier.of(AuthorizationUtils.ofRoleNamespace(metalake).levels()),
+ LockType.READ,
+ () ->
+ Utils.ok(
+ new GroupResponse(
+ DTOConverters.toDTO(
+
accessControlManager.grantRolesToGroup(
+ metalake,
request.getRoleNames(), group)))))));
} catch (Exception e) {
return ExceptionHandlers.handleGroupPermissionOperationException(
OperationType.GRANT, StringUtils.join(request.getRoleNames(), ","),
group, e);
@@ -113,11 +133,19 @@ public class PermissionOperations {
return Utils.doAs(
httpRequest,
() ->
- Utils.ok(
- new UserResponse(
- DTOConverters.toDTO(
- accessControlManager.revokeRolesFromUser(
- metalake, request.getRoleNames(), user)))));
+ TreeLockUtils.doWithTreeLock(
+ AuthorizationUtils.ofUser(metalake, user),
+ LockType.WRITE,
+ () ->
+ TreeLockUtils.doWithTreeLock(
+
NameIdentifier.of(AuthorizationUtils.ofRoleNamespace(metalake).levels()),
+ LockType.READ,
+ () ->
+ Utils.ok(
+ new UserResponse(
+ DTOConverters.toDTO(
+
accessControlManager.revokeRolesFromUser(
+ metalake,
request.getRoleNames(), user)))))));
} catch (Exception e) {
return ExceptionHandlers.handleUserPermissionOperationException(
OperationType.REVOKE, StringUtils.join(request.getRoleNames(), ","),
user, e);
@@ -137,11 +165,19 @@ public class PermissionOperations {
return Utils.doAs(
httpRequest,
() ->
- Utils.ok(
- new GroupResponse(
- DTOConverters.toDTO(
- accessControlManager.revokeRolesFromGroup(
- metalake, request.getRoleNames(), group)))));
+ TreeLockUtils.doWithTreeLock(
+ AuthorizationUtils.ofGroup(metalake, group),
+ LockType.WRITE,
+ () ->
+ TreeLockUtils.doWithTreeLock(
+
NameIdentifier.of(AuthorizationUtils.ofRoleNamespace(metalake).levels()),
+ LockType.READ,
+ () ->
+ Utils.ok(
+ new GroupResponse(
+ DTOConverters.toDTO(
+
accessControlManager.revokeRolesFromGroup(
+ metalake,
request.getRoleNames(), group)))))));
} catch (Exception e) {
return ExceptionHandlers.handleGroupPermissionOperationException(
OperationType.REVOKE, StringUtils.join(request.getRoleNames()),
group, e);
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 fdd4a0afb..66393a0ea 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
@@ -37,6 +37,7 @@ import org.apache.gravitino.MetadataObject;
import org.apache.gravitino.MetadataObjects;
import org.apache.gravitino.NameIdentifier;
import org.apache.gravitino.authorization.AccessControlManager;
+import org.apache.gravitino.authorization.AuthorizationUtils;
import org.apache.gravitino.authorization.Privilege;
import org.apache.gravitino.authorization.Privileges;
import org.apache.gravitino.authorization.SecurableObject;
@@ -75,9 +76,13 @@ public class RoleOperations {
return Utils.doAs(
httpRequest,
() ->
- Utils.ok(
- new RoleResponse(
-
DTOConverters.toDTO(accessControlManager.getRole(metalake, role)))));
+ TreeLockUtils.doWithTreeLock(
+ AuthorizationUtils.ofRole(metalake, role),
+ LockType.READ,
+ () ->
+ Utils.ok(
+ new RoleResponse(
+
DTOConverters.toDTO(accessControlManager.getRole(metalake, role))))));
} catch (Exception e) {
return ExceptionHandlers.handleRoleException(OperationType.GET, role,
metalake, e);
}
@@ -118,14 +123,18 @@ public class RoleOperations {
.collect(Collectors.toList())))
.collect(Collectors.toList());
- return Utils.ok(
- new RoleResponse(
- DTOConverters.toDTO(
- accessControlManager.createRole(
- metalake,
- request.getName(),
- request.getProperties(),
- securableObjects))));
+ return TreeLockUtils.doWithTreeLock(
+
NameIdentifier.of(AuthorizationUtils.ofRoleNamespace(metalake).levels()),
+ LockType.WRITE,
+ () ->
+ Utils.ok(
+ new RoleResponse(
+ DTOConverters.toDTO(
+ accessControlManager.createRole(
+ metalake,
+ request.getName(),
+ request.getProperties(),
+ securableObjects)))));
});
} catch (Exception e) {
@@ -145,7 +154,11 @@ public class RoleOperations {
return Utils.doAs(
httpRequest,
() -> {
- boolean deleted = accessControlManager.deleteRole(metalake, role);
+ boolean deleted =
+ TreeLockUtils.doWithTreeLock(
+
NameIdentifier.of(AuthorizationUtils.ofRoleNamespace(metalake).levels()),
+ LockType.WRITE,
+ () -> accessControlManager.deleteRole(metalake, role));
if (!deleted) {
LOG.warn("Failed to delete role {} under metalake {}", role,
metalake);
}
diff --git
a/server/src/main/java/org/apache/gravitino/server/web/rest/UserOperations.java
b/server/src/main/java/org/apache/gravitino/server/web/rest/UserOperations.java
index 4203cd510..7b63082f4 100644
---
a/server/src/main/java/org/apache/gravitino/server/web/rest/UserOperations.java
+++
b/server/src/main/java/org/apache/gravitino/server/web/rest/UserOperations.java
@@ -30,11 +30,15 @@ import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import org.apache.gravitino.GravitinoEnv;
+import org.apache.gravitino.NameIdentifier;
import org.apache.gravitino.authorization.AccessControlManager;
+import org.apache.gravitino.authorization.AuthorizationUtils;
import org.apache.gravitino.dto.requests.UserAddRequest;
import org.apache.gravitino.dto.responses.RemoveResponse;
import org.apache.gravitino.dto.responses.UserResponse;
import org.apache.gravitino.dto.util.DTOConverters;
+import org.apache.gravitino.lock.LockType;
+import org.apache.gravitino.lock.TreeLockUtils;
import org.apache.gravitino.metrics.MetricNames;
import org.apache.gravitino.server.authorization.NameBindings;
import org.apache.gravitino.server.web.Utils;
@@ -68,9 +72,13 @@ public class UserOperations {
return Utils.doAs(
httpRequest,
() ->
- Utils.ok(
- new UserResponse(
-
DTOConverters.toDTO(accessControlManager.getUser(metalake, user)))));
+ TreeLockUtils.doWithTreeLock(
+ AuthorizationUtils.ofGroup(metalake, user),
+ LockType.READ,
+ () ->
+ Utils.ok(
+ new UserResponse(
+
DTOConverters.toDTO(accessControlManager.getUser(metalake, user))))));
} catch (Exception e) {
return ExceptionHandlers.handleUserException(OperationType.GET, user,
metalake, e);
}
@@ -85,10 +93,14 @@ public class UserOperations {
return Utils.doAs(
httpRequest,
() ->
- Utils.ok(
- new UserResponse(
- DTOConverters.toDTO(
- accessControlManager.addUser(metalake,
request.getName())))));
+ TreeLockUtils.doWithTreeLock(
+
NameIdentifier.of(AuthorizationUtils.ofGroupNamespace(metalake).levels()),
+ LockType.WRITE,
+ () ->
+ Utils.ok(
+ new UserResponse(
+ DTOConverters.toDTO(
+ accessControlManager.addUser(metalake,
request.getName()))))));
} catch (Exception e) {
return ExceptionHandlers.handleUserException(
OperationType.ADD, request.getName(), metalake, e);
@@ -106,7 +118,11 @@ public class UserOperations {
return Utils.doAs(
httpRequest,
() -> {
- boolean removed = accessControlManager.removeUser(metalake, user);
+ boolean removed =
+ TreeLockUtils.doWithTreeLock(
+
NameIdentifier.of(AuthorizationUtils.ofGroupNamespace(metalake).levels()),
+ LockType.WRITE,
+ () -> accessControlManager.removeUser(metalake, user));
if (!removed) {
LOG.warn("Failed to remove user {} under metalake {}", user,
metalake);
}
diff --git
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestMetalakeAdminOperations.java
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestMetalakeAdminOperations.java
deleted file mode 100644
index c7b074e26..000000000
---
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestMetalakeAdminOperations.java
+++ /dev/null
@@ -1,213 +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.server.web.rest;
-
-import static org.apache.gravitino.Configs.TREE_LOCK_CLEAN_INTERVAL;
-import static org.apache.gravitino.Configs.TREE_LOCK_MAX_NODE_IN_MEMORY;
-import static org.apache.gravitino.Configs.TREE_LOCK_MIN_NODE_IN_MEMORY;
-import static org.mockito.ArgumentMatchers.any;
-
-import java.io.IOException;
-import java.time.Instant;
-import java.util.Collections;
-import javax.servlet.http.HttpServletRequest;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.core.Application;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import org.apache.commons.lang3.reflect.FieldUtils;
-import org.apache.gravitino.Config;
-import org.apache.gravitino.GravitinoEnv;
-import org.apache.gravitino.authorization.AccessControlManager;
-import org.apache.gravitino.authorization.User;
-import org.apache.gravitino.dto.authorization.UserDTO;
-import org.apache.gravitino.dto.requests.UserAddRequest;
-import org.apache.gravitino.dto.responses.ErrorConstants;
-import org.apache.gravitino.dto.responses.ErrorResponse;
-import org.apache.gravitino.dto.responses.RemoveResponse;
-import org.apache.gravitino.dto.responses.UserResponse;
-import org.apache.gravitino.exceptions.UserAlreadyExistsException;
-import org.apache.gravitino.lock.LockManager;
-import org.apache.gravitino.meta.AuditInfo;
-import org.apache.gravitino.meta.UserEntity;
-import org.apache.gravitino.rest.RESTUtils;
-import org.glassfish.hk2.utilities.binding.AbstractBinder;
-import org.glassfish.jersey.server.ResourceConfig;
-import org.glassfish.jersey.test.JerseyTest;
-import org.glassfish.jersey.test.TestProperties;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-import org.mockito.Mockito;
-
-public class TestMetalakeAdminOperations extends JerseyTest {
-
- private static final AccessControlManager manager =
Mockito.mock(AccessControlManager.class);
-
- private static class MockServletRequestFactory extends
ServletRequestFactoryBase {
- @Override
- public HttpServletRequest get() {
- HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
- Mockito.when(request.getRemoteUser()).thenReturn(null);
- return request;
- }
- }
-
- @BeforeAll
- public static void setup() throws IllegalAccessException {
- Config config = Mockito.mock(Config.class);
- Mockito.doReturn(100000L).when(config).get(TREE_LOCK_MAX_NODE_IN_MEMORY);
- Mockito.doReturn(1000L).when(config).get(TREE_LOCK_MIN_NODE_IN_MEMORY);
- Mockito.doReturn(36000L).when(config).get(TREE_LOCK_CLEAN_INTERVAL);
- FieldUtils.writeField(GravitinoEnv.getInstance(), "lockManager", new
LockManager(config), true);
- FieldUtils.writeField(GravitinoEnv.getInstance(), "accessControlManager",
manager, true);
- }
-
- @Override
- protected Application configure() {
- try {
- forceSet(
- TestProperties.CONTAINER_PORT,
String.valueOf(RESTUtils.findAvailablePort(2000, 3000)));
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
-
- ResourceConfig resourceConfig = new ResourceConfig();
- resourceConfig.register(MetalakeAdminOperations.class);
- resourceConfig.register(
- new AbstractBinder() {
- @Override
- protected void configure() {
-
bindFactory(MockServletRequestFactory.class).to(HttpServletRequest.class);
- }
- });
-
- return resourceConfig;
- }
-
- @Test
- public void testAddMetalakeAdmin() {
- UserAddRequest req = new UserAddRequest("user1");
- User user = buildUser("user1");
-
- Mockito.when(manager.addMetalakeAdmin(any())).thenReturn(user);
-
- Response resp =
- target("/admins")
- .request(MediaType.APPLICATION_JSON_TYPE)
- .accept("application/vnd.gravitino.v1+json")
- .post(Entity.entity(req, MediaType.APPLICATION_JSON_TYPE));
-
- Assertions.assertEquals(Response.Status.OK.getStatusCode(),
resp.getStatus());
- Assertions.assertEquals(MediaType.APPLICATION_JSON_TYPE,
resp.getMediaType());
-
- UserResponse userResponse = resp.readEntity(UserResponse.class);
- Assertions.assertEquals(0, userResponse.getCode());
-
- UserDTO userDTO = userResponse.getUser();
- Assertions.assertEquals("user1", userDTO.name());
- Assertions.assertNotNull(userDTO.roles());
- Assertions.assertTrue(userDTO.roles().isEmpty());
-
- // Test to throw UserAlreadyExistsException
- Mockito.doThrow(new UserAlreadyExistsException("mock error"))
- .when(manager)
- .addMetalakeAdmin(any());
- Response resp2 =
- target("/admins")
- .request(MediaType.APPLICATION_JSON_TYPE)
- .accept("application/vnd.gravitino.v1+json")
- .post(Entity.entity(req, MediaType.APPLICATION_JSON_TYPE));
-
- Assertions.assertEquals(Response.Status.CONFLICT.getStatusCode(),
resp2.getStatus());
-
- ErrorResponse errorResponse1 = resp2.readEntity(ErrorResponse.class);
- Assertions.assertEquals(ErrorConstants.ALREADY_EXISTS_CODE,
errorResponse1.getCode());
- Assertions.assertEquals(
- UserAlreadyExistsException.class.getSimpleName(),
errorResponse1.getType());
-
- // Test to throw internal RuntimeException
- Mockito.doThrow(new RuntimeException("mock
error")).when(manager).addMetalakeAdmin(any());
- Response resp3 =
- target("/admins")
- .request(MediaType.APPLICATION_JSON_TYPE)
- .accept("application/vnd.gravitino.v1+json")
- .post(Entity.entity(req, MediaType.APPLICATION_JSON_TYPE));
-
- 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());
- }
-
- private User buildUser(String user) {
- return UserEntity.builder()
- .withId(1L)
- .withName(user)
- .withRoleNames(Collections.emptyList())
- .withAuditInfo(
-
AuditInfo.builder().withCreator("creator").withCreateTime(Instant.now()).build())
- .build();
- }
-
- @Test
- public void testRemoveMetalakeAdmin() {
- Mockito.when(manager.removeMetalakeAdmin(any())).thenReturn(true);
-
- Response resp =
- target("/admins/user1")
- .request(MediaType.APPLICATION_JSON_TYPE)
- .accept("application/vnd.gravitino.v1+json")
- .delete();
-
- Assertions.assertEquals(Response.Status.OK.getStatusCode(),
resp.getStatus());
- RemoveResponse removeResponse = resp.readEntity(RemoveResponse.class);
- Assertions.assertEquals(0, removeResponse.getCode());
- Assertions.assertTrue(removeResponse.removed());
-
- // Test when failed to remove user
- Mockito.when(manager.removeMetalakeAdmin(any())).thenReturn(false);
- Response resp2 =
- target("/admins/user1")
- .request(MediaType.APPLICATION_JSON_TYPE)
- .accept("application/vnd.gravitino.v1+json")
- .delete();
-
- Assertions.assertEquals(Response.Status.OK.getStatusCode(),
resp2.getStatus());
- RemoveResponse removeResponse2 = resp2.readEntity(RemoveResponse.class);
- Assertions.assertEquals(0, removeResponse2.getCode());
- Assertions.assertFalse(removeResponse2.removed());
-
- Mockito.doThrow(new RuntimeException("mock
error")).when(manager).removeMetalakeAdmin(any());
- Response resp3 =
- target("/admins/user1")
- .request(MediaType.APPLICATION_JSON_TYPE)
- .accept("application/vnd.gravitino.v1+json")
- .delete();
-
- Assertions.assertEquals(
- Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(),
resp3.getStatus());
-
- ErrorResponse errorResponse = resp3.readEntity(ErrorResponse.class);
- Assertions.assertEquals(ErrorConstants.INTERNAL_ERROR_CODE,
errorResponse.getCode());
- Assertions.assertEquals(RuntimeException.class.getSimpleName(),
errorResponse.getType());
- }
-}