NHibernate PreSelect? - PullRequest
       3

NHibernate PreSelect?

3 голосов
/ 07 февраля 2011

Я пытаюсь реализовать привилегии с помощью NHibernate, и я хочу, чтобы каждый раз, когда есть запрос Select, проверял, какой тип возврата был, и если это тип с включенной безопасностью (такой как счета), я хочудобавить ограничения к объекту ICriteria, ограничить получение только определенных записей (в зависимости от того, прочитал ли пользователь все или прочитал собственные привилегии).

Мне удалось реализовать привилегии такого типа для операций вставки и обновления, используя

NHibernater.Event.IPreUpdateEventListener
NHibernater.Event.IPreInsertEventListener

но, к сожалению, IPreLoadEventListener вызывается после запроса к базе данных, и поэтому это бесполезно, поскольку фильтрация будет выполняться локально на компьютере, а не на базе данных.

Кто-нибудьзнаете, если NHibernate предоставляет какое-то событие, которое вызывается перед выполнением запроса?

Ответы [ 2 ]

2 голосов
/ 07 февраля 2011

Если вы можете использовать его, проверьте Rhino.Security Он делает именно то, что вы пытаетесь сделать.Даже если вы не сможете его использовать, вы сможете увидеть его реализацию этой проблемы.

2 голосов
/ 07 февраля 2011

Не можете ли вы добиться этого с помощью фильтров?

Более подробную информацию можно найти здесь

Я использовал это в сочетании с перехватчиками в моем проекте:

У меня есть некоторые объекты, из которых каждый пользователь может создавать экземпляры, но только пользователь, создавший их, должен иметь возможность видеть / изменять эти экземпляры. Другие пользователи не могут видеть экземпляры, созданные пользователем X.

Для этого я создал интерфейс IUserContextAware. Объекты, которые «осведомлены о контексте пользователя», реализуют этот интерфейс.

При создании фабрики сессий я создал необходимые фильтры:

 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);

            }
        }
}
...