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

persistence.datomic.daos.OpenIDInfoDAO.scala Maven / Gradle / Ivy

package persistence.datomic.daos

import javax.inject.Inject

import com.mohiva.play.silhouette.api.LoginInfo
import com.mohiva.play.silhouette.impl.providers.OpenIDInfo
import com.mohiva.play.silhouette.persistence.daos.DelegableAuthInfoDAO
import datomisca.DatomicMapping._
import datomisca._
import datomiscadao.DB
import persistence.datomic.DatomicAuthService

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.language.reflectiveCalls

/**
 * The DAO to persist the OAuth1 information.
 */
final class OpenIDInfoDAO @Inject() (myDatomisca: DatomicAuthService)
    extends DelegableAuthInfoDAO[OpenIDInfo] {

  implicit val conn = myDatomisca.conn
  protected[this] val e = conn

  /**
   * Finds the auth info which is linked to the specified login info.
   *
   * @param loginInfo The linked login info.
   * @return The found auth info or None if no auth info could be found for the given login info.
   */
  override def find(loginInfo: LoginInfo): Future[Option[OpenIDInfo]] =
    Future.successful(OpenIDInfoImpl.findWithId(loginInfo).map(_._2))

  /**
   * Adds new auth info for the given login info.
   *
   * @param loginInfo The login info for which the auth info should be added.
   * @param authInfo  The auth info to add.
   * @return The added auth info.
   */
  override def add(loginInfo: LoginInfo, authInfo: OpenIDInfo): Future[OpenIDInfo] =
    OpenIDInfoImpl.add(loginInfo, authInfo)

  /**
   * Updates the auth info for the given login info.
   *
   * @param loginInfo The login info for which the auth info should be updated.
   * @param authInfo  The auth info to update.
   * @return The updated auth info.
   */
  override def update(loginInfo: LoginInfo, authInfo: OpenIDInfo): Future[OpenIDInfo] =
    OpenIDInfoImpl.update(loginInfo, authInfo)

  /**
   * Saves the auth info for the given login info.
   *
   * This method either adds the auth info if it doesn't exists or it updates the auth info
   * if it already exists.
   *
   * @param loginInfo The login info for which the auth info should be saved.
   * @param authInfo  The auth info to save.
   * @return The saved auth info.
   */
  override def save(loginInfo: LoginInfo, authInfo: OpenIDInfo): Future[OpenIDInfo] = {
    find(loginInfo).flatMap {
      case Some(_) => update(loginInfo, authInfo)
      case None => add(loginInfo, authInfo)
    }
  }

  override def remove(loginInfo: LoginInfo): Future[Unit] = Future.successful(LoginInfoImpl.remove(loginInfo)(conn))

}

object OpenIDInfoImpl extends DB[OpenIDInfo] {

  object Schema {

    object ns {
      val openIdInfo = new Namespace("oauth1Info")
    }

    val id = Attribute(ns.openIdInfo / "id", SchemaType.string, Cardinality.one).withDoc("The openID")
    val attributes = Attribute(ns.openIdInfo / "attributes", SchemaType.string, Cardinality.one).withDoc("The attributes passed by the provider")

    val schema = Seq(
      id, attributes
    )

  }

  def mapToString(mapOpt: Map[String, String]): String = ""

  def stringToMap(string: String): Map[String, String] = Map[String, String]()

  implicit val reader: EntityReader[OpenIDInfo] = (
    Schema.id.read[String] and
    Schema.attributes.read[String].map(stringToMap)
  )(OpenIDInfo.apply _)

  implicit val writer: PartialAddEntityWriter[OpenIDInfo] = (
    Schema.id.write[String] and
    Schema.attributes.write[String].contramap(mapToString)
  )(unlift(OpenIDInfo.unapply))

  def findWithId(loginInfo: LoginInfo)(implicit conn: Connection): Option[(Long, OpenIDInfo)] = {
    val query = Query(
      """
      [
        :find ?e
        :in $ ?providerId ?providerKey
        :where
          [?l :loginInfo/providerId ?providerId]
          [?l :loginInfo/providerKey ?providerKey]
          [?l :loginInfo/openIdInfo ?e]
      ]
      """
    )

    DB.headOptionWithId(Datomic.q(query, Datomic.database, loginInfo.providerID, loginInfo.providerKey), Datomic.database())

  }

  def add(loginInfo: LoginInfo, oAuth1Info: OpenIDInfo)(implicit conn: Connection): Future[OpenIDInfo] = {
    implicit val loginInfoWriter = persistence.datomic.daos.LoginInfoImpl.writer
    val oAuth1InfoFact = DatomicMapping.toEntity(DId(Partition.USER))(oAuth1Info)

    val loginInfoFact = DatomicMapping.toEntity(DId(Partition.USER))(loginInfo)

    val loginInfoPasswordFact = SchemaFact.add(loginInfoFact.id)(LoginInfoImpl.Schema.oAuth1Info -> oAuth1InfoFact)

    for {
      tx <- Datomic.transact(loginInfoFact, oAuth1InfoFact, loginInfoPasswordFact)
    } yield OpenIDInfoImpl.get(tx.resolve(oAuth1InfoFact.id))

  }

  def update(loginInfo: LoginInfo, oAuth1Info: OpenIDInfo)(implicit conn: Connection): Future[OpenIDInfo] = {

    val foundInfo: (Long, OpenIDInfo) = OpenIDInfoImpl.findWithId(loginInfo).get
    implicit val primaryId = foundInfo._1
    val o = foundInfo._2

    val passwordInfoFacts: Seq[TxData] = Seq(
      DB.factOrNone(o.id, oAuth1Info.id, Schema.id -> oAuth1Info.id),
      DB.factOrNone(o.attributes, oAuth1Info.attributes, Schema.attributes -> mapToString(oAuth1Info.attributes))
    ).flatten

    for {
      tx <- Datomic.transact(passwordInfoFacts)
    } yield oAuth1Info

  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy