Skip to content

Commit

Permalink
[apache#4154] improvment(client): Move access control function to Gra…
Browse files Browse the repository at this point in the history
…vitinoClient (apache#4215)

### What changes were proposed in this pull request?

 Move access control function to GravitinoClient

### Why are the changes needed?

Fix: apache#4154

### Does this PR introduce _any_ user-facing change?
No.

### How was this patch tested?
Modified the UTs.
  • Loading branch information
jerqi committed Aug 6, 2024
1 parent 5f4d733 commit 03e7ff3
Show file tree
Hide file tree
Showing 6 changed files with 659 additions and 425 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,35 +27,14 @@
import java.util.stream.Collectors;
import org.apache.gravitino.MetalakeChange;
import org.apache.gravitino.SupportsMetalakes;
import org.apache.gravitino.authorization.Group;
import org.apache.gravitino.authorization.Role;
import org.apache.gravitino.authorization.SecurableObject;
import org.apache.gravitino.authorization.User;
import org.apache.gravitino.dto.authorization.SecurableObjectDTO;
import org.apache.gravitino.dto.requests.GroupAddRequest;
import org.apache.gravitino.dto.requests.MetalakeCreateRequest;
import org.apache.gravitino.dto.requests.MetalakeUpdateRequest;
import org.apache.gravitino.dto.requests.MetalakeUpdatesRequest;
import org.apache.gravitino.dto.requests.RoleCreateRequest;
import org.apache.gravitino.dto.requests.RoleGrantRequest;
import org.apache.gravitino.dto.requests.RoleRevokeRequest;
import org.apache.gravitino.dto.requests.UserAddRequest;
import org.apache.gravitino.dto.responses.DeleteResponse;
import org.apache.gravitino.dto.responses.DropResponse;
import org.apache.gravitino.dto.responses.GroupResponse;
import org.apache.gravitino.dto.responses.MetalakeListResponse;
import org.apache.gravitino.dto.responses.MetalakeResponse;
import org.apache.gravitino.dto.responses.RemoveResponse;
import org.apache.gravitino.dto.responses.RoleResponse;
import org.apache.gravitino.dto.responses.UserResponse;
import org.apache.gravitino.exceptions.GroupAlreadyExistsException;
import org.apache.gravitino.exceptions.MetalakeAlreadyExistsException;
import org.apache.gravitino.exceptions.NoSuchGroupException;
import org.apache.gravitino.exceptions.NoSuchMetalakeException;
import org.apache.gravitino.exceptions.NoSuchRoleException;
import org.apache.gravitino.exceptions.NoSuchUserException;
import org.apache.gravitino.exceptions.RoleAlreadyExistsException;
import org.apache.gravitino.exceptions.UserAlreadyExistsException;

/**
* Apache Gravitino Client for the administrator to interact with the Gravitino API, allowing the
Expand All @@ -64,11 +43,6 @@
* <p>Normal users should use {@link GravitinoClient} to connect with the Gravitino server.
*/
public class GravitinoAdminClient extends GravitinoClientBase implements SupportsMetalakes {
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_PERMISSION_PATH = "api/metalakes/%s/permissions/%s";
private static final String BLANK_PLACE_HOLDER = "";

/**
* Constructs a new GravitinoClient with the given URI, authenticator and AuthDataProvider.
Expand Down Expand Up @@ -189,341 +163,6 @@ public boolean dropMetalake(String name) {
return resp.dropped();
}

/**
* Adds a new User.
*
* @param metalake The Metalake of the User.
* @param user The name of the User.
* @return The added User instance.
* @throws UserAlreadyExistsException If a User with the same name already exists.
* @throws NoSuchMetalakeException If the Metalake with the given name does not exist.
* @throws RuntimeException If adding the User encounters storage issues.
*/
public User addUser(String metalake, String user)
throws UserAlreadyExistsException, NoSuchMetalakeException {
UserAddRequest req = new UserAddRequest(user);
req.validate();

UserResponse resp =
restClient.post(
String.format(API_METALAKES_USERS_PATH, metalake, BLANK_PLACE_HOLDER),
req,
UserResponse.class,
Collections.emptyMap(),
ErrorHandlers.userErrorHandler());
resp.validate();

return resp.getUser();
}

/**
* Removes a User.
*
* @param metalake The Metalake of the User.
* @param user The name of the User.
* @return True if the User was successfully removed, false only when there's no such user,
* otherwise it will throw an exception.
* @throws NoSuchMetalakeException If the Metalake with the given name does not exist.
* @throws RuntimeException If removing the User encounters storage issues.
*/
public boolean removeUser(String metalake, String user) throws NoSuchMetalakeException {
RemoveResponse resp =
restClient.delete(
String.format(API_METALAKES_USERS_PATH, metalake, user),
RemoveResponse.class,
Collections.emptyMap(),
ErrorHandlers.userErrorHandler());
resp.validate();

return resp.removed();
}

/**
* Gets a User.
*
* @param metalake The Metalake of the User.
* @param user The name of the User.
* @return The getting User instance.
* @throws NoSuchUserException If the User with the given name does not exist.
* @throws NoSuchMetalakeException If the Metalake with the given name does not exist.
* @throws RuntimeException If getting the User encounters storage issues.
*/
public User getUser(String metalake, String user)
throws NoSuchUserException, NoSuchMetalakeException {
UserResponse resp =
restClient.get(
String.format(API_METALAKES_USERS_PATH, metalake, user),
UserResponse.class,
Collections.emptyMap(),
ErrorHandlers.userErrorHandler());
resp.validate();

return resp.getUser();
}

/**
* Adds a new Group.
*
* @param metalake The Metalake of the Group.
* @param group The name of the Group.
* @return The Added Group instance.
* @throws GroupAlreadyExistsException If a Group with the same name already exists.
* @throws NoSuchMetalakeException If the Metalake with the given name does not exist.
* @throws RuntimeException If adding the Group encounters storage issues.
*/
public Group addGroup(String metalake, String group)
throws GroupAlreadyExistsException, NoSuchMetalakeException {
GroupAddRequest req = new GroupAddRequest(group);
req.validate();

GroupResponse resp =
restClient.post(
String.format(API_METALAKES_GROUPS_PATH, metalake, BLANK_PLACE_HOLDER),
req,
GroupResponse.class,
Collections.emptyMap(),
ErrorHandlers.groupErrorHandler());
resp.validate();

return resp.getGroup();
}

/**
* Removes a Group.
*
* @param metalake The Metalake of the Group.
* @param group THe name of the Group.
* @return True if the Group was successfully removed, false only when there's no such group,
* otherwise it will throw an exception.
* @throws NoSuchMetalakeException If the Metalake with the given name does not exist.
* @throws RuntimeException If removing the Group encounters storage issues.
*/
public boolean removeGroup(String metalake, String group) throws NoSuchMetalakeException {
RemoveResponse resp =
restClient.delete(
String.format(API_METALAKES_GROUPS_PATH, metalake, group),
RemoveResponse.class,
Collections.emptyMap(),
ErrorHandlers.groupErrorHandler());
resp.validate();

return resp.removed();
}

/**
* Gets a Group.
*
* @param metalake The Metalake of the Group.
* @param group The name of the Group.
* @return The getting Group instance.
* @throws NoSuchGroupException If the Group with the given name does not exist.
* @throws NoSuchMetalakeException If the Metalake with the given name does not exist.
* @throws RuntimeException If getting the Group encounters storage issues.
*/
public Group getGroup(String metalake, String group)
throws NoSuchGroupException, NoSuchMetalakeException {
GroupResponse resp =
restClient.get(
String.format(API_METALAKES_GROUPS_PATH, metalake, group),
GroupResponse.class,
Collections.emptyMap(),
ErrorHandlers.groupErrorHandler());
resp.validate();

return resp.getGroup();
}

/**
* Gets a Role.
*
* @param metalake The Metalake of the Role.
* @param role The name of the Role.
* @return The getting Role instance.
* @throws NoSuchRoleException If the Role with the given name does not exist.
* @throws NoSuchMetalakeException If the Metalake with the given name does not exist.
* @throws RuntimeException If getting the Role encounters storage issues.
*/
public Role getRole(String metalake, String role)
throws NoSuchRoleException, NoSuchMetalakeException {
RoleResponse resp =
restClient.get(
String.format(API_METALAKES_ROLES_PATH, metalake, role),
RoleResponse.class,
Collections.emptyMap(),
ErrorHandlers.roleErrorHandler());
resp.validate();

return resp.getRole();
}

/**
* Deletes a Role.
*
* @param metalake The Metalake of the Role.
* @param role The name of the Role.
* @return True if the Role was successfully deleted, false only when there's no such role,
* otherwise it will throw an exception.
* @throws NoSuchMetalakeException If the Metalake with the given name does not exist.
* @throws RuntimeException If deleting the Role encounters storage issues.
*/
public boolean deleteRole(String metalake, String role) throws NoSuchMetalakeException {
DeleteResponse resp =
restClient.delete(
String.format(API_METALAKES_ROLES_PATH, metalake, role),
DeleteResponse.class,
Collections.emptyMap(),
ErrorHandlers.roleErrorHandler());
resp.validate();

return resp.deleted();
}

/**
* Creates a new Role.
*
* @param metalake The Metalake of the Role.
* @param role The name of the Role.
* @param properties The properties of the Role.
* @param securableObjects The securable objects of the Role.
* @return The created Role instance.
* @throws RoleAlreadyExistsException If a Role with the same name already exists.
* @throws NoSuchMetalakeException If the Metalake with the given name does not exist.
* @throws RuntimeException If creating the Role encounters storage issues.
*/
public Role createRole(
String metalake,
String role,
Map<String, String> properties,
List<SecurableObject> securableObjects)
throws RoleAlreadyExistsException, NoSuchMetalakeException {
RoleCreateRequest req =
new RoleCreateRequest(
role,
properties,
securableObjects.stream()
.map(DTOConverters::toSecurableObject)
.toArray(SecurableObjectDTO[]::new));
req.validate();

RoleResponse resp =
restClient.post(
String.format(API_METALAKES_ROLES_PATH, metalake, BLANK_PLACE_HOLDER),
req,
RoleResponse.class,
Collections.emptyMap(),
ErrorHandlers.roleErrorHandler());
resp.validate();

return resp.getRole();
}
/**
* Grant roles to a user.
*
* @param metalake The metalake of the User.
* @param user The name of the User.
* @param roles The names of the Role.
* @return The Group after granted.
* @throws NoSuchUserException If the User with the given name does not exist.
* @throws NoSuchRoleException If the Role with the given name does not exist.
* @throws NoSuchMetalakeException If the Metalake with the given name does not exist.
* @throws RuntimeException If granting roles to a user encounters storage issues.
*/
public User grantRolesToUser(String metalake, List<String> roles, String user)
throws NoSuchUserException, NoSuchRoleException, NoSuchMetalakeException {
RoleGrantRequest request = new RoleGrantRequest(roles);
UserResponse resp =
restClient.put(
String.format(API_PERMISSION_PATH, metalake, String.format("users/%s/grant", user)),
request,
UserResponse.class,
Collections.emptyMap(),
ErrorHandlers.permissionOperationErrorHandler());
resp.validate();

return resp.getUser();
}

/**
* Grant roles to a group.
*
* @param metalake The metalake of the Group.
* @param group The name of the Group.
* @param roles The names of the Role.
* @return The Group after granted.
* @throws NoSuchGroupException If the Group with the given name does not exist.
* @throws NoSuchRoleException If the Role with the given name does not exist.
* @throws NoSuchMetalakeException If the Metalake with the given name does not exist.
* @throws RuntimeException If granting roles to a group encounters storage issues.
*/
public Group grantRolesToGroup(String metalake, List<String> roles, String group)
throws NoSuchGroupException, NoSuchRoleException, NoSuchMetalakeException {
RoleGrantRequest request = new RoleGrantRequest(roles);
GroupResponse resp =
restClient.put(
String.format(API_PERMISSION_PATH, metalake, String.format("groups/%s/grant", group)),
request,
GroupResponse.class,
Collections.emptyMap(),
ErrorHandlers.permissionOperationErrorHandler());
resp.validate();

return resp.getGroup();
}

/**
* Revoke roles from a user.
*
* @param metalake The metalake of the User.
* @param user The name of the User.
* @param roles The names of the Role.
* @return The User after revoked.
* @throws NoSuchUserException If the User with the given name does not exist.
* @throws NoSuchRoleException If the Role with the given name does not exist.
* @throws NoSuchMetalakeException If the Metalake with the given name does not exist.
* @throws RuntimeException If revoking roles from a user encounters storage issues.
*/
public User revokeRolesFromUser(String metalake, List<String> roles, String user)
throws NoSuchUserException, NoSuchRoleException, NoSuchMetalakeException {
RoleRevokeRequest request = new RoleRevokeRequest(roles);
UserResponse resp =
restClient.put(
String.format(API_PERMISSION_PATH, metalake, String.format("users/%s/revoke", user)),
request,
UserResponse.class,
Collections.emptyMap(),
ErrorHandlers.permissionOperationErrorHandler());
resp.validate();

return resp.getUser();
}

/**
* Revoke roles from a group.
*
* @param metalake The metalake of the Group.
* @param group The name of the Group.
* @param roles The names of the Role.
* @return The Group after revoked.
* @throws NoSuchGroupException If the Group with the given name does not exist.
* @throws NoSuchRoleException If the Role with the given name does not exist.
* @throws NoSuchMetalakeException If the Metalake with the given name does not exist.
* @throws RuntimeException If revoking roles from a group encounters storage issues.
*/
public Group revokeRolesFromGroup(String metalake, List<String> roles, String group)
throws NoSuchGroupException, NoSuchRoleException, NoSuchMetalakeException {
RoleRevokeRequest request = new RoleRevokeRequest(roles);
GroupResponse resp =
restClient.put(
String.format(API_PERMISSION_PATH, metalake, String.format("groups/%s/revoke", group)),
request,
GroupResponse.class,
Collections.emptyMap(),
ErrorHandlers.permissionOperationErrorHandler());
resp.validate();

return resp.getGroup();
}

/**
* Creates a new builder for constructing a GravitinoClient.
*
Expand Down
Loading

0 comments on commit 03e7ff3

Please sign in to comment.