All Downloads are FREE. Search and download functionalities are using the official Maven repository.

securesocial.core.authenticator.StoreBackedAuthenticator.scala Maven / Gradle / Ivy

/**
 * Copyright 2013-2014 Jorge Aliss (jaliss at gmail dot com) - twitter: @jaliss
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package securesocial.core.authenticator

import org.joda.time.DateTime
import scala.annotation.meta.getter
import scala.concurrent.{ ExecutionContext, Future }
import play.api.mvc.Result

/**
 * Base trait for the Cookie and Http Header based authenticators
 *
 * @tparam U the user object type
 * @tparam T the authenticator type
 */
trait StoreBackedAuthenticator[U, T <: Authenticator[U]] extends Authenticator[U] {
  @transient
  protected val logger = play.api.Logger(this.getClass.getName)

  @(transient @getter)
  val store: AuthenticatorStore[T]

  /**
   * The time an authenticator is allowed to live in the store
   */
  val absoluteTimeoutInSeconds: Int

  /**
   * The inactivity period after which an authenticator is considered invalid
   */
  val idleTimeoutInMinutes: Int

  /**
   * Returns a copy of this authenticator with the given last used time
   *
   * @param time the new time
   * @return the modified authenticator
   */
  def withLastUsedTime(time: DateTime): T

  /**
   * Returns a copy of this Authenticator with the given user
   *
   * @param user the new user
   * @return the modified authenticator
   */
  def withUser(user: U): T

  /**
   * Updated the last used timestamp
   *
   * @return a future with the updated authenticator
   */
  override def touch: Future[T] = {
    val updated = withLastUsedTime(DateTime.now())
    logger.debug(s"touched: lastUsed = $lastUsed")
    store.save(updated, absoluteTimeoutInSeconds)
  }

  /**
   * Updates the user information associated with this authenticator
   *
   * @param user the user object
   * @return a future with the updated authenticator
   */
  override def updateUser(user: U): Future[T] = {
    val updated = withUser(user)
    logger.debug(s"updated user: $updated")
    store.save(updated, absoluteTimeoutInSeconds)
  }

  /**
   * Checks if the authenticator has expired. This is an absolute timeout since the creation of
   * the authenticator
   *
   * @return true if the authenticator has expired, false otherwise.
   */
  def expired: Boolean = expirationDate.isBeforeNow

  /**
   * Checks if the time elapsed since the last time the authenticator was used is longer than
   * the maximum idle timeout specified in the properties.
   *
   * @return true if the authenticator timed out, false otherwise.
   */
  def timedOut: Boolean = lastUsed.plusMinutes(CookieAuthenticator.idleTimeout).isBeforeNow

  /**
   * Checks if the authenticator is valid.  For this implementation it means that the
   * authenticator has not expired or timed out.
   *
   * @return true if the authenticator is valid, false otherwise.
   */
  override def isValid: Boolean = !expired && !timedOut

  /////// Result handling methods
  /**
   * Adds a touched authenticator to the result (for Scala).  In this implementation there's no need
   * to do anything with the result
   *
   * @param result
   * @return
   */
  override def touching(result: Result): Future[Result] = {
    Future.successful(result)
  }

  /**
   * Adds a touched authenticator to the result(for Java).  In this implementation there's no need
   * to do anything with the result
   *
   * @param javaContext the current invocation context
   */
  def touching(javaContext: play.mvc.Http.Context): Future[Unit] = {
    Future.successful(())
  }

  /**
   * Ends an authenticator session.  This is invoked when the user logs out or if the
   * authenticator becomes invalid (maybe due to a timeout)
   *
   * @param result the result that is about to be sent to the client.
   * @return the result modified to signal the authenticator is no longer valid
   */
  override def discarding(result: Result): Future[Result] = {
    import ExecutionContext.Implicits.global
    store.delete(id).map { _ => result }
  }

  /**
   * Ends an authenticator session.  This is invoked when the authenticator becomes invalid (for Java actions)
   *
   * @param javaContext the current http context
   * @return the current http context modified to signal the authenticator is no longer valid
   */
  override def discarding(javaContext: play.mvc.Http.Context): Future[Unit] = {
    import ExecutionContext.Implicits.global
    store.delete(id).map { _ => () }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy