package com.azavea.rf.api.uploads

import java.util.UUID

import com.azavea.rf.api.utils.{Auth0Exception, Config}
import com.azavea.rf.datamodel.User

import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import akka.http.scaladsl.unmarshalling.Unmarshal

import com.typesafe.scalalogging.LazyLogging

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

import io.circe.generic.auto._
import io.circe.optics.JsonPath._
import io.circe.Json
import de.heikoseeberger.akkahttpcirce.CirceSupport._


case class Credentials (
  AccessKeyId: String,
  Expiration: String,
  SecretAccessKey: String,
  SessionToken: String
)

case class CredentialsWithBucketPath (
  credentials: Credentials,
  bucketPath: String
)

object Auth0DelegationService extends Config with LazyLogging {
  import com.azavea.rf.api.AkkaSystem._

  val uri = Uri(s"https://$auth0Domain/delegation")

  // The AWS Delegation response has many things, most of which we don't care
  // about. We only want the "Credentials" key, so we setup this path to
  // optionally retrieve it from Json response.
  private val credentialsPath = root.Credentials.as[Credentials]

  def getCredentials(user: User, uploadId: UUID, jwt: String): Future[CredentialsWithBucketPath] = {
    val params = FormData(
      "api-type" -> "aws",
      "client_id" -> auth0ClientId,
      "grant_type" -> "urn:ietf:params:oauth:grant-type:jwt-bearer",
      "id_token" -> jwt,
      "target" -> auth0ClientId
    ).toEntity

    Http()
      .singleRequest(HttpRequest(
        method = HttpMethods.POST,
        uri = uri,
        entity = params
      ))
      .flatMap {
        case HttpResponse(StatusCodes.OK, _, entity, _) =>
          Unmarshal(entity).to[Json].map(credentialsPath.getOption).map {
            case Some(credentials) => CredentialsWithBucketPath(
              credentials,
              s"https://s3.amazonaws.com/${dataBucket}/user-uploads/${user.id}/${uploadId.toString}"
            )
            case None => throw new Auth0Exception(
              StatusCodes.InternalServerError,
              "Missing credentials in AWS STS delegation response"
            )
          }
        case HttpResponse(errCode, _, err, _) =>
          throw new Auth0Exception(errCode, err.toString)
      }
  }
}

Add Auth0 helper for getting delegated S3 creds
Add Auth0 helper for getting delegated S3 creds

Auth0 and AWS STS have been configured in #1323 to allow
a web-authenticated user to get scoped credentials to a
folder in S3 for uploading files.

The helper added here allows making that Auth0 api call
from the Raster Foundry backend.
