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

im.actor.server.activation.gate.GateCodeActivation.scala Maven / Gradle / Ivy

There is a newer version: 3.0.0
Show newest version
package im.actor.server.activation.gate

import akka.actor.ActorSystem
import akka.event.Logging
import im.actor.server.activation.Activation.Code
import im.actor.server.activation._
import im.actor.server.persist
import slick.dbio.DBIO
import spray.client.pipelining._
import spray.http.HttpMethods.{ POST, GET }
import spray.http._
import spray.httpx.PlayJsonSupport
import spray.httpx.marshalling._
import spray.httpx.unmarshalling._

import scala.concurrent.Future
import scala.reflect.ClassTag
import scalaz.{ -\/, \/, \/- }

class GateCodeActivation(config: GateConfig)(implicit system: ActorSystem) extends CodeActivation with JsonFormatters with PlayJsonSupport {
  import system.dispatcher

  private val log = Logging(system, getClass)

  val pipeline: HttpRequest ⇒ Future[HttpResponse] = addHeader("X-Auth-Token", config.authToken) ~> sendReceive

  override def send(optTransactionHash: Option[String], code: Code): DBIO[CodeFailure \/ Unit] = {
    val codeResponse: Future[CodeResponse] = for {
      entity ← marshalToEntity(code)
      request = HttpRequest(method = POST, uri = s"${config.uri}/v1/codes/send", entity = entity)
      _ = log.debug("Requesting code send with {}", request)
      resp ← pipeline(request)
      codeResp ← unmarshal[CodeResponse](resp)
    } yield codeResp

    for {
      codeResponse ← DBIO.from(codeResponse)
      result ← codeResponse match {
        case CodeHash(hash) ⇒
          optTransactionHash.map { transactionHash ⇒
            for (_ ← persist.auth.GateAuthCodeRepo.createOrUpdate(transactionHash, hash)) yield \/-(())
          } getOrElse DBIO.successful(\/-(()))
        case failure: CodeFailure ⇒
          DBIO.successful(-\/(failure))
      }
    } yield result
  }

  override def validate(transactionHash: String, code: String): DBIO[ValidationResponse] = {
    for {
      optCodeHash ← persist.auth.GateAuthCodeRepo.find(transactionHash)
      validationResponse ← DBIO.from(optCodeHash map { codeHash ⇒
        val validationUri = Uri(s"${config.uri}/v1/codes/validate/${codeHash.codeHash}").withQuery("code" → code)
        val request = HttpRequest(GET, validationUri)
        log.debug("Requesting code validation with {}", request)

        for {
          response ← pipeline(request)
          vr ← unmarshal[ValidationResponse](response)
        } yield vr
      } getOrElse Future.successful(InvalidHash))
    } yield validationResponse
  }

  override def finish(transactionHash: String): DBIO[Unit] = persist.auth.GateAuthCodeRepo.delete(transactionHash).map(_ ⇒ ())

  private def marshalToEntity[T: ClassTag](value: T)(implicit marshaller: Marshaller[T]): Future[HttpEntity] =
    marshal[T](value) match {
      case Left(e) ⇒
        log.warning("Failed to marshal value: {}", e)
        Future.failed(e)
      case Right(entity) ⇒ Future.successful(entity)
    }

  private def unmarshal[T: ClassTag](response: HttpResponse)(implicit um: FromResponseUnmarshaller[T]): Future[T] =
    response.as[T] match {
      case Left(e)       ⇒ Future.failed(new Exception(s"Failed to parse json: ${response.entity.asString}"))
      case Right(result) ⇒ Future.successful(result)
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy