Сохранение моделей Groovy в прослушивателе событий Spring Security - PullRequest
0 голосов
/ 14 февраля 2012

Я добавил onAuthenticationSuccessEvent в мой config.groovy, чтобы попытаться добавить модель входа в список в модели пользователя User. Проблема, с которой я столкнулся, заключается в том, что прослушиватель событий является замыканием и поэтому не имеет HibernateSession или доступа к состоянию за пределами замыкания.

Я знаю, что можно связать HibernateSession, выполнив что-то вроде этого:

grails.plugins.springsecurity.onInteractiveAuthenticationSuccessEvent = { e, appCtx ->
    Login.withTransaction{
        login = new Login()
    }
}

Проблема в том, что Логин принадлежит Пользователю, и ему необходимо определить пользователя в своем конструкторе. Как передать пользователя в закрытие?

Я хочу сделать что-то вроде:

def user = grails.admin.User.read(appCtx.springSecurityService.currentUser.id)
Login.withTransaction{ user ->
    login = new Login(user: user)
}

но не знаю, как передать конкретного пользователя.

Ответы [ 2 ]

1 голос
/ 15 февраля 2012

Вы не можете сделать Login.withTransaction{ user ->, так как параметр замыкания, который вы передаете методу withTransaction, принимает аргумент, который является TransactionStatus - вы не можете указать тип, только имя.

Но я не уверен, почему вы видите то, что видите, в отношении объема закрытия.Крутая вещь о замыканиях заключается в том, что они заключают в свои рамки, отсюда и название.Таким образом, переменные вне замыкания всегда доступны внутри замыкания.

Вы бы хотели, чтобы User был загружен внутри блока withTransaction, хотя он находится в том же сеансе Hibernate, что и транзакция, в противном случае Login сохранить не удастся, так как User будет отключен.И используйте load(), а не read(), так как вы просто устанавливаете внешний ключ в Login, поэтому load() работает лучше всего, поскольку он просто создает прокси и не попадает в базу данных, но делает идентификатор доступнымдля Login сохранения.По той же причине, по которой вы хотели бы избежать использования метода currentUser, поскольку это всего лишь ярлык для User.get().

Сказав все это, у меня получилось:

grails.plugins.springsecurity.onInteractiveAuthenticationSuccessEvent = { e, appCtx ->
   Login.withTransaction { status ->
      new Login(user: appCtx.springSecurityService.currentUser).save()
   }
}

но поскольку переменная e является InteractiveAuthenticationSuccessEvent, вам лучше использовать это:

grails.plugins.springsecurity.onInteractiveAuthenticationSuccessEvent = { e, appCtx ->
   Login.withTransaction { status ->
      def user = User.load(e.authentication.principal.id)
      new Login(user: user).save()
   }
}
0 голосов
/ 14 февраля 2012

Почему вы не можете сделать что-то, как показано ниже, просто приведите пользователя в закрытие.

Login.withNewSession {
  def user = grails.admin.User.read(appCtx.springSecurityService.currentUser.id)
  login = new Login(user: user)
}

ИЛИ

Login.withTransaction{
  def user = grails.admin.User.read(appCtx.springSecurityService.currentUser.id)
  login = new Login(user: user)
}
...