Secure Social Play 2.x / Сохранение временного, незарегистрированного (т.е. еще не вошедшего в систему) пользователя в сеансе?

Я использую Play Framework (Scala) и SecureSocial для аутентификации пользователей.

Я хочу, чтобы мой сайт позволял не вошедшим пользователям просматривать и заполнять определенные пользовательские данные (например, адрес электронной почты) во время сеанса.

У меня есть настраиваемая реализация UserService, которая сохраняет зарегистрированных пользователей в БД (и мой собственный объект модели User, который реализует функцию securesocial.core.Identity)

У меня есть подкласс UnregisteredUser, который я хотел бы сохранить в сеансе, пока пользователь не вошел в систему.

Какова наилучшая практика для этого, пожалуйста?


person Chris Beach    schedule 13.05.2013    source источник


Ответы (1)


Я предполагаю, что ваша конкретная цель - эффективно собрать все данные относительно незарегистрированного пользователя в каждом из ваших заинтересованных действий контроллера. Проблема: мы хотим получить сборку UnregisteredUser, напрямую собирающую все эти данные в сеансе.

Во-первых, сохраняйте данные UnregisteredUser, когда захотите, в сеансе, используя базовый API Play 2 сеансы. :

Ok("Welcome Guest User!").withSession(
  "email" -> "unregisteredUserEmail"  //  assuming a randomly chosen Id since not logged yet
  // many other data here
)

Затем вы можете просто написать trait, расширяющий вашу фактическую черту SecureSocial, содержащую:

case class GuestRequest[A](optUnregisteredUser: Option[UnregisteredUser], request: Request[A]) extends WrappedRequest(request)

def GuestAction(f: GuestRequest[AnyContent] => Result): Action[AnyContent] = {
    implicit request => {
      val optUnregisteredUserEmail = session.get("currentUnregisteredUser")
      val unregisteredUser = UnregisteredUser(optUnregisteredUserEmail) 
      f(GuestRequest(optUnregisteredUser, request))
}

В каждом из ваших заинтересованных контроллеров вы просто сделаете:

def addToCard = GuestAction {
    implicit request =>
      val currentUnregisteredUser: UnregisteredUser = optUnregisteredUser.getOrElse(.....)
      //remaining instructions here
  }

--------------ОБНОВЛЕНИЕ--------------

Действительно, вы можете использовать UserAwareAction из существующей черты SecureSocial для обоих пользовательских стилей. Таким образом, вы должны переопределить UserAwareAction в своем трейте, расширяющем SecureSocial, чтобы объединить функции:

    override def UserAwareAction[A](p: BodyParser[A])(f: RequestWithUser[A] => Result) = Action(p) {
        implicit request => {
          val user = for (
            authenticator <- authenticatorFromRequest;
            user <- userServices.findByUserName(authenticator.userName)
          ) yield {
            touch(authenticator)
            user
          }
          if(user.isEmpty){  //meaning user is not logged
            f(RequestWithUser(tryToBuildUnRegisteredUser, request))  //setting your unregisteredUser
          }
          else{
            f(RequestWithUser(user, request))
          }
        }
      }

 private def tryToBuildUnregisteredUser = {
    val optUnregisteredUserEmail = session.get("currentUnregisteredUser")
    optUnregisteredUserEmail match {
      case Some(e) => Some(UnregisteredUser(e)) 
      case _ => None
    }
 }

Конечно, вы можете изменить его :)

person Mik378    schedule 13.05.2013
comment
Я пытаюсь реализовать ваше решение, пока мы говорим, и внимательно слежу за вашими правками, так как я новичок в Play, и дополнительное объяснение очень ценится. - person Chris Beach; 13.05.2013
comment
Я стремлюсь иметь иерархию пользовательских объектов, в которой есть абстрактный суперкласс, содержащий такие поля, как электронная почта, и подклассы для UnregisteredUser и RegisteredUser (который, например, содержит идентификатор БД). Я бы хотел, чтобы мои методы контроллера ожидали подкласса User, что позволило бы мне одинаково работать как с зарегистрированными, так и с незарегистрированными пользователями. В настоящее время я использую оболочку UserAwareAction, предоставленную SecureSocial. Есть ли способ связать с этим ваш GuestAction, поэтому в моем методе контроллера я получаю подкласс User независимо от того, пришел ли он из SecureSocial или объекта сеанса GuestAction? - person Chris Beach; 13.05.2013