Interface RowLevelSecurityProvider
- All Known Subinterfaces:
RowLevelSecurityService
- All Known Implementing Classes:
AbstractRowLevelSecurityProvider,RowLevelSecurityServiceImpl
A component that can apply row-level security to the admin
Implementations of this class should extend from the AbstractRowLevelSecurityProvider
- Author:
- Phillip Verheyden (phillipuniverse), Jeff Fischer
-
Method Summary
Modifier and TypeMethodDescriptionvoidaddFetchRestrictions(AdminUser currentUser, String ceilingEntity, List<jakarta.persistence.criteria.Predicate> restrictions, List<jakarta.persistence.criteria.Order> sorts, jakarta.persistence.criteria.Root entityRoot, jakarta.persistence.criteria.CriteriaQuery criteria, jakarta.persistence.criteria.CriteriaBuilder criteriaBuilder) Used to further restrict a result set in the admin for a particular admin user.booleancanAdd(AdminUser currentUser, String sectionClassname, ClassMetadata cmd) Hook to determine if the given entity can be added by a user.booleanHook to determine if the given entity can be deleted by a user.booleanHook to determine if the given entity can be updated or not.getFetchRestrictionRoot(AdminUser currentUser, Class<Serializable> ceilingEntity, List<FilterMapping> filterMappings) Contributes toRootdetermination foraddFetchRestrictions(AdminUser, String, List, List, Root, CriteriaQuery, CriteriaBuilder).validateAddRequest(AdminUser currentUser, Entity entity, PersistencePackage persistencePackage) Validates whether a user has permissions to actually perform the record addition.validateRemoveRequest(AdminUser currentUser, Entity entity, PersistencePackage persistencePackage) Validates whether a user has permissions to actually perform the record deletion.validateUpdateRequest(AdminUser currentUser, Entity entity, PersistencePackage persistencePackage) Validates whether a user has permissions to actually perform the update.
-
Method Details
-
addFetchRestrictions
void addFetchRestrictions(AdminUser currentUser, String ceilingEntity, List<jakarta.persistence.criteria.Predicate> restrictions, List<jakarta.persistence.criteria.Order> sorts, jakarta.persistence.criteria.Root entityRoot, jakarta.persistence.criteria.CriteriaQuery criteria, jakarta.persistence.criteria.CriteriaBuilder criteriaBuilder) Used to further restrict a result set in the admin for a particular admin user. This can be done by adding additional
Predicates to the given list of restrictions. You can also attach additional sorting from the given list of sorts.You should not attach any of these
Predicates to the given criteria, you should instead modify the given lists. These lists will be automatically attached to the criteria after execution.Existing
Predicates and sorts will already be added into the given restrictions and sorts lists.If you are filtering on a property that exists only in a subclass of an OOB framework entity (like if you extended ProductImpl and you need to add a restriction targeting MyProductImpl) then you need to override
getFetchRestrictionRoot(AdminUser, Class, List)to return the class that you are adding criteria to. Otherwise, the entityRoot will be wrong and if you try to get aPathfrom it then you will run intoIllegalArgumentExceptions.This method is executed prior to any
CriteriaTranslatorEventHandler.- Parameters:
currentUser- the currently logged inAdminUserceilingEntity- the entity currently being queried fromrestrictions- the restrictions that will be applied to the criteria but have not been yet. AdditionalPredicates to further filter the query should be added to this listsorts- the sorts that will be applied to the criteria. Additional sorts should be added to this listentityRoot- the JPA root for ceilingEntitycriteria- the criteria that will be executed. NoPredicates orOrders have been applied to this criteria, and nor should they be. All modifications should instead be to the given restrictions and/or sortscriteriaBuilder- used to create additionalPredicates orOrders to add to restrictions and/or sorts
-
getFetchRestrictionRoot
Class<Serializable> getFetchRestrictionRoot(AdminUser currentUser, Class<Serializable> ceilingEntity, List<FilterMapping> filterMappings) Contributes to
Rootdetermination foraddFetchRestrictions(AdminUser, String, List, List, Root, CriteriaQuery, CriteriaBuilder). Normally, the queryRootis determined in the admin via the given filterMappings. Since row security deals with aCriteriaBuilderdirectly, if you want to be able to target subclasses then a newRootmust be established for that specific subclass.Note that depending on how you have your filters in the admin frontend (the list grids) set up, you might have to take into account the given filterMappings. The admin will not be able to find a correct root if there is an active filter set on a sibling class that you are attempting to also add more criteria to. For instance, if a class hierarchy exists for A -> B and also A -> C, if there is an active
FilterMappingfor a property from B and you attempt to add a fetch restriction on a property from C that will not work.It is acceptable to return null from this method if
addFetchRestrictions(AdminUser, String, List, List, Root, CriteriaQuery, CriteriaBuilder)does not rely on any properties from a child class.- Parameters:
ceilingEntity- the entity being queried forfilterMappings- the existing filters passed from the admin frontend- Returns:
- the root class that is going to be used for
addFetchRestrictions(AdminUser, String, List, List, Root, CriteriaQuery, CriteriaBuilder)or null if no specific root needs to be used
-
canUpdate
Hook to determine if the given entity can be updated or not. This is used to drive the form displayed in the admin frontend to remove modifier actions and set the entire
EntityFormas readonly.If the entity cannot be updated, then by default it can also not be removed. You can change this by explicitly overriding
canRemove(AdminUser, Entity) -
canRemove
Hook to determine if the given entity can be deleted by a user. This is used to drive the
DefaultEntityFormActions.DELETEbutton from appearing on the admin frontend.You might consider tying the remove to
canUpdate(AdminUser, Entity)and explicitly invoking that action yourself.- Parameters:
currentUser- the currently logged inAdminUserentity-- Returns:
- true if the given entity can be deleted, false otherwise
-
canAdd
Hook to determine if the given entity can be added by a user.
- Parameters:
currentUser- the currently logged inAdminUsersectionClassname-cmd-- Returns:
- true if the given entity can be added, false otherwise
-
validateUpdateRequest
GlobalValidationResult validateUpdateRequest(AdminUser currentUser, Entity entity, PersistencePackage persistencePackage) Validates whether a user has permissions to actually perform the update. The result of this method is a validation result that indicates if something in the entire entity is in error. The message key from the resulting
GlobalValidationResultwill be automatically added to the given entityEntity.getGlobalValidationErrors().If you would like to add individual property errors, you can do that with the given entity by using
Entity.addValidationError(String, String). Even if you attach errors to specific properties you should still return an appropriateGlobalValidationResult. In that case however, it might be more suitable to use aPropertyValidatorinstead.For convenience, this is usually a simple invocation to
canUpdate(AdminUser, Entity). However, it might be that you want to allow the user to see certain update fields but not allow the user to save certain fields for update.- Parameters:
currentUser- the currently logged inAdminUserentity- the DTO representation that is attempting to be deleted. Comes fromPersistencePackage.getEntity()persistencePackage- the full persiste- Returns:
- a
GlobalValidationResultwithGlobalValidationResult.isValid()set to denote if the given entity failed row-level security validation or not.
-
validateRemoveRequest
GlobalValidationResult validateRemoveRequest(AdminUser currentUser, Entity entity, PersistencePackage persistencePackage) Validates whether a user has permissions to actually perform the record deletion. The result of this method is a validation result that indicates if something in the entire entity is in error. The message key from the resulting
GlobalValidationResultwill be automatically added to the given entityEntity.getGlobalValidationErrors().If you would like to add individual property errors, you can do that with the given entity by using
Entity.addValidationError(String, String). Even if you attach errors to specific properties you should still return an appropriateGlobalValidationResult. In that case however, it might be more suitable to use aPropertyValidatorinstead.This is usually a simple invocation to
#canDelete(AdminUser, Entity).- Parameters:
currentUser- the currently logged inAdminUserentity- the DTO representation that is attempting to be deleted. Comes fromPersistencePackage.getEntity()persistencePackage- the full request sent from the frontend through the admin pipeline- Returns:
- a
GlobalValidationResultwithGlobalValidationResult.isValid()set to denote if the given entity failed row-level security validation or not.
-
validateAddRequest
GlobalValidationResult validateAddRequest(AdminUser currentUser, Entity entity, PersistencePackage persistencePackage) Validates whether a user has permissions to actually perform the record addition. The result of this method is a validation result that indicates if something in the entire entity is in error. The message key from the resulting
GlobalValidationResultwill be automatically added to the given entityEntity.getGlobalValidationErrors().If you would like to add individual property errors, you can do that with the given entity by using
Entity.addValidationError(String, String). Even if you attach errors to specific properties you should still return an appropriateGlobalValidationResult. In that case however, it might be more suitable to use aPropertyValidatorinstead.This is usually a simple invocation to
#canAdd(AdminUser, Entity).- Parameters:
currentUser- the currently logged inAdminUserentity- the DTO representation that is attempting to be deleted. Comes fromPersistencePackage.getEntity()persistencePackage- the full request sent from the frontend through the admin pipeline- Returns:
- a
GlobalValidationResultwithGlobalValidationResult.isValid()set to denote if the given entity failed row-level security validation or not.
-