Filtering Linq to Nhibernate queries with Rhino Security

October 5, 2009

Rhino Security provides the ability to filter NHibernate queries based on permissions. To do this, an IAuthorizationService interface is provided, that can be used in the following way:

var criteria = DetachedCriteria.For<Company>();
AuthorizationService.AddPermissionsToQuery(currentUser.Value, "/Company/View", criteria);
return criteria.GetExecutableCriteria(Session).List<Company>();

This way, a user only gets to see the companies he has permissions for. The AddPermissionsToQuery method expects a user, an operation and an NHibernate ICiteria object. The ICriteria object is the NHibernate Criteria that needs to be extended with permissions.

This works really well, a nice optimized query is generated. However, when working with Linq-to-Nhibernate, you don’t have an ICriteria object, so how can we add the permissions to those queries?

To figure this out, I downloaded the latest sources for Linq-to-Nhibernate and discovered a QueryOptions property on the INhibernateQueryable interface, which returns a QueryOptions type. The QueryOptions type provides a RegisterCustomAction method, which takes a parameter of the the type Action<ICriteria>, this looks hopeful.

By doing some tests, I found out that internally Linq-to-Nhibernate translates linq queries into a Criteria object. The RegisterCustomAction method allows us to perform custom actions on this criteria object, making it possible to add our own restrictions, excellent!

Integrating Rhino Security with Linq-to-NHibernate then gets us the following code:

INHibernateQueryable<User> query = Session.Linq<User>();
query.QueryOptions.RegisterCustomAction(x=>
          AuthorizationService.AddPermissionsToQuery(user, "/User/View", x));
return query.ToList<User>();

This results in the same query as the one resulting from the DetachedCriteria scenario. So this way you can have Rhino Security filter your queries based on permissions and still use Linq-to-Nhibernate.

Comments

comments powered by Disqus