jerqi commented on code in PR #5021:
URL: https://github.com/apache/gravitino/pull/5021#discussion_r1792697675
##########
core/src/main/java/org/apache/gravitino/authorization/PermissionManager.java:
##########
@@ -373,11 +377,302 @@ User revokeRolesFromUser(String metalake, List<String>
roles, String user) {
}
}
- private List<String> toRoleNames(List<RoleEntity> roleEntities) {
- return
roleEntities.stream().map(RoleEntity::name).collect(Collectors.toList());
+ Role grantPrivilegesToRole(
+ String metalake, String role, MetadataObject object, List<Privilege>
privileges) {
+ try {
+ AuthorizationPluginCallbackWrapper authorizationPluginCallbackWrapper =
+ new AuthorizationPluginCallbackWrapper();
+
+ Role updatedRole =
+ store.update(
+ AuthorizationUtils.ofRole(metalake, role),
+ RoleEntity.class,
+ Entity.EntityType.ROLE,
+ roleEntity -> {
+ List<SecurableObject> grantedSecurableObjects =
+ generateNewSecurableObjects(
+ roleEntity.securableObjects(),
+ object,
+ targetObject -> {
+ if (targetObject == null) {
+ return createNewSecurableObject(
+ metalake,
+ role,
+ object,
+ privileges,
+ roleEntity,
+ authorizationPluginCallbackWrapper);
+ } else {
+ return updateGrantedSecurableObject(
+ metalake,
+ role,
+ object,
+ privileges,
+ roleEntity,
+ targetObject,
+ authorizationPluginCallbackWrapper);
+ }
+ });
+
+ AuditInfo auditInfo =
+ AuditInfo.builder()
+ .withCreator(roleEntity.auditInfo().creator())
+ .withCreateTime(roleEntity.auditInfo().createTime())
+
.withLastModifier(PrincipalUtils.getCurrentPrincipal().getName())
+ .withLastModifiedTime(Instant.now())
+ .build();
+
+ return RoleEntity.builder()
+ .withId(roleEntity.id())
+ .withName(roleEntity.name())
+ .withNamespace(roleEntity.namespace())
+ .withProperties(roleEntity.properties())
+ .withAuditInfo(auditInfo)
+ .withSecurableObjects(grantedSecurableObjects)
+ .build();
+ });
+
+ // Execute the authorization plugin callback
+ authorizationPluginCallbackWrapper.execute();
+ return updatedRole;
+ } catch (NoSuchEntityException nse) {
+ LOG.error("Failed to grant, role {} does not exist in the metalake {}",
role, metalake, nse);
+ throw new NoSuchRoleException(ROLE_DOES_NOT_EXIST_MSG, role, metalake);
+ } catch (IOException ioe) {
+ throw new RuntimeException(ioe);
+ }
+ }
+
+ private static SecurableObject updateGrantedSecurableObject(
+ String metalake,
+ String role,
+ MetadataObject object,
+ List<Privilege> privileges,
+ RoleEntity roleEntity,
+ SecurableObject targetObject,
+ AuthorizationPluginCallbackWrapper authorizationPluginCallbackWrapper) {
+ // Removed duplicated privileges by set
+ Set<Privilege> updatePrivileges = Sets.newHashSet();
+ updatePrivileges.addAll(targetObject.privileges());
+ // If old object contains all the privileges to grant, the object doesn't
+ // need to update.
+ if (updatePrivileges.containsAll(privileges)) {
+ return targetObject;
+ } else {
+ updatePrivileges.addAll(privileges);
+ AuthorizationUtils.checkDuplicatedNamePrivilege(privileges);
+
+ SecurableObject newSecurableObject =
+ SecurableObjects.parse(
+ targetObject.fullName(), targetObject.type(),
Lists.newArrayList(updatePrivileges));
+
+ // We set authorization callback here, we won't execute this callback in
this place.
+ // We will execute the callback after we execute the SQL transaction.
+ authorizationPluginCallbackWrapper.setCallback(
+ () ->
+ AuthorizationUtils.callAuthorizationPluginForMetadataObject(
+ metalake,
+ object,
+ authorizationPlugin -> {
+ authorizationPlugin.onRoleUpdated(
+ roleEntity,
+ RoleChange.updateSecurableObject(role, targetObject,
newSecurableObject));
+ }));
+
+ return newSecurableObject;
+ }
+ }
+
+ private static SecurableObject createNewSecurableObject(
+ String metalake,
+ String role,
+ MetadataObject object,
+ List<Privilege> privileges,
+ RoleEntity roleEntity,
+ AuthorizationPluginCallbackWrapper authorizationPluginCallbackWrapper) {
+ // Add a new securable object if there doesn't exist the object in the role
+ SecurableObject securableObject =
+ SecurableObjects.parse(object.fullName(), object.type(),
Lists.newArrayList(privileges));
+
+ // We set authorization callback here, we won't execute this callback in
this place.
+ // We will execute the callback after we execute the SQL transaction.
+ authorizationPluginCallbackWrapper.setCallback(
+ () ->
+ AuthorizationUtils.callAuthorizationPluginForMetadataObject(
+ metalake,
+ object,
+ authorizationPlugin -> {
+ authorizationPlugin.onRoleUpdated(
+ roleEntity, RoleChange.addSecurableObject(role,
securableObject));
+ }));
+
+ return securableObject;
+ }
+
+ Role revokePrivilegesFromRole(
+ String metalake, String role, MetadataObject object, List<Privilege>
privileges) {
+ try {
+ AuthorizationPluginCallbackWrapper authorizationCallbackWrapper =
+ new AuthorizationPluginCallbackWrapper();
+
+ RoleEntity updatedRole =
+ store.update(
+ AuthorizationUtils.ofRole(metalake, role),
+ RoleEntity.class,
+ Entity.EntityType.ROLE,
+ roleEntity -> {
+ List<SecurableObject> revokedSecurableObjects =
+ generateNewSecurableObjects(
+ roleEntity.securableObjects(),
+ object,
+ targetObject -> {
+ // If the securable object doesn't exist, we do
nothing except for
+ // logging.
+ if (targetObject == null) {
+ LOG.warn(
+ "Securable object {} type {} doesn't exist in
the role {}",
+ object.fullName(),
+ object.type(),
+ role);
+ return null;
+ } else {
+ // If the securable object exists, we remove the
privileges of the
+ // securable object and will remove duplicated
privileges at the same
+ // time.
+ return updateRevokedSecurableObject(
+ metalake,
+ role,
+ object,
+ privileges,
+ roleEntity,
+ targetObject,
+ authorizationCallbackWrapper);
+ }
+ });
+
+ AuditInfo auditInfo =
+ AuditInfo.builder()
+ .withCreator(roleEntity.auditInfo().creator())
+ .withCreateTime(roleEntity.auditInfo().createTime())
+
.withLastModifier(PrincipalUtils.getCurrentPrincipal().getName())
+ .withLastModifiedTime(Instant.now())
+ .build();
+
+ return RoleEntity.builder()
+ .withId(roleEntity.id())
+ .withName(roleEntity.name())
+ .withNamespace(roleEntity.namespace())
+ .withProperties(roleEntity.properties())
+ .withAuditInfo(auditInfo)
+ .withSecurableObjects(revokedSecurableObjects)
+ .build();
+ });
+
+ authorizationCallbackWrapper.execute();
+
+ return updatedRole;
+ } catch (NoSuchEntityException nse) {
+ LOG.error("Failed to revoke, role {} does not exist in the metalake {}",
role, metalake, nse);
+ throw new NoSuchRoleException(ROLE_DOES_NOT_EXIST_MSG, role, metalake);
+ } catch (IOException ioe) {
+ throw new RuntimeException(ioe);
+ }
+ }
+
+ private static SecurableObject updateRevokedSecurableObject(
+ String metalake,
+ String role,
+ MetadataObject object,
+ List<Privilege> privileges,
+ RoleEntity roleEntity,
+ SecurableObject targetObject,
+ AuthorizationPluginCallbackWrapper authorizationCallbackWrapper) {
+ // Use set to deduplicate the privileges
+ Set<Privilege> updatePrivileges = Sets.newHashSet();
+ updatePrivileges.addAll(targetObject.privileges());
+ privileges.forEach(updatePrivileges::remove);
+
+ // If the object still contain privilege, we should update the object
Review Comment:
Fixed.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]