app/controllers/Admin.scala (249 lines of code) (raw):

package controllers import com.gu.pandomainauth.PanDomainAuthSettingsRefresher import com.gu.permissions.PermissionsProvider import com.gu.workflow.api.{DesksAPI, SectionDeskMappingsAPI, SectionsAPI} import config.Config import io.circe.{Json, parser} import lib.AdminPermissionFilter import models.api.ApiError import models._ import models.api.ApiError import play.api.Logging import play.api.data.Form import play.api.i18n.I18nSupport import play.api.libs.ws.WSClient import play.api.mvc._ import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future class Admin( sectionsAPI: SectionsAPI, desksAPI: DesksAPI, sectionDeskMappingsAPI: SectionDeskMappingsAPI, override val permissions: PermissionsProvider, override val config: Config, override val controllerComponents: ControllerComponents, override val wsClient: WSClient, override val panDomainSettings: PanDomainAuthSettingsRefresher ) extends BaseController with PanDomainAuthActions with I18nSupport with Logging { private val PermissionFilter = new AdminPermissionFilter(config, permissions) import play.api.data.Forms._ def getSortedSections(): Future[List[Section]] = { sectionsAPI.getSections.asFuture.map { case Left(err) => logger.error(s"error fetching sections: $err"); List() case Right(sections) => sections.sortBy(_.name) } } def getDesks(): Future[List[Desk]] = { desksAPI.getDesks.asFuture.map { case Right(desks) => desks case Left(err) => logger.error(s"error fetching desks: $err"); List() } } def getSectionMappings( selectedDeskIdOption: Option[Long], sectionListFromDB: List[Section], deskList: List[Desk]): Future[List[Section]] = { val selectedDeskOption = for { selectedDeskId <- selectedDeskIdOption selectedDesk <- deskList.find((desk) => selectedDeskId == desk.id) } yield { selectedDesk } selectedDeskOption.map { selectedDesk => sectionDeskMappingsAPI .getSectionsWithRelation(selectedDesk, sectionListFromDB) .asFuture .map { case Right(relations) => relations case Left(err) => logger.error(s"unable to fetch the sections in the relation: $err") List() } }.getOrElse(Future(sectionListFromDB)) } def index = (AuthAction andThen PermissionFilter) { Redirect("/admin/desks-and-sections") } def desksAndSections(selectedDeskIdOption: Option[Long]) = (AuthAction andThen PermissionFilter).async { implicit request => for { deskList <- getDesks() sectionListFromDB <- getSortedSections() sectionList <- getSectionMappings(selectedDeskIdOption, sectionListFromDB, deskList) } yield { val selectedDeskOption = for { selectedDeskId <- selectedDeskIdOption selectedDesk <- deskList.find((desk) => selectedDeskId == desk.id) } yield selectedDesk val desks = selectedDeskOption.map { selectedDesk => deskList.map { desk => if (desk.id == selectedDesk.id) desk.copy(name = desk.name, selected = true) else desk } }.getOrElse(deskList) Ok( views.html.admin.desksAndSections( Json.Null, sectionList.sortBy(_.name), addSectionForm, desks.sortBy(_.name), addDeskForm, selectedDeskOption) ) } } val addSectionForm = Form( mapping( "name" -> nonEmptyText, "selected" -> boolean, "id" -> longNumber )(Section.apply)(Section.unapply) ) val addDeskForm = Form( mapping( "name" -> nonEmptyText, "selected" -> boolean, "id" -> longNumber )(Desk.apply)(Desk.unapply) ) case class assignSectionToDeskFormData(desk: Long, sections: List[String]) val assignSectionToDeskForm = Form( mapping( "desk" -> longNumber, "sections" -> list(text) )(assignSectionToDeskFormData.apply)(assignSectionToDeskFormData.unapply) ) def assignSectionToDesk = (AuthAction andThen PermissionFilter).async { implicit request => assignSectionToDeskForm.bindFromRequest().fold( formWithErrors => Future(BadRequest("failed to update section assignments")), sectionAssignment => { sectionDeskMappingsAPI.assignSectionsToDesk(sectionAssignment.desk, sectionAssignment.sections.map(id => id.toLong)) .asFuture .map { case Right(_) => Redirect(routes.Admin.desksAndSections(Some(sectionAssignment.desk))) case Left(err) => logger.error(s"error upserting section desk mapping: $err") InternalServerError } } ) } /* SECTION routes */ def addSection = (AuthAction andThen PermissionFilter).async { implicit request => addSectionForm.bindFromRequest().fold( formWithErrors => Future(BadRequest("failed to add section")), section => { sectionsAPI.upsertSection(section).asFuture.map { case Right(_) => Redirect(routes.Admin.desksAndSections(None)) case Left(err) => logger.error(s"error upserting section: $err") InternalServerError } } ) } def removeSection = (AuthAction andThen PermissionFilter).async { implicit request => addSectionForm.bindFromRequest().fold( formWithErrors => Future(BadRequest("failed to remove section")), section => { for { _ <- sectionDeskMappingsAPI.removeSectionMapping(section.id).asFuture _ <- sectionsAPI.removeSection(section).asFuture } yield NoContent } ) } /* DESK routes */ def addDesk = (AuthAction andThen PermissionFilter).async { implicit request => addDeskForm.bindFromRequest().fold( formWithErrors => Future(BadRequest(s"failed to add desk ${formWithErrors.errors}")), desk => { desksAPI.upsertDesk(desk).asFuture.map { case Right(_) => Redirect(routes.Admin.desksAndSections(None)) case Left(err) => logger.error(s"error creating desk: $err") InternalServerError } } ) } def removeDesk = (AuthAction andThen PermissionFilter).async { implicit request => addDeskForm.bindFromRequest().fold( formWithErrors => Future(BadRequest("failed to remove desk")), desk => { for { _ <- sectionDeskMappingsAPI.removeDeskMapping(desk.id).asFuture _ <- desksAPI.removeDesk(desk).asFuture } yield { NoContent } } ) } /* Section Tag association */ val addSectionTagForm = Form( mapping( "section_id" -> longNumber, "tag_id" -> nonEmptyText )(assignTagToSectionFormData.apply)(assignTagToSectionFormData.unapply) ) val removeSectionTagForm = Form( mapping( "section_id" -> longNumber, "tag_id" -> nonEmptyText )(unAssignTagToSectionFormData.apply)(unAssignTagToSectionFormData.unapply) ) def sectionsAndTags(selectedSectionIdOption: Option[Long]) = (AuthAction andThen PermissionFilter).async { val selectedSectionOptionFt:Future[Option[Section]] = selectedSectionIdOption match { case Some(selectedSectionId) => for { sections <- getSortedSections() } yield Some(sections.filter( x => x.id == selectedSectionId ).head) case None => Future(None) } val tagIdsFuture: Future[List[String]] = selectedSectionIdOption match { case Some(selectedSectionId) => val tagIdsFt: Future[Either[ApiError, List[String]]] = sectionsAPI.getTagsForSectionFt(selectedSectionId).asFuture tagIdsFt.map(_.toOption.get) case None => Future.successful(List()) } for { deskList <- getDesks() sectionListFromDB <- getSortedSections() tagIds <- tagIdsFuture selectedSectionOption <- selectedSectionOptionFt } yield { val capiKeyJson: Json = parser.parse(s"""{"CAPI_API_KEY": ${config.capiKey}}""").toOption.get Ok( views.html.admin.sectionsAndTags( capiKeyJson, sectionListFromDB, selectedSectionIdOption, selectedSectionOption, tagIds, addSectionTagForm ) ) } } def addSectionTag = (AuthAction andThen PermissionFilter) { implicit request => addSectionTagForm.bindFromRequest().fold( formWithErrors => { BadRequest("failed to execute controllers.admin.addSectionTag()") }, data => { sectionsAPI.insertSectionTag(data.sectionId,data.tagId) NoContent } ) } def removeSectionTag = (AuthAction andThen PermissionFilter) { implicit request => removeSectionTagForm.bindFromRequest().fold( formWithErrors => { BadRequest("failed to execute controllers.admin.removeSectionTag()") }, data => { sectionsAPI.removeSectionTag(data.sectionId,data.tagId) NoContent } ) } }