-
Notifications
You must be signed in to change notification settings - Fork 593
[#4903] feat(core,server): Support to grant or revoke privileges for a role #5021
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
6b06613
to
32bb163
Compare
@lw-yang Could you help me review this pull request? |
fc4ee73
to
9e62ca7
Compare
NoSuchRoleException.class, | ||
() -> | ||
metalake.revokePrivilegesFromRole( | ||
"not-exist", metadataObject, Lists.newArrayList(Privileges.CreateCatalog.allow()))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should you add the tests about binding wrong privileges to the metadata object?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You'd better add more bad cases to test the robustness of your logic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added.
@@ -93,6 +94,10 @@ public Map<String, String> properties() { | |||
*/ | |||
@Override | |||
public List<SecurableObject> securableObjects() { | |||
if (securableObjects == null) { | |||
return Collections.emptyList(); | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will we return a null securableObjects
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Legacy code. Removed.
String.format("Doesn't support the type %s", object.type())); | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can create a helper method like this to simplify the code.
public static void check(final boolean expression, Supplier<? extends RuntimeException> exceptionToThrowSupplier) {
if (!expression) {
throw checkNotNull(exceptionToThrowSupplier).get();
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK.
|
||
List<SecurableObject> updateSecurableObjects = Lists.newArrayList(); | ||
// Only update the first matched securable object privilege | ||
for (SecurableObject securableObject : securableObjects) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible that there are many securable objects that equals to the object
in the List?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but it's enough that we add the first matched securable object like the comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not remove duplicated items in the roleEntity
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I can add the limitation for them.
List<SecurableObject> updateSecurableObjects = Lists.newArrayList(); | ||
// Only update the first matched securable object privilege | ||
for (SecurableObject securableObject : securableObjects) { | ||
if (!objectExist | ||
&& securableObject.type() == object.type() | ||
&& securableObject.fullName().equals(object.fullName())) { | ||
objectExist = true; | ||
Set<Privilege> updatePrivileges = Sets.newHashSet(); | ||
updatePrivileges.addAll(securableObject.privileges()); | ||
// If privileges has granted, we won't generate the new securable object. | ||
if (updatePrivileges.containsAll(privileges)) { | ||
updateSecurableObjects.add(securableObject); | ||
} else { | ||
updatePrivileges.addAll(privileges); | ||
SecurableObject newSecurableObject = | ||
SecurableObjects.parse( | ||
securableObject.fullName(), | ||
securableObject.type(), | ||
Lists.newArrayList(updatePrivileges)); | ||
|
||
updateSecurableObjects.add(newSecurableObject); | ||
AuthorizationUtils.callAuthorizationPluginForMetadataObject( | ||
metalake, | ||
object, | ||
authorizationPlugin -> { | ||
authorizationPlugin.onRoleUpdated( | ||
roleEntity, | ||
RoleChange.updateSecurableObject( | ||
role, securableObject, newSecurableObject)); | ||
}); | ||
} | ||
|
||
} else { | ||
updateSecurableObjects.add(securableObject); | ||
} | ||
} | ||
|
||
// If the role doesn't contain the securable object, the role appends a new securable | ||
// object. | ||
if (!objectExist) { | ||
SecurableObject securableObject = | ||
SecurableObjects.parse( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
List<SecurableObject> updateSecurableObjects = Lists.newArrayList(); | |
// Only update the first matched securable object privilege | |
for (SecurableObject securableObject : securableObjects) { | |
if (!objectExist | |
&& securableObject.type() == object.type() | |
&& securableObject.fullName().equals(object.fullName())) { | |
objectExist = true; | |
Set<Privilege> updatePrivileges = Sets.newHashSet(); | |
updatePrivileges.addAll(securableObject.privileges()); | |
// If privileges has granted, we won't generate the new securable object. | |
if (updatePrivileges.containsAll(privileges)) { | |
updateSecurableObjects.add(securableObject); | |
} else { | |
updatePrivileges.addAll(privileges); | |
SecurableObject newSecurableObject = | |
SecurableObjects.parse( | |
securableObject.fullName(), | |
securableObject.type(), | |
Lists.newArrayList(updatePrivileges)); | |
updateSecurableObjects.add(newSecurableObject); | |
AuthorizationUtils.callAuthorizationPluginForMetadataObject( | |
metalake, | |
object, | |
authorizationPlugin -> { | |
authorizationPlugin.onRoleUpdated( | |
roleEntity, | |
RoleChange.updateSecurableObject( | |
role, securableObject, newSecurableObject)); | |
}); | |
} | |
} else { | |
updateSecurableObjects.add(securableObject); | |
} | |
} | |
// If the role doesn't contain the securable object, the role appends a new securable | |
// object. | |
if (!objectExist) { | |
SecurableObject securableObject = | |
SecurableObjects.parse( | |
List<SecurableObject> updateSecurableObjects = Lists.newArrayList(securableObjects); | |
SecurableObject se = | |
securableObjects.stream().filter(securableObject -> securableObject.type() == object.type() | |
&& securableObject.fullName().equals(object.fullName())) | |
.findFirst().orElse(null); | |
if (se == null) { | |
SecurableObject securableObject = | |
SecurableObjects.parse( | |
object.fullName(), object.type(), Lists.newArrayList(privileges)); | |
AuthorizationUtils.callAuthorizationPluginForMetadataObject( | |
metalake, | |
object, | |
authorizationPlugin -> { | |
authorizationPlugin.onRoleUpdated( | |
roleEntity, RoleChange.addSecurableObject(role, securableObject)); | |
}); | |
updateSecurableObjects.add(securableObject); | |
} else { | |
Set<Privilege> updatePrivileges = Sets.newHashSet(); | |
updatePrivileges.addAll(se.privileges()); | |
if (!updatePrivileges.containsAll(privileges)) { | |
updatePrivileges.addAll(privileges); | |
SecurableObject newSecurableObject = | |
SecurableObjects.parse( | |
se.fullName(), | |
se.type(), | |
Lists.newArrayList(updatePrivileges)); | |
// Remove the old one and add the new one | |
updateSecurableObjects.remove(se); | |
updateSecurableObjects.add(newSecurableObject); | |
// Update the new newSecurableObject in the authorization plugin | |
AuthorizationUtils.callAuthorizationPluginForMetadataObject( | |
metalake, | |
object, | |
authorizationPlugin -> { | |
authorizationPlugin.onRoleUpdated( | |
roleEntity, | |
RoleChange.updateSecurableObject( | |
role, se, newSecurableObject)); | |
}); | |
} | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I rewrite here.
private List<String> toRoleNames(List<RoleEntity> roleEntities) { | ||
return roleEntities.stream().map(RoleEntity::name).collect(Collectors.toList()); | ||
Role grantPrivilegeToRole( | ||
String metalake, String role, MetadataObject object, List<Privilege> privileges) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you need to check if these privileges can be bound to this metadata object before you update the role.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also I think you need to deduplicate the privileges if the user inputs the same privileges.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I deduplicate privileges in the PermissonManager.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if two same privileges with one allow
and one deny
are both set, what will be happened and do you handle such scenario?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I add new check logic to avoid this case.
boolean objectExist = false; | ||
|
||
List<SecurableObject> updateSecurableObjects = Lists.newArrayList(); | ||
// Only update the first matched securable object privilege |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the meaning of this comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After discussing with Yuqi, I add more limitations. We won't have duplicated securable objects. So I remove this comment.
Lists.newArrayList(updatePrivileges)); | ||
|
||
updateSecurableObjects.add(newSecurableObject); | ||
AuthorizationUtils.callAuthorizationPluginForMetadataObject( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should you do this in the SQL transaction, or after the update is done?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
* @throws NoSuchMetadataObjectException If the metadata object 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
“grant”, not "revoke".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
* @throws RuntimeException If revoking roles from a group encounters storage issues. | ||
*/ | ||
public Role grantPrivilegeToRole(String role, MetadataObject object, List<Privilege> privileges) | ||
throws NoSuchRoleException, NoSuchMetadataObjectException, NoSuchMetalakeException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should also add an exception about failed to grant/revoke privileges to role, because some privileges cannot be bound to some metadata objects.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used IllegalArgumentException. WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On a second thought, maybe we should explicitly define an exception for illegal grant/revoke action, so that users will know better what issue it is, not implicitly thrown an exception here. Even for IllegalArgumentException
I would suggest clearly define it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I will do it.
* @throws NoSuchMetadataObjectException If the metadata object 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check all the codes to make sure no such error for "grant" or "revoke".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
|
||
Preconditions.checkArgument( | ||
securableObjects != null && securableObjects.length != 0, | ||
"\"securableObjects\" can't null or empty"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a UT and IT about the changes here, to check to create a role with empty/null privilege?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added.
* @return The role after granted. | ||
* @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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also here...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
.withAuditInfo(auditInfo) | ||
.withSecurableObjects(updateSecurableObjects) | ||
.build(); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The update logic here is too long, you'd better split into several helper methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
List<SecurableObject> securableObjects = roleEntity.securableObjects(); | ||
|
||
List<SecurableObject> updateSecurableObjects = Lists.newArrayList(); | ||
// Remove all the matching securable object privileges |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if all the securable object are not matched, or the privileges are not/partially matched, should you at least add some logs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added.
.build(); | ||
}); | ||
} catch (NoSuchEntityException nse) { | ||
LOG.warn("Failed to revoke, role {} does not exist in the metalake {}", role, metalake, nse); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
|
||
List<SecurableObject> updateSecurableObjects = Lists.newArrayList(); | ||
// Only update the first matched securable object privilege | ||
for (SecurableObject securableObject : securableObjects) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not remove duplicated items in the roleEntity
?
* @throws RuntimeException If revoking roles from a group encounters storage issues. | ||
*/ | ||
public Role grantPrivilegeToRole(String role, MetadataObject object, List<Privilege> privileges) | ||
throws NoSuchRoleException, NoSuchMetadataObjectException, NoSuchMetalakeException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On a second thought, maybe we should explicitly define an exception for illegal grant/revoke action, so that users will know better what issue it is, not implicitly thrown an exception here. Even for IllegalArgumentException
I would suggest clearly define it.
private List<String> toRoleNames(List<RoleEntity> roleEntities) { | ||
return roleEntities.stream().map(RoleEntity::name).collect(Collectors.toList()); | ||
Role grantPrivilegeToRole( | ||
String metalake, String role, MetadataObject object, List<Privilege> privileges) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if two same privileges with one allow
and one deny
are both set, what will be happened and do you handle such scenario?
object.type(), | ||
Lists.newArrayList(privileges)); | ||
|
||
authorizationPluginCallbackWrapper.setCallBack( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we do this out of SQL transaction, this will hurt the performance and lead to unexpected behavior if we put it here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This place we only set the callback. After we execute SQL transaction, we execute the callbak.
if (updatePrivileges.containsAll(privileges)) { | ||
return oldObject; | ||
} else { | ||
updatePrivileges.addAll(privileges); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should you check the allow
and deny
of the privileges here?
Also, do you need to check if the privileges are inclusive or exclusive, so you don't have store some particular privileges to the storage?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- If the privilege have the same Name , but it have different conditions. They are different privileges.
- I don't know the meaning about
inclusive or exclusive
.
If you mean the case aboutuse schema
andselect table
, we don't check it in the granting or revoking operations.
If you mean the case about schema'sselect table
and table'sselect table
, we don't check it, too. grant/revoke operation is effect on a specific object, schema and table are different objects.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I will check the privileges. We don't allow the same name privilege is allowed and denied at the same time.
.withAuditInfo(auditInfo) | ||
.withSecurableObjects(updateSecurableObjects) | ||
.build(); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the method is still too big, you need to split it into some methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Already splitted.
object.fullName(), | ||
object.type(), | ||
role); | ||
return null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What will be happened in the client side when we return a null object?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is updater. If this return null, we don't include the the new object.
// securable object. Remove duplicated privileges | ||
Set<Privilege> updatePrivileges = Sets.newHashSet(); | ||
updatePrivileges.addAll(oldObject.privileges()); | ||
privileges.forEach(updatePrivileges::remove); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same question here, some privileges are not exactly the same, but they're inclusive, should you handle this problem?
RoleChange.removeSecurableObject(role, oldObject)); | ||
})); | ||
|
||
return null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also here, it would be better to 1) simplify the current method to split into several small methods; 2) move the callback out of transaction to avoid transaction block.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will split it.
|
||
// 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( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Callback is a word, please change to Callback
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK.
|
||
return newSecurableObject; | ||
} else { | ||
// If the object doesn't contain any privilege, we remove this object. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to remove this in the database?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have removed the object in the database in the current logic.
Function<SecurableObject, SecurableObject> objectUpdater) { | ||
boolean isExist = false; | ||
List<SecurableObject> updateSecurableObjects = Lists.newArrayList(); | ||
for (SecurableObject securableObject : securableObjects) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we support updating multiple securable objects in one time? I don't quite understand the code here, can you please explain more?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't support to update multiple securable objects. We find one target securable object and update the privileges of the obejct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we don't support, why don't we just search the matched securable object and update it, no need to do this in a loop add a flag?
For example:
securableObject = get matched securableObject
updater.apply(securableOject)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method name isn't good. I should generate all the securable objects for the role. I changed to
generateNewSecurableObjects
And I tune the logic of this method and I make it clear.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
List<SecurableObject> updateSecurableObjects = Lists.newArrayList(securableObjects);
SecurableObject matchedSecurableObject = securableObjects.stream().filter(targetObject::equals).findFirst().orElse(null);
if (matchedSecurableObject != null) {
updateSecurableObjects.remove(matchedSecurableObject);
}
This may be more efficient that the above.
Entity.EntityType.ROLE, | ||
roleEntity -> { | ||
List<SecurableObject> updateSecurableObjects = | ||
updateSecurableObjects( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The variable here is the same as method name, can you change to a different name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed to grantedSecurableObjects
.
MetadataObject targetObject, | ||
Function<SecurableObject, SecurableObject> objectUpdater) { | ||
boolean isExist = false; | ||
List<SecurableObject> updateSecurableObjects = Lists.newArrayList(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also here, can you use a different name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to RevokedSecurableObjects
.
|
||
// If there not exists a securable object matching the target object. | ||
if (!isExist) { | ||
SecurableObject newSecurableObject = objectUpdater.apply(null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the code I saw that if the input is null
, then the output of this function is always null, can you please confirm this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In grant method, if apply null
, we will return a new created object.
for (SecurableObjectPO objectPO : deleteSecurableObjectPOS) { | ||
SessionUtils.doWithoutCommit( | ||
SecurableObjectMapper.class, | ||
mapper -> | ||
mapper.softDeleteSecurableObjectsByObjectIdAndPrivileges( | ||
objectPO.getRoleId(), | ||
objectPO.getMetadataObjectId(), | ||
objectPO.getPrivilegeConditions(), | ||
objectPO.getPrivilegeNames())); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we do this in a batch?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried. It's ok to use batch.
Function<SecurableObject, SecurableObject> objectUpdater) { | ||
boolean isExist = false; | ||
List<SecurableObject> updateSecurableObjects = Lists.newArrayList(); | ||
for (SecurableObject securableObject : securableObjects) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
List<SecurableObject> updateSecurableObjects = Lists.newArrayList(securableObjects);
SecurableObject matchedSecurableObject = securableObjects.stream().filter(targetObject::equals).findFirst().orElse(null);
if (matchedSecurableObject != null) {
updateSecurableObjects.remove(matchedSecurableObject);
}
This may be more efficient that the above.
List<Privilege> privileges, | ||
RoleEntity roleEntity, | ||
AuthorizationPluginCallbackWrapper authorizationPluginCallbackWrapper) { | ||
// Add a new securable object if there not exists the object in the role |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if there doesn't exist the...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
return newRoleEntity; | ||
} | ||
|
||
List<SecurableObjectPO> deleteSecurableObjectPOS = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"POs", not "POS"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
} | ||
} | ||
|
||
private List<SecurableObjectPO> toSecurablePOs( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
toSecurableObjectPOs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
Generally LGTM, @yuqi1129 can you please take another look at this PR? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some minor ones, others LGTM.
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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed that you have logged NoSuchEntityException
. Why don't you also add logs here? Do you have any other considerations?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added the log.
updatePrivileges.addAll(targetObject.privileges()); | ||
privileges.forEach(updatePrivileges::remove); | ||
|
||
// If the object still contain privilege, we should update the object |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
contain -> contains
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
for (Privilege privilege : privileges) { | ||
if (privilegeNameSet.contains(privilege.name())) { | ||
throw new IllegalPrivilegeException( | ||
"Doesn't support duplicated privilege name %s with different condition", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you output all the duplicated privilege names , not just one of them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be unnecessary. It will be allow and deny the privilege name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some minor ones, others LGTM.
"Catalog %s type %s don't support privilege %s", | ||
catalogIdent, catalog.type(), privilege)); | ||
throw new IllegalPrivilegeException( | ||
"Catalog %s type %s don't support privilege %s", catalogIdent, catalog.type(), privilege); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"doesn't support..."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@jerqi the cherry-pick is failed, please do it manually against branch-0.6. |
…s for a role (apache#5021) Supports to grant or revoke privileges for a role Fix: apache#4903 I will add the document later. Add the UT.
What changes were proposed in this pull request?
Supports to grant or revoke privileges for a role
Why are the changes needed?
Fix: #4903
Does this PR introduce any user-facing change?
I will add the document later.
How was this patch tested?
Add the UT.