app/controllers/StoryPackagesController.scala (131 lines of code) (raw):

package controllers import java.net.{URLDecoder, URLEncoder} import story_packages.auth.PanDomainAuthActions import com.gu.facia.client.models.CollectionJson import story_packages.metrics.FaciaToolMetrics import story_packages.model.{Cached, StoryPackage} import story_packages.permissions.APIKeyAuthAction import play.api.libs.json.{JsValue, Json} import play.api.libs.ws.WSClient import play.api.mvc._ import story_packages.services.{Database, FrontsApi} import conf.ApplicationConfiguration import story_packages.switchboard.SwitchManager import story_packages.updates._ import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future import scala.util.{Success, Failure} import scala.util.control.NonFatal class StoryPackagesController(config: ApplicationConfiguration, components: ControllerComponents, database: Database, updatesStream: UpdatesStream, frontsApi: FrontsApi, reindexJob: Reindex, wsClient: WSClient) extends StoryPackagesBaseController(config, components, wsClient) with PanDomainAuthActions { private def serializeSuccess(result: StoryPackage): Future[Result] = { Future.successful(Ok(Json.toJson(result)))} private def isHidden(request: Request[AnyContent]): Boolean = { request.queryString.getOrElse("isHidden", Seq("false")).contains("true") } def create() = APIAuthAction.async { request => request.body.asJson.flatMap(_.asOpt[StoryPackage]).map { case story: StoryPackage => database.createStoryPackage(story, request.user) .flatMap{storyPackage => { updatesStream.putStreamCreate(storyPackage, request.user.email) serializeSuccess(storyPackage) }} .recover { case NonFatal(e) => InternalServerError(e.getMessage) } case _ => Future.successful(BadRequest) }.getOrElse(Future.successful(NotAcceptable))} def capiLatest() = APIAuthAction.async { request => val hidden = isHidden(request) FaciaToolMetrics.ProxyCount.increment() val contentApiHost = if (hidden) config.contentApi.packagesDraftHost else config.contentApi.packagesLiveHost val pageSize = config.latest.pageSize val url = s"$contentApiHost/packages?order-by=newest&page-size=$pageSize&${config.contentApi.key.map(key => s"api-key=$key").getOrElse("")}" Logger.info(s"Proxying latest packages API query to: $url") wsClient.url(url).get().map { response => Cached(60) { Ok(response.body).as("application/javascript") } } } def capiSearch(term: String) = APIAuthAction.async { request => val hidden = isHidden(request) val encodedTerm = URLEncoder.encode(URLDecoder.decode(term, "utf-8"), "utf-8") FaciaToolMetrics.ProxyCount.increment() val contentApiHost = if (hidden) config.contentApi.packagesDraftHost else config.contentApi.packagesLiveHost val url = s"$contentApiHost/packages?order-by=relevance&q=$encodedTerm${config.contentApi.key.map(key => s"&api-key=$key").getOrElse("")}" Logger.info(s"Proxying search query to: $url") wsClient.url(url).get().flatMap { response => val json: JsValue = Json.parse(response.body) val packageIds = (json \ "response" \ "results" \\ "packageId").map(_.as[String]) for { packages <- Future.sequence( packageIds.map(id => database.getPackage(id).map(Some.apply).recover { case _ => None }) ) } yield { Cached(60) { Ok(Json.toJson(packages.flatten)).as("application/javascript") } } } } def getPackage(id: String) = APIAuthAction.async { request => database.getPackage(id) .flatMap(serializeSuccess) .recover { case NonFatal(e) => NotFound } } def deletePackage(id: String) = APIAuthAction.async { request => database.removePackage(id).map(storyPackage => { val isHidden = storyPackage.isHidden.getOrElse(false) val deleteMessage = DeletePackage(id, isHidden, storyPackage.name.getOrElse("-unknown-")) val streamUpdate = AuditUpdate(deleteMessage, request.user.email, Map(), storyPackage) updatesStream.putStreamDelete(streamUpdate, id, isHidden) Ok }) } def editPackage(id: String) = APIAuthAction.async { request => val name = (request.body.asJson.get \ "name").as[String] database.touchPackage(id, request.user, Some(name)).map(storyPackage => { for { packageId <- storyPackage.id displayName <- storyPackage.name } yield { frontsApi.amazonClient.collection(packageId).map { case Some(coll) => val collections: Map[String, CollectionJson] = Map((packageId, coll)) val updateMessage = UpdateName(packageId, displayName) val streamUpdate = AuditUpdate(updateMessage, request.user.email, collections, storyPackage) updatesStream.putStreamUpdate(streamUpdate) case None => Logger.info(s"Ignore sending update of empty story package $packageId") } } Ok(Json.toJson(storyPackage)) }) } def reindex(isHidden: Boolean) = new APIKeyAuthAction(config, components.parsers.defaultBodyParser, defaultExecutionContext).async { request => if (SwitchManager.getStatus("story-packages-disable-reindex-endpoint")) { Future.successful(Forbidden("Reindex endpoint disabled by a switch")) } else { reindexJob.scheduleJob(isHidden).map{ case Some(job) => Created(s"Reindex scheduled at ${job.startTime}") case None => Forbidden("Reindex already running") } } } def reindexProgress(isHidden: Boolean) = (new APIKeyAuthAction(config, components.parsers.defaultBodyParser, defaultExecutionContext)) { request => reindexJob.getJobProgress(isHidden) match { case Some(progress) => Ok(Json.toJson(progress)) case None => NotFound("Reindex never run") } } }