automatic filter on entity = feature request?

9 posts / 0 new
Last post
Marc
Offline
Joined: 07/08/2009
automatic filter on entity = feature request?

Hi,

 

I have a question regarding filters.

 

I am looking to implement a concept like an automatic entity filter.

 

Consider for instance an entity like holiday requests:

-an employee can only see his own holiday requests

-a line manager can (only) see the holiday requests of his department

-an HR administrative employee can see all holiday requests

 

On page 75 of the reference manual I find a means to filter automatically, but:

-it seems that this option pre-fills some filter fields for the user, but the user can still search wider?

-also it seems, at least at first, still quite complex to achieve something like the above?

 

What are your ideas? Is there a fairly easy way to implement such requirement or should we make a feature request out of it? Would that then be feasible to implement such request?

 

Thanks for your insights,

Marc

vvandens
Offline
Joined: 05/29/2008
automatic filter on entity

Marc,

At first sight, I don't know if this feature could be implemented as a generic action; I mean, you could have arbitrary complex queries involving joints for instance. I think it goes beyond what can be achieved with Spring parametrization only (or maybe do you have some ideas ?).

Nevertheless, Jspresso allows you to define custom actions you can afterwards reference in your application.

For instance, you could populate a collection module at startup with a fine-tuned custom query based on the logged-in user, his profile, ... This collection module, then, doesn't need to have the filter/query panel and there is no chance a user can change the query.

Take a lok at this comment. It gives you some hints to do so. Of course, this requires little more work since you won't rely directly on the full-featured abstractFilterableBeanCollectionModule.

Regarding the example page 75, you could also refine it by changing the action that performs the search to inject your custom query (or refine the default one).

This is only some hints but if you have a precise UI use-case, we could investigate further.

 

Hope this helps,

Vincent

Marc
Offline
Joined: 07/08/2009
Well, it has taken me a while

Well, it has taken me a while to take this back up but here we are:

I read that queries on entities can be specialized as follows:

  • Initialization mapping of search properties
  • Specialising the QueryEntities action using the hook ICreteriaRefiner
  • Specialising the QueryEntities action using the hook IQueryComponentRefiner

 

I have difficulties understanding which one to use and how. So I will explain the use case I want to achieve:

 

I have an entity “Deal”. I foresaw the property s_creator in a deal and filled it automatically with the user that created the deal. A user with the role “Executive” is only allowed to see the deals that he created himself, with other words the visibility restriction for executives is:

            s_creator = current user

 

For users with the role “Manager”, the visibility constraint is different: managers may see the deals created by all executives reporting to them. With other words, for managers visibility restriction is:

            s_creator.boss = current user

 

(an entity user with property boss would contain the boss relationship).

 

Moreover, we want to provide all users (executives and managers) with the usual search capabilities within their visibility area: so the usual entity search panel should be visible and work.

 

Also note that I will have to foresee this visibility constraint also in properties referring to a “Deal” entity: the po-up window with the search panel for the LOV should behave likewise. I wander then if I will have to repeat the same constraint in the entity search panel and for every LOV referring to it?

 

I would like to understand how I can hook in my extra visibility constraint into the search that will finally be entered by the user, with the extra difficulty that my constraint is dependent on the role of the user.

 

Thanks in advance for your insights,

Marc

 

elan
Offline
Joined: 05/28/2010
Queryrefiner depending on people

Hi Marc,

I guess you can make a refiner (ICriteriaRefiner) according to the role of each people by getting the role of the connected people.

It will give something like this to get user :

UserPrincipal userPrincipal = getBackendController(context).getApplicationSession().getPrincipal();

User user = (User) userPrincipal.getCustomProperty(UserSessionInitAction.USER_ENTITY_KEY);

then get role (user.getRoles()) and according to the role you can specify the criteria.

Hope this helps.

Eric.

 

vvandens
Offline
Joined: 05/29/2008
automatic filter on entity

Marc,

Regarding the general application of a security criteria refiner to the aplication, it should be quite straightforward since all QBE entity query actions (LOV, filter module, ...) use the same action definition, i.e. queryEntitiesBackAction.

What you can do is :

  1. Create a general purpose query refiner that applies the security filter based on the type of entity referenced in the query component passed in parameter (so that you can perform the customized required joins).
  2. override queryEntitiesBackAction (copy/paste the standard definition in your backend context) to assign it your security query refiner.

 

HTH,

Vincent

Marc
Offline
Joined: 07/08/2009
[help] query refiner

Hi,

After looking into related forum items and into the source I still am nowhere, but that is entirely due to myself. Could somebody help me again a step further. With relation to my use case above I suggest to only consider the manager role for reasons of simplicity. So then I end up with the 2 questions below

1)Could you provide a very simple example of a query refiner (for instance creator.boss=xxx  ; creator being a property of the entity deal; boss being a property of the entity user; xxx being a value that I would set to the current user id)? Do I write my query refiner in Java, or in Hibernate QL, or in SQL?

2)Would I then insert this refiner into queryEntitiesAction using Sping or should I do it entirely do it entirely in Java?

Thanks again for your help.

Marc

vvandens
Offline
Joined: 05/29/2008
[help] query refiner

Hi Marc,

1/ A query refiner is a java class that implements:

org.jspresso.framework.application.backend.action.persistence.hibernate.ICriteriaRefiner

All you have to implement is a single method where you have, passed as parameter :

  • the default Hibernate criteria as built for the QBE filter (either in the filter module or LOV)
  • the query component, i.e. the filter model
  • the action context

The idea is, in this method, to complement the Hibernate criteria with some extra restrictions, e.g. your security restriction using the API documented here. In your case, that would be something like (un-verified) :

criteria.getSubCriteriaFor(criteria, "creator")
    .getSubCriteriaFor(criteria, "boss")
    .add(Restrictions.eq("userName", sessionUserName))

Of course, sessionUserName should be retrieved from the action context. In order to ease things further, you can make your criteria refiner descend from AbstractActionContextAware to inherit context exploration utility methods.

2/ You inject your query refiner instance into queryEntitiesBackAction using Spring, e.g. :

 

  <bean
id="queryEntitiesBackAction"
parent="abstractHibernateBackAction"
class="org.jspresso.framework.application.backend.action.persistence.hibernate.QueryEntitiesAction">
<property name="criteriaFactory" ref="criteriaFactory"/>
<property name="criteriaRefiner" ref="myCriteriaRefiner"/> </bean>

As explained in a previous post, this will install your criteria refiner into ALL QBE queries. So you have to make your criteria refiner generic enough, i.e. you might need to leverage the query component descriptor to know on which type of entity you are working and thus adapt what you are doing on the Hibernate criteria.

 

HTH,

Vincent

Marc
Offline
Joined: 07/08/2009
[help] on get role(s)

Hi,

Thanks to your input I am almost there: filter works indeed.

Only I get stuck in getting the roles of the current user.

I quite can get the user itself, as follows:

((AbstractBackendController)context.get("BACK_CONTROLLER")).getApplicationSession().getPrincipal().getName()

But I do not see anywhere a way to get the roles of the userPrincipal.

Currently I simply rely on the jaas.config file to specify the roles. So I do not have an entity that contains the roles.

JSpresso is frequently authorizing against the role, so I thought there should be an easy way to get the roles, without having to create custom properties on the application sesssion context.

Thanks,

Marc

vvandens
Offline
Joined: 05/29/2008
[help] on get role(s)

Hi Marc,

Take a look at the code of the security helper. You have to start from the JAAS subject in the application session, then iterate until you find the principal named "Roles". This JAAS structure holds the roles of the session user.

To get the JAAS subject from the application session :

((AbstractBackendController)context.get("BACK_CONTROLLER")).getApplicationSession().getSubject()

Or even better, as mentionned before, your class can inherit from AbstractActionContextAware to ease action context navigation. Once done, the the above line would be more robust by writing :

getBackendController(context).getApplicationSession().getSubject()

 

HTH,

Vincent