<commit_before>package com.azavea.rf.api.exports

import java.util.UUID

import akka.http.scaladsl.server.Route
import com.typesafe.scalalogging.LazyLogging
import cats.implicits._
import cats.data._
import com.lonelyplanet.akka.http.extensions.{PageRequest, PaginationDirectives}
import de.heikoseeberger.akkahttpcirce.CirceSupport._
import io.circe._

import com.azavea.rf.common._
import com.azavea.rf.database.tables.Exports
import com.azavea.rf.database.query._
import com.azavea.rf.database.{ActionRunner, Database}
import com.azavea.rf.datamodel._

import scala.concurrent.ExecutionContext.Implicits.global

trait ExportRoutes extends Authentication
  with ExportQueryParameterDirective
  with PaginationDirectives
  with CommonHandlers
  with UserErrorHandler
  with LazyLogging
  with Airflow
  with ActionRunner {
  implicit def database: Database

  val exportRoutes: Route = handleExceptions(userExceptionHandler) {
    pathEndOrSingleSlash {
      get { listExports } ~
      post { createExport }
    } ~
    pathPrefix(JavaUUID) { exportId =>
      pathEndOrSingleSlash {
        get { getExport(exportId) } ~
        put { updateExport(exportId) } ~
        delete { deleteExport(exportId) }
      } ~
      pathPrefix("definition") {
        pathEndOrSingleSlash {
          get { getExportDefinition(exportId) }
        }
      }
    }
  }

  def listExports: Route = authenticate { user =>
    (withPagination & exportQueryParams) {
      (page: PageRequest, queryParams: ExportQueryParameters) =>
        complete {
          list[Export](Exports.listExports(page.offset, page.limit, queryParams, user),
            page.offset, page.limit)
        }
    }
  }

  def getExport(exportId: UUID): Route = authenticate { user =>
    rejectEmptyResponse {
      complete {
        readOne[Export](Exports.getExport(exportId, user))
      }
    }
  }

  def getExportDefinition(exportId: UUID): Route = authenticate { user =>
    rejectEmptyResponse {
      complete {
        readOne[Export](Exports.getExport(exportId, user))
          .map { _.map { Exports.getExportDefinition(_, user) } }
          .map(_.sequence.map(_.flatten)).flatten
      }
    }
  }

  def createExport: Route = authenticate { user =>
    entity(as[Export.Create]) { newExport =>
      authorize(user.isInRootOrSameOrganizationAs(newExport)) {
        onSuccess(write[Export](Exports.insertExport(newExport, user))) { export =>
          kickoffProjectExport(export.id)
          complete(export)
        }
      }
    }
  }

  def updateExport(uploadId: UUID): Route = authenticate { user =>
    entity(as[Export]) { updateExport =>
      authorize(user.isInRootOrSameOrganizationAs(updateExport)) {
        onSuccess(update(Exports.updateExport(updateExport, uploadId, user))) {
          completeSingleOrNotFound
        }
      }
    }
  }

  def deleteExport(exportId: UUID): Route = authenticate { user =>
    onSuccess(drop(Exports.deleteExport(exportId, user))) {
      completeSingleOrNotFound
    }<commit_msg>Check JSON parameters before writing them to DB (#1812)<commit_after>package com.azavea.rf.api.exports

import java.util.UUID

import akka.http.scaladsl.server.Route
import akka.http.scaladsl.model.StatusCodes
import com.typesafe.scalalogging.LazyLogging
import cats.implicits._
import cats.data._
import com.lonelyplanet.akka.http.extensions.{PageRequest, PaginationDirectives}
import de.heikoseeberger.akkahttpcirce.CirceSupport._
import io.circe._
import io.circe.parser.decode

import com.azavea.rf.common._
import com.azavea.rf.database.tables.Exports
import com.azavea.rf.database.query._
import com.azavea.rf.database.{ActionRunner, Database}
import com.azavea.rf.datamodel._

import scala.concurrent.ExecutionContext.Implicits.global

trait ExportRoutes extends Authentication
  with ExportQueryParameterDirective
  with PaginationDirectives
  with CommonHandlers
  with UserErrorHandler
  with LazyLogging
  with Airflow
  with ActionRunner {
  implicit def database: Database

  val exportRoutes: Route = handleExceptions(userExceptionHandler) {
    pathEndOrSingleSlash {
      get { listExports } ~
      post { createExport }
    } ~
    pathPrefix(JavaUUID) { exportId =>
      pathEndOrSingleSlash {
        get { getExport(exportId) } ~
        put { updateExport(exportId) } ~
        delete { deleteExport(exportId) }
      } ~
      pathPrefix("definition") {
        pathEndOrSingleSlash {
          get { getExportDefinition(exportId) }
        }
      }
    }
  }

  def listExports: Route = authenticate { user =>
    (withPagination & exportQueryParams) {
      (page: PageRequest, queryParams: ExportQueryParameters) =>
        complete {
          list[Export](Exports.listExports(page.offset, page.limit, queryParams, user),
            page.offset, page.limit)
        }
    }
  }

  def getExport(exportId: UUID): Route = authenticate { user =>
    rejectEmptyResponse {
      complete {
        readOne[Export](Exports.getExport(exportId, user))
      }
    }
  }

  def getExportDefinition(exportId: UUID): Route = authenticate { user =>
    rejectEmptyResponse {
      complete {
        readOne[Export](Exports.getExport(exportId, user))
          .map { _.map { Exports.getExportDefinition(_, user) } }
          .map(_.sequence.map(_.flatten)).flatten
      }
    }
  }

  def createExport: Route = authenticate { user =>
    entity(as[Export.Create]) { newExport =>
      authorize(user.isInRootOrSameOrganizationAs(newExport)) {
        newExport.exportOptions.as[ExportOptions] match {
          case Left(df:DecodingFailure) => complete((StatusCodes.BadRequest, s"JSON decoder exception: ${df.show}"))
          case Right(x) =>
            onSuccess(write(Exports.insertExport(newExport, user))) { export =>
              kickoffProjectExport(export.id)
              complete(export)
            }
        }
      }
    }
  }

  def updateExport(uploadId: UUID): Route = authenticate { user =>
    entity(as[Export]) { updateExport =>
      authorize(user.isInRootOrSameOrganizationAs(updateExport)) {
        onSuccess(update(Exports.updateExport(updateExport, uploadId, user))) {
          completeSingleOrNotFound
        }
      }
    }
  }

  def deleteExport(exportId: UUID): Route = authenticate { user =>
    onSuccess(drop(Exports.deleteExport(exportId, user))) {
      completeSingleOrNotFound
    }
{'fraction_non_alphanumeric': 0.10150848522941547, 'fraction_numerical': 0.0006285355122564425, 'mean_word_length': 3.1628515369522563, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6737677', 'n_tokens_mistral': 1939, 'n_tokens_neox': 1906, 'n_words': 331}