app/controllers/HyperMediaApi.scala (92 lines of code) (raw):
package controllers
import com.gu.pandomainauth.PanDomainAuthSettingsRefresher
import model._
import play.api.libs.json._
import play.api.mvc.{BaseController, ControllerComponents}
import repositories._
import services.Config.conf
import helpers.CORSable
import play.api.Logging
import play.api.libs.ws.WSClient
import scala.concurrent.ExecutionContext
class HyperMediaApi(
val wsClient: WSClient,
override val controllerComponents: ControllerComponents,
val panDomainSettings: PanDomainAuthSettingsRefresher
)(
implicit ec: ExecutionContext
)
extends BaseController
with PanDomainAuthActions
with Logging {
def hyper = CORSable(conf.corsableDomains: _*) {
Action {
val res = EmptyResponse()
.addLink("tag-sponsorships", HyperMediaHelpers.fullUri("/hyper/tags/{id}/sponsorships"))
.addLink("sponsorship-item", HyperMediaHelpers.fullUri("/hyper/sponsorships/{id}"))
.addLink("tag-item", HyperMediaHelpers.fullUri("/hyper/tags/{id}"))
.addLink("tags", HyperMediaHelpers.fullUri("/hyper/tags{?offset,limit,query,type,internalName,externalName,externalReferenceType,externalReferenceToken,subType}"))
Ok(Json.toJson(res))
}
}
def tag(id: Long) = CORSable(conf.corsableDomains: _*) {
Action {
TagRepository.getTag(id).map { tag =>
Ok(Json.toJson(EntityResponse(TagEntity(tag))))
}.getOrElse(NotFound)
}
}
def tags = CORSable(conf.corsableDomains: _*) {
Action { implicit req =>
// we need to map keyword to topic in the types changes as flex searches for keywords - this might change (07/01/2016)
val types = req.getQueryString("type").map(_.replaceAll(" ", "").split(",").toList.map { x =>
if(x.toLowerCase() == "keyword") "topic" else x
})
val criteria = TagSearchCriteria(
q = req.getQueryString("query"),
searchField = req.getQueryString("searchField"),
types = types,
referenceType = req.getQueryString("externalReferenceType"),
internalName = req.getQueryString("internalName"),
externalName = req.getQueryString("externalName"),
referenceToken = req.getQueryString("externalReferenceToken"),
subType = req.getQueryString("subType")
)
val limit = req.getQueryString("limit").getOrElse("25").toInt
val offset = req.getQueryString("offset").getOrElse("0").toInt
val tags = TagLookupCache.search(criteria).drop(offset).take(limit).map { tag =>
EmbeddedEntity(HyperMediaHelpers.tagUri(tag.id), Some(TagEntity(tag)))
}
Ok(Json.toJson(CollectionResponse(offset, limit, Some(tags.size), tags)))
}
}
def sponsorship(id: Long) = CORSable(conf.corsableDomains: _*) {
Action {
SponsorshipRepository.getSponsorship(id).map { s =>
Ok(Json.toJson(EntityResponse(s)))
}.getOrElse(NotFound)
}
}
def tagSponsorships(id: Long) = CORSable(conf.corsableDomains: _*) {
Action {
TagRepository.getTag(id).map { tag =>
val activeSponsorships = tag.activeSponsorships.flatMap{sid => SponsorshipRepository.getSponsorship(sid)}
val paidSponsorship = tag.sponsorship.flatMap(SponsorshipRepository.getSponsorship(_))
val sponsorships = (activeSponsorships ::: paidSponsorship.toList).distinct
Ok(Json.toJson(CollectionResponse(
offset = 0,
limit = sponsorships.length,
total = Some(sponsorships.length),
data = sponsorships.map{ s => EmbeddedEntity(HyperMediaHelpers.sponsorshipUri(s.id), Some(s))}
)))
}.getOrElse(NotFound)
}
}
def preflight(routes: String) = CORSable(conf.corsableDomains: _*) {
Action { implicit req =>
val requestedHeaders = req.headers.get("Access-Control-Request-Headers")
NoContent.withHeaders(
CORSable.CORS_ALLOW_METHODS -> "GET, DELETE, PUT",
CORSable.CORS_ALLOW_HEADERS -> requestedHeaders.getOrElse(""))
}
}
}