@Service(value="blRowLevelSecurityService") public class RowLevelSecurityServiceImpl extends Object implements RowLevelSecurityService, ExceptionAwareRowLevelSecurityProvider
RowLevelSecurityService
Modifier and Type | Field and Description |
---|---|
protected List<RowLevelSecurityProvider> |
providers |
Constructor and Description |
---|
RowLevelSecurityServiceImpl() |
Modifier and Type | Method and Description |
---|---|
void |
addFetchRestrictions(AdminUser currentUser,
String ceilingEntity,
List<javax.persistence.criteria.Predicate> restrictions,
List<javax.persistence.criteria.Order> sorts,
javax.persistence.criteria.Root entityRoot,
javax.persistence.criteria.CriteriaQuery criteria,
javax.persistence.criteria.CriteriaBuilder criteriaBuilder)
Used to further restrict a result set in the admin for a particular admin user.
|
boolean |
canAdd(AdminUser currentUser,
String sectionClassName,
ClassMetadata cmd)
Hook to determine if the given entity can be added by a user.
|
boolean |
canRemove(AdminUser currentUser,
Entity entity)
Hook to determine if the given entity can be deleted by a user.
|
boolean |
canUpdate(AdminUser currentUser,
Entity entity)
Hook to determine if the given entity can be updated or not.
|
Class<Serializable> |
getFetchRestrictionRoot(AdminUser currentUser,
Class<Serializable> ceilingEntity,
List<FilterMapping> filterMappings)
Contributes to
Root determination for RowLevelSecurityProvider.addFetchRestrictions(AdminUser, String, List, List, Root, CriteriaQuery, CriteriaBuilder) . |
List<RowLevelSecurityProvider> |
getProviders()
Gets all of the registered providers
|
EntityFormModifierConfiguration |
getUpdateDenialExceptions()
Provide a modifier capable of manipulating an
EntityForm that has been marked as readonly and modify its
state, presumably to set one or more aspects of the form as editable. |
void |
setProviders(List<RowLevelSecurityProvider> providers) |
GlobalValidationResult |
validateAddRequest(AdminUser currentUser,
Entity entity,
PersistencePackage persistencePackage)
Validates whether a user has permissions to actually perform the record addition.
|
GlobalValidationResult |
validateRemoveRequest(AdminUser currentUser,
Entity entity,
PersistencePackage persistencePackage)
Validates whether a user has permissions to actually perform the record deletion.
|
GlobalValidationResult |
validateUpdateRequest(AdminUser currentUser,
Entity entity,
PersistencePackage persistencePackage)
Validates whether a user has permissions to actually perform the update.
|
protected List<RowLevelSecurityProvider> providers
public void addFetchRestrictions(AdminUser currentUser, String ceilingEntity, List<javax.persistence.criteria.Predicate> restrictions, List<javax.persistence.criteria.Order> sorts, javax.persistence.criteria.Root entityRoot, javax.persistence.criteria.CriteriaQuery criteria, javax.persistence.criteria.CriteriaBuilder criteriaBuilder)
RowLevelSecurityProvider
Used to further restrict a result set in the admin for a particular admin user. This can be done by adding additional
Predicate
s 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 Predicate
s to the given criteria, you should instead modify the
given lists. These lists will be automatically attached to the criteria after execution.
Existing Predicate
s 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 a Path
from it then you will run into
IllegalArgumentException
s.
This method is executed prior to any CriteriaTranslatorEventHandler
.
addFetchRestrictions
in interface RowLevelSecurityProvider
currentUser
- the currently logged in AdminUser
ceilingEntity
- the entity currently being queried fromrestrictions
- the restrictions that will be applied to the criteria but have not been yet. Additional
Predicate
s 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. No Predicate
s or Order
s 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 additional Predicate
s or Order
s to add to restrictions
and/or sorts#getFetchRestrictionRoot(Class, List)}
,
CriteriaTranslatorImpl#addRestrictions}
public Class<Serializable> getFetchRestrictionRoot(AdminUser currentUser, Class<Serializable> ceilingEntity, List<FilterMapping> filterMappings)
RowLevelSecurityProvider
Contributes to Root
determination for RowLevelSecurityProvider.addFetchRestrictions(AdminUser, String, List, List, Root, CriteriaQuery, CriteriaBuilder)
.
Normally, the query Root
is determined in the admin via the given filterMappings. Since row security deals with
a CriteriaBuilder
directly, if you want to be able to target subclasses then a new Root
must 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 FilterMapping
for 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.
getFetchRestrictionRoot
in interface RowLevelSecurityProvider
ceilingEntity
- the entity being queried forfilterMappings
- the existing filters passed from the admin frontendRowLevelSecurityProvider.addFetchRestrictions(AdminUser, String, List, List, Root, CriteriaQuery, CriteriaBuilder)
or null if no specific root needs to be usedCriteriaTranslatorImpl#determineRoot}
,
FilterMapping#getInheritedFromClass()}
public boolean canUpdate(AdminUser currentUser, Entity entity)
RowLevelSecurityProvider
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 EntityForm
as 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)
canUpdate
in interface RowLevelSecurityProvider
currentUser
- the currently logged in AdminUser
entity
- the Entity
DTO that is attempting to be updatedFormBuilderServiceImpl#setReadOnlyState}
public EntityFormModifierConfiguration getUpdateDenialExceptions()
ExceptionAwareRowLevelSecurityProvider
EntityForm
that has been marked as readonly and modify its
state, presumably to set one or more aspects of the form as editable.getUpdateDenialExceptions
in interface ExceptionAwareRowLevelSecurityProvider
EntityFormModifier
public boolean canRemove(AdminUser currentUser, Entity entity)
RowLevelSecurityProvider
Hook to determine if the given entity can be deleted by a user. This is used to drive the DefaultEntityFormActions.DELETE
button from appearing on the admin frontend.
You might consider tying the remove to RowLevelSecurityProvider.canUpdate(AdminUser, Entity)
and explicitly invoking that action yourself.
canRemove
in interface RowLevelSecurityProvider
currentUser
- the currently logged in AdminUser
FormBuilderServiceImpl#addDeleteActionIfAllowed}
public boolean canAdd(AdminUser currentUser, String sectionClassName, ClassMetadata cmd)
RowLevelSecurityProvider
Hook to determine if the given entity can be added by a user.
canAdd
in interface RowLevelSecurityProvider
currentUser
- the currently logged in AdminUser
public GlobalValidationResult validateUpdateRequest(AdminUser currentUser, Entity entity, PersistencePackage persistencePackage)
RowLevelSecurityProvider
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
GlobalValidationResult
will be automatically added to the given entity Entity.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 appropriate GlobalValidationResult
. In that case however, it might be more suitable to use a
PropertyValidator
instead.
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.
validateUpdateRequest
in interface RowLevelSecurityProvider
currentUser
- the currently logged in AdminUser
entity
- the DTO representation that is attempting to be deleted. Comes from PersistencePackage.getEntity()
persistencePackage
- the full persisteGlobalValidationResult
with GlobalValidationResult.isValid()
set to denote if the given
entity failed row-level security validation or not.public GlobalValidationResult validateRemoveRequest(AdminUser currentUser, Entity entity, PersistencePackage persistencePackage)
RowLevelSecurityProvider
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
GlobalValidationResult
will be automatically added to the given entity Entity.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 appropriate GlobalValidationResult
. In that case however, it might be more suitable to use a
PropertyValidator
instead.
This is usually a simple invocation to #canDelete(AdminUser, Entity)
.
validateRemoveRequest
in interface RowLevelSecurityProvider
currentUser
- the currently logged in AdminUser
entity
- the DTO representation that is attempting to be deleted. Comes from PersistencePackage.getEntity()
persistencePackage
- the full request sent from the frontend through the admin pipelineGlobalValidationResult
with GlobalValidationResult.isValid()
set to denote if the given
entity failed row-level security validation or not.public GlobalValidationResult validateAddRequest(AdminUser currentUser, Entity entity, PersistencePackage persistencePackage)
RowLevelSecurityProvider
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
GlobalValidationResult
will be automatically added to the given entity Entity.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 appropriate GlobalValidationResult
. In that case however, it might be more suitable to use a
PropertyValidator
instead.
This is usually a simple invocation to #canAdd(AdminUser, Entity)
.
validateAddRequest
in interface RowLevelSecurityProvider
currentUser
- the currently logged in AdminUser
entity
- the DTO representation that is attempting to be deleted. Comes from PersistencePackage.getEntity()
persistencePackage
- the full request sent from the frontend through the admin pipelineGlobalValidationResult
with GlobalValidationResult.isValid()
set to denote if the given
entity failed row-level security validation or not.public List<RowLevelSecurityProvider> getProviders()
RowLevelSecurityService
getProviders
in interface RowLevelSecurityService
public void setProviders(List<RowLevelSecurityProvider> providers)
Copyright © 2022. All rights reserved.