NHibernate PreSelect?

I am trying to implement privileges using NHibernate, and what I want to do, every time there is a Select request, check what the return type is, and if it is a type with security enabled (for example, invoices), I want to add restrictions to the ICriteria object to restrict the receipt of only certain records (if the user has read everything or read their own privileges).

I managed to implement these privileges to insert and update using

NHibernater.Event.IPreUpdateEventListener
NHibernater.Event.IPreInsertEventListener

but, unfortunately, it IPreLoadEventListeneris called after the database query and, therefore, it is a waste, since filtering will be performed locally on the computer, and not in the database.

Does anyone know if NHibernate supports any event that is fired before the request is executed?

+3
source share
2 answers

If you are able to use it, look at Rhino.Security. It does exactly what you are trying to do. Even if you cannot use it, you can see its implementation of this problem.

+2
source

Can't you achieve this using filters?

More information can be found here.

I used this in conjunction with Interceptors in my project:

I have several objects in which each user can create instances, but only the user who created them should be able to see / modify these instances. Other users cannot see instances created by user X.

IUserContextAware. , "- ", .

factory :

 var currentUserFilterParametersType = new Dictionary<string, NHibernate.Type.IType> (1);
 currentUserFilterParametersType.Add (CurrentUserContextFilterParameter, NHibernateUtil.Guid);
 cfg.AddFilterDefinition (new FilterDefinition (CurrentUserContextFilter,
                                                           "(:{0} = UserId or UserId is null)".FormatString (CurrentUserContextFilterParameter),
                                                           currentUserFilterParametersType,
                                                           false));

, :

 foreach( var mapping in cfg.ClassMappings )
 {
    if( typeof (IUserContextAware).IsAssignableFrom (mapping.MappedClass) )
    {
       // The filter should define the names of the columns that are used in the DB, rather then propertynames.
      // Therefore, we need to have a look at the mapping information.

      Property userProperty = mapping.GetProperty ("UserId");

      foreach( Column c in userProperty.ColumnIterator )
      {
          string filterExpression = ":{0} = {1}";

          // When the BelongsToUser field is not mandatory, NULL should be taken into consideration as well.
          // (For instance: a PrestationGroup instance that is not User-bound (that can be used by any user), will have
          //  a NULL value in its BelongsToUser field).
          if( c.IsNullable )
          {
              filterExpression = filterExpression + " or {1} is null";
          }

          mapping.AddFilter (CurrentUserContextFilter, "(" + filterExpression.FormatString (CurrentUserContextFilterParameter, c.Name) + ")");
          break;
     }
 }

, ISession, , :

:

    internal class ContextAwareInterceptor : EmptyInterceptor
    {
        public override void SetSession( ISession session )
        {
            if( AppInstance.Current == null )
            {
                return;
            }

            // When a User is logged on, the CurrentUserContextFilter should be enabled.
            if( AppInstance.Current.CurrentUser != null )
            {
                session.EnableFilter (AppInstance.CurrentUserContextFilter)
                                            .SetParameter (AppInstance.CurrentUserContextFilterParameter,
                                                           AppInstance.Current.CurrentUser.Id);

            }
        }
}
+2

Source: https://habr.com/ru/post/1790468/


All Articles