Class RowLevelSecurityServiceImpl
- All Implemented Interfaces:
ExceptionAwareRowLevelSecurityProvider,RowLevelSecurityProvider,RowLevelSecurityService
- Author:
- Phillip Verheyden (phillipuniverse), Jeff Fischer
- See Also:
-
Field Summary
Fields -
Constructor Summary
Constructors -
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 forRowLevelSecurityProvider.addFetchRestrictions(AdminUser, String, List, List, Root, CriteriaQuery, CriteriaBuilder).Gets all of the registered providersProvide a modifier capable of manipulating anEntityFormthat has been marked as readonly and modify its state, presumably to set one or more aspects of the form as editable.voidsetProviders(List<RowLevelSecurityProvider> providers) 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.
-
Field Details
-
providers
-
-
Constructor Details
-
RowLevelSecurityServiceImpl
public RowLevelSecurityServiceImpl()
-
-
Method Details
-
addFetchRestrictions
public 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) Description copied from interface:RowLevelSecurityProviderUsed 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
RowLevelSecurityProvider.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.- Specified by:
addFetchRestrictionsin interfaceRowLevelSecurityProvider- 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
public Class<Serializable> getFetchRestrictionRoot(AdminUser currentUser, Class<Serializable> ceilingEntity, List<FilterMapping> filterMappings) Description copied from interface:RowLevelSecurityProviderContributes to
Rootdetermination forRowLevelSecurityProvider.addFetchRestrictions(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
RowLevelSecurityProvider.addFetchRestrictions(AdminUser, String, List, List, Root, CriteriaQuery, CriteriaBuilder)does not rely on any properties from a child class.- Specified by:
getFetchRestrictionRootin interfaceRowLevelSecurityProviderceilingEntity- the entity being queried forfilterMappings- the existing filters passed from the admin frontend- Returns:
- the root class that is going to be used for
RowLevelSecurityProvider.addFetchRestrictions(AdminUser, String, List, List, Root, CriteriaQuery, CriteriaBuilder)or null if no specific root needs to be used
-
canUpdate
Description copied from interface:RowLevelSecurityProviderHook 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
RowLevelSecurityProvider.canRemove(AdminUser, Entity)- Specified by:
canUpdatein interfaceRowLevelSecurityProvider- Parameters:
currentUser- the currently logged inAdminUserentity- theEntityDTO that is attempting to be updated- Returns:
- true if the given entity can be updated, false otherwise
-
getUpdateDenialExceptions
Description copied from interface:ExceptionAwareRowLevelSecurityProviderProvide a modifier capable of manipulating anEntityFormthat has been marked as readonly and modify its state, presumably to set one or more aspects of the form as editable.- Specified by:
getUpdateDenialExceptionsin interfaceExceptionAwareRowLevelSecurityProvider- Returns:
- package containing the modifier implementations and any configurations for those modifiers
- See Also:
-
canRemove
Description copied from interface:RowLevelSecurityProviderHook 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
RowLevelSecurityProvider.canUpdate(AdminUser, Entity)and explicitly invoking that action yourself.- Specified by:
canRemovein interfaceRowLevelSecurityProvider- Parameters:
currentUser- the currently logged inAdminUser- Returns:
- true if the given entity can be deleted, false otherwise
-
canAdd
Description copied from interface:RowLevelSecurityProviderHook to determine if the given entity can be added by a user.
- Specified by:
canAddin interfaceRowLevelSecurityProvider- Parameters:
currentUser- the currently logged inAdminUser- Returns:
- true if the given entity can be added, false otherwise
-
validateUpdateRequest
public GlobalValidationResult validateUpdateRequest(AdminUser currentUser, Entity entity, PersistencePackage persistencePackage) Description copied from interface:RowLevelSecurityProviderValidates 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
RowLevelSecurityProvider.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.- Specified by:
validateUpdateRequestin interfaceRowLevelSecurityProvider- 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
public GlobalValidationResult validateRemoveRequest(AdminUser currentUser, Entity entity, PersistencePackage persistencePackage) Description copied from interface:RowLevelSecurityProviderValidates 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).- Specified by:
validateRemoveRequestin interfaceRowLevelSecurityProvider- 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
public GlobalValidationResult validateAddRequest(AdminUser currentUser, Entity entity, PersistencePackage persistencePackage) Description copied from interface:RowLevelSecurityProviderValidates 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).- Specified by:
validateAddRequestin interfaceRowLevelSecurityProvider- 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.
-
getProviders
Description copied from interface:RowLevelSecurityServiceGets all of the registered providers- Specified by:
getProvidersin interfaceRowLevelSecurityService- Returns:
- the providers configured for this service
-
setProviders
-