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 <ror...@apache.org>
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;
-
-@NameBindings.AccessControlInterfaces
-@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());
-  }
-}

Reply via email to