play.api.mvc.ControllerComponents Scala Examples

The following examples show how to use play.api.mvc.ControllerComponents. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example.
Example 1
Source File: LanguageSwitchController.scala    From pertax-frontend   with Apache License 2.0 5 votes vote down vote up
package controllers

import config.ConfigDecorator
import com.google.inject.Inject
import play.api.Configuration
import play.api.i18n.{Lang, MessagesApi}
import play.api.mvc.{Action, AnyContent, ControllerComponents, MessagesControllerComponents}
import uk.gov.hmrc.play.language.{LanguageController, LanguageUtils}

class LanguageSwitchController @Inject()(
  configDecorator: ConfigDecorator,
  configuration: Configuration,
  languageUtils: LanguageUtils,
  cc: ControllerComponents)
    extends LanguageController(configuration, languageUtils, cc) {

  def enGb(): Action[AnyContent] = switchToLanguage(language = "english")
  def cyGb(): Action[AnyContent] = switchToLanguage(language = "cymraeg")
  def fallbackURL: String = configDecorator.pertaxFrontendService
  def languageMap: Map[String, Lang] = Map(
    "english" -> Lang("en"),
    "cymraeg" -> Lang("cy")
  )

} 
Example 2
Source File: AuthJourney.scala    From pertax-frontend   with Apache License 2.0 5 votes vote down vote up
package controllers.auth

import com.google.inject.{ImplementedBy, Inject}
import controllers.auth.requests.UserRequest
import play.api.mvc.{ActionBuilder, AnyContent, ControllerComponents}
@ImplementedBy(classOf[AuthJourneyImpl])
trait AuthJourney {
  val authWithPersonalDetails: ActionBuilder[UserRequest, AnyContent]
  val authWithSelfAssessment: ActionBuilder[UserRequest, AnyContent]
  val minimumAuthWithSelfAssessment: ActionBuilder[UserRequest, AnyContent]
}

class AuthJourneyImpl @Inject()(
  authAction: AuthAction,
  minimumAuthAction: MinimumAuthAction,
  selfAssessmentStatusAction: SelfAssessmentStatusAction,
  getPersonDetailsAction: GetPersonDetailsAction,
  cc: ControllerComponents)
    extends AuthJourney {

  override val authWithPersonalDetails
    : ActionBuilder[UserRequest, AnyContent] = authAction andThen selfAssessmentStatusAction andThen getPersonDetailsAction

  override val authWithSelfAssessment
    : ActionBuilder[UserRequest, AnyContent] = authAction andThen selfAssessmentStatusAction

  override val minimumAuthWithSelfAssessment
    : ActionBuilder[UserRequest, AnyContent] = minimumAuthAction andThen selfAssessmentStatusAction

} 
Example 3
Source File: SelfAssessmentStatusAction.scala    From pertax-frontend   with Apache License 2.0 5 votes vote down vote up
package controllers.auth

import com.google.inject.Inject
import controllers.auth.requests._
import models._
import play.api.mvc.{ActionFunction, ActionRefiner, ControllerComponents, Result}
import services.{CitizenDetailsService, EnrolmentStoreCachingService, MatchingDetailsSuccessResponse}
import uk.gov.hmrc.domain.{Nino, SaUtr}
import uk.gov.hmrc.http.HeaderCarrier
import uk.gov.hmrc.play.HeaderCarrierConverter

import scala.concurrent.{ExecutionContext, Future}

class SelfAssessmentStatusAction @Inject()(
  citizenDetailsService: CitizenDetailsService,
  enrolmentsCachingService: EnrolmentStoreCachingService,
  cc: ControllerComponents)(implicit ec: ExecutionContext)
    extends ActionRefiner[AuthenticatedRequest, UserRequest] with ActionFunction[AuthenticatedRequest, UserRequest] {

  private def getSaUtrFromCitizenDetailsService(nino: Nino)(implicit hc: HeaderCarrier): Future[Option[SaUtr]] =
    citizenDetailsService.getMatchingDetails(nino) map {
      case MatchingDetailsSuccessResponse(matchingDetails) => matchingDetails.saUtr
      case _                                               => None
    }

  private def getSelfAssessmentUserType[A](
    implicit hc: HeaderCarrier,
    request: AuthenticatedRequest[A]): Future[SelfAssessmentUserType] =
    request.nino.fold[Future[SelfAssessmentUserType]](Future.successful(NonFilerSelfAssessmentUser)) { nino =>
      request.saEnrolment match {
        case Some(SelfAssessmentEnrolment(saUtr, Activated)) =>
          Future.successful(ActivatedOnlineFilerSelfAssessmentUser(saUtr))
        case Some(SelfAssessmentEnrolment(saUtr, NotYetActivated)) =>
          Future.successful(NotYetActivatedOnlineFilerSelfAssessmentUser(saUtr))
        case None =>
          getSaUtrFromCitizenDetailsService(nino).flatMap {
            case Some(saUtr) =>
              enrolmentsCachingService.getSaUserTypeFromCache(saUtr)
            case None => Future.successful(NonFilerSelfAssessmentUser)
          }
      }
    }

  override protected def refine[A](request: AuthenticatedRequest[A]): Future[Either[Result, UserRequest[A]]] = {
    implicit val hc: HeaderCarrier =
      HeaderCarrierConverter.fromHeadersAndSession(request.headers, Some(request.session))
    getSelfAssessmentUserType(hc, request).map { saType =>
      Right(
        UserRequest(
          request.nino,
          request.name,
          saType,
          request.credentials,
          request.confidenceLevel,
          None,
          request.trustedHelper,
          request.profile,
          None,
          None,
          None,
          request.request
        )
      )
    }
  }

  override protected def executionContext: ExecutionContext = cc.executionContext
} 
Example 4
Source File: GetPersonDetailsAction.scala    From pertax-frontend   with Apache License 2.0 5 votes vote down vote up
package controllers.auth

import com.google.inject.Inject
import config.ConfigDecorator
import controllers.auth.requests.UserRequest
import models.PersonDetails
import play.api.i18n.{I18nSupport, MessagesApi}
import play.api.mvc.Results.Locked
import play.api.mvc.{ActionFunction, ActionRefiner, ControllerComponents, MessagesControllerComponents, Result}
import services.partials.MessageFrontendService
import services.{CitizenDetailsService, PersonDetailsHiddenResponse, PersonDetailsSuccessResponse}
import uk.gov.hmrc.http.HeaderCarrier
import uk.gov.hmrc.play.HeaderCarrierConverter
import uk.gov.hmrc.renderer.TemplateRenderer
import util.LocalPartialRetriever

import scala.concurrent.{ExecutionContext, Future}

class GetPersonDetailsAction @Inject()(
  citizenDetailsService: CitizenDetailsService,
  messageFrontendService: MessageFrontendService,
  cc: ControllerComponents,
  val messagesApi: MessagesApi)(
  implicit configDecorator: ConfigDecorator,
  partialRetriever: LocalPartialRetriever,
  ec: ExecutionContext,
  templateRenderer: TemplateRenderer)
    extends ActionRefiner[UserRequest, UserRequest] with ActionFunction[UserRequest, UserRequest] with I18nSupport {

  override protected def refine[A](request: UserRequest[A]): Future[Either[Result, UserRequest[A]]] =
    populatingUnreadMessageCount()(request).flatMap { messageCount =>
      if (!request.uri.contains("/signout")) {
        getPersonDetails()(request).map { a =>
          a.fold(
            Left(_),
            pd =>
              Right(
                UserRequest(
                  request.nino,
                  request.retrievedName,
                  request.saUserType,
                  request.credentials,
                  request.confidenceLevel,
                  pd,
                  request.trustedHelper,
                  request.profile,
                  messageCount,
                  request.activeTab,
                  request.breadcrumb,
                  request.request
                )
            )
          )
        }
      } else {
        Future.successful(
          Right(
            UserRequest(
              request.nino,
              request.retrievedName,
              request.saUserType,
              request.credentials,
              request.confidenceLevel,
              None,
              request.trustedHelper,
              request.profile,
              messageCount,
              request.activeTab,
              request.breadcrumb,
              request.request
            )
          )
        )
      }
    }

  def populatingUnreadMessageCount()(implicit request: UserRequest[_]): Future[Option[Int]] =
    messageFrontendService.getUnreadMessageCount

  private def getPersonDetails()(implicit request: UserRequest[_]): Future[Either[Result, Option[PersonDetails]]] = {

    implicit val hc: HeaderCarrier =
      HeaderCarrierConverter.fromHeadersAndSession(request.headers, Some(request.session))

    request.nino match {
      case Some(nino) =>
        citizenDetailsService.personDetails(nino).map {
          case PersonDetailsSuccessResponse(pd) => Right(Some(pd))
          case PersonDetailsHiddenResponse =>
            Left(Locked(views.html.manualCorrespondence()))
          case _ => Right(None)
        }
      case _ => Future.successful(Right(None))
    }
  }

  override protected def executionContext: ExecutionContext = cc.executionContext
} 
Example 5
Source File: WebSockets.scala    From Scala-Programming-Projects   with MIT License 5 votes vote down vote up
package controllers

import actors.{BrowserManagerActor, BrowserActor}
import akka.actor.{ActorRef, ActorSystem}
import akka.stream.Materializer
import javax.inject._
import play.api.Logger
import play.api.libs.streams.ActorFlow
import play.api.mvc.{AbstractController, ControllerComponents, WebSocket}

@Singleton
class WebSockets @Inject()(
                            implicit actorSystem: ActorSystem,
                            materializer: Materializer,
                            cc: ControllerComponents) extends AbstractController(cc) {

  val managerActor: ActorRef = actorSystem.actorOf(BrowserManagerActor.props(), "manager-actor")

  def cartEventWS: WebSocket = WebSocket.accept[String, String] {
    implicit request =>
      ActorFlow.actorRef { out =>
        Logger.info(s"Got a new websocket connection from ${request.host}")
        managerActor ! BrowserManagerActor.AddBrowser(out)
        BrowserActor.props(managerActor)
      }
  }
} 
Example 6
Source File: ProfilesController.scala    From crm-seed   with Apache License 2.0 5 votes vote down vote up
package com.dataengi.crm.profiles.controllers

import com.dataengi.crm.identities.actions.SecuredFilteredAction
import cats.instances.all._
import com.google.inject.{Inject, Singleton}
import com.mohiva.play.silhouette.api.Silhouette
import com.dataengi.crm.common.context.types._
import com.dataengi.crm.common.controllers.ApplicationController
import play.api.mvc.{AbstractController, ControllerComponents}
import com.dataengi.crm.profiles.formatters.ProfilesFormatter._
import com.dataengi.crm.profiles.services.ProfilesService
import com.dataengi.crm.identities.utils.auth.DefaultEnv

import scala.concurrent.ExecutionContext

@Singleton
class ProfilesController @Inject()(profilesService: ProfilesService,
                                   val silhouette: Silhouette[DefaultEnv],
                                   components: ControllerComponents,
                                   implicit val executionContext: ExecutionContext)
  extends ApplicationController(components) with SecuredFilteredAction {

  def update = SecuredAccessAction.async(parse.json(updateProfileFormatter)) { implicit request =>
    profilesService.update(request.body, request.identity)
  }

  def get = SecuredAccessAction.async { implicit request =>
    profilesService.get(request.identity)
  }

  def getProfilesByUsers = SecuredAccessAction.async(parse.json(getUsersProfilesDataFormatter)) { implicit request =>
    profilesService.get(request.body)
  }

  def checkNickname(nickname: String) = SecuredAccessAction.async { implicit request =>
    profilesService.existProfileWithNickname(nickname)
  }

} 
Example 7
Source File: CompaniesController.scala    From crm-seed   with Apache License 2.0 5 votes vote down vote up
package com.dataengi.crm.identities.controllers

import com.dataengi.crm.common.controllers.ApplicationController
import com.dataengi.crm.identities.actions.SecuredFilteredAction
import com.google.inject.Inject
import com.mohiva.play.silhouette.api.Silhouette
import com.dataengi.crm.identities.formatters.companies.CompaniesFormatter._
import com.dataengi.crm.identities.services.CompaniesService
import play.api.i18n.I18nSupport
import play.api.mvc.ControllerComponents
import com.dataengi.crm.identities.utils.auth.DefaultEnv

import scala.concurrent.ExecutionContext

class CompaniesController @Inject()(companiesService: CompaniesService,
                                    val silhouette: Silhouette[DefaultEnv],
                                    components: ControllerComponents,
                                    implicit val executionContext: ExecutionContext)
    extends ApplicationController(components)
    with SecuredFilteredAction
    with I18nSupport {

  def all = SecuredAccessAction.async { implicit request =>
    companiesService.all()
  }

  def get(id: Long) = SecuredAccessAction.async { implicit request =>
    companiesService.get(id)
  }

  def findByName(name: String) = SecuredAccessAction.async { implicit request =>
    companiesService.find(name)
  }

  def create = SecuredAccessAction.async(parse.json(companyDataFormatter)) { implicit request =>
    companiesService.create(request.body)
  }

} 
Example 8
Source File: InvitesController.scala    From crm-seed   with Apache License 2.0 5 votes vote down vote up
package com.dataengi.crm.identities.controllers

import java.util.UUID

import com.dataengi.crm.identities.errors.InvitesControllerErrors
import cats.instances.all._
import com.dataengi.crm.common.context.types._
import com.dataengi.crm.common.controllers.ApplicationController
import com.dataengi.crm.identities.actions.SecuredFilteredAction
import com.dataengi.crm.identities.errors.AuthenticationServiceErrors
import com.dataengi.crm.identities.formatters.invites.InviteFormatter._
import com.google.inject.Inject
import com.mohiva.play.silhouette.api.Silhouette
import com.dataengi.crm.identities.formatters.invites.{InviteAdvertiserDataFormatter, InviteDataFormatter}
import com.dataengi.crm.identities.models.{Invite, InviteStatuses}
import com.dataengi.crm.identities.services.{AuthenticationService, InvitesService}
import play.api.mvc.{Action, AnyContent, ControllerComponents, Result}
import com.dataengi.crm.identities.utils.auth.DefaultEnv
import com.dataengi.crm.identities.views.html
import com.dataengi.crm.identities.views.html.error

import scala.concurrent.ExecutionContext

class InvitesController @Inject()(invitesService: InvitesService,
                                  authenticationService: AuthenticationService,
                                  val silhouette: Silhouette[DefaultEnv],
                                  components: ControllerComponents,
                                  implicit val executionContext: ExecutionContext)
    extends ApplicationController(components)
    with SecuredFilteredAction {

  def create() = SecuredAccessAction.async(parse.json(InviteDataFormatter.inviteDataFormatter)) { implicit request =>
    invitesService.create(request.body, request.identity.id.get)
  }

  def createAdvertiserInvite() =
    SecuredAccessAction.async(parse.json(InviteAdvertiserDataFormatter.inviteAdvertiserDataFormatter)) { implicit request =>
      invitesService.createAdvertiserInvite(request.body, request.identity.company.id.get, request.identity.id.get)
    }

  def getByCompany = SecuredAccessAction.async { implicit request =>
    for {
      companyId <- request.identity.company.id.toOrWithLeftError(InvitesControllerErrors.CompanyIdIsEmpty)
      invites   <- invitesService.getByCompanyId(companyId)
    } yield invites
  }

  def toSignUp(hash: UUID): Action[AnyContent] = Action.async {
    val getSignUpUrl = for {
      invite            <- invitesService.getByHash(hash).flatMap(checkStatus)
      redirectInviteUrl <- invitesService.getInviteUrl(invite)
    } yield Redirect(redirectInviteUrl)
    //    getSignUpUrl.asyncResult
    getSignUpUrl.value.map {
      case Right(result: Result) => result
      case Left(appErrorResult: ForbiddenResult) =>
        Ok(error(403, "URL is not active", appErrorResult.description))
      case Left(appErrorResult: AppErrorResult) =>
        Ok(html.error(403, "URL is not active", appErrorResult.description))
      case Left(appErrorResult: AppError) =>
        Ok(html.error(403, "URL is not active", appErrorResult.toString))
    }
  }

  private def checkStatus(invite: Invite): Or[Invite] =
    if (invite.status == InviteStatuses.Waiting)
      invite.toOr
    else
      AuthenticationServiceErrors.SignUpUrlAlreadyUsed.toErrorOrWithType[Invite]

  def all = SecuredAccessAction.async { implicit request =>
    invitesService.all()
  }

  def getByInvitedUser(invitedBy: Long) = SecuredAccessAction.async { implicit request =>
    invitesService.getByUserIdWhichInvite(invitedBy)
  }

  def remove(id: Long) = SecuredAccessAction.async { implicit request =>
    invitesService.remove(id)
  }

  def checkExistUser(email: String) = SecuredAccessAction.async { implicit request =>
    authenticationService.checkUserExist(email)
  }
} 
Example 9
Source File: RolesController.scala    From crm-seed   with Apache License 2.0 5 votes vote down vote up
package com.dataengi.crm.identities.controllers

import com.dataengi.crm.identities.actions.SecuredFilteredAction
import com.dataengi.crm.identities.services.RolesService
import com.dataengi.crm.identities.formatters.roles.RoleFormatter._
import com.dataengi.crm.common.controllers.ApplicationController
import com.google.inject.Inject
import com.mohiva.play.silhouette.api.Silhouette
import play.api.i18n.I18nSupport
import play.api.mvc.ControllerComponents
import com.dataengi.crm.identities.utils.auth.DefaultEnv

import scala.concurrent.ExecutionContext

class RolesController @Inject()(rolesService: RolesService,
                                val silhouette: Silhouette[DefaultEnv],
                                components: ControllerComponents,
                                implicit val executionContext: ExecutionContext)
    extends ApplicationController(components)
    with SecuredFilteredAction
    with I18nSupport {
  def all = SecuredAccessAction.async { implicit request =>
    rolesService.allRoles(request.identity)
  }

  def get(id: Long) = SecuredAccessAction.async { implicit request =>
    rolesService.get(id)
  }

  def findByName(name: String) = SecuredAccessAction.async { implicit request =>
    rolesService.find(name)
  }

} 
Example 10
Source File: UsersManagementController.scala    From crm-seed   with Apache License 2.0 5 votes vote down vote up
package com.dataengi.crm.identities.controllers

import com.dataengi.crm.identities.actions.SecuredFilteredAction
import com.google.inject.Inject
import com.mohiva.play.silhouette.api.Silhouette
import com.dataengi.crm.identities.services.UsersManagementService
import com.dataengi.crm.identities.formatters.authentication.IdentityFormatter._
import com.dataengi.crm.common.controllers.ApplicationController
import play.api.mvc.ControllerComponents
import play.api.i18n.I18nSupport
import com.dataengi.crm.identities.utils.auth.DefaultEnv

import scala.concurrent.ExecutionContext

class UsersManagementController @Inject()(usersManagementService: UsersManagementService,
                                          val silhouette: Silhouette[DefaultEnv],
                                          components: ControllerComponents,
                                          implicit val executionContext: ExecutionContext)
    extends ApplicationController(components)
    with SecuredFilteredAction
    with I18nSupport {

  def getCompanyMembers(companyId: Long) = SecuredAccessAction.async { implicit request =>
    usersManagementService.getCompanyMembers(companyId, request.identity)
  }

  def getCompanyCurrentMembers = SecuredAccessAction.async { implicit request =>
    usersManagementService.getCompanyMembers(request.identity.company.id.get, request.identity)

  }

  def identityInfo = SecuredAccessAction.async { implicit request =>
    usersManagementService.identityInfo(request.identity)
  }

  def activateUser(userId: Long) = SecuredAccessAction.async { implicit request =>
    usersManagementService.activateUser(userId)
  }

  def deactivateUser(userId: Long) = SecuredAccessAction.async { implicit request =>
    usersManagementService.deactivateUser(userId)
  }

} 
Example 11
Source File: PaymentsController.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package v1.controllers

import cats.data.EitherT
import cats.implicits._
import javax.inject.{Inject, Singleton}
import play.api.http.MimeTypes
import play.api.libs.json.Json
import play.api.mvc.{Action, AnyContent, ControllerComponents, Result}
import utils.{EndpointLogContext, Logging}
import v1.audit.AuditEvents
import v1.controllers.requestParsers.PaymentsRequestParser
import v1.models.audit.AuditResponse
import v1.models.errors._
import v1.models.request.payments.PaymentsRawData
import v1.services.{AuditService, EnrolmentsAuthService, PaymentsService}

import scala.concurrent.{ExecutionContext, Future}

@Singleton
class PaymentsController @Inject()(val authService: EnrolmentsAuthService,
                                   requestParser: PaymentsRequestParser,
                                   service: PaymentsService,
                                   auditService: AuditService,
                                   cc: ControllerComponents)(implicit ec: ExecutionContext)
extends AuthorisedController(cc) with BaseController with Logging {

  implicit val endpointLogContext: EndpointLogContext =
    EndpointLogContext(
      controllerName = "PaymentsController",
      endpointName = "retrievePayments"
    )

  def retrievePayments(vrn: String, from: Option[String], to: Option[String]): Action[AnyContent] =
    authorisedAction(vrn).async{ implicit request =>
      logger.info(s"[${endpointLogContext.controllerName}][${endpointLogContext.endpointName}] " +
        s"Successfully retrieved Payments from DES")

      val rawRequest: PaymentsRawData =
        PaymentsRawData(
          vrn = vrn,
          from = from,
          to = to
        )

      val result =
        for {
          parsedRequest <- EitherT.fromEither[Future](requestParser.parseRequest(rawRequest))
          serviceResponse <- EitherT(service.retrievePayments(parsedRequest))
        } yield {
          logger.info(s"[${endpointLogContext.controllerName}][${endpointLogContext.endpointName}] " +
            s"Successfully retrieved Payments from DES")

          auditService.auditEvent(AuditEvents.auditPayments(serviceResponse.correlationId,
            request.userDetails, AuditResponse(OK, Right(Some(Json.toJson(serviceResponse.responseData))))))

          Ok(Json.toJson(serviceResponse.responseData))
            .withApiHeaders(serviceResponse.correlationId)
            .as(MimeTypes.JSON)
        }

      result.leftMap{errorWrapper =>
        val correlationId = getCorrelationId(errorWrapper)
        val result = errorResult(errorWrapper).withApiHeaders(correlationId)
        logger.warn(ControllerError(endpointLogContext ,vrn, request, result.header.status, errorWrapper.error.message))

        auditService.auditEvent(AuditEvents.auditPayments(correlationId,
          request.userDetails, AuditResponse(httpStatus = result.header.status, Left(errorWrapper.auditErrors))))

        result
      }.merge

    }

  private def errorResult(errorWrapper: ErrorWrapper): Result = {
    (errorWrapper.error: @unchecked) match {
      case VrnFormatError | VrnFormatErrorDes |
           FinancialDataInvalidDateFromError | InvalidDateFromErrorDes |
           FinancialDataInvalidDateToError | InvalidDateToErrorDes |
           FinancialDataInvalidDateRangeError | InvalidDataError
      => BadRequest(Json.toJson(errorWrapper))
      case LegacyNotFoundError => NotFound(Json.toJson(errorWrapper))
      case DownstreamError => InternalServerError(Json.toJson(errorWrapper))
    }
  }
} 
Example 12
Source File: LiabilitiesController.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package v1.controllers

import cats.data.EitherT
import cats.implicits._
import javax.inject.{Inject, Singleton}
import play.api.libs.json.Json
import play.api.mvc.{Action, AnyContent, ControllerComponents}
import play.mvc.Http.MimeTypes
import utils.{EndpointLogContext, Logging}
import v1.audit.AuditEvents
import v1.controllers.requestParsers.LiabilitiesRequestParser
import v1.models.audit.AuditResponse
import v1.models.errors.ControllerError._
import v1.models.errors._
import v1.models.request.liabilities.LiabilitiesRawData
import v1.services.{AuditService, EnrolmentsAuthService, LiabilitiesService}

import scala.concurrent.{ExecutionContext, Future}

@Singleton
class LiabilitiesController @Inject()(val authService: EnrolmentsAuthService,
                                      requestParser: LiabilitiesRequestParser,
                                      service: LiabilitiesService,
                                      auditService: AuditService,
                                      cc: ControllerComponents)(implicit ec: ExecutionContext)
  extends AuthorisedController(cc) with BaseController with Logging {

  implicit val endpointLogContext: EndpointLogContext =
    EndpointLogContext(
      controllerName = "LiabilitiesController",
      endpointName = "retrieveLiabilities"
    )

  def retrieveLiabilities(vrn: String, from: Option[String], to: Option[String]): Action[AnyContent] =
    authorisedAction(vrn).async { implicit request =>
      logger.info(message = s"[${endpointLogContext.controllerName}][${endpointLogContext.endpointName}] " +
        s"Retrieving Liabilities from DES")

      val rawRequest: LiabilitiesRawData = LiabilitiesRawData(vrn, from, to)

      val result = for {
        parsedRequest <- EitherT.fromEither[Future](requestParser.parseRequest(rawRequest))
        serviceResponse <- EitherT(service.retrieveLiabilities(parsedRequest))
      } yield {
        logger.info(message = s"[${endpointLogContext.controllerName}][${endpointLogContext.endpointName}] " +
          s"Successfully retrieved Liabilities from DES")

        auditService.auditEvent(AuditEvents.auditLiabilities(serviceResponse.correlationId,
          request.userDetails, AuditResponse(OK, Right(Some(Json.toJson(serviceResponse.responseData))))))

        Ok(Json.toJson(serviceResponse.responseData))
          .withApiHeaders(serviceResponse.correlationId)
          .as(MimeTypes.JSON)
      }

      result.leftMap { errorWrapper =>
        val correlationId = getCorrelationId(errorWrapper)
        val result = errorResult(errorWrapper).withApiHeaders(correlationId)
        logger.warn(ControllerError(endpointLogContext ,vrn, request, result.header.status, errorWrapper.error.message))

        auditService.auditEvent(AuditEvents.auditLiabilities(correlationId,
          request.userDetails, AuditResponse(httpStatus = result.header.status, Left(errorWrapper.auditErrors))))

        result
      }.merge

    }

  private def errorResult(errorWrapper: ErrorWrapper) = {
    (errorWrapper.error: @unchecked) match {
      case VrnFormatError | VrnFormatErrorDes | BadRequestError |
           FinancialDataInvalidDateFromError | InvalidDateFromErrorDes |
           FinancialDataInvalidDateToError | InvalidDateToErrorDes |
           FinancialDataInvalidDateRangeError | InvalidDataError
      => BadRequest(Json.toJson(errorWrapper))
      case LegacyNotFoundError => NotFound(Json.toJson(errorWrapper))
      case DownstreamError => InternalServerError(Json.toJson(errorWrapper))
    }
  }
} 
Example 13
Source File: ObligationsController.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package v1.controllers

import cats.data.EitherT
import cats.implicits._
import javax.inject.{Inject, Singleton}
import play.api.libs.json.Json
import play.api.mvc.{Action, AnyContent, ControllerComponents}
import play.mvc.Http.MimeTypes
import utils.{EndpointLogContext, Logging}
import v1.audit.AuditEvents
import v1.controllers.requestParsers.ObligationsRequestParser
import v1.models.audit.AuditResponse
import v1.models.errors._
import v1.models.request.obligations.ObligationsRawData
import v1.services.{AuditService, EnrolmentsAuthService, ObligationsService}

import scala.concurrent.{ExecutionContext, Future}

@Singleton
class ObligationsController @Inject()(val authService: EnrolmentsAuthService,
                                      requestParser: ObligationsRequestParser,
                                      service: ObligationsService,
                                      auditService: AuditService,
                                      cc: ControllerComponents)(implicit ec: ExecutionContext)
  extends AuthorisedController(cc) with BaseController with Logging {

  implicit val endpointLogContext: EndpointLogContext =
    EndpointLogContext(
      controllerName = "ObligationsController",
      endpointName = "retrieveObligations"
    )

  def retrieveObligations(vrn: String, from: Option[String], to: Option[String], status: Option[String]): Action[AnyContent] =
    authorisedAction(vrn).async{ implicit request =>
      logger.info(message = s"[${endpointLogContext.controllerName}][${endpointLogContext.endpointName}] Retrieve obligations for VRN : $vrn")

      val rawRequest: ObligationsRawData =
        ObligationsRawData(
          vrn = vrn,
          from = from,
          to = to,
          status = status
        )

      val result =
        for {
          parsedRequest <- EitherT.fromEither[Future](requestParser.parseRequest(rawRequest))
          serviceResponse <- EitherT(service.retrieveObligations(parsedRequest))
        } yield {
          logger.info(message = s"[${endpointLogContext.controllerName}][${endpointLogContext.endpointName}] Successfully retrieved Obligations from DES")

          auditService.auditEvent(AuditEvents.auditObligations(serviceResponse.correlationId,
            request.userDetails, AuditResponse(OK, Right(Some(Json.toJson(serviceResponse.responseData))))))

          Ok(Json.toJson(serviceResponse.responseData))
            .withApiHeaders(serviceResponse.correlationId)
            .as(MimeTypes.JSON)
        }

      result.leftMap { errorWrapper =>
        val correlationId = getCorrelationId(errorWrapper)
        val result = errorResult(errorWrapper).withApiHeaders(correlationId)
        logger.warn(ControllerError(endpointLogContext ,vrn, request, result.header.status, errorWrapper.error.message))

        auditService.auditEvent(AuditEvents.auditObligations(correlationId,
          request.userDetails, AuditResponse(httpStatus = result.header.status, Left(errorWrapper.auditErrors))))

        result
      }.merge

    }

  private def errorResult(errorWrapper: ErrorWrapper) = {
    (errorWrapper.error: @unchecked) match {
      case VrnFormatError | VrnFormatErrorDes |
           InvalidFromError | InvalidToError |
           InvalidStatusError | InvalidDateFromErrorDes |
           InvalidDateToErrorDes | InvalidStatusErrorDes |
           RuleDateRangeInvalidError | RuleOBLDateRangeTooLargeError |
           RuleMissingDateRangeError | BadRequestError => BadRequest(Json.toJson(errorWrapper))
      case LegacyNotFoundError => NotFound(Json.toJson(errorWrapper))
      case DownstreamError => InternalServerError(Json.toJson(errorWrapper))
    }
  }
} 
Example 14
Source File: ViewReturnController.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package v1.controllers

import cats.data.EitherT
import cats.implicits._
import javax.inject.{Inject, Singleton}
import play.api.libs.json.Json
import play.api.mvc.{Action, AnyContent, ControllerComponents}
import play.mvc.Http.MimeTypes
import utils.{EndpointLogContext, Logging}
import v1.audit.AuditEvents
import v1.controllers.requestParsers.ViewReturnRequestParser
import v1.models.audit.AuditResponse
import v1.models.errors._
import v1.models.request.viewReturn.ViewRawData
import v1.services.{AuditService, EnrolmentsAuthService, ViewReturnService}

import scala.concurrent.{ExecutionContext, Future}

@Singleton
class ViewReturnController @Inject()(val authService: EnrolmentsAuthService,
                                    requestParser: ViewReturnRequestParser,
                                    service: ViewReturnService,
                                    auditService: AuditService,
                                    cc: ControllerComponents)(implicit ec: ExecutionContext)
  extends AuthorisedController(cc) with BaseController with Logging {

  implicit val endpointLogContext: EndpointLogContext =
    EndpointLogContext(
      controllerName = "ViewReturnController",
      endpointName = "viewReturn"
    )

  def viewReturn(vrn: String, periodKey: String): Action[AnyContent] =
    authorisedAction(vrn).async{ implicit request =>
      logger.info(message = s"[${endpointLogContext.controllerName}][${endpointLogContext.endpointName}] " +
        s"Retrieve VAT returns for VRN : $vrn")

      val rawRequest: ViewRawData =
        ViewRawData(
          vrn = vrn,
          periodKey = periodKey
        )

      val result =
        for {
          parsedRequest <- EitherT.fromEither[Future](requestParser.parseRequest(rawRequest))
          serviceResponse <- EitherT(service.viewReturn(parsedRequest))
        } yield {
          logger.info(message = s"[${endpointLogContext.controllerName}][${endpointLogContext.endpointName}] " +
            s"Successfully retrieved Vat Return from DES")

          auditService.auditEvent(AuditEvents.auditReturns(serviceResponse.correlationId,
            request.userDetails, AuditResponse(OK, Right(Some(Json.toJson(serviceResponse.responseData))))))

          Ok(Json.toJson(serviceResponse.responseData))
            .withApiHeaders(serviceResponse.correlationId)
            .as(MimeTypes.JSON)
        }

      result.leftMap { errorWrapper =>
        val correlationId = getCorrelationId(errorWrapper)
        val result = errorResult(errorWrapper).withApiHeaders(correlationId)
        logger.warn(ControllerError(endpointLogContext ,vrn, request, result.header.status, errorWrapper.error.message))

        auditService.auditEvent(AuditEvents.auditReturns(correlationId,
          request.userDetails, AuditResponse(httpStatus = result.header.status, Left(errorWrapper.auditErrors))))

        result
      }.merge

    }

  private def errorResult(errorWrapper: ErrorWrapper) = {
    (errorWrapper.error: @unchecked) match {
      case VrnFormatError | VrnFormatErrorDes |
           PeriodKeyFormatError | PeriodKeyFormatErrorDes |
           BadRequestError => BadRequest(Json.toJson(errorWrapper))
      case RuleDateRangeTooLargeError | InvalidInputDataError => Forbidden(Json.toJson(errorWrapper))
      case PeriodKeyFormatErrorDesNotFound => NotFound(Json.toJson(errorWrapper))
      case EmptyNotFoundError => NotFound
      case DownstreamError => InternalServerError(Json.toJson(errorWrapper))
    }
  }
} 
Example 15
Source File: DocumentationController.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package config

import controllers.Assets
import definition.ApiDefinitionFactory
import javax.inject.{Inject, Singleton}
import play.api.http.HttpErrorHandler
import play.api.libs.json.Json
import play.api.mvc.{Action, AnyContent, ControllerComponents}
import uk.gov.hmrc.api.controllers.{DocumentationController => HmrcDocumentationController}

@Singleton
class DocumentationController @Inject()(vatApiDefinition: ApiDefinitionFactory,
                                        cc: ControllerComponents, assets: Assets, errorHandler: HttpErrorHandler)
  extends HmrcDocumentationController(cc,assets , errorHandler ) {

  override def definition(): Action[AnyContent] = Action {
    Ok(Json.toJson(vatApiDefinition.definition))
  }

  def raml(version: String, file: String): Action[AnyContent] = {
    assets.at(s"/public/api/conf/$version", file)
  }
} 
Example 16
Source File: ObligationsResource.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.vatapi.resources

import javax.inject.{Inject, Singleton}
import play.api.mvc.{Action, AnyContent, ControllerComponents}
import uk.gov.hmrc.domain.Vrn
import uk.gov.hmrc.vatapi.audit.AuditEvents
import uk.gov.hmrc.vatapi.connectors.ObligationsConnector
import uk.gov.hmrc.vatapi.models.{Errors, ObligationsQueryParams}
import uk.gov.hmrc.vatapi.resources.wrappers.Response
import uk.gov.hmrc.vatapi.services.{AuditService, AuthorisationService}
import uk.gov.hmrc.vatapi.utils.pagerDutyLogging.Endpoint

import scala.concurrent.ExecutionContext

@Singleton
class ObligationsResource @Inject()(
                                     connector: ObligationsConnector,
                                     val authService: AuthorisationService,
                                     auditService: AuditService,
                                     cc: ControllerComponents
                                   )(implicit ec: ExecutionContext) extends BaseResource(cc) {

  def retrieveObligations(vrn: Vrn, params: ObligationsQueryParams): Action[AnyContent] = APIAction(vrn).async { implicit request =>
    logger.debug(s"[ObligationsResource][retrieveObligations] - Retrieve Obligations for VRN : $vrn")

    val arn = getArn
    val clientId = getClientId

    implicit val endpoint: Endpoint = Endpoint.RetrieveObligations

    def audit(vatResult: VatResult, correlationId: String) =
      auditService.audit(AuditEvents.retrieveVatObligationsAudit(correlationId,
        request.authContext.affinityGroup, arn, clientId, vatResult.auditResponse))

    val result =
      for {
        desResponse <- connector.get(vrn, params)
      } yield {
        val result = desResponse.filter {
          case OK =>
            desResponse.obligations(vrn) match {
              case Right(Some(obligations)) =>
                logger.debug(s"[ObligationsResource][retrieveObligations] Successfully retrieved Obligations from DES")
                VatResult.Success(OK, obligations)
              case Right(None) =>
                VatResult.Failure(NOT_FOUND, Errors.NotFound)
              case Left(ex) =>
                logger.error(s"[ObligationsResource][retrieveObligations] Json format from DES doesn't match the Obligations model: ${ex.msg}")
                VatResult.Failure(INTERNAL_SERVER_ERROR, Errors.InternalServerError)
            }
        }
        audit(result, desResponse.getCorrelationId)
        result
      }

    result.recover {
      case ex =>
        logger.warn(s"[ObligationsResource][retrieveObligations] Unexpected downstream error thrown ${ex.getMessage}")
        val result = VatResult.Failure(INTERNAL_SERVER_ERROR, Errors.InternalServerError)
        audit(result, Response.defaultCorrelationId)
        result
    }.map(_.result)
  }
} 
Example 17
Source File: DocumentationController.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.vatapi.controllers.definition

import controllers.Assets
import javax.inject.{Inject, Singleton}
import play.api.http.HttpErrorHandler
import play.api.libs.json.Json
import play.api.mvc.{Action, AnyContent, ControllerComponents}
import uk.gov.hmrc.api.controllers.{DocumentationController => HmrcDocumentationController}
import uk.gov.hmrc.vatapi.controllers.definition.JsonFormatters._

@Singleton
class DocumentationController @Inject()(vatApiDefinition: VatApiDefinition,
                                        cc: ControllerComponents, assets: Assets, errorHandler: HttpErrorHandler)
  extends HmrcDocumentationController(cc, assets , errorHandler ) {

  override def definition() = Action {
    Ok(Json.toJson(vatApiDefinition.definition))
  }

  def raml(version: String, file: String): Action[AnyContent] = {
    assets.at(s"/public/api/conf/$version", file)
  }
} 
Example 18
Source File: ControllerBaseSpec.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package v1.controllers

import play.api.http.{HeaderNames, MimeTypes, Status}
import play.api.mvc.{AnyContentAsEmpty, ControllerComponents}
import play.api.test.Helpers.stubControllerComponents
import play.api.test.{FakeRequest, ResultExtractors}
import support.UnitSpec

class ControllerBaseSpec extends UnitSpec
  with Status
  with MimeTypes
  with HeaderNames
  with ResultExtractors {

  implicit lazy val fakeRequest: FakeRequest[AnyContentAsEmpty.type] = FakeRequest()

  lazy val cc: ControllerComponents = stubControllerComponents()

  lazy val fakeGetRequest: FakeRequest[AnyContentAsEmpty.type] = fakeRequest.withHeaders(
    HeaderNames.AUTHORIZATION -> "Bearer Token", "X-Client-Id" -> "client-Id"
  )

  def fakePostRequest[T](body: T): FakeRequest[T] = fakeRequest.withBody(body)
} 
Example 19
Source File: ResourceSpec.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.vatapi.resources

import org.scalatest.OptionValues
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec
import play.api.http.{HeaderNames, MimeTypes, Status}
import play.api.mvc.ControllerComponents
import play.api.test.Helpers.stubControllerComponents
import play.api.test.{DefaultAwaitTimeout, ResultExtractors}
import uk.gov.hmrc.domain.Vrn
import uk.gov.hmrc.vatapi.TestUtils
import uk.gov.hmrc.vatapi.config.AppContext
import uk.gov.hmrc.vatapi.mocks.auth.MockAuthorisationService

trait ResourceSpec extends AnyWordSpec
  with Matchers
  with OptionValues
  with TestUtils
  with ResultExtractors
  with HeaderNames
  with Status
  with DefaultAwaitTimeout
  with MimeTypes
  with MockAuthorisationService {

  val vrn: Vrn = generateVrn

  val mockAppContext = mock[AppContext]

  lazy val cc: ControllerComponents = stubControllerComponents()

  def mockAuthAction(vrn: Vrn) = {
    MockAuthorisationService.authCheck(vrn)
  }

  def mockAuthActionWithNrs(vrn: Vrn) = {
    MockAuthorisationService.authCheckWithNrsRequirement(vrn)
  }
} 
Example 20
Source File: ThingsController.scala    From swagger-check   with MIT License 5 votes vote down vote up
package controllers

import java.util.UUID
import javax.inject.Inject

import dal.ThingsRepository
import models.{Link, ThingType, ThingsPage, ThingsPageLinks}
import play.api.libs.json.Json
import play.api.mvc.{AbstractController, ControllerComponents}

import scala.concurrent.ExecutionContext

class ThingsController @Inject()(
    thingRepository: ThingsRepository,
    components: ControllerComponents)(implicit ec: ExecutionContext)
    extends AbstractController(components) {
  def getPage(thingType: Option[ThingType.Type], offset: Int, limit: Int) =
    Action.async { implicit request =>
      thingRepository.getPage(thingType, offset, limit).map { things =>
        val page = ThingsPage(
          things,
          ThingsPageLinks(
            Link.fromCall(
              routes.ThingsController.getPage(thingType, offset, limit)),
            None,
            None))
        Ok(Json.toJson(page))
      }
    }

  def createThing = Action {
    Created
  }

  def getThing(id: UUID) = Action.async { implicit request =>
    thingRepository.getById(id).map {
      case Some(thing) =>
        Ok(Json.toJson(thing))
      case None =>
        NotFound
    }
  }
} 
Example 21
Source File: StatusCtrl.scala    From Cortex   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.thp.cortex.controllers

import scala.concurrent.ExecutionContext

import play.api.Configuration
import play.api.http.Status
import play.api.libs.json.Json.toJsFieldJsValueWrapper
import play.api.libs.json.{JsBoolean, JsString, Json}
import play.api.mvc.{AbstractController, Action, AnyContent, ControllerComponents}

import com.sksamuel.elastic4s.http.ElasticDsl
import javax.inject.{Inject, Singleton}
import org.elasticsearch.client.Node
import org.thp.cortex.models.Worker

import org.elastic4play.database.DBIndex
import org.elastic4play.services.AuthSrv
import org.elastic4play.services.auth.MultiAuthSrv

@Singleton
class StatusCtrl @Inject()(
    configuration: Configuration,
    authSrv: AuthSrv,
    dbIndex: DBIndex,
    components: ControllerComponents,
    implicit val ec: ExecutionContext
) extends AbstractController(components)
    with Status {

  private[controllers] def getVersion(c: Class[_]) = Option(c.getPackage.getImplementationVersion).getOrElse("SNAPSHOT")

  def get: Action[AnyContent] = Action {
    Ok(
      Json.obj(
        "versions" → Json.obj(
          "Cortex"               → getVersion(classOf[Worker]),
          "Elastic4Play"         → getVersion(classOf[AuthSrv]),
          "Play"                 → getVersion(classOf[AbstractController]),
          "Elastic4s"            → getVersion(classOf[ElasticDsl]),
          "ElasticSearch client" → getVersion(classOf[Node])
        ),
        "config" → Json.obj(
          "protectDownloadsWith" → configuration.get[String]("datastore.attachment.password"),
          "authType" → (authSrv match {
            case multiAuthSrv: MultiAuthSrv ⇒
              multiAuthSrv.authProviders.map { a ⇒
                JsString(a.name)
              }
            case _ ⇒ JsString(authSrv.name)
          }),
          "capabilities" → authSrv.capabilities.map(c ⇒ JsString(c.toString)),
          "ssoAutoLogin" → JsBoolean(configuration.getOptional[Boolean]("auth.sso.autologin").getOrElse(false))
        )
      )
    )
  }

  def health: Action[AnyContent] = TODO
} 
Example 22
Source File: AnalyzerConfigCtrl.scala    From Cortex   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.thp.cortex.controllers

import javax.inject.{Inject, Singleton}
import scala.concurrent.{ExecutionContext, Future}

import play.api.libs.json.JsObject
import play.api.mvc.{AbstractController, Action, AnyContent, ControllerComponents}

import org.thp.cortex.models.{BaseConfig, Roles}
import org.thp.cortex.services.{AnalyzerConfigSrv, UserSrv}

import org.elastic4play.BadRequestError
import org.elastic4play.controllers.{Authenticated, Fields, FieldsBodyParser, Renderer}

@Singleton
class AnalyzerConfigCtrl @Inject()(
    analyzerConfigSrv: AnalyzerConfigSrv,
    userSrv: UserSrv,
    authenticated: Authenticated,
    fieldsBodyParser: FieldsBodyParser,
    renderer: Renderer,
    components: ControllerComponents,
    implicit val ec: ExecutionContext
) extends AbstractController(components) {

  def get(analyzerConfigName: String): Action[AnyContent] = authenticated(Roles.orgAdmin).async { request ⇒
    analyzerConfigSrv
      .getForUser(request.userId, analyzerConfigName)
      .map(renderer.toOutput(OK, _))
  }

  def list(): Action[AnyContent] = authenticated(Roles.orgAdmin).async { request ⇒
    analyzerConfigSrv
      .listConfigForUser(request.userId)
      .map { bc ⇒
        renderer.toOutput(
          OK,
          bc.sortWith {
            case (BaseConfig("global", _, _, _), _)               ⇒ true
            case (_, BaseConfig("global", _, _, _))               ⇒ false
            case (BaseConfig(a, _, _, _), BaseConfig(b, _, _, _)) ⇒ a.compareTo(b) < 0
          }
        )
      }
  }

  def update(analyzerConfigName: String): Action[Fields] = authenticated(Roles.orgAdmin).async(fieldsBodyParser) { implicit request ⇒
    request.body.getValue("config").flatMap(_.asOpt[JsObject]) match {
      case Some(config) ⇒
        analyzerConfigSrv
          .updateOrCreate(request.userId, analyzerConfigName, config)
          .map(renderer.toOutput(OK, _))
      case None ⇒ Future.failed(BadRequestError("attribute config has invalid format"))
    }
  }
} 
Example 23
Source File: AnalyzerCtrl.scala    From Cortex   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.thp.cortex.controllers

import scala.concurrent.{ExecutionContext, Future}

import play.api.libs.json.{JsObject, JsString, Json}
import play.api.mvc.{AbstractController, Action, AnyContent, ControllerComponents}

import akka.stream.Materializer
import javax.inject.{Inject, Singleton}
import org.thp.cortex.models.{Roles, Worker}
import org.thp.cortex.services.{UserSrv, WorkerSrv}

import org.elastic4play.controllers.{Authenticated, Fields, FieldsBodyParser, Renderer}
import org.elastic4play.services.JsonFormat.queryReads
import org.elastic4play.services.{QueryDSL, QueryDef}

@Singleton
class AnalyzerCtrl @Inject()(
    workerSrv: WorkerSrv,
    userSrv: UserSrv,
    authenticated: Authenticated,
    fieldsBodyParser: FieldsBodyParser,
    renderer: Renderer,
    components: ControllerComponents,
    implicit val ec: ExecutionContext,
    implicit val mat: Materializer
) extends AbstractController(components) {

  def find: Action[Fields] = authenticated(Roles.read).async(fieldsBodyParser) { request ⇒
    val query                      = request.body.getValue("query").fold[QueryDef](QueryDSL.any)(_.as[QueryDef])
    val range                      = request.body.getString("range")
    val sort                       = request.body.getStrings("sort").getOrElse(Nil)
    val isAdmin                    = request.roles.contains(Roles.orgAdmin)
    val (analyzers, analyzerTotal) = workerSrv.findAnalyzersForUser(request.userId, query, range, sort)
    renderer.toOutput(OK, analyzers.map(analyzerJson(isAdmin)), analyzerTotal)
  }

  def get(analyzerId: String): Action[AnyContent] = authenticated(Roles.read).async { request ⇒
    val isAdmin = request.roles.contains(Roles.orgAdmin)
    workerSrv
      .getForUser(request.userId, analyzerId)
      .map(a ⇒ renderer.toOutput(OK, analyzerJson(isAdmin)(a)))
  }

  private def analyzerJson(isAdmin: Boolean)(analyzer: Worker): JsObject =
    if (isAdmin)
      analyzer.toJson + ("configuration" → Json.parse(analyzer.configuration())) + ("analyzerDefinitionId" → JsString(analyzer.workerDefinitionId()))
    else
      analyzer.toJson + ("analyzerDefinitionId" → JsString(analyzer.workerDefinitionId()))

  def listForType(dataType: String): Action[AnyContent] = authenticated(Roles.read).async { request ⇒
    import org.elastic4play.services.QueryDSL._
    val (responderList, responderCount) = workerSrv.findAnalyzersForUser(request.userId, "dataTypeList" ~= dataType, Some("all"), Nil)
    renderer.toOutput(OK, responderList.map(analyzerJson(isAdmin = false)), responderCount)
  }

  def create(analyzerDefinitionId: String): Action[Fields] = authenticated(Roles.orgAdmin).async(fieldsBodyParser) { implicit request ⇒
    for {
      organizationId   ← userSrv.getOrganizationId(request.userId)
      workerDefinition ← Future.fromTry(workerSrv.getDefinition(analyzerDefinitionId))
      analyzer         ← workerSrv.create(organizationId, workerDefinition, request.body)
    } yield renderer.toOutput(CREATED, analyzerJson(isAdmin = false)(analyzer))
  }

  def listDefinitions: Action[AnyContent] = authenticated(Roles.orgAdmin, Roles.superAdmin).async { _ ⇒
    val (analyzers, analyzerTotal) = workerSrv.listAnalyzerDefinitions
    renderer.toOutput(OK, analyzers, analyzerTotal)
  }

  def scan: Action[AnyContent] = authenticated(Roles.orgAdmin, Roles.superAdmin) { _ ⇒
    workerSrv.rescan()
    NoContent
  }

  def delete(analyzerId: String): Action[AnyContent] = authenticated(Roles.orgAdmin, Roles.superAdmin).async { implicit request ⇒
    for {
      analyzer ← workerSrv.getForUser(request.userId, analyzerId)
      _        ← workerSrv.delete(analyzer)
    } yield NoContent
  }

  def update(analyzerId: String): Action[Fields] = authenticated(Roles.orgAdmin).async(fieldsBodyParser) { implicit request ⇒
    for {
      analyzer        ← workerSrv.getForUser(request.userId, analyzerId)
      updatedAnalyzer ← workerSrv.update(analyzer, request.body)
    } yield renderer.toOutput(OK, analyzerJson(isAdmin = true)(updatedAnalyzer))
  }
} 
Example 24
Source File: ResponderConfigCtrl.scala    From Cortex   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.thp.cortex.controllers

import scala.concurrent.{ExecutionContext, Future}

import play.api.libs.json.JsObject
import play.api.mvc.{AbstractController, Action, AnyContent, ControllerComponents}

import javax.inject.{Inject, Singleton}
import org.thp.cortex.models.{BaseConfig, Roles}
import org.thp.cortex.services.{ResponderConfigSrv, UserSrv}

import org.elastic4play.BadRequestError
import org.elastic4play.controllers.{Authenticated, Fields, FieldsBodyParser, Renderer}

@Singleton
class ResponderConfigCtrl @Inject()(
    responderConfigSrv: ResponderConfigSrv,
    userSrv: UserSrv,
    authenticated: Authenticated,
    fieldsBodyParser: FieldsBodyParser,
    renderer: Renderer,
    components: ControllerComponents,
    implicit val ec: ExecutionContext
) extends AbstractController(components) {

  def get(analyzerConfigName: String): Action[AnyContent] = authenticated(Roles.orgAdmin).async { request ⇒
    responderConfigSrv
      .getForUser(request.userId, analyzerConfigName)
      .map(renderer.toOutput(OK, _))
  }

  def list(): Action[AnyContent] = authenticated(Roles.orgAdmin).async { request ⇒
    responderConfigSrv
      .listConfigForUser(request.userId)
      .map { bc ⇒
        renderer.toOutput(
          OK,
          bc.sortWith {
            case (BaseConfig("global", _, _, _), _)               ⇒ true
            case (_, BaseConfig("global", _, _, _))               ⇒ false
            case (BaseConfig(a, _, _, _), BaseConfig(b, _, _, _)) ⇒ a.compareTo(b) < 0
          }
        )
      }
  }

  def update(analyzerConfigName: String): Action[Fields] = authenticated(Roles.orgAdmin).async(fieldsBodyParser) { implicit request ⇒
    request.body.getValue("config").flatMap(_.asOpt[JsObject]) match {
      case Some(config) ⇒
        responderConfigSrv
          .updateOrCreate(request.userId, analyzerConfigName, config)
          .map(renderer.toOutput(OK, _))
      case None ⇒ Future.failed(BadRequestError("attribute config has invalid format"))
    }
  }
} 
Example 25
Source File: OAuth2ProviderActionBuildersSpec.scala    From play2-oauth2-provider   with MIT License 5 votes vote down vote up
package scalaoauth2.provider

import javax.inject.Inject

import org.scalatest._
import org.scalatest.Matchers._
import play.api.mvc.{AbstractController, ControllerComponents}
import play.api.test._
import play.api.test.Helpers._
import play.api.test.FakeRequest

class OAuth2ProviderActionBuildersSpec extends FlatSpec {

  class MyController @Inject() (components: ControllerComponents)
      extends AbstractController(components)
      with OAuth2ProviderActionBuilders {

    val action = AuthorizedAction(new MockDataHandler) { request =>
      Ok(request.authInfo.user.name)
    }

  }

  it should "return BadRequest" in {
    val controller = new MyController(Helpers.stubControllerComponents())
    val result = controller.action(FakeRequest())
    status(result) should be(400)
    contentAsString(result) should be("")
  }

} 
Example 26
Source File: LogoutController.scala    From dependency   with MIT License 5 votes vote down vote up
package controllers

import io.flow.dependency.www.lib.UiData
import io.flow.play.util.Config
import play.api.i18n.I18nSupport
import play.api.mvc.ControllerComponents

class LogoutController @javax.inject.Inject() (
  config: Config,
  val controllerComponents: ControllerComponents
) extends play.api.mvc.BaseController with I18nSupport {

  def logged_out = Action { implicit request =>
    Ok(
      views.html.logged_out(
        UiData(requestPath = request.path, config = config)
      )
    )
  }

  def index() = Action {
    Redirect("/logged_out").withNewSession
  }

} 
Example 27
Source File: SelfAssessmentResource.scala    From self-assessment-api   with Apache License 2.0 5 votes vote down vote up
package router.resources

import javax.inject.Inject
import play.api.libs.json.JsValue
import play.api.mvc.{Action, AnyContent, ControllerComponents}
import router.services.SelfAssessmentService
import uk.gov.hmrc.auth.core.AuthConnector

import scala.concurrent.ExecutionContext

class SelfAssessmentResource @Inject()(service: SelfAssessmentService,
                                       val cc: ControllerComponents,
                                       val authConnector: AuthConnector)
                                      (implicit ec: ExecutionContext) extends BaseResource(cc, authConnector) {

  def get(route: Any*): Action[AnyContent] = AuthAction.async {
    implicit request =>
      service.get().map{
        case Left(error) => buildErrorResponse(error)
        case Right(apiResponse) => buildResponse(apiResponse)
      }
  }

  def post(route: Any*): Action[JsValue] = AuthAction.async(parse.json) {
    implicit request =>
      withJsonBody[JsValue]{
        service.post(_).map {
          case Left(error) => buildErrorResponse(error)
          case Right(apiResponse) => buildResponse(apiResponse)
        }
      }
  }

  def put(route: Any*): Action[JsValue] = AuthAction.async(parse.json) {
    implicit request =>
      withJsonBody[JsValue]{
        service.put(_).map {
          case Left(error) => buildErrorResponse(error)
          case Right(apiResponse) => buildResponse(apiResponse)
        }
      }
  }
} 
Example 28
Source File: CrystallisationResource.scala    From self-assessment-api   with Apache License 2.0 5 votes vote down vote up
package router.resources

import javax.inject.Inject
import play.api.libs.json.{JsNull, JsValue}
import play.api.mvc.{Action, AnyContent, BodyParser, ControllerComponents}
import router.constants.Versions
import router.constants.Versions._
import router.services.{CrystallisationService, Service}
import uk.gov.hmrc.auth.core.AuthConnector
import scala.concurrent.ExecutionContext.Implicits.global

class CrystallisationResource @Inject()(service: CrystallisationService,
                                        val cc: ControllerComponents,
                                        val authConnector: AuthConnector) extends BaseResource(cc, authConnector) with Service {

  def post(param: Any*): Action[JsValue] = AuthAction.async(parse.json) {
    implicit request =>
      withJsonBody[JsValue] {
        service.post(_).map {
          case Left(error) => buildErrorResponse(error)
          case Right(apiResponse) => buildResponse(apiResponse)
        }
      }
  }

  // Note that intent V1 requires empty JSON (i.e. {}) whereas V2 requires completely empty body. So we need to parse
  // accordingly these with the empty body parsed to JsNull
  private val jsonOrEmptyParser: BodyParser[JsValue] = parse.using { request =>

    if (Versions.getFromRequest(request).contains(VERSION_1))
      parse.json
    else
      parse.empty.map(_ => JsNull)
  }

  def intent(param: Any*): Action[JsValue] = AuthAction.async(jsonOrEmptyParser) { implicit request =>
    withJsonBody[JsValue] { body =>
      val serviceOutcome = body match {
        case JsNull => service.postEmpty
        case json => service.post(json)
      }

      serviceOutcome.map {
        case Left(error) => buildErrorResponse(error)
        case Right(apiResponse) => buildResponse(apiResponse)
      }
    }
  }

  def get(param: Any*): Action[AnyContent] = {
    AuthAction.async {
      implicit request =>
        service.get().map{
          case Left(error) => buildErrorResponse(error)
          case Right(apiResponse) => buildResponse(apiResponse)
        }
    }
  }
} 
Example 29
Source File: SelfEmploymentEopsDeclarationResource.scala    From self-assessment-api   with Apache License 2.0 5 votes vote down vote up
package router.resources

import javax.inject.Inject
import play.api.libs.json.JsValue
import play.api.mvc.{Action, ControllerComponents}
import router.services.SelfEmploymentEopsDeclarationService
import uk.gov.hmrc.auth.core.AuthConnector

import scala.concurrent.ExecutionContext

class SelfEmploymentEopsDeclarationResource @Inject()(service: SelfEmploymentEopsDeclarationService,
                                                      val cc: ControllerComponents,
                                                      val authConnector: AuthConnector)
                                                     (implicit ec: ExecutionContext) extends BaseResource(cc, authConnector) {

  def post(seId: String, nino: String, from: String, to: String): Action[JsValue] = AuthAction.async(parse.json) {
    implicit request =>
      withJsonBody[JsValue] {
        service.post(_).map {
          case Left(error) => buildErrorResponse(error)
          case Right(apiResponse) => buildResponse(apiResponse)
        }
      }
  }
} 
Example 30
Source File: PropertyEopsDeclarationResource.scala    From self-assessment-api   with Apache License 2.0 5 votes vote down vote up
package router.resources

import javax.inject.Inject
import play.api.libs.json.JsValue
import play.api.mvc.{Action, ControllerComponents}
import router.services.PropertyEopsDeclarationService
import uk.gov.hmrc.auth.core.AuthConnector

import scala.concurrent.ExecutionContext

class PropertyEopsDeclarationResource @Inject()(service: PropertyEopsDeclarationService,
                                                val cc: ControllerComponents,
                                                val authConnector: AuthConnector)
                                               (implicit ec: ExecutionContext) extends BaseResource(cc, authConnector) {

  def post(nino: String, from: String, to: String): Action[JsValue] = AuthAction.async(parse.json) {
    implicit request =>
      withJsonBody[JsValue]{
        service.post(_).map {
          case Left(error) => buildErrorResponse(error)
          case Right(apiResponse) => buildResponse(apiResponse)
        }
      }

  }
} 
Example 31
Source File: CharitableGivingResource.scala    From self-assessment-api   with Apache License 2.0 5 votes vote down vote up
package router.resources

import javax.inject.Inject
import play.api.libs.json.JsValue
import play.api.mvc.{Action, AnyContent, ControllerComponents}
import router.services.CharitableGivingService
import uk.gov.hmrc.auth.core.AuthConnector

import scala.concurrent.ExecutionContext

class CharitableGivingResource @Inject()(service: CharitableGivingService,
                                         val cc: ControllerComponents,
                                         val authConnector: AuthConnector)
                                        (implicit ec: ExecutionContext) extends BaseResource(cc, authConnector) {


  def put(param:Any*): Action[JsValue] = AuthAction.async(parse.json) {
    implicit request =>
      withJsonBody[JsValue]{
        service.put(_).map {
          case Left(error) => buildErrorResponse(error)
          case Right(apiResponse) => buildResponse(apiResponse)
        }
      }
  }

  def get(param:Any*): Action[AnyContent] =
    AuthAction.async {
      implicit request =>
        service.get().map{
          case Left(error) => buildErrorResponse(error)
          case Right(apiResponse) => buildResponse(apiResponse)
        }
    }
} 
Example 32
Source File: PropertyEopsObligationsResource.scala    From self-assessment-api   with Apache License 2.0 5 votes vote down vote up
package router.resources

import javax.inject.Inject
import play.api.mvc.{Action, AnyContent, ControllerComponents}
import router.services.PropertyEopsObligationsService
import uk.gov.hmrc.auth.core.AuthConnector

import scala.concurrent.ExecutionContext

class PropertyEopsObligationsResource @Inject()(service: PropertyEopsObligationsService,
                                                val cc: ControllerComponents,
                                                val authConnector: AuthConnector)
                                               (implicit ec: ExecutionContext) extends BaseResource(cc, authConnector) {

  def get(nino: String, from: String, to: String): Action[AnyContent] = AuthAction.async {
    implicit request =>
      service.get().map{
        case Left(error) => buildErrorResponse(error)
        case Right(apiResponse) => buildResponse(apiResponse)
      }
  }
} 
Example 33
Source File: SavingsAccountResource.scala    From self-assessment-api   with Apache License 2.0 5 votes vote down vote up
package router.resources

import javax.inject.Inject
import play.api.libs.json.JsValue
import play.api.mvc.{Action, AnyContent, ControllerComponents}
import router.services.SavingsAccountService
import uk.gov.hmrc.auth.core.AuthConnector

import scala.concurrent.ExecutionContext

class SavingsAccountResource @Inject()(service: SavingsAccountService,
                                       val cc: ControllerComponents,
                                       val authConnector: AuthConnector)
                                      (implicit ec: ExecutionContext) extends BaseResource(cc, authConnector) {


  def post(param: Any*): Action[JsValue] = AuthAction.async(parse.json) { implicit request =>
    withJsonBody[JsValue] {
      service.post(_).map {
        case Left(error) => buildErrorResponse(error)
        case Right(apiResponse) => buildResponse(apiResponse)
      }
    }
  }

  def get(param: Any*): Action[AnyContent] = AuthAction.async { implicit request =>
    service.get().map {
      case Left(error) => buildErrorResponse(error)
      case Right(apiResponse) => buildResponse(apiResponse)
    }
  }

  def put(param: Any*): Action[JsValue] = AuthAction.async(parse.json) { implicit request =>
    withJsonBody[JsValue] {
      service.put(_).map {
        case Left(error) => buildErrorResponse(error)
        case Right(apiResponse) => buildResponse(apiResponse)
      }
    }
  }

} 
Example 34
Source File: BaseResource.scala    From self-assessment-api   with Apache License 2.0 5 votes vote down vote up
package router.resources

import javax.inject.Inject
import play.api.Logger
import play.api.libs.json.JsValue
import play.api.mvc.{ActionBuilder, AnyContent, BodyParser, ControllerComponents, Request, Result}
import router.errors.{ErrorCode, IncorrectAPIVersion, SelfAssessmentAPIError, UnsupportedAPIVersion}
import uk.gov.hmrc.auth.core.{AuthConnector, AuthorisationException, AuthorisedFunctions, InvalidBearerToken}
import uk.gov.hmrc.http.HttpResponse
import uk.gov.hmrc.play.bootstrap.controller.BackendController

import scala.concurrent.{ExecutionContext, Future}
import scala.util.{Success, Try}

class BaseResource @Inject()(cc: ControllerComponents, connector: AuthConnector) extends BackendController(cc) {

  def AuthAction: ActionBuilder[Request, AnyContent] = new ActionBuilder[Request, AnyContent] {

    private val authFunction: AuthorisedFunctions = new AuthorisedFunctions {
      override def authConnector: AuthConnector = connector
    }

    override def parser: BodyParser[AnyContent] = cc.parsers.defaultBodyParser

    override implicit protected def executionContext: ExecutionContext = cc.executionContext

    override def invokeBlock[A](request: Request[A], block: Request[A] => Future[Result]): Future[Result] = {
      implicit val req: Request[A] = request
      authFunction.authorised()(block(request)).recover{
        case _: InvalidBearerToken =>
          Logger.warn(s"[AuthorisedActions] invalid bearer token when trying to access ${request.uri}")
          Forbidden(ErrorCode.invalidBearerToken.asJson)
        case ex: AuthorisationException =>
          Logger.warn(s"[AuthorisedActions] authorisation exception caught when trying to access ${request.uri} : ${ex.reason}")
          Forbidden(ErrorCode.unauthorisedError.asJson)
      }
    }
  }

  private[resources] def buildResponse(apiResponse: HttpResponse): Result = {
    Try(apiResponse.json) match {
      case Success(_: JsValue) =>
        new Status(apiResponse.status)(apiResponse.json)
          .withHeaders(toSimpleHeaders(apiResponse.allHeaders):_*)
      case _ =>
        new Status(apiResponse.status)
          .withHeaders(toSimpleHeaders(apiResponse.allHeaders):_*)
    }
  }

  private[resources] def buildErrorResponse(error: SelfAssessmentAPIError): Result = {
    error match {
      case IncorrectAPIVersion => NotAcceptable(ErrorCode.invalidAcceptHeader.asJson)
      case UnsupportedAPIVersion => NotFound(ErrorCode.notFound.asJson)
    }
  }

  def toSimpleHeaders(headers: Map[String, Seq[String]]): Seq[(String, String)] = {
    (headers ++ Map(
      "X-Content-Type-Options" -> Seq("nosniff"),
      "Content-Type" -> Seq("application/json")
    )).flatMap { case (name, values) => values.map(name -> _) }.toSeq
  }

} 
Example 35
Source File: DividendsResource.scala    From self-assessment-api   with Apache License 2.0 5 votes vote down vote up
package router.resources

import javax.inject.Inject
import play.api.libs.json.JsValue
import play.api.mvc.{Action, AnyContent, ControllerComponents}
import router.services.DividendsService
import uk.gov.hmrc.auth.core.AuthConnector

import scala.concurrent.ExecutionContext

class DividendsResource @Inject()(service: DividendsService,
                                  val cc: ControllerComponents,
                                  val authConnector: AuthConnector)
                                 (implicit ec: ExecutionContext) extends BaseResource(cc, authConnector) {


  def put(param:Any*): Action[JsValue] = AuthAction.async(parse.json) {
    implicit request =>
      withJsonBody[JsValue]{
        service.put(_).map {
          case Left(error) => buildErrorResponse(error)
          case Right(apiResponse) => buildResponse(apiResponse)
        }
      }
  }

  def get(param:Any*): Action[AnyContent] =
    AuthAction.async {
      implicit request =>
        service.get().map{
          case Left(error) => buildErrorResponse(error)
          case Right(apiResponse) => buildResponse(apiResponse)
        }
    }
} 
Example 36
Source File: ReleaseTwoResource.scala    From self-assessment-api   with Apache License 2.0 5 votes vote down vote up
package router.resources

import javax.inject.Inject
import play.api.libs.json.JsValue
import play.api.mvc.{Action, AnyContent, ControllerComponents}
import router.services.ReleaseTwoService
import uk.gov.hmrc.auth.core.AuthConnector

import scala.concurrent.ExecutionContext

class ReleaseTwoResource @Inject()(service: ReleaseTwoService,
                                   val cc: ControllerComponents,
                                   val authConnector: AuthConnector)
                                  (implicit ec: ExecutionContext) extends BaseResource(cc, authConnector) {

    def create(param:Any*): Action[JsValue] = AuthAction.async(parse.json) {
    implicit request =>
      withJsonBody[JsValue]{
        service.create(_).map {
          case Left(error) => buildErrorResponse(error)
          case Right(apiResponse) => buildResponse(apiResponse)
        }
      }
  }

  def get(param:Any*): Action[AnyContent] = AuthAction.async {
    implicit request =>
      service.get().map {
          case Left(error) => buildErrorResponse(error)
          case Right(apiResponse) => buildResponse(apiResponse)
      }
  }

  def update(param:Any*): Action[JsValue] = AuthAction.async(parse.json) {
    implicit request =>
      withJsonBody[JsValue]{
        service.amend(_).map {
          case Left(error) => buildErrorResponse(error)
          case Right(apiResponse) => buildResponse(apiResponse)
        }
      }
  }
} 
Example 37
Source File: TaxCalcResource.scala    From self-assessment-api   with Apache License 2.0 5 votes vote down vote up
package router.resources

import javax.inject.Inject
import play.api.mvc.{Action, AnyContent, ControllerComponents}
import router.services.TaxCalcService
import uk.gov.hmrc.auth.core.AuthConnector

import scala.concurrent.ExecutionContext

class TaxCalcResource @Inject()(service: TaxCalcService,
                                val cc: ControllerComponents,
                                val authConnector: AuthConnector)
                               (implicit ec: ExecutionContext) extends BaseResource(cc, authConnector) {

  def get(nino: String, calculationId: String): Action[AnyContent] = AuthAction.async {
    implicit request =>
      service.get().map{
        case Left(error) => buildErrorResponse(error)
        case Right(apiResponse) => buildResponse(apiResponse)
      }
  }
} 
Example 38
Source File: DocumentationController.scala    From self-assessment-api   with Apache License 2.0 5 votes vote down vote up
package router.controllers

import controllers.Assets
import javax.inject.{Inject, Singleton}
import play.api.http.HttpErrorHandler
import play.api.libs.json.Json
import play.api.mvc.{Action, AnyContent, ControllerComponents}
import router.definition.SelfAssessmentApiDefinition
import uk.gov.hmrc.api.controllers.{DocumentationController => HmrcDocumentationController}

@Singleton
class DocumentationController @Inject()(selfAssessmentApiDefinition: SelfAssessmentApiDefinition,
                                        cc: ControllerComponents, assets: Assets, errorHandler: HttpErrorHandler)
  extends HmrcDocumentationController(cc, assets, errorHandler) {

  override def definition(): Action[AnyContent] = Action {
    Ok(Json.toJson(selfAssessmentApiDefinition.definition))
  }

  override def conf(version: String, file: String): Action[AnyContent] = {
    assets.at(s"/public/api/conf/$version", file)
  }
} 
Example 39
Source File: UnitSpec.scala    From self-assessment-api   with Apache License 2.0 5 votes vote down vote up
package support

import org.scalatest.EitherValues
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpecLike
import play.api.http.{HeaderNames, MimeTypes, Status}
import play.api.mvc.ControllerComponents
import play.api.test.Helpers.stubControllerComponents
import play.api.test.{DefaultAwaitTimeout, FutureAwaits, ResultExtractors}
import uk.gov.hmrc.http.HeaderCarrier

import scala.util.control.NoStackTrace

trait UnitSpec extends AnyWordSpecLike
  with EitherValues
  with Matchers
  with FutureAwaits
  with DefaultAwaitTimeout
  with ResultExtractors
  with HeaderNames
  with Status
  with MimeTypes {

  lazy val controllerComponents: ControllerComponents = stubControllerComponents()

  implicit val hc: HeaderCarrier = HeaderCarrier()

  val testException: Throwable = new NoStackTrace {
    override def getMessage: String = "A test exception was thrown"
  }
} 
Example 40
package commons.controllers

import commons.exceptions.ValidationException
import commons.models.ValidationResultWrapper
import play.api.libs.json.{JsError, Json, Reads}
import play.api.mvc.{AbstractController, BodyParser, ControllerComponents, Result}

import scala.concurrent.ExecutionContext

abstract class RealWorldAbstractController(controllerComponents: ControllerComponents)
  extends AbstractController(controllerComponents) {

  implicit protected val executionContext: ExecutionContext = defaultExecutionContext

  protected def validateJson[A: Reads]: BodyParser[A] = parse.json.validate(
    _.validate[A].asEither.left.map(e => BadRequest(JsError.toJson(e)))
  )

  protected def handleFailedValidation: PartialFunction[Throwable, Result] = {
    case e: ValidationException =>
      val errors = e.violations
        .groupBy(_.property)
        .view
        .mapValues(_.map(propertyViolation => propertyViolation.violation.message))
        .toMap

      val wrapper: ValidationResultWrapper = ValidationResultWrapper(errors)
      UnprocessableEntity(Json.toJson(wrapper))
  }

} 
Example 41
Source File: TagController.scala    From scala-play-realworld-example-app   with MIT License 5 votes vote down vote up
package articles.controllers

import commons.services.ActionRunner
import articles.models._
import articles.services.TagService
import commons.controllers.RealWorldAbstractController
import play.api.libs.json._
import play.api.mvc.{Action, AnyContent, ControllerComponents}

class TagController(actionRunner: ActionRunner,
                    tagService: TagService,
                    components: ControllerComponents)
  extends RealWorldAbstractController(components) {

  def findAll: Action[AnyContent] = Action.async {
    val allAction = tagService.findAll
      .map(tags => tags.map(_.name))
      .map(TagListWrapper(_))
      .map(Json.toJson(_))
      .map(Ok(_))

    actionRunner.runTransactionally(allAction)
  }

} 
Example 42
Source File: CommentController.scala    From scala-play-realworld-example-app   with MIT License 5 votes vote down vote up
package articles.controllers

import commons.exceptions.MissingModelException
import commons.services.ActionRunner
import articles.exceptions.AuthorMismatchException
import articles.models._
import articles.services.CommentService
import commons.controllers.RealWorldAbstractController
import org.apache.commons.lang3.StringUtils
import play.api.libs.json._
import play.api.mvc.{Action, AnyContent, ControllerComponents}
import users.controllers.{AuthenticatedActionBuilder, OptionallyAuthenticatedActionBuilder}

class CommentController(authenticatedAction: AuthenticatedActionBuilder,
                        optionallyAuthenticatedActionBuilder: OptionallyAuthenticatedActionBuilder,
                        actionRunner: ActionRunner,
                        commentService: CommentService,
                        components: ControllerComponents)
  extends RealWorldAbstractController(components) {

  def delete(id: CommentId): Action[AnyContent] = authenticatedAction.async { request =>

    actionRunner.runTransactionally(commentService.delete(id, request.user.userId))
      .map(_ => Ok)
      .recover({
        case _: AuthorMismatchException => Forbidden
        case _: MissingModelException => NotFound
      })
  }

  def findByArticleSlug(slug: String): Action[AnyContent] = optionallyAuthenticatedActionBuilder.async { request =>
    require(StringUtils.isNotBlank(slug))

    val maybeUserId = request.authenticatedUserOption.map(_.userId)
    actionRunner.runTransactionally(commentService.findByArticleSlug(slug, maybeUserId))
      .map(CommentList(_))
      .map(Json.toJson(_))
      .map(Ok(_))
      .recover({
        case _: MissingModelException => NotFound
      })
  }

  def create(slug: String): Action[_] = authenticatedAction.async(validateJson[NewCommentWrapper]) { request =>
    require(StringUtils.isNotBlank(slug))

    val newComment = request.body.comment
    val userId = request.user.userId

    actionRunner.runTransactionally(commentService.create(newComment, slug, userId)
      .map(CommentWrapper(_))
      .map(Json.toJson(_))
      .map(Ok(_)))
      .recover({
        case _: MissingModelException => NotFound
      })
  }

} 
Example 43
Source File: UserController.scala    From silhouette-vuejs-app   with Apache License 2.0 5 votes vote down vote up
package controllers

import java.util.UUID

import com.mohiva.play.silhouette.api.Silhouette
import javax.inject.Inject
import models.services.AuthenticateService
import play.api.libs.json.Json
import play.api.mvc.{AbstractController, ControllerComponents}
import utils.auth.DefaultEnv

import scala.concurrent.{ExecutionContext, Future}

class UserController @Inject()(silhouette: Silhouette[DefaultEnv],
                               authenticateService: AuthenticateService,
                               components: ControllerComponents)(implicit ec: ExecutionContext) extends AbstractController(components) {

  def fetchLinkedAccounts(userId: UUID) = silhouette.SecuredAction.async { implicit req =>
    if (userId == req.identity.userID) {
      authenticateService.getAuthenticationProviders(req.identity.email.get).map(providers => Ok(Json.toJson(providers)))
    } else {
      Future.successful(Forbidden)
    }
  }
} 
Example 44
Source File: ChangePasswordController.scala    From silhouette-vuejs-app   with Apache License 2.0 5 votes vote down vote up
package controllers

import javax.inject.Inject
import com.mohiva.play.silhouette.api._
import com.mohiva.play.silhouette.api.actions.SecuredRequest
import com.mohiva.play.silhouette.api.exceptions.ProviderException
import com.mohiva.play.silhouette.api.repositories.AuthInfoRepository
import com.mohiva.play.silhouette.api.util.{Credentials, PasswordHasherRegistry, PasswordInfo}
import com.mohiva.play.silhouette.impl.providers.CredentialsProvider
import forms.ChangePasswordForm
import play.api.i18n.{I18nSupport, Messages}
import play.api.libs.json.Json
import play.api.mvc.{AbstractController, AnyContent, ControllerComponents}
import utils.auth.{DefaultEnv, HasSignUpMethod}

import scala.concurrent.{ExecutionContext, Future}


  def submit = silhouette.SecuredAction(hasSignUpMethod[DefaultEnv#A](CredentialsProvider.ID)).async {
    implicit request: SecuredRequest[DefaultEnv, AnyContent] =>
      ChangePasswordForm.form.bindFromRequest.fold(
        form => Future.successful(BadRequest),
        password => {
          val (currentPassword, newPassword) = password
          val credentials = Credentials(request.identity.email.getOrElse(""), currentPassword)
          credentialsProvider.authenticate(credentials).flatMap { loginInfo =>
            val passwordInfo = passwordHasherRegistry.current.hash(newPassword)
            authInfoRepository.update[PasswordInfo](loginInfo, passwordInfo).map { _ =>
              Ok(Json.obj("success" -> Messages("password.changed")))
            }
          }.recover {
            case _: ProviderException =>
              BadRequest(Json.obj("message" -> Messages("current.password.invalid")))
          }
        }
      )
  }
} 
Example 45
Source File: ResetPasswordController.scala    From silhouette-vuejs-app   with Apache License 2.0 5 votes vote down vote up
package controllers

import java.util.UUID

import javax.inject.Inject
import com.mohiva.play.silhouette.api._
import com.mohiva.play.silhouette.api.repositories.AuthInfoRepository
import com.mohiva.play.silhouette.api.util.{PasswordHasherRegistry, PasswordInfo}
import com.mohiva.play.silhouette.impl.providers.CredentialsProvider
import forms.ResetPasswordForm
import models.services.{AuthTokenService, UserService}
import play.api.libs.json.Json
import play.api.mvc.{AbstractController, AnyContent, ControllerComponents, Request}
import utils.auth.DefaultEnv

import scala.concurrent.{ExecutionContext, Future}


  def submit(token: UUID) = silhouette.UnsecuredAction.async { implicit request: Request[AnyContent] =>
    authTokenService.validate(token).flatMap {
      case Some(authToken) =>
        ResetPasswordForm.form.bindFromRequest.fold(
          _ => Future.successful(BadRequest),
          password => userService.retrieveUserLoginInfo(authToken.userID, CredentialsProvider.ID).flatMap {
            case Some((user, loginInfo)) =>
              val passwordInfo = passwordHasherRegistry.current.hash(password)
              authInfoRepository.update[PasswordInfo](loginInfo, passwordInfo).map { _ =>
                Ok
              }
            case _ => Future.successful(BadRequest(Json.obj("message" -> "Reset token is either invalid or has expired. Please reset your password again.")))
          }
        )
      case None => Future.successful(BadRequest(Json.obj("message" -> "Reset token is either invalid or has expired. Please reset your password again.")))
    }
  }
} 
Example 46
Source File: SignUpController.scala    From silhouette-vuejs-app   with Apache License 2.0 5 votes vote down vote up
package controllers

import java.util.UUID

import javax.inject.Inject
import com.mohiva.play.silhouette.api._
import forms.SignUpForm
import models.services._
import play.api.i18n.I18nSupport
import play.api.mvc.{AbstractController, AnyContent, ControllerComponents, Request}
import utils.auth.DefaultEnv

import scala.concurrent.{ExecutionContext, Future}


  def submit = silhouette.UnsecuredAction.async { implicit request: Request[AnyContent] =>
    SignUpForm.form.bindFromRequest.fold(
      _ => Future.successful(BadRequest),
      data => {
        val activationUrlProvider: UUID => String = authTokenId => routes.ActivateAccountController.activate(authTokenId).absoluteURL()

        signUpService.signUpByCredentials(data, request.remoteAddress, activationUrlProvider).map {
          case UserCreated(user) =>
            silhouette.env.eventBus.publish(SignUpEvent(user, request))
            Ok
          case UserAlreadyExists =>
            Conflict
          case InvalidRecaptchaCode =>
            BadRequest("Captcha code is not correct")
        }
      }
    )
  }
} 
Example 47
Source File: ActivateAccountController.scala    From silhouette-vuejs-app   with Apache License 2.0 5 votes vote down vote up
package controllers

import java.net.URLDecoder
import java.util.UUID

import javax.inject.Inject
import com.mohiva.play.silhouette.api._
import com.mohiva.play.silhouette.impl.providers.CredentialsProvider
import models.services.{AuthTokenService, MailService, UserService}
import play.api.mvc.{AbstractController, ControllerComponents}
import utils.auth.DefaultEnv

import scala.concurrent.{ExecutionContext, Future}


  def activate(token: UUID) = silhouette.UnsecuredAction.async {
    authTokenService.validate(token).flatMap {
      case Some(authToken) => userService.retrieveUserLoginInfo(authToken.userID, CredentialsProvider.ID).flatMap {
        case Some((user, _)) =>
          userService.setEmailActivated(user).map { _ =>
            Redirect("/signin?message=emailVerified")
          }
        case _ => Future.successful(Redirect("/error?message=activationTokenInvalid"))
      }
      case None => Future.successful(Redirect("/error?message=activationTokenInvalid"))
    }
  }
} 
Example 48
Source File: ApplicationRequestProxy.scala    From HAT2.0   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.hatdex.hat.api.controllers

import com.mohiva.play.silhouette.api.Silhouette
import javax.inject.Inject
import org.hatdex.hat.api.json.ApplicationJsonProtocol
import org.hatdex.hat.api.models.applications.HatApplication
import org.hatdex.hat.api.models.{ ApplicationManage, ErrorMessage, Owner }
import org.hatdex.hat.api.service.RemoteExecutionContext
import org.hatdex.hat.api.service.applications.ApplicationsService
import org.hatdex.hat.authentication.{ ContainsApplicationRole, HatApiAuthEnvironment, HatApiController, WithRole }
import play.api.Logger
import play.api.http.HttpEntity
import play.api.libs.json.Json
import play.api.libs.ws.WSClient
import play.api.mvc.{ Action, AnyContent, ControllerComponents }

import scala.concurrent.Future

class ApplicationRequestProxy @Inject() (
    components: ControllerComponents,
    silhouette: Silhouette[HatApiAuthEnvironment],
    wsClient: WSClient)(
    implicit
    val ec: RemoteExecutionContext,
    applicationsService: ApplicationsService)
  extends HatApiController(components, silhouette) with ApplicationJsonProtocol {

  import org.hatdex.hat.api.json.HatJsonFormats.errorMessage

  val logger = Logger(this.getClass)

  def proxyRequest(id: String, path: String, method: String = "GET"): Action[AnyContent] = SecuredAction(ContainsApplicationRole(Owner(), ApplicationManage(id)) || WithRole(Owner())).async { implicit request =>
    logger.info(s"Proxy $method request for $id to $path with parameters: ${request.queryString}")
    applicationsService.applicationStatus(id).flatMap { maybeStatus ⇒
      maybeStatus map {
        case HatApplication(app, _, true, _, _, _) ⇒

          applicationsService.applicationToken(request.identity, app)
            .flatMap { token ⇒
              val baseRequest = wsClient.url(s"${app.kind.url}/$path")
                .withHttpHeaders("x-auth-token" → token.accessToken)
                .addQueryStringParameters(request.queryString.map(p ⇒ (p._1, p._2.head)).toSeq: _*)
                .withMethod(method)

              request.body.asJson.fold(baseRequest)(b ⇒ baseRequest.withBody(b))
                .stream()
                .map(r ⇒ new Status(r.status).sendEntity(HttpEntity.Strict(r.bodyAsBytes, Some("application/json"))))
            }

        case _ ⇒ Future.successful(BadRequest(Json.toJson(ErrorMessage(
          "Application not active",
          s"Application $id does not appear to be activated by the user"))))
      } getOrElse {
        Future.successful(NotFound(Json.toJson(ErrorMessage(
          "Application not Found",
          s"Application $id does not appear to be a valid application registered with the DEX"))))
      }
    }
  }
} 
Example 49
Source File: LogController.scala    From HAT2.0   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.hatdex.hat.api.controllers

import com.mohiva.play.silhouette.api.Silhouette
import javax.inject.Inject
import org.hatdex.hat.api.json.HatJsonFormats
import org.hatdex.hat.api.models._
import org.hatdex.hat.api.service.{ LogService, RemoteExecutionContext }
import org.hatdex.hat.authentication.{ HatApiAuthEnvironment, HatApiController }
import org.hatdex.hat.utils.HatBodyParsers
import play.api.Logger
import play.api.libs.json.Json
import play.api.mvc.{ Action, ControllerComponents }

import scala.util.Try

class LogController @Inject() (
    components: ControllerComponents,
    parsers: HatBodyParsers,
    logService: LogService,
    silhouette: Silhouette[HatApiAuthEnvironment])(implicit val ec: RemoteExecutionContext)
  extends HatApiController(components, silhouette) with HatJsonFormats {

  private val logger = Logger(this.getClass)

  def logFrontendAction(): Action[LogRequest] = SecuredAction.async(parsers.json[LogRequest]) { request =>
    val logRequest = request.body
    val hatAddress = request.dynamicEnvironment.domain
    val appDetails = request.authenticator.customClaims.flatMap { customClaims =>
      Try(((customClaims \ "application").as[String], (customClaims \ "applicationVersion").as[String])).toOption
    }

    logService.logAction(hatAddress, logRequest, appDetails).map { _ =>
      Ok(Json.toJson(SuccessResponse(s"${logRequest.actionCode} logged")))
    }.recover {
      case e =>
        logger.error(s"Failed to log action ${logRequest.actionCode}. Reason:\n${e.getMessage}")
        InternalServerError(Json.toJson(ErrorMessage("Internal server error", s"Could not log ${logRequest.actionCode} action")))
    }
  }
} 
Example 50
Source File: MyController.scala    From play-grpc   with Apache License 2.0 5 votes vote down vote up
// #using-client
package controllers

import example.myapp.helloworld.grpc.helloworld.GreeterServiceClient
import example.myapp.helloworld.grpc.helloworld.HelloRequest
import javax.inject.Inject
import javax.inject.Singleton
import play.api.mvc.AbstractController
import play.api.mvc.ControllerComponents

import scala.concurrent.ExecutionContext

@Singleton
class MyController @Inject() (
    implicit greeterClient: GreeterServiceClient,
    cc: ControllerComponents,
    exec: ExecutionContext,
) extends AbstractController(cc) {

  def sayHello(name: String) = Action.async {
    greeterClient
      .sayHello(HelloRequest(name))
      .map { reply =>
        Ok(s"response: ${reply.message}")
      }
  }

}
// #using-client 
Example 51
Source File: HealthController.scala    From vinyldns   with Apache License 2.0 5 votes vote down vote up
package controllers

import javax.inject.{Inject, Singleton}
import play.api.mvc.{AbstractController, Action, AnyContent, ControllerComponents}
import vinyldns.core.health.HealthService

@Singleton
class HealthController @Inject() (components: ControllerComponents, healthService: HealthService)
    extends AbstractController(components)
    with CacheHeader {

  def health(): Action[AnyContent] = Action { implicit request =>
    healthService
      .checkHealth()
      .map {
        case Nil => Ok("OK").withHeaders(cacheHeaders: _*)
        case _ =>
          InternalServerError("There was an internal server error.").withHeaders(cacheHeaders: _*)
      }
      .unsafeRunSync()
  }
} 
Example 52
Source File: HealthControllerSpec.scala    From vinyldns   with Apache License 2.0 5 votes vote down vote up
package controllers

import cats.effect.IO
import org.junit.runner.RunWith
import org.specs2.mutable.Specification
import org.specs2.runner.JUnitRunner
import play.api.mvc.ControllerComponents
import play.api.test.Helpers.{GET, status}
import play.api.test.{FakeRequest, Helpers}
import vinyldns.core.health.HealthService
import vinyldns.core.health.HealthCheck._
import play.api.test.Helpers._

@RunWith(classOf[JUnitRunner])
class HealthControllerSpec extends Specification {

  val components: ControllerComponents = Helpers.stubControllerComponents()

  "HealthController" should {
    "send 200 if the healthcheck succeeds" in {
      val healthService =
        new HealthService(List(IO.unit.attempt.asHealthCheck(classOf[HealthControllerSpec])))
      val controller = new HealthController(components, healthService)

      val result = controller
        .health()
        .apply(FakeRequest(GET, "/health"))

      status(result) must beEqualTo(200)
    }
    "send 500 if a healthcheck fails" in {
      val err = IO
        .raiseError(new RuntimeException("bad!!"))
        .attempt
        .asHealthCheck(classOf[HealthControllerSpec])
      val healthService =
        new HealthService(List(IO.unit.attempt.asHealthCheck(classOf[HealthControllerSpec]), err))
      val controller = new HealthController(components, healthService)

      val result = controller
        .health()
        .apply(FakeRequest(GET, "/health"))

      status(result) must beEqualTo(500)
    }
  }
} 
Example 53
Source File: ProfileCtrl.scala    From gospeak   with Apache License 2.0 5 votes vote down vote up
package gospeak.web.pages.user.profile

import cats.effect.IO
import com.mohiva.play.silhouette.api.Silhouette
import gospeak.core.domain.User
import gospeak.core.services.storage.{UserGroupRepo, UserProposalRepo, UserTalkRepo, UserUserRepo}
import gospeak.web.AppConf
import gospeak.web.auth.domain.CookieEnv
import gospeak.web.domain.Breadcrumb
import gospeak.web.pages.published.speakers.routes.{SpeakerCtrl => PublishedSpeakerRoutes}
import gospeak.web.pages.user.UserCtrl
import gospeak.web.pages.user.profile.ProfileCtrl._
import gospeak.web.utils.{GsForms, UICtrl, UserReq}
import play.api.data.Form
import play.api.mvc.{Action, AnyContent, ControllerComponents, Result}

class ProfileCtrl(cc: ControllerComponents,
                  silhouette: Silhouette[CookieEnv],
                  conf: AppConf,
                  groupRepo: UserGroupRepo,
                  proposalRepo: UserProposalRepo,
                  talkRepo: UserTalkRepo,
                  userRepo: UserUserRepo) extends UICtrl(cc, silhouette, conf) {
  def edit(): Action[AnyContent] = UserAction { implicit req =>
    editView(GsForms.user)
  }

  def doEdit(): Action[AnyContent] = UserAction { implicit req =>
    GsForms.user.bindFromRequest.fold(
      formWithErrors => editView(formWithErrors),
      data => userRepo.edit(data)
        .map(_ => Redirect(PublishedSpeakerRoutes.detail(req.user.slug)).flashing("success" -> "Profile updated"))
    )
  }

  private def editView(form: Form[User.Data])(implicit req: UserReq[AnyContent]): IO[Result] = {
    val filledForm = if (form.hasErrors) form else form.fill(req.user.data)
    IO(Ok(html.edit(filledForm)(editBreadcrumb)))
  }
}

object ProfileCtrl {
  def breadcrumb(implicit req: UserReq[AnyContent]): Breadcrumb =
    UserCtrl.breadcrumb.add("Profile" -> PublishedSpeakerRoutes.detail(req.user.slug))

  def editBreadcrumb(implicit req: UserReq[AnyContent]): Breadcrumb =
    breadcrumb.add("Edit" -> routes.ProfileCtrl.edit())
} 
Example 54
Source File: ProposalCtrl.scala    From gospeak   with Apache License 2.0 5 votes vote down vote up
package gospeak.web.pages.user.proposals

import com.mohiva.play.silhouette.api.Silhouette
import gospeak.core.services.storage.SpeakerExternalProposalRepo
import gospeak.libs.scala.domain.Page
import gospeak.web.AppConf
import gospeak.web.auth.domain.CookieEnv
import gospeak.web.domain.Breadcrumb
import gospeak.web.pages.user.UserCtrl
import gospeak.web.pages.user.proposals.ProposalCtrl._
import gospeak.web.utils.{UICtrl, UserReq}
import play.api.mvc.{Action, AnyContent, ControllerComponents}

class ProposalCtrl(cc: ControllerComponents,
                   silhouette: Silhouette[CookieEnv],
                   conf: AppConf,
                   externalProposalRepo: SpeakerExternalProposalRepo) extends UICtrl(cc, silhouette, conf) {
  def list(params: Page.Params): Action[AnyContent] = UserAction { implicit req =>
    externalProposalRepo.listCommon(params).map(proposals => Ok(html.list(proposals)(listBreadcrumb)))
  }
}

object ProposalCtrl {
  def listBreadcrumb(implicit req: UserReq[AnyContent]): Breadcrumb =
    UserCtrl.breadcrumb.add("Proposals" -> routes.ProposalCtrl.list())
} 
Example 55
Source File: VideoCtrl.scala    From gospeak   with Apache License 2.0 5 votes vote down vote up
package gospeak.web.pages.published.videos

import cats.data.OptionT
import com.mohiva.play.silhouette.api.Silhouette
import gospeak.core.domain.Video
import gospeak.core.services.storage.PublicVideoRepo
import gospeak.infra.services.EmbedSrv
import gospeak.libs.scala.domain.{Html, Page, Url}
import gospeak.web.AppConf
import gospeak.web.auth.domain.CookieEnv
import gospeak.web.domain.Breadcrumb
import gospeak.web.pages.published.HomeCtrl
import gospeak.web.pages.published.videos.VideoCtrl._
import gospeak.web.utils.UICtrl
import play.api.mvc.{Action, AnyContent, ControllerComponents}

class VideoCtrl(cc: ControllerComponents,
                silhouette: Silhouette[CookieEnv],
                conf: AppConf,
                videoRepo: PublicVideoRepo) extends UICtrl(cc, silhouette, conf) {
  def list(params: Page.Params): Action[AnyContent] = UserAwareAction { implicit req =>
    videoRepo.list(params).map(videos => Ok(html.list(videos)(listBreadcrumb())))
  }

  def detail(video: Url.Video.Id): Action[AnyContent] = UserAwareAction { implicit req =>
    (for {
      videoElt <- OptionT(videoRepo.find(video))
      embed: Html <- OptionT.liftF(EmbedSrv.embedCode(videoElt.url))
      b = breadcrumb(videoElt)
    } yield Ok(html.detail(videoElt, embed)(b))).value.map(_.getOrElse(publicVideoNotFound(video)))
  }
}

object VideoCtrl {
  def listBreadcrumb(): Breadcrumb =
    HomeCtrl.breadcrumb().add("Videos" -> routes.VideoCtrl.list())

  def breadcrumb(video: Video): Breadcrumb =
    listBreadcrumb().add(video.title -> routes.VideoCtrl.detail(video.id))
} 
Example 56
Source File: CfpCtrl.scala    From gospeak   with Apache License 2.0 5 votes vote down vote up
package gospeak.web.pages.orga.cfps

import cats.data.OptionT
import cats.effect.IO
import com.mohiva.play.silhouette.api.Silhouette
import gospeak.core.domain.utils.OrgaCtx
import gospeak.core.domain.{Cfp, Event, Group}
import gospeak.core.services.storage._
import gospeak.web.AppConf
import gospeak.web.auth.domain.CookieEnv
import gospeak.web.domain.Breadcrumb
import gospeak.web.pages.orga.GroupCtrl
import gospeak.web.pages.orga.cfps.CfpCtrl._
import gospeak.web.pages.orga.events.routes.{EventCtrl => EventRoutes}
import gospeak.web.utils.{GsForms, OrgaReq, UICtrl}
import gospeak.libs.scala.domain.Page
import play.api.data.Form
import play.api.mvc.{Action, AnyContent, ControllerComponents, Result}

class CfpCtrl(cc: ControllerComponents,
              silhouette: Silhouette[CookieEnv],
              conf: AppConf,
              userRepo: OrgaUserRepo,
              val groupRepo: OrgaGroupRepo,
              cfpRepo: OrgaCfpRepo,
              eventRepo: OrgaEventRepo,
              proposalRepo: OrgaProposalRepo) extends UICtrl(cc, silhouette, conf) with UICtrl.OrgaAction {
  def list(group: Group.Slug, params: Page.Params): Action[AnyContent] = OrgaAction(group) { implicit req =>
    val customParams = params.withNullsFirst
    cfpRepo.list(customParams).map(cfps => Ok(html.list(cfps)(listBreadcrumb))) // TODO listWithProposalCount
  }

  def create(group: Group.Slug, event: Option[Event.Slug]): Action[AnyContent] = OrgaAction(group) { implicit req =>
    createView(group, GsForms.cfp, event)
  }

  def doCreate(group: Group.Slug, event: Option[Event.Slug]): Action[AnyContent] = OrgaAction(group) { implicit req =>
    GsForms.cfp.bindFromRequest.fold(
      formWithErrors => createView(group, formWithErrors, event),
      data => (for {
        // TODO check if slug not already exist
        cfpElt <- OptionT.liftF(cfpRepo.create(data))
        redirect <- OptionT.liftF(event.map { e =>
          eventRepo.attachCfp(e, cfpElt.id)
            .map(_ => Redirect(EventRoutes.detail(group, e)))
          // TODO recover and redirect to cfp detail
        }.getOrElse {
          IO.pure(Redirect(routes.CfpCtrl.detail(group, data.slug)))
        })
      } yield redirect).value.map(_.getOrElse(groupNotFound(group)))
    )
  }

  private def createView(group: Group.Slug, form: Form[Cfp.Data], event: Option[Event.Slug])(implicit req: OrgaReq[AnyContent]): IO[Result] = {
    val b = listBreadcrumb.add("New" -> routes.CfpCtrl.create(group))
    IO.pure(Ok(html.create(form, event)(b)))
  }

  def detail(group: Group.Slug, cfp: Cfp.Slug, params: Page.Params): Action[AnyContent] = OrgaAction(group) { implicit req =>
    (for {
      cfpElt <- OptionT(cfpRepo.find(cfp))
      proposals <- OptionT.liftF(proposalRepo.listFull(cfp, params))
      speakers <- OptionT.liftF(userRepo.list(proposals.items.flatMap(_.users).distinct))
      userRatings <- OptionT.liftF(proposalRepo.listRatings(cfp))
      b = breadcrumb(cfpElt)
    } yield Ok(html.detail(cfpElt, proposals, speakers, userRatings)(b))).value.map(_.getOrElse(cfpNotFound(group, cfp)))
  }

  def edit(group: Group.Slug, cfp: Cfp.Slug, redirect: Option[String]): Action[AnyContent] = OrgaAction(group) { implicit req =>
    editView(group, cfp, GsForms.cfp, redirect)
  }

  def doEdit(group: Group.Slug, cfp: Cfp.Slug, redirect: Option[String]): Action[AnyContent] = OrgaAction(group) { implicit req =>
    GsForms.cfp.bindFromRequest.fold(
      formWithErrors => editView(group, cfp, formWithErrors, redirect),
      data => (for {
        cfpOpt <- OptionT.liftF(cfpRepo.find(data.slug))
        res <- OptionT.liftF(cfpOpt match {
          case Some(duplicate) if data.slug != cfp => editView(group, cfp, GsForms.cfp.fillAndValidate(data).withError("slug", s"Slug already taken by cfp: ${duplicate.name.value}"), redirect)
          case _ => cfpRepo.edit(cfp, data).map { _ => redirectOr(redirect, routes.CfpCtrl.detail(group, data.slug)) }
        })
      } yield res).value.map(_.getOrElse(groupNotFound(group)))
    )
  }

  private def editView(group: Group.Slug, cfp: Cfp.Slug, form: Form[Cfp.Data], redirect: Option[String])(implicit req: OrgaReq[AnyContent], ctx: OrgaCtx): IO[Result] = {
    (for {
      cfpElt <- OptionT(cfpRepo.find(cfp))
      filledForm = if (form.hasErrors) form else form.fill(cfpElt.data)
      b = breadcrumb(cfpElt).add("Edit" -> routes.CfpCtrl.edit(group, cfp))
    } yield Ok(html.edit(cfpElt, filledForm, redirect)(b))).value.map(_.getOrElse(cfpNotFound(group, cfp)))
  }
}

object CfpCtrl {
  def listBreadcrumb(implicit req: OrgaReq[AnyContent]): Breadcrumb =
    GroupCtrl.breadcrumb.add("CFPs" -> routes.CfpCtrl.list(req.group.slug))

  def breadcrumb(cfp: Cfp)(implicit req: OrgaReq[AnyContent]): Breadcrumb =
    listBreadcrumb.add(cfp.name.value -> routes.CfpCtrl.detail(req.group.slug, cfp.slug))
} 
Example 57
Source File: SpeakerCtrl.scala    From gospeak   with Apache License 2.0 5 votes vote down vote up
package gospeak.web.pages.orga.speakers

import cats.data.OptionT
import com.mohiva.play.silhouette.api.Silhouette
import gospeak.core.domain.{Group, User}
import gospeak.core.services.storage.{OrgaEventRepo, OrgaGroupRepo, OrgaProposalRepo, OrgaUserRepo}
import gospeak.web.AppConf
import gospeak.web.auth.domain.CookieEnv
import gospeak.web.domain.Breadcrumb
import gospeak.web.pages.orga.GroupCtrl
import gospeak.web.pages.orga.speakers.SpeakerCtrl._
import gospeak.web.utils.{OrgaReq, UICtrl}
import gospeak.libs.scala.domain.Page
import play.api.mvc.{Action, AnyContent, ControllerComponents}

class SpeakerCtrl(cc: ControllerComponents,
                  silhouette: Silhouette[CookieEnv],
                  conf: AppConf,
                  userRepo: OrgaUserRepo,
                  val groupRepo: OrgaGroupRepo,
                  eventRepo: OrgaEventRepo,
                  proposalRepo: OrgaProposalRepo) extends UICtrl(cc, silhouette, conf) with UICtrl.OrgaAction {
  def list(group: Group.Slug, params: Page.Params): Action[AnyContent] = OrgaAction(group) { implicit req =>
    userRepo.speakers(params).map(speakers => Ok(html.list(speakers)(listBreadcrumb)))
  }

  def detail(group: Group.Slug, speaker: User.Slug, params: Page.Params): Action[AnyContent] = OrgaAction(group) { implicit req =>
    (for {
      speakerElt <- OptionT(userRepo.find(speaker))
      proposals <- OptionT.liftF(proposalRepo.listFull(speakerElt.id, params))
      speakers <- OptionT.liftF(userRepo.list(proposals.items.flatMap(_.users)))
      userRatings <- OptionT.liftF(proposalRepo.listRatings(proposals.items.map(_.id)))
      res = Ok(html.detail(speakerElt, proposals, speakers, userRatings)(breadcrumb(speakerElt)))
    } yield res).value.map(_.getOrElse(speakerNotFound(group, speaker)))
  }
}

object SpeakerCtrl {
  def listBreadcrumb(implicit req: OrgaReq[AnyContent]): Breadcrumb =
    GroupCtrl.breadcrumb.add("Speakers" -> routes.SpeakerCtrl.list(req.group.slug))

  def breadcrumb(speaker: User)(implicit req: OrgaReq[AnyContent]): Breadcrumb =
    listBreadcrumb.add(speaker.name.value -> routes.SpeakerCtrl.detail(req.group.slug, speaker.slug))
} 
Example 58
Source File: SwaggerCtrl.scala    From gospeak   with Apache License 2.0 5 votes vote down vote up
package gospeak.web.api.swagger

import cats.effect.IO
import com.mohiva.play.silhouette.api.Silhouette
import gospeak.web.AppConf
import gospeak.web.auth.domain.CookieEnv
import gospeak.web.utils.{OpenApiUtils, UICtrl}
import play.api.mvc.{Action, AnyContent, ControllerComponents}

class SwaggerCtrl(cc: ControllerComponents,
                  silhouette: Silhouette[CookieEnv],
                  conf: AppConf) extends UICtrl(cc, silhouette, conf) {
  private val spec = OpenApiUtils.loadSpec().get // to fail app on start

  def getSpec: Action[AnyContent] = UserAwareAction { implicit req =>
    IO.pure(Ok(spec))
  }

  def getUi: Action[AnyContent] = UserAwareAction { implicit req =>
    IO.pure(Ok(html.swaggerUi()))
  }
} 
Example 59
Source File: SpeakerCtrl.scala    From gospeak   with Apache License 2.0 5 votes vote down vote up
package gospeak.web.api.published

import com.mohiva.play.silhouette.api.Silhouette
import gospeak.core.domain.User
import gospeak.core.services.storage.PublicUserRepo
import gospeak.web.AppConf
import gospeak.web.api.domain.ApiUser
import gospeak.web.api.domain.utils.ApiResult
import gospeak.web.auth.domain.CookieEnv
import gospeak.web.utils.ApiCtrl
import gospeak.libs.scala.domain.Page
import play.api.mvc.{Action, AnyContent, ControllerComponents}

class SpeakerCtrl(cc: ControllerComponents,
                  silhouette: Silhouette[CookieEnv],
                  conf: AppConf,
                  userRepo: PublicUserRepo) extends ApiCtrl(cc, silhouette, conf) {
  def list(params: Page.Params): Action[AnyContent] = UserAwareAction[Seq[ApiUser.Published]] { implicit req =>
    // TODO add proposals, talks, groups member and owners
    userRepo.listPublic(params).map(ApiResult.of(_, ApiUser.published))
  }

  def detail(speaker: User.Slug): Action[AnyContent] = UserAwareAction[ApiUser.Published] { implicit req =>
    // TODO add proposals, talks, groups member and owners
    userRepo.findPublic(speaker).map(_.map(g => ApiResult.of(ApiUser.published(g))).getOrElse(userNotFound(speaker)))
  }
} 
Example 60
Source File: CfpCtrl.scala    From gospeak   with Apache License 2.0 5 votes vote down vote up
package gospeak.web.api.published

import cats.data.OptionT
import com.mohiva.play.silhouette.api.Silhouette
import gospeak.core.domain.{Cfp, CommonCfp, ExternalCfp}
import gospeak.core.services.storage.{PublicExternalCfpRepo, PublicGroupRepo}
import gospeak.web.AppConf
import gospeak.web.api.domain.ApiCfp
import gospeak.web.api.domain.utils.ApiResult
import gospeak.web.auth.domain.CookieEnv
import gospeak.web.utils.ApiCtrl
import gospeak.libs.scala.domain.Page
import play.api.mvc.{Action, AnyContent, ControllerComponents}

class CfpCtrl(cc: ControllerComponents,
              silhouette: Silhouette[CookieEnv],
              conf: AppConf,
              groupRepo: PublicGroupRepo,
              externalCfpRepo: PublicExternalCfpRepo) extends ApiCtrl(cc, silhouette, conf) {
  def list(params: Page.Params): Action[AnyContent] = UserAwareAction[Seq[ApiCfp.Published]] { implicit req =>
    for {
      cfps <- externalCfpRepo.listIncoming(params)
      groups <- groupRepo.list(cfps.items.flatMap(_.internal.map(_.group.id)))
    } yield ApiResult.of(cfps, (cfp: CommonCfp) => ApiCfp.published(cfp, groups))
  }

  def detail(cfp: Cfp.Slug): Action[AnyContent] = UserAwareAction[ApiCfp.Published] { implicit req =>
    (for {
      cfpElt <- OptionT(externalCfpRepo.findCommon(cfp))
      groups <- OptionT.liftF(groupRepo.list(cfpElt.internal.map(_.group.id).toList))
      res = ApiResult.of(ApiCfp.published(cfpElt, groups))
    } yield res).value.map(_.getOrElse(cfpNotFound(cfp)))
  }

  def detailExt(cfp: ExternalCfp.Id): Action[AnyContent] = UserAwareAction[ApiCfp.Published] { implicit req =>
    (for {
      cfpElt <- OptionT(externalCfpRepo.findCommon(cfp))
      groups <- OptionT.liftF(groupRepo.list(cfpElt.internal.map(_.group.id).toList))
      res = ApiResult.of(ApiCfp.published(cfpElt, groups))
    } yield res).value.map(_.getOrElse(cfpNotFound(cfp)))
  }
} 
Example 61
Source File: GroupCtrl.scala    From gospeak   with Apache License 2.0 5 votes vote down vote up
package gospeak.web.api.published

import cats.data.OptionT
import com.mohiva.play.silhouette.api.Silhouette
import gospeak.core.domain.{Event, Group, Proposal}
import gospeak.core.services.meetup.MeetupSrv
import gospeak.core.services.storage._
import gospeak.web.AppConf
import gospeak.web.api.domain._
import gospeak.web.api.domain.utils.ApiResult
import gospeak.web.auth.domain.CookieEnv
import gospeak.web.utils.ApiCtrl
import gospeak.libs.scala.Extensions._
import gospeak.libs.scala.domain.Page
import play.api.mvc.{Action, AnyContent, ControllerComponents}

class GroupCtrl(cc: ControllerComponents,
                silhouette: Silhouette[CookieEnv],
                conf: AppConf,
                groupRepo: PublicGroupRepo,
                eventRepo: PublicEventRepo,
                proposalRepo: PublicProposalRepo,
                venueRepo: PublicVenueRepo,
                userRepo: PublicUserRepo,
                groupSettingsRepo: PublicGroupSettingsRepo,
                meetupSrv: MeetupSrv) extends ApiCtrl(cc, silhouette, conf) {
  def list(params: Page.Params): Action[AnyContent] = UserAwareAction[Seq[ApiGroup.Published]] { implicit req =>
    groupRepo.listFull(params).map(ApiResult.of(_, ApiGroup.published))
  }

  def detail(group: Group.Slug): Action[AnyContent] = UserAwareAction[ApiGroup.Published] { implicit req =>
    groupRepo.findFull(group).map(_.map(g => ApiResult.of(ApiGroup.published(g))).getOrElse(groupNotFound(group)))
  }

  def events(group: Group.Slug, params: Page.Params): Action[AnyContent] = UserAwareAction[Seq[ApiEvent.Published]] { implicit req =>
    (for {
      groupElt <- OptionT(groupRepo.find(group))
      events <- OptionT.liftF(eventRepo.listPublished(groupElt.id, params))
      talks <- OptionT.liftF(proposalRepo.listPublic(events.items.flatMap(_.talks).distinct))
      speakers <- OptionT.liftF(userRepo.list(talks.flatMap(_.speakers.toList).distinct))
      res = ApiResult.of(events, ApiEvent.published(_, talks, speakers))
    } yield res).value.map(_.getOrElse(groupNotFound(group)))
  }

  def event(group: Group.Slug, event: Event.Slug): Action[AnyContent] = UserAwareAction[ApiEvent.Published] { implicit req =>
    (for {
      groupElt <- OptionT(groupRepo.find(group))
      eventElt <- OptionT(eventRepo.findPublished(groupElt.id, event))
      talks <- OptionT.liftF(proposalRepo.listPublic(eventElt.talks.distinct))
      speakers <- OptionT.liftF(userRepo.list(talks.flatMap(_.speakers.toList).distinct))
      res = ApiResult.of(ApiEvent.published(eventElt, talks, speakers))
    } yield res).value.map(_.getOrElse(eventNotFound(group, event)))
  }

  def eventDrawMeetupAttendee(group: Group.Slug, event: Event.Slug): Action[AnyContent] = UserAwareAction[Seq[ApiAttendee.Published]] { implicit req =>
    (for {
      groupElt <- OptionT(groupRepo.find(group))
      eventElt <- OptionT(eventRepo.findPublished(groupElt.id, event))
      creds <- OptionT(groupSettingsRepo.findMeetup(groupElt.id))
      attendees <- OptionT(eventElt.event.refs.meetup.map(r => meetupSrv.getAttendees(r.group, r.event, conf.app.aesKey, creds)).sequence)
      host = req.getQueryString("host")
      response = req.getQueryString("response")
      cleanAttendees = attendees.filter(a => a.id.value != 0L && response.forall(_ == a.response) && host.forall(_ == a.host.toString))
      res = ApiResult.of(cleanAttendees.map(ApiAttendee.published(_, creds.group)))
    } yield res).value.map(_.getOrElse(eventNotFound(group, event)))
  }

  def talks(group: Group.Slug, params: Page.Params): Action[AnyContent] = UserAwareAction[Seq[ApiProposal.Published]] { implicit req =>
    (for {
      groupElt <- OptionT(groupRepo.find(group))
      talks <- OptionT.liftF(proposalRepo.listPublicFull(groupElt.id, params))
      speakers <- OptionT.liftF(userRepo.list(talks.items.flatMap(_.speakers.toList).distinct))
      res = ApiResult.of(talks, ApiProposal.published(_, speakers))
    } yield res).value.map(_.getOrElse(groupNotFound(group)))
  }

  def talk(group: Group.Slug, talk: Proposal.Id): Action[AnyContent] = UserAwareAction[ApiProposal.Published] { implicit req =>
    (for {
      groupElt <- OptionT(groupRepo.find(group))
      talkElt <- OptionT(proposalRepo.findPublicFull(groupElt.id, talk))
      speakers <- OptionT.liftF(userRepo.list(talkElt.speakers.toList.distinct))
      res = ApiResult.of(ApiProposal.published(talkElt, speakers))
    } yield res).value.map(_.getOrElse(talkNotFound(group, talk)))
  }

  def speakers(group: Group.Slug, params: Page.Params): Action[AnyContent] = UserAwareAction[Seq[ApiUser.Published]] { implicit req =>
    (for {
      groupElt <- OptionT(groupRepo.find(group))
      speakers <- OptionT.liftF(userRepo.speakersPublic(groupElt.id, params))
      // TODO add proposals, talks, groups member and owners for each speaker
      res = ApiResult.of(speakers, ApiUser.published)
    } yield res).value.map(_.getOrElse(groupNotFound(group)))
  }
} 
Example 62
Source File: ApiProposalCtrl.scala    From gospeak   with Apache License 2.0 5 votes vote down vote up
package gospeak.web.api.orga

import cats.data.OptionT
import com.mohiva.play.silhouette.api.Silhouette
import gospeak.core.domain.{Cfp, Group, Proposal}
import gospeak.core.services.storage._
import gospeak.web.AppConf
import gospeak.web.api.domain.utils.ApiResult
import gospeak.web.api.domain.{ApiComment, ApiProposal}
import gospeak.web.auth.domain.CookieEnv
import gospeak.web.utils.ApiCtrl
import gospeak.libs.scala.domain.Page
import play.api.mvc.{Action, AnyContent, ControllerComponents}

class ApiProposalCtrl(cc: ControllerComponents,
                      silhouette: Silhouette[CookieEnv],
                      conf: AppConf,
                      userRepo: OrgaUserRepo,
                      val groupRepo: OrgaGroupRepo,
                      cfpRepo: OrgaCfpRepo,
                      proposalRepo: OrgaProposalRepo,
                      commentRepo: OrgaCommentRepo,
                      userRequestRepo: OrgaUserRequestRepo) extends ApiCtrl(cc, silhouette, conf) with ApiCtrl.OrgaAction {
  def list(group: Group.Slug, cfp: Cfp.Slug, params: Page.Params): Action[AnyContent] = OrgaAction[Seq[ApiProposal.Orga]](group) { implicit req =>
    for {
      proposals <- proposalRepo.listFull(cfp, params)
      users <- userRepo.list(proposals.items.flatMap(_.users))
    } yield ApiResult.of(proposals, (p: Proposal.Full) => ApiProposal.orga(p, users))
  }

  def listAll(group: Group.Slug, params: Page.Params): Action[AnyContent] = OrgaAction[Seq[ApiProposal.Orga]](group) { implicit req =>
    for {
      proposals <- proposalRepo.listFull(params)
      users <- userRepo.list(proposals.items.flatMap(_.users))
    } yield ApiResult.of(proposals, (p: Proposal.Full) => ApiProposal.orga(p, users))
  }

  def detail(group: Group.Slug, cfp: Cfp.Slug, proposal: Proposal.Id): Action[AnyContent] = OrgaAction[ApiProposal.Orga](group) { implicit req =>
    (for {
      proposalElt <- OptionT(proposalRepo.findFull(cfp, proposal))
      users <- OptionT.liftF(userRepo.list(proposalElt.users))
      res = ApiResult.of(ApiProposal.orga(proposalElt, users))
    } yield res).value.map(_.getOrElse(proposalNotFound(cfp, proposal)))
  }

  def ratings(group: Group.Slug, cfp: Cfp.Slug, proposal: Proposal.Id): Action[AnyContent] = OrgaAction[Seq[ApiProposal.Orga.Rating]](group) { implicit req =>
    for {
      ratings <- proposalRepo.listRatings(proposal)
      users <- userRepo.list(ratings.flatMap(_.users))
    } yield ApiResult.of(ratings.map(ApiProposal.Orga.Rating.from(_, users)))
  }

  def speakerComments(group: Group.Slug, cfp: Cfp.Slug, proposal: Proposal.Id): Action[AnyContent] = OrgaAction[Seq[ApiComment]](group) { implicit req =>
    commentRepo.getComments(proposal).map(comments => ApiResult.of(comments.map(ApiComment.from)))
  }

  def orgaComments(group: Group.Slug, cfp: Cfp.Slug, proposal: Proposal.Id): Action[AnyContent] = OrgaAction[Seq[ApiComment]](group) { implicit req =>
    commentRepo.getOrgaComments(proposal).map(comments => ApiResult.of(comments.map(ApiComment.from)))
  }

  def invites(group: Group.Slug, cfp: Cfp.Slug, proposal: Proposal.Id): Action[AnyContent] = OrgaAction[Int](group) { implicit req =>
    userRequestRepo.listPendingInvites(proposal)
    ??? // TODO
  }
} 
Example 63
Source File: ApiEventCtrl.scala    From gospeak   with Apache License 2.0 5 votes vote down vote up
package gospeak.web.api.orga

import cats.data.OptionT
import com.mohiva.play.silhouette.api.Silhouette
import gospeak.core.domain.{Event, Group}
import gospeak.core.services.storage.{OrgaEventRepo, OrgaGroupRepo, OrgaProposalRepo, OrgaUserRepo}
import gospeak.web.AppConf
import gospeak.web.api.domain.ApiEvent
import gospeak.web.api.domain.utils.ApiResult
import gospeak.web.auth.domain.CookieEnv
import gospeak.web.utils.ApiCtrl
import gospeak.libs.scala.domain.Page
import play.api.mvc.{Action, AnyContent, ControllerComponents}

class ApiEventCtrl(cc: ControllerComponents,
                   silhouette: Silhouette[CookieEnv],
                   conf: AppConf,
                   userRepo: OrgaUserRepo,
                   val groupRepo: OrgaGroupRepo,
                   eventRepo: OrgaEventRepo,
                   proposalRepo: OrgaProposalRepo) extends ApiCtrl(cc, silhouette, conf) with ApiCtrl.OrgaAction {
  def list(group: Group.Slug, params: Page.Params): Action[AnyContent] = OrgaAction[Seq[ApiEvent.Orga]](group) { implicit req =>
    for {
      events <- eventRepo.listFull(params)
      proposals <- proposalRepo.list(events.items.flatMap(_.talks))
      users <- userRepo.list(events.items.flatMap(_.users) ++ proposals.flatMap(_.users))
    } yield ApiResult.of(events, (e: Event.Full) => ApiEvent.orga(e, proposals, users))
  }

  def detail(group: Group.Slug, event: Event.Slug): Action[AnyContent] = OrgaAction[ApiEvent.Orga](group) { implicit req =>
    (for {
      eventElt <- OptionT(eventRepo.findFull(event))
      proposals <- OptionT.liftF(proposalRepo.list(eventElt.talks))
      users <- OptionT.liftF(userRepo.list(eventElt.users ++ proposals.flatMap(_.users)))
      res = ApiResult.of(ApiEvent.orga(eventElt, proposals, users))
    } yield res).value.map(_.getOrElse(eventNotFound(group, event)))
  }
} 
Example 64
Source File: ApiCfpCtrl.scala    From gospeak   with Apache License 2.0 5 votes vote down vote up
package gospeak.web.api.orga

import cats.data.OptionT
import com.mohiva.play.silhouette.api.Silhouette
import gospeak.core.domain.{Cfp, Group}
import gospeak.core.services.storage.{OrgaCfpRepo, OrgaGroupRepo, OrgaUserRepo}
import gospeak.web.AppConf
import gospeak.web.api.domain.ApiCfp
import gospeak.web.api.domain.utils.ApiResult
import gospeak.web.auth.domain.CookieEnv
import gospeak.web.utils.ApiCtrl
import gospeak.libs.scala.domain.Page
import play.api.mvc.{Action, AnyContent, ControllerComponents}

class ApiCfpCtrl(cc: ControllerComponents,
                 silhouette: Silhouette[CookieEnv],
                 conf: AppConf,
                 userRepo: OrgaUserRepo,
                 val groupRepo: OrgaGroupRepo,
                 cfpRepo: OrgaCfpRepo) extends ApiCtrl(cc, silhouette, conf) with ApiCtrl.OrgaAction {
  def list(group: Group.Slug, params: Page.Params): Action[AnyContent] = OrgaAction[Seq[ApiCfp.Orga]](group) { implicit req =>
    for {
      cfps <- cfpRepo.list(params)
      users <- userRepo.list(cfps.items.flatMap(_.users))
    } yield ApiResult.of(cfps, (c: Cfp) => ApiCfp.orga(c, users))
  }

  def detail(group: Group.Slug, cfp: Cfp.Slug): Action[AnyContent] = OrgaAction[ApiCfp.Orga](group) { implicit req =>
    (for {
      cfpElt <- OptionT(cfpRepo.find(cfp))
      users <- OptionT.liftF(userRepo.list(cfpElt.users))
      res = ApiResult.of(ApiCfp.orga(cfpElt, users))
    } yield res).value.map(_.getOrElse(cfpNotFound(cfp)))
  }

  // TODO def userRatings(group: Group.Slug, cfp: Cfp.Slug)
} 
Example 65
Source File: JobRunController.scala    From metronome   with Apache License 2.0 5 votes vote down vote up
package dcos.metronome
package api.v1.controllers

import dcos.metronome.api.v1.models._
import dcos.metronome.api.{ApiConfig, Authorization, UnknownJob, UnknownJobRun}
import dcos.metronome.jobrun.{JobRunService, StartedJobRun}
import dcos.metronome.jobspec.JobSpecService
import dcos.metronome.model.{JobId, JobRunId}
import mesosphere.marathon.metrics.Metrics
import mesosphere.marathon.plugin.auth.{Authenticator, Authorizer, UpdateRunSpec, ViewRunSpec}
import play.api.mvc.ControllerComponents

import scala.async.Async.{async, await}
import scala.concurrent.ExecutionContext

class JobRunController(
    cc: ControllerComponents,
    jobSpecService: JobSpecService,
    jobRunService: JobRunService,
    metrics: Metrics,
    authenticator: Authenticator,
    authorizer: Authorizer,
    config: ApiConfig
)(implicit ec: ExecutionContext)
    extends Authorization(cc, metrics, authenticator, authorizer, config) {

  def getAllJobRuns =
    measured {
      AuthorizedAction.async { implicit request =>
        jobRunService.listRuns(request.isAllowed).map(Ok(_))
      }
    }

  def getJobRuns(id: JobId) =
    measured {
      AuthorizedAction.async { implicit request =>
        async {
          await(jobSpecService.getJobSpec(id)) match {
            case Some(spec) =>
              if (request.isAllowed(spec)) {
                await {
                  jobRunService.activeRuns(id).map(Ok(_))
                }
              } else {
                Ok(Array.empty[StartedJobRun])
              }
            case None => NotFound(UnknownJob(id))
          }
        }
      }
    }

  def getJobRun(id: JobId, runId: String) =
    measured {
      AuthorizedAction.async { implicit request =>
        async {
          await(jobRunService.getJobRun(JobRunId(id, runId))) match {
            case Some(run) => request.authorized(ViewRunSpec, run.jobRun.jobSpec, Ok(run))
            case None => NotFound(UnknownJobRun(id, runId))
          }
        }
      }
    }

  def killJobRun(id: JobId, runId: String) =
    measured {
      AuthorizedAction.async { implicit request =>
        async {
          await(jobSpecService.getJobSpec(id)) match {
            case Some(spec) =>
              await {
                request.authorizedAsync(UpdateRunSpec, spec) { _ =>
                  jobRunService.killJobRun(JobRunId(id, runId)).map(Ok(_)).recover {
                    case JobRunDoesNotExist(_) => NotFound(UnknownJobRun(id, runId))
                  }
                }
              }
            case None => NotFound(UnknownJob(id))
          }
        }
      }
    }

  def triggerJob(id: JobId) =
    measured {
      AuthorizedAction.async { implicit request =>
        async {
          await(jobSpecService.getJobSpec(id)) match {
            case Some(spec) =>
              await {
                request.authorizedAsync(UpdateRunSpec, spec) { _ =>
                  jobRunService.startJobRun(spec).map(Created(_))
                }
              }
            case None =>
              NotFound(UnknownJob(id))
          }
        }
      }
    }
} 
Example 66
Source File: ApplicationController.scala    From metronome   with Apache License 2.0 5 votes vote down vote up
package dcos.metronome
package api.v1.controllers

import dcos.metronome.api.{ErrorDetail, RestController}
import dcos.metronome.api.v1.models.{errorFormat, LeaderInfoWrites, MetronomeInfoWrites}
import mesosphere.marathon.MetricsModule
import mesosphere.marathon.core.election.ElectionService
import mesosphere.marathon.raml.MetricsConversion._
import mesosphere.marathon.raml.Raml
import play.api.http.ContentTypes
import play.api.libs.json.Json
import play.api.mvc.ControllerComponents

class ApplicationController(cc: ControllerComponents, metricsModule: MetricsModule, electionService: ElectionService)
    extends RestController(cc) {

  def ping = Action { Ok("pong") }

  def info =
    Action {
      Ok(MetronomeInfoWrites.writes(MetronomeInfoBuilder.metronomeInfo))
    }

  def leader =
    Action {
      electionService.leaderHostPort match {
        case None => NotFound(errorFormat.writes(ErrorDetail("There is no leader")))
        case Some(leader) => Ok(LeaderInfoWrites.writes(LeaderInfo(leader)))
      }
    }

  def showMetrics =
    Action {
      val metricsJsonString = metricsModule.snapshot() match {
        case Left(_) =>
          // Kamon snapshot
          throw new IllegalArgumentException(
            "Only Dropwizard format is supported, cannot render metrics from Kamon snapshot. Make sure your metrics are configured correctly."
          )
        case Right(dropwizardRegistry) => Json.stringify(Json.toJson(Raml.toRaml(dropwizardRegistry)))
      }
      Ok(metricsJsonString).as(ContentTypes.JSON)
    }
} 
Example 67
Source File: LaunchQueueController.scala    From metronome   with Apache License 2.0 5 votes vote down vote up
package dcos.metronome
package api.v1.controllers

import dcos.metronome.api.v1.models.QueuedJobRunMapWrites
import dcos.metronome.api.{ApiConfig, Authorization}
import dcos.metronome.queue.LaunchQueueService
import mesosphere.marathon.metrics.Metrics
import mesosphere.marathon.plugin.auth.{Authenticator, Authorizer}
import play.api.mvc.ControllerComponents

import scala.concurrent.ExecutionContext

class LaunchQueueController(
    cc: ControllerComponents,
    queueService: LaunchQueueService,
    metrics: Metrics,
    authenticator: Authenticator,
    authorizer: Authorizer,
    config: ApiConfig
)(implicit ec: ExecutionContext)
    extends Authorization(cc, metrics, authenticator, authorizer, config) {

  def queue() =
    measured {
      AuthorizedAction.apply { implicit request =>
        Ok(QueuedJobRunMapWrites.writes(queueService.list().filter(request.isAllowed).groupBy(_.jobId)))
      }
    }
} 
Example 68
Source File: ApiModule.scala    From metronome   with Apache License 2.0 5 votes vote down vote up
package dcos.metronome
package api

import com.softwaremill.macwire._
import controllers.Assets
import dcos.metronome.api.v0.controllers.ScheduledJobSpecController
import dcos.metronome.api.v1.controllers._
import dcos.metronome.jobinfo.JobInfoService
import dcos.metronome.jobrun.JobRunService
import dcos.metronome.jobspec.JobSpecService
import dcos.metronome.queue.LaunchQueueService
import mesosphere.marathon.MetricsModule
import mesosphere.marathon.core.auth.AuthModule
import mesosphere.marathon.core.base.ActorsModule
import mesosphere.marathon.core.election.ElectionService
import mesosphere.marathon.core.plugin.PluginManager
import mesosphere.marathon.metrics.Metrics
import mesosphere.marathon.plugin.auth.{Authenticator, Authorizer}
import play.api.http.HttpErrorHandler
import play.api.mvc.ControllerComponents
import play.api.routing.Router
import router.Routes

import scala.concurrent.ExecutionContext

class ApiModule(
    controllerComponents: ControllerComponents,
    assets: Assets,
    httpErrorHandler: HttpErrorHandler,
    config: ApiConfig,
    jobSpecService: JobSpecService,
    jobRunService: JobRunService,
    jobInfoService: JobInfoService,
    pluginManager: PluginManager,
    launchQueueService: LaunchQueueService,
    actorsModule: ActorsModule,
    metricsModule: MetricsModule,
    electionService: ElectionService
)(implicit ec: ExecutionContext) {

  lazy val authModule: AuthModule = new AuthModule(pluginManager)

  lazy val authorizer: Authorizer = authModule.authorizer
  lazy val authenticator: Authenticator = authModule.authenticator
  lazy val metrics: Metrics = metricsModule.metrics

  lazy val applicationController: ApplicationController = wire[ApplicationController]
  lazy val jobsSpecController: JobSpecController = wire[JobSpecController]
  lazy val jobRunsController: JobRunController = wire[JobRunController]
  lazy val jobSchedulerController: JobScheduleController = wire[JobScheduleController]
  lazy val scheduledJobSchedulerController: ScheduledJobSpecController = wire[ScheduledJobSpecController]
  lazy val launchQueueController: LaunchQueueController = wire[LaunchQueueController]

  lazy val router: Router = {
    // add the prefix string in local scope for the Routes constructor
    val prefix: String = "/" // scalafix:ok
    wire[Routes]
  }
} 
Example 69
Source File: ScheduledJobSpecController.scala    From metronome   with Apache License 2.0 5 votes vote down vote up
package dcos.metronome
package api.v0.controllers

import dcos.metronome.api._
import dcos.metronome.api.v1.models.{JobSpecFormat => _, _}
import dcos.metronome.jobspec.JobSpecService
import dcos.metronome.model.{JobId, JobRunSpec, JobSpec, ScheduleSpec}
import mesosphere.marathon.api.v2.json.Formats.FormatWithDefault
import mesosphere.marathon.metrics.Metrics
import mesosphere.marathon.plugin.auth.{Authenticator, Authorizer, CreateRunSpec, UpdateRunSpec}
import play.api.libs.functional.syntax._
import play.api.libs.json._
import play.api.mvc.ControllerComponents

import scala.concurrent.ExecutionContext

class ScheduledJobSpecController(
    cc: ControllerComponents,
    jobSpecService: JobSpecService,
    metrics: Metrics,
    authenticator: Authenticator,
    authorizer: Authorizer,
    config: ApiConfig
)(implicit ec: ExecutionContext)
    extends Authorization(cc, metrics, authenticator, authorizer, config) {

  import ScheduledJobSpecController._

  def createJob =
    AuthorizedAction.async(validate.json[JobSpec]) { implicit request =>
      request.authorizedAsync(CreateRunSpec) { jobSpec =>
        jobSpecService
          .createJobSpec(jobSpec)
          .map(Created(_))
          .recover {
            case JobSpecAlreadyExists(_) => Conflict(ErrorDetail("Job with this id already exists"))
          }
      }
    }

  def updateJob(id: JobId) =
    AuthorizedAction.async(validate.jsonWith[JobSpec](_.copy(id = id))) { implicit request =>
      request.authorizedAsync(UpdateRunSpec) { jobSpec =>
        jobSpecService.updateJobSpec(id, _ => jobSpec).map(Ok(_)).recover {
          case JobSpecDoesNotExist(_) => NotFound(UnknownJob(id))
        }
      }
    }
}

object ScheduledJobSpecController {
  implicit lazy val JobSpecWithScheduleFormat: Format[JobSpec] = ((__ \ "id").format[JobId] ~
    (__ \ "description").formatNullable[String] ~
    (__ \ "labels").formatNullable[Map[String, String]].withDefault(Map.empty) ~
    (__ \ "schedules").formatNullable[Seq[ScheduleSpec]].withDefault(Seq.empty) ~
    (__ \ "run").format[JobRunSpec])(JobSpec.apply, unlift(JobSpec.unapply))

  implicit lazy val JobSpecSchema: JsonSchema[JobSpec] =
    JsonSchema.fromResource("/public/api/v0/schema/jobspec_v0.schema.json")
} 
Example 70
Source File: HelpController.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package controllers.help

import controllers.HasVisitLogging
import javax.inject.{Inject, Singleton}
import services.visit.VisitService
import org.webjars.play.WebJarsUtil
import play.api.{Configuration, Environment}
import play.api.mvc.{Action, AbstractController, ControllerComponents, RequestHeader}
import play.twirl.api.HtmlFormat
import scala.concurrent.ExecutionContext
import scala.io.Source
import scala.util.Try
import services.entity.{AuthorityFileService, EntityType}

@Singleton
class HelpController @Inject() (
  val authorities: AuthorityFileService,
  val components: ControllerComponents,
  val config: Configuration,
  val env: Environment,
  implicit val ctx: ExecutionContext,
  implicit val visits: VisitService,
  implicit val webjars: WebJarsUtil
) extends AbstractController(components) with HasVisitLogging {

  private val adminEmail = config.get[String]("admin.email")
  private val imprint =
    Try(Source.fromFile(env.getFile("conf/imprint"))).toOption.map { _.getLines.mkString("\n") }

  private def result(template: HtmlFormat.Appendable)(implicit request: RequestHeader) = {
    logPageView()
    Ok(template)
  }

  def localizedTutorial(lang: String) = Action { implicit request =>
    lang.toUpperCase match {
      case "DE" => result(views.html.help.tutorial.tutorial_de())
      case "ES" => result(views.html.help.tutorial.tutorial_es())
      case "FA" => result(views.html.help.tutorial.tutorial_fa())
      case "FR" => result(views.html.help.tutorial.tutorial_fr())
      case "IT" => result(views.html.help.tutorial.tutorial_it())
      case "NL" => result(views.html.help.tutorial.tutorial_nl())
      case "TR" => result(views.html.help.tutorial.tutorial_tr())
      case _ => NotFound(views.html.error404())
    }
  }

  def faq = Action.async { implicit request => 
    authorities.listAll(Some(EntityType.PLACE)).map { gazetteers =>
      result(views.html.help.faq(gazetteers)) 
    }
  }

  def index = Action { implicit request => result(views.html.help.index()) }

  def about        = Action { implicit request => result(views.html.help.general.about(imprint, adminEmail)) }
  def privacy      = Action { implicit request => result(views.html.help.general.privacy(adminEmail)) }
  def relations    = Action { implicit request => result(views.html.help.relations()) }
  def cloning      = Action { implicit request => result(views.html.help.cloning()) }
  def sharingLinks = Action { implicit request => result(views.html.help.sharing_links()) }
  def terms        = Action { implicit request => result(views.html.help.general.terms()) }
  def tutorial     = Action { implicit request => result(views.html.help.tutorial.tutorial()) }
  def workspace    = Action { implicit request => result(views.html.help.workspace()) }

  def swaggerUi = Action {
    Redirect(url = "/webjars/swagger-ui/2.2.0/index.html", queryString = Map("url" -> Seq("/swagger.json")))
  }

} 
Example 71
Source File: BaseAuthController.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package controllers

import services.RuntimeAccessLevel
import services.document.{ExtendedDocumentMetadata, DocumentService}
import services.generated.tables.records.{DocumentFilepartRecord, DocumentRecord}
import services.user.{User, UserService}
import play.api.Configuration
import play.api.mvc.{ControllerComponents, Result}
import scala.concurrent.ExecutionContext

abstract class BaseAuthController(
    components: ControllerComponents,
    config: Configuration,
    documents: DocumentService,
    users: UserService
  ) extends BaseController(components, config, users) {
  
  
  protected def documentPartResponse(
    docId: String,
    partNo: Int,
    user: User,
    response: (ExtendedDocumentMetadata, DocumentFilepartRecord, RuntimeAccessLevel) => Result
  )(implicit ctx: ExecutionContext) = {
    documentResponse(docId, user, { case (doc, accesslevel) =>
      doc.fileparts.find(_.getSequenceNo == partNo) match {
        case None => NotFoundPage
        case Some(part) => response(doc, part, accesslevel)
      }
    })
  }
  
} 
Example 72
Source File: ResetPasswordController.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package controllers.landing

import javax.inject.{Inject, Singleton}
import services.user.UserService
import services.generated.tables.records.UserRecord
import play.api.data.Form
import play.api.data.Forms._
import play.api.i18n.I18nSupport
import play.api.libs.mailer._
import play.api.mvc.{Action, AbstractController, ControllerComponents}
import scala.concurrent.{ExecutionContext, Future}

case class ResetPasswordData(email: String)

@Singleton
class ResetPasswordController @Inject() (
    val components: ControllerComponents,
    val users: UserService,
    val mailerClient: MailerClient,
    implicit val ctx: ExecutionContext
  ) extends AbstractController(components) with I18nSupport {
  
  val resetPasswordForm = Form(
    mapping("email" -> email)(ResetPasswordData.apply)(ResetPasswordData.unapply)
  )

  
  private def sendMail(user: UserRecord, newPassword: String) = Future {
    val name = Option(user.getRealName).getOrElse(user.getUsername)
    
    val message =
      s"""Dear $name,
        |
        |Your Recogito password was reset to
        |
        |   $newPassword
        |
        |Please log in to Recogito with this password. You can change it
        |in your personal Account Settings.
        |
        |Cheers,
        |the Recogito Team""".stripMargin
    
    // TODO this now hard-wires "[email protected]" as reply address
    // TODO see if we can take this directly from the config file instead
    val email = Email(
      "Your Recogito password was reset",
      "Recogito Team <[email protected]>",
      Seq(users.decryptEmail(user.getEmail)),
      Some(message)
    )
    
    mailerClient.send(email)
  } recover { case t: Throwable =>
    t.printStackTrace
  }
  
  def showResetForm = Action { implicit request =>
    Ok(views.html.landing.resetPassword(resetPasswordForm))
  }
  
  def resetPassword = Action.async { implicit request =>
    resetPasswordForm.bindFromRequest.fold(
      formWithErrors =>
        Future.successful(BadRequest(views.html.landing.resetPassword(formWithErrors))),

      resetData => 
        users.findByEmail(resetData.email).flatMap {
          case Some(user) => 
            users.resetPassword(user.getUsername).map { password =>
              sendMail(user, password)
              Ok(views.html.landing.resetPasswordOk())
            }
                       
          case None =>
            Future.successful(Redirect(routes.ResetPasswordController.showResetForm()).flashing("error" -> "Can't find that e-mail, sorry."))
        }
    )
  }
  
} 
Example 73
Source File: LoginLogoutController.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package controllers.landing

import com.mohiva.play.silhouette.api.{LoginInfo, Silhouette}
import controllers.{HasConfig, HasUserService, Security}
import java.util.UUID
import javax.inject.{Inject, Singleton}
import services.announcement.AnnouncementService
import services.user.UserService
import play.api.Configuration
import play.api.data.Form
import play.api.data.Forms._
import play.api.i18n.I18nSupport
import play.api.mvc.{AbstractController, ControllerComponents}
import scala.concurrent.{ ExecutionContext, Future }

case class LoginData(usernameOrPassword: String, password: String)

@Singleton
class LoginLogoutController @Inject() (  
  val announcements: AnnouncementService,
  val components: ControllerComponents,
  val config: Configuration,
  val silhouette: Silhouette[Security.Env],
  val users: UserService,
  implicit val ctx: ExecutionContext
) extends AbstractController(components) with HasConfig with HasUserService with I18nSupport {

  private val MESSAGE = "message"

  private val INVALID_LOGIN = "Invalid Username or Password"
  
  private val auth = silhouette.env.authenticatorService

  val loginForm = Form(
    mapping(
      "username" -> nonEmptyText,
      "password" -> nonEmptyText
    )(LoginData.apply)(LoginData.unapply)
  )

  def showLoginForm(destination: Option[String]) = Action { implicit request =>
    destination match {
      case None => Ok(views.html.landing.login(loginForm))
      case Some(dest) => Ok(views.html.landing.login(loginForm)).withSession("access_uri" -> dest)
    }
  }

  def processLogin = silhouette.UserAwareAction.async { implicit request =>    
    loginForm.bindFromRequest.fold(
      formWithErrors =>
        Future(BadRequest(views.html.landing.login(formWithErrors))),

      loginData =>
        users.validateUser(loginData.usernameOrPassword, loginData.password).flatMap {
          case Some(validUser) =>
            
            val destination = request.session.get("access_uri").getOrElse(routes.LandingController.index.toString)
            users.updateLastLogin(validUser.getUsername)
            
            val fAuthentication = auth.create(LoginInfo(Security.PROVIDER_ID, validUser.getUsername))
              .flatMap(auth.init(_))
                          
            fAuthentication.flatMap { authentication =>               
                auth.embed(authentication,
                  Redirect(destination).withSession(request.session - "access_uri"))
            }
          
          case None => Future(Redirect(routes.LoginLogoutController.showLoginForm()).flashing(MESSAGE -> INVALID_LOGIN))
        }
    )
  }

  def confirmServiceAnnouncement(id: UUID, response: String, destination: Option[String]) = silhouette.SecuredAction.async { implicit request =>
    announcements.confirm(id, request.identity.username, response).map { success =>
      if (success) destination.map(Redirect(_)).getOrElse(Redirect(routes.LandingController.index))
      else InternalServerError
    }
  }

  def logout = silhouette.SecuredAction.async { implicit request =>
    auth.discard(request.authenticator, Redirect(routes.LandingController.index))
  }

} 
Example 74
Source File: LandingController.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package controllers.landing

import com.mohiva.play.silhouette.api.Silhouette
import controllers.{ HasConfig, HasUserService, HasVisitLogging, HasPrettyPrintJSON, Security }
import java.io.FileInputStream
import javax.inject.{ Inject, Singleton }
import java.net.URI
import org.webjars.play.WebJarsUtil
import play.api.Configuration
import play.api.i18n.I18nSupport
import play.api.libs.json.{Json, JsObject}
import play.api.mvc.{Action, AbstractController, ControllerComponents}
import scala.concurrent.ExecutionContext
import services.annotation.AnnotationService
import services.contribution.ContributionService
import services.document.DocumentService
import services.user.UserService
import services.visit.VisitService

@Singleton
class LandingController @Inject() (
    val components: ControllerComponents,
    val config: Configuration,
    val annotations: AnnotationService,
    val contributions: ContributionService,
    val documents: DocumentService,
    val users: UserService,
    val silhouette: Silhouette[Security.Env],
    implicit val ctx: ExecutionContext,
    implicit val visits: VisitService,
    implicit val webjars: WebJarsUtil
) extends AbstractController(components) with HasConfig with HasUserService with HasVisitLogging with HasPrettyPrintJSON with I18nSupport {

  def index = silhouette.UserAwareAction { implicit request =>
    // Temporary hack only
    request.queryString.get("lang").flatMap(_.headOption) match {
      case Some(lang) =>
        Redirect(routes.LandingController.index).withLang(play.api.i18n.Lang(lang))
      case None =>
        request.identity match {
          case Some(user) =>
            Redirect(controllers.my.routes.WorkspaceController.workspace(user.username))

          case None =>
            logPageView()
            Ok(views.html.landing.index())
        }
    }
  }

  def getStats() = silhouette.UnsecuredAction.async { implicit request =>
    val fAnnotations = annotations.countTotal()
    val fEdits = contributions.countLast24hrs()
    val fUsers = users.countUsers()

    val f = for {
      annotations <- fAnnotations
      edits <- fEdits
      users <- fUsers
    } yield (annotations, edits, users)

    f.map { case (annotations, edits, users) =>
      jsonOk(Json.obj(
        "annotations" -> annotations,
        "edits" -> edits,
        "users" -> users
      ))
    }
  }

  def sitemap() = Action.async { implicit request =>
    documents.listOwnersWithPublicDocuments().map { users =>
      val baseURL = routes.LandingController.index().absoluteURL()
      val sitemap = users.map(user => s"${baseURL}${user}").mkString("\n")
      Ok(sitemap).as("text/plain")
    }
  }

  def robots() = Action { implicit request =>
    val sitemapURL = routes.LandingController.sitemap().absoluteURL()
    Ok(s"SITEMAP: ${sitemapURL}").as("text/plain")
  }

  def swaggerConfig() = Action { implicit request => 
    val json = Json.parse(new FileInputStream("conf/swagger.json"))
    val baseURL = new URI(routes.LandingController.index.absoluteURL)
    val host = if (baseURL.getPort == -1) baseURL.getHost else s"${baseURL.getHost}:${baseURL.getPort}"
    jsonOk(json.as[JsObject] ++ Json.obj("host" -> host))
  }

} 
Example 75
Source File: StatusController.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package controllers.landing

import javax.inject.{Inject, Singleton}
import play.api.mvc.{AbstractController, Action, ControllerComponents}
import scala.concurrent.ExecutionContext
import services.user.UserService
import services.contribution.ContributionService

@Singleton
class StatusController @Inject()(
  val components: ControllerComponents,
  val users: UserService,
  val edits: ContributionService,
  implicit val ctx: ExecutionContext
) extends AbstractController(components) {
  
  def index = Action.async { request =>
    val fDBOnline = users.countUsers()
      .map { _ => true }
      .recover { case t: Throwable => false }
      
    val fIndexOnline = edits.countLast24hrs()
      .map { _ => true }
      .recover { case t: Throwable => false }
    
    val f = for {
      dbOnline <- fDBOnline
      idxOnline <- fIndexOnline
    } yield (dbOnline, idxOnline)
    
    f.map { case (dbOnline, idxOnline) =>
      Ok(views.html.landing.status(dbOnline, idxOnline))
    }    
  }
  
} 
Example 76
Source File: MaintenanceController.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package controllers.admin.maintenance

import com.mohiva.play.silhouette.api.Silhouette
import controllers.{BaseAuthController, Security, HasPrettyPrintJSON}
import java.io.File
import javax.inject.{Inject, Singleton}
import org.joda.time.DateTime
import org.webjars.play.WebJarsUtil
import play.api.{Configuration, Environment}
import play.api.mvc.ControllerComponents
import play.api.libs.json._
import play.api.libs.functional.syntax._
import scala.concurrent.ExecutionContext
import services.announcement.AnnouncementService
import services.document.DocumentService
import services.generated.tables.records.UploadRecord
import services.upload.UploadService
import services.user.UserService
import services.user.Roles._
import services.HasDate
import storage.es.ES
import storage.uploads.Uploads

@Singleton
class MaintenanceController @Inject()(
  val announcements: AnnouncementService,
  val components: ControllerComponents, 
  val config: Configuration,
  val documents: DocumentService,
  val env: Environment,
  val es: ES,
  val silhouette: Silhouette[Security.Env],
  val uploadService: UploadService,
  val uploadStorage: Uploads,
  val users: UserService,
  implicit val ctx: ExecutionContext,
  implicit val webJarsUtil: WebJarsUtil
) extends BaseAuthController(components, config, documents, users) with HasPrettyPrintJSON with HasDate {

  implicit val uploadRecordWrites: Writes[UploadRecord] = (
    (JsPath \ "owner").write[String] and
    (JsPath \ "title").write[String] and
    (JsPath \ "created_at").write[DateTime]
  )(upload => (
    upload.getOwner,
    upload.getTitle,
    new DateTime(upload.getCreatedAt)
  ))
  
  def index = silhouette.SecuredAction(Security.WithRole(Admin)).async { implicit request =>
    uploadService.listPendingUploads().map { uploads =>
      Ok(views.html.admin.maintenance())
    }
  }

  
  def insertBroadcast = silhouette.SecuredAction(Security.WithRole(Admin)).async { implicit request =>
    announcements.insertBroadcastAnnouncement(
    """# Like Recogito? Vote for us!

We are excited that Recogito has been nominated for the [Digital Humanities Awards](http://dhawards.org/dhawards2018/voting/) this year. 
If you like Recogito, do consider voting for us.

Many thanks & happy annotating!
    """).map(_ => Ok)
  }
  
  def deleteAllServiceAnnouncements = silhouette.SecuredAction(Security.WithRole(Admin)).async { implicit request =>
    announcements.clearAll().map { success =>
      if (success) Ok
      else InternalServerError
    }
  }
  
} 
Example 77
Source File: BackupAdminController.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package controllers.admin.backup

import akka.actor.ActorSystem
import akka.stream.scaladsl.FileIO
import com.mohiva.play.silhouette.api.Silhouette
import controllers.{BaseAuthController, Security}
import controllers.document.BackupReader
import javax.inject.{Inject, Singleton}
import services.ContentType
import services.annotation.AnnotationService
import services.document.DocumentService
import services.generated.tables.records.DocumentFilepartRecord
import services.user.UserService
import services.user.Roles._
import services.visit.VisitService
import org.joda.time.DateTime
import org.joda.time.format.DateTimeFormat
import org.webjars.play.WebJarsUtil
import play.api.Configuration
import play.api.mvc.{ControllerComponents, ResponseHeader, Result}
import play.api.libs.Files.TemporaryFileCreator
import play.api.http.HttpEntity
import scala.concurrent.{ExecutionContext, Future}
import storage.db.DB
import storage.es.migration.AnnotationMigrationUtil
import transform.tiling.TilingService

@Singleton
class BackupAdminController @Inject() (
    val components: ControllerComponents,
    val config: Configuration,
    val migrationUtil: AnnotationMigrationUtil,
    val users: UserService,
    val visits: VisitService,
    val silhouette: Silhouette[Security.Env],
    implicit val db: DB,
    implicit val tilingService: TilingService,
    implicit val annotations: AnnotationService,
    implicit val documents: DocumentService,
    implicit val ctx: ExecutionContext,
    implicit val system: ActorSystem,
    implicit val tmpFileCreator: TemporaryFileCreator,
    implicit val webJarsUtil: WebJarsUtil
  ) extends BaseAuthController(components, config, documents, users) with BackupReader {

  

  def restore = silhouette.SecuredAction(Security.WithRole(Admin)).async { implicit request =>
    request.body.asMultipartFormData.flatMap(_.file("backup")) match {
      case Some(formData) =>
        restoreBackup(formData.ref.path.toFile, runAsAdmin = true, forcedOwner = None).map { case (doc, fileparts) =>
          Ok
        }.recover { case t: Throwable =>
          t.printStackTrace()
          InternalServerError
        }

      case None =>
        Future.successful(BadRequest)
    }
  }

  def exportVisits = silhouette.SecuredAction(Security.WithRole(Admin)).async { implicit request =>
    visits.scrollExport().map { path =>
      val fmt = DateTimeFormat.forPattern("yyyy-MM-dd")
      val source = FileIO.fromPath(path)
      val filename = s"visits-exported-${fmt.print(DateTime.now)}.csv"
      Result(
        header = ResponseHeader(200, Map("Content-Disposition" -> s"""attachment; filename="${filename}"""")),
        body = HttpEntity.Streamed(source, None, Some("text/csv"))
      )
    }
  }

  def deleteVisitsOlderThan(date: Option[String]) = silhouette.SecuredAction(Security.WithRole(Admin)).async { implicit request =>
    date match {
      case Some(_) =>
        Future.successful(BadRequest("User-provided dates not supported yet."))

      case _ =>
        val cutoffDate = DateTime.now minusMonths 6
        visits.deleteOlderThan(cutoffDate).map { success =>
          if (success) Ok("Done.")
          else InternalServerError("Something went wrong.")
        }
    }
  }

} 
Example 78
Source File: AdminController.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package controllers.admin

import com.mohiva.play.silhouette.api.Silhouette
import controllers.{BaseAuthController, Security}
import javax.inject.{Inject, Singleton}
import services.annotation.AnnotationService
import services.contribution.ContributionService
import services.document.{DocumentService, DocumentToJSON}
import services.user.UserService
import services.user.Roles._
import services.visit.VisitService
import org.webjars.play.WebJarsUtil
import play.api.Configuration
import play.api.libs.json.Json
import play.api.mvc.ControllerComponents
import scala.concurrent.ExecutionContextExecutor
import controllers.HasPrettyPrintJSON

@Singleton
class AdminController @Inject() (
  val components: ControllerComponents, 
  val config: Configuration,
  val annotations: AnnotationService,
  val contributions: ContributionService,
  val documents: DocumentService,
  val users: UserService,
  val visits: VisitService,
  val silhouette: Silhouette[Security.Env],
  implicit val ctx: ExecutionContextExecutor,
  implicit val webJarsUtil: WebJarsUtil
) extends BaseAuthController(components, config, documents, users) with HasPrettyPrintJSON {
        
  def index = silhouette.SecuredAction(Security.WithRole(Admin)) { implicit request =>
    Ok(views.html.admin.activity())
  }
  
  def getStats() = silhouette.SecuredAction(Security.WithRole(Admin)).async { implicit request =>
    // DocumentRecord JSON serialization
    import DocumentToJSON._
    
    val fRecentContributions = contributions.getMostRecent(10)
    val fSystemStats = contributions.getSystemStats()
    val fTotalAnnotations = annotations.countTotal()
    val fTotalVisits = visits.countTotal()
    val fTotalUsers = users.countUsers()

    val f = for {
      recentContributions <- fRecentContributions
      recentAffectedDocuments <- documents.getDocumentRecordsById(recentContributions.map(_.affectsItem.documentId))
      stats <- fSystemStats
      annotationCount <- fTotalAnnotations
      visitCount <- fTotalVisits
      userCount <- fTotalUsers
    } yield (recentContributions, recentAffectedDocuments, stats, annotationCount, visitCount, userCount)
    
    f.map { case (recentContributions, recentAffectedDocuments, stats, annotationCount, visitCount, userCount) =>
      val response =
        Json.obj(
          "recent_contributions" -> recentContributions,
          "recent_documents" -> recentAffectedDocuments,
          "contribution_stats" -> stats,
          "total_annotations" -> annotationCount,
          "total_visits" -> visitCount,
          "total_users" -> userCount)
      jsonOk(response)
    }
  }

  def getSignupHistory = silhouette.SecuredAction(Security.WithRole(Admin)).async { implicit request =>
    users.getSignupsOverTime().map { history =>
      val json = history.map(t => Json.obj("timestamp" -> t._1, "count" -> t._2))
      jsonOk(Json.toJson(json))
    }
  }
  
} 
Example 79
Source File: AuthoritiesAPIController.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package controllers.api.entity

import controllers.{BaseOptAuthController, HasPrettyPrintJSON}
import javax.inject.{Inject, Singleton}
import play.api.Configuration
import play.api.libs.json.{Json, JsObject}
import play.api.mvc.ControllerComponents
import scala.concurrent.ExecutionContext
import services.document.DocumentService
import services.entity.{AuthorityFileService, EntityType}
import services.entity.builtin.EntityService
import services.user.UserService

@Singleton
class AuthoritiesAPIController @Inject() (
  val authorities: AuthorityFileService,
  val components: ControllerComponents,
  val config: Configuration,
  val documents: DocumentService,
  val entities: EntityService,
  val users: UserService,
  implicit val ctx: ExecutionContext
) extends BaseOptAuthController(components, config, documents, users) with HasPrettyPrintJSON {

  def listGazetteers = Action.async { implicit request =>
    val fMetadata = authorities.listAll(Some(EntityType.PLACE))
    val fRecordCounts = entities.countByAuthority(Some(EntityType.PLACE))
    
    val f = for {
      metadata <- fMetadata
      counts <- fRecordCounts
    } yield (metadata, counts)
    
    f.map { case (listedGazetteers, counts) =>
      import AuthorityFileService._ // Import implicit JSON serialization
      
      // In order to see possible inconsistencies between DB and index,
      // we separately handle: i) gazetteers described in the DB, ii) gazetteer
      // IDs recorded in the index, but without a metadata record in the DB.
      // Normally, the list below should be empty.
      val unlistedGazetteers = counts.filterNot { case (id, count) => 
        listedGazetteers.map(_.getId).contains(id) 
      }
      
      val json = listedGazetteers.map {  m =>
          val count = counts.find(_._1 == m.getId).map(_._2).getOrElse(0l)
          Json.toJson(m).as[JsObject] ++ Json.obj("count" -> count)
        } ++ unlistedGazetteers.map { case (id, count) =>
          Json.obj(
            "identifier" -> id,
            "authority_type" -> "PLACE",
            "shortname" -> id,
            "count" -> count,
            "conflicted" -> true)
        }
      
      jsonOk(Json.toJson(json))
    }
  }

} 
Example 80
Source File: PlaceAPIController.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package controllers.api.entity

import com.mohiva.play.silhouette.api.Silhouette
import com.vividsolutions.jts.geom.Coordinate
import controllers.{BaseOptAuthController, HasPrettyPrintJSON, Security}
import javax.inject.{Inject, Singleton}
import services.document.DocumentService
import services.entity.builtin.EntityService
import services.user.UserService
import services.user.Roles._
import play.api.Configuration
import play.api.libs.json.Json
import play.api.mvc.{Action, ControllerComponents}
import scala.concurrent.{Future, ExecutionContext }
import scala.util.{Try, Success, Failure}
import services.entity.EntityType

@Singleton
class PlaceAPIController @Inject() (
  val components: ControllerComponents,
  val config: Configuration,
  val documents: DocumentService,
  val users: UserService,
  val entities: EntityService,
  val silhouette: Silhouette[Security.Env],
  implicit val ctx: ExecutionContext
) extends BaseOptAuthController(components, config, documents, users) with HasPrettyPrintJSON {

  
  def searchPlacesInDocument(query: String, docId: String, offset: Int, size: Int) = silhouette.UserAwareAction.async { implicit request =>
    documentResponse(docId, request.identity, { case (metadata, accesslevel) =>
      if (accesslevel.canReadData)
        entities.searchEntitiesInDocument(query, docId, Some(EntityType.PLACE), offset, size).map { results =>
          jsonOk(Json.toJson(results.map(_.entity)))
        }
      else
        Future.successful(Forbidden)
    })
  }

} 
Example 81
Source File: ContributionAPIController.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package controllers.api.contribution

import com.mohiva.play.silhouette.api.Silhouette
import controllers.{BaseOptAuthController, Security, HasPrettyPrintJSON}
import javax.inject.{Inject, Singleton}
import play.api.Configuration
import play.api.libs.json.Json
import play.api.mvc.ControllerComponents 
import scala.concurrent.{ExecutionContext, Future}
import services.HasDate
import services.contribution.ContributionService
import services.document.DocumentService
import services.user.UserService

@Singleton
class ContributionAPIController @Inject() (
  val components: ControllerComponents,
  val config: Configuration,
  val contributions: ContributionService,
  val documents: DocumentService,
  val users: UserService,
  val silhouette: Silhouette[Security.Env],
  implicit val ctx: ExecutionContext
) extends BaseOptAuthController(components, config, documents, users) with HasPrettyPrintJSON with HasDate {

  def getDocumentStats(id: String) = silhouette.UserAwareAction.async { implicit request => 
    documentResponse(id, request.identity, { case (doc, accesslevel) => 
      if (accesslevel.canReadData) {
        contributions.getDocumentStats(id).map { stats => 
          jsonOk(Json.toJson(stats))
        }
      } else {
        Future.successful(Forbidden)
      }
    })
  }

  def countContributionsSince(docId: String, timestamp: String) = silhouette.UserAwareAction.async { implicit request => 
    documentResponse(docId, request.identity, { case (doc, accesslevel) =>
      if (accesslevel.canReadData) {
        parseDate(timestamp) match {
          case Some(date) => 
            contributions.countContributionsSince(docId, date).map { count => 
            jsonOk(Json.obj(
              "id" -> doc.id, 
              "contributions" -> count,
              "since" -> formatDate(date)))
          }

          case None => 
            Future.successful(BadRequest)
        }
      } else {
        Future.successful(Forbidden)
      }
    })
  }
  
} 
Example 82
Source File: PluginAPIController.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package controllers.api.plugin

import controllers.{BaseOptAuthController, HasPrettyPrintJSON}
import javax.inject.{Inject, Singleton}
import org.pelagios.recogito.sdk.ner.NERPlugin
import play.api.Configuration
import play.api.libs.json._
import play.api.libs.functional.syntax._
import play.api.mvc.ControllerComponents
import plugins.PluginRegistry
import scala.collection.JavaConverters._
import scala.concurrent.ExecutionContext
import services.document.DocumentService
import services.user.UserService
import transform.ner.NERPluginManager

@Singleton
class PluginAPIController @Inject() (
  val components: ControllerComponents,
  val config: Configuration,
  val documents: DocumentService,
  val users: UserService,
  implicit val ctx: ExecutionContext
) extends BaseOptAuthController(components, config, documents, users) with HasPrettyPrintJSON {

  implicit val pluginWrites: Writes[NERPlugin] = (
    (JsPath \ "identifier").write[String] and
    (JsPath \ "name").write[String] and
    (JsPath \ "languages").write[Seq[String]] and
    (JsPath \ "organization").write[String] and
    (JsPath \ "description").write[String] and 
    (JsPath \ "version").write[String]
  )(p => (
     p.getClass.getName,
     p.getName,
     p.getSupportedLanguages.asScala,
     p.getOrganization,
     p.getDescription,
     p.getVersion
  ))

  def listNERPlugins = Action { implicit request =>
    val plugins = NERPluginManager.plugins
    jsonOk(Json.toJson(plugins))
  }

  def loadPlugin(ext: String, id: String) = Action.async { implicit request =>
    PluginRegistry.loadPlugin(ext, id).map { _ match {
      case Some(js) => Ok(js).as("application/javascript")
      case None => NotFound 
    }}
  }

  def loadCSS(ext: String, id: String) = Action.async { implicit request => 
    PluginRegistry.loadCSS(ext, id).map { _ match {
      case Some(css) => Ok(css).as("text/css")
      case None => NotFound
    }}
  }

} 
Example 83
Source File: SimilarityAPIController.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package controllers.api.similarity

import com.mohiva.play.silhouette.api.Silhouette
import controllers.{BaseOptAuthController, Security, HasPrettyPrintJSON}
import javax.inject.{Inject, Singleton}
import play.api.Configuration
import play.api.libs.json._
import play.api.libs.functional.syntax._
import play.api.mvc.ControllerComponents 
import scala.concurrent.{ExecutionContext, Future}
import services.RuntimeAccessLevel
import services.document.{DocumentService, ExtendedDocumentMetadata}
import services.generated.tables.records.DocumentRecord
import services.user.UserService
import services.similarity.{Similarity, SimilarityService}

@Singleton
class SimilarityAPIController @Inject() (
  val components: ControllerComponents,
  val config: Configuration,
  val documents: DocumentService,
  val similarities: SimilarityService,
  val users: UserService,
  val silhouette: Silhouette[Security.Env],
  implicit val ctx: ExecutionContext
) extends BaseOptAuthController(components, config, documents, users) with HasPrettyPrintJSON {

  implicit val similarDocumentWrites: Writes[(DocumentRecord, RuntimeAccessLevel, Similarity)] = (
    (JsPath \ "document_id").write[String] and
    (JsPath \ "author").writeNullable[String] and
    (JsPath \ "title").write[String] and 
    (JsPath \ "owner").write[String] and
    (JsPath \ "similarity").write[JsValue]
  )(t => (
      t._1.getId, 
      Option(t._1.getAuthor),
      t._1.getTitle,
      t._1.getOwner,
      Json.obj(
        "title" -> t._3.jaroWinkler, 
        "entities" -> t._3.jaccard)
  ))

  implicit val similarityAPIResponseWrites: Writes[(ExtendedDocumentMetadata, Seq[(DocumentRecord, RuntimeAccessLevel, Similarity)])] = (
    (JsPath \ "document_id").write[String] and
    (JsPath \ "author").writeNullable[String] and
    (JsPath \ "title").write[String] and 
    (JsPath \ "owner").write[String] and 
    (JsPath \ "similar").write[Seq[(DocumentRecord, RuntimeAccessLevel, Similarity)]]
  )(t => (
      t._1.id,
      t._1.author,
      t._1.title,
      t._1.ownerName,
      t._2
  ))

  def getSimilar(docId: String) = silhouette.UserAwareAction.async { implicit request => 
    documentResponse(docId, request.identity, { case (doc, accesslevel) => 
      if (accesslevel.canReadData) {
        similarities.findSimilar(docId, request.identity.map(_.username)).map { response => 
          jsonOk(Json.toJson((doc, response)))
        }
      } else {
        Future.successful(Forbidden)
      }
    })
  }
  
} 
Example 84
Source File: TaskAPIController.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package controllers.api.task

import akka.actor.ActorSystem
import com.mohiva.play.silhouette.api.Silhouette
import controllers.{BaseAuthController, HasPrettyPrintJSON, Security}
import java.util.UUID
import javax.inject.{Inject, Singleton}
import play.api.Configuration
import play.api.libs.json.Json
import play.api.mvc.ControllerComponents 
import services.document.DocumentService
import services.task.{TaskType, TaskService, TaskRecordAggregate}
import services.user.UserService
import services.user.Roles._
import scala.concurrent.{ExecutionContext, Future}
import transform.JobDefinition
import transform.georesolution.{GeoresolutionService, TableGeoresolutionJobDefinition}
import transform.ner.{NERService, NERJobDefinition}

@Singleton
class TaskAPIController @Inject() (
  val components: ControllerComponents,
  val config: Configuration,
  val documents: DocumentService,
  val users: UserService,
  val ner: NERService,
  val georesolution: GeoresolutionService,
  val silhouette: Silhouette[Security.Env],
  val tasks: TaskService,
  implicit val system: ActorSystem,
  implicit val ctx: ExecutionContext
) extends BaseAuthController(components, config, documents, users) with HasPrettyPrintJSON {

  def spawnJob = silhouette.SecuredAction.async { implicit request =>
    request.body.asJson.map(json => Json.fromJson[JobDefinition](json)) match {
      case Some(result) if result.isSuccess =>
        val taskDefinition = result.get
        documentResponse(taskDefinition.documents.head, request.identity, { case (docInfo, accesslevel) =>
          if (accesslevel.canWrite)
            taskDefinition.taskType match {  
              case TaskType("GEORESOLUTION") =>
                val definition = Json.fromJson[TableGeoresolutionJobDefinition](request.body.asJson.get).get
                georesolution.spawnJob(docInfo.document, docInfo.fileparts, definition)
                Ok

              case TaskType("NER") =>
                val definition = Json.fromJson[NERJobDefinition](request.body.asJson.get).get
                val jobId = ner.spawnJob(docInfo.document, docInfo.fileparts, definition)
                jsonOk(Json.obj("job_id" -> jobId))
                
              case t =>
                BadRequest(Json.parse("{ \"error\": \"unsupported task type: " + t + "\" }"))
            }
          else
            Forbidden(Json.parse("{ \"error\": \"insufficient access privileges\"}"))
        })
        
      case Some(result) if result.isError => Future.successful(BadRequest(Json.parse("{ \"error\": \"JSON parse error\" }")))
      case None => Future.successful(BadRequest(Json.parse("{ \"error\": \"missing task definition\" }")))
    }
  }

  def getJobProgress(jobId: UUID) = silhouette.SecuredAction.async { implicit request => 
    tasks.findByJobId(jobId).map { _ match {
      case Some(progress) => jsonOk(Json.toJson(progress))
      case None => NotFound
    }}
  }

  def progressByDocument(id: String) = silhouette.SecuredAction.async { implicit request =>    
    documents.getExtendedMeta(id, Some(request.identity.username)).flatMap(_ match {
      case Some((doc, accesslevel)) =>
        if (accesslevel.canReadAll) {
          tasks.findByDocument(id).map {
            case Some(taskRecord) => jsonOk(Json.toJson(taskRecord))
            case None => NotFound
          }
        } else {
          Future.successful(Forbidden)
        }
        
      case None => Future.successful(NotFound)
    })
  }
  
} 
Example 85
Source File: BaseOptAuthController.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package controllers

import services.RuntimeAccessLevel
import services.document.{ExtendedDocumentMetadata, DocumentService}
import services.generated.tables.records.{DocumentFilepartRecord, DocumentRecord}
import services.user.{User, UserService}
import play.api.Configuration
import play.api.mvc.{AnyContent, ControllerComponents, Request, Result}
import scala.concurrent.{ExecutionContext, Future}

abstract class BaseOptAuthController(
    components: ControllerComponents,
    config: Configuration,
    documents: DocumentService,
    users: UserService
  ) extends BaseController(components, config, users) {
 
  
  protected def documentPartResponse(
      documentId: String,
      partNo: Int,
      maybeUser: Option[User],
      response: (ExtendedDocumentMetadata, DocumentFilepartRecord, RuntimeAccessLevel) => Future[Result]
    )(implicit ctx: ExecutionContext, request: Request[AnyContent]) = {
    
    documentReadResponse(documentId, maybeUser, { case (doc, accesslevel) =>
      doc.fileparts.find(_.getSequenceNo == partNo) match {
        case None => Future.successful(NotFoundPage)
        case Some(part) => response(doc, part, accesslevel)
      }
    })
  }
  
} 
Example 86
Source File: DocumentActionsController.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package controllers.my.directory.delete

import com.mohiva.play.silhouette.api.Silhouette
import controllers.{BaseController, HasPrettyPrintJSON, Security}
import javax.inject.{Inject, Singleton}
import play.api.Configuration
import play.api.libs.json.{Json, JsValue}
import play.api.mvc.ControllerComponents
import scala.concurrent.{ExecutionContext, Future}
import scala.util.Try
import services.RuntimeAccessLevel
import services.annotation.AnnotationService
import services.contribution.ContributionService
import services.document.DocumentService
import services.folder.FolderService
import services.generated.tables.records.DocumentRecord
import services.user.UserService

@Singleton
class DocumentActionsController @Inject() (
  val annotations: AnnotationService,
  val components: ControllerComponents,
  val contributions: ContributionService,
  val documents: DocumentService,
  val folders: FolderService,
  val silhouette: Silhouette[Security.Env],
  val users: UserService,
  val config: Configuration,
  implicit val ctx: ExecutionContext
) extends BaseController(components, config, users)
    with HasPrettyPrintJSON {

  
  def bulkUnshareDocuments() = silhouette.SecuredAction.async { implicit request => 
    val docIds = getDocIdPayload(request.body.asJson)
    val user = request.identity.username

    Future.sequence {
      docIds.map(documents.removeDocumentCollaborator(_, user))
    }.map { results =>
      val success = !results.exists(!_)
      if (success) Ok else BadRequest
    }
  }

} 
Example 87
Source File: FolderActionsController.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package controllers.my.directory.delete

import com.mohiva.play.silhouette.api.Silhouette
import controllers.{BaseController, HasPrettyPrintJSON, Security}
import java.util.UUID
import javax.inject.{Inject, Singleton}
import play.api.Configuration
import play.api.mvc.ControllerComponents
import scala.concurrent.{ExecutionContext, Future}
import services.SharingLevel
import services.folder.FolderService
import services.generated.tables.records.{FolderRecord, SharingPolicyRecord}
import services.user.UserService

@Singleton
class FolderActionsController @Inject() (
  val components: ControllerComponents,
  val folders: FolderService,
  val silhouette: Silhouette[Security.Env],
  val users: UserService,
  val config: Configuration,
  implicit val ctx: ExecutionContext
) extends BaseController(components, config, users)
    with HasPrettyPrintJSON {

  
  private def isAllowed(username: String, folder: FolderRecord, policy: Option[SharingPolicyRecord]) = {
    folder.getOwner == username || 
      policy.map { p => 
        p.getSharedWith == username && p.getAccessLevel == SharingLevel.ADMIN.toString
      }.getOrElse(false)
  }

  def deleteFolder(id: UUID) = silhouette.SecuredAction.async { implicit request =>
    folders.getFolder(id, request.identity.username).flatMap { _ match {
      case Some((folder, policy)) =>
        if (isAllowed(request.identity.username, folder, policy)) {
          folders.deleteFolder(folder.getId).map { success => 
            if (success) Ok
            else InternalServerError
          }
        } else {
          Future.successful(Forbidden)
        }

      case None => Future.successful(NotFound)
    }}
  }

  def bulkDeleteFolders() =
    silhouette.SecuredAction.async { implicit request => ??? }

  def unshareFolder(id: UUID) =
    silhouette.SecuredAction.async { implicit request => ??? }

  def bulkUnshareFolders() =
    silhouette.SecuredAction.async { implicit request => ??? }

  def deleteReadme(folderId: UUID) =
    silhouette.SecuredAction.async { implicit request => 
      val f = Option(folderId) match {
        case Some(id) => folders.deleteReadme(folderId)
        case None => users.deleteReadme(request.identity.username)
      }

      f.map { success => 
        if (success) Ok else InternalServerError
      }
    }

} 
Example 88
Source File: SearchController.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package controllers.my.directory.search

import controllers.{Security, HasPrettyPrintJSON}
import controllers.my.directory.ConfiguredPresentation
import com.mohiva.play.silhouette.api.Silhouette
import javax.inject.{Inject, Singleton}
import org.joda.time.DateTime
import play.api.libs.json._
import play.api.libs.functional.syntax._
import play.api.mvc.{AnyContent, Request, AbstractController, ControllerComponents}
import scala.concurrent.{ExecutionContext, Future}
import scala.util.Try
import services.HasDate
import services.document.DocumentService
import services.document.search._

@Singleton
class SearchController @Inject() (
  components: ControllerComponents,
  silhouette: Silhouette[Security.Env],
  documentService: DocumentService,
  implicit val ctx: ExecutionContext
) extends AbstractController(components) 
    with HasPrettyPrintJSON
    with HasDate {

  import ConfiguredPresentation._

  implicit val searchOptionsReads: Reads[SearchArgs] = (
    (JsPath \ "q").readNullable[String] and
    (JsPath \ "in").readNullable[String]
      .map(_.flatMap(Scope.withName).getOrElse(Scope.ALL)) and
    (JsPath \ "type").readNullable[String]
      .map(_.flatMap(DocumentType.withName)) and
    (JsPath \ "owner").readNullable[String] and
    (JsPath \ "max_age").readNullable[DateTime]
  )(SearchArgs.apply _) 

  private def parseQueryString(params: Map[String, String]) = 
    params.get("q").map { q => // Require at least a query phrase
      SearchArgs(
        Some(q),
        params.get("in").flatMap(Scope.withName).getOrElse(Scope.ALL),
        params.get("type").flatMap(DocumentType.withName),
        params.get("owner"),
        params.get("max_age").flatMap(parseDate)
      ) 
    }

  def parseSearchArgs(request: Request[AnyContent]) = request.body.asJson match {
    case Some(json) =>
      Try(Json.fromJson[SearchArgs](json).get).toOption

    case None => // Try query string instead
      val asMap = request.queryString
        .mapValues(_.headOption)
        .filter(_._2.isDefined)
        .mapValues(_.get)
      parseQueryString(asMap)
  }
  
  
  def search = silhouette.UserAwareAction.async { implicit request =>
    parseSearchArgs(request) match {
      case Some(args) => 
        documentService.search(request.identity.map(_.username), args).map { documents => 
          val presentation = ConfiguredPresentation.forMyDocument(documents, None, None)
          jsonOk(Json.toJson(presentation))
        }

      case None =>
        Future.successful(BadRequest)
    } 
  }

} 
Example 89
Source File: WorkspaceController.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package controllers.my

import com.mohiva.play.silhouette.api.Silhouette
import controllers.{BaseController, Security, HasPrettyPrintJSON}
import javax.inject.{Inject, Singleton}
import services.contribution.{Contribution, ContributionService}
import services.user.{User, UserService}
import org.webjars.play.WebJarsUtil
import play.api.{Configuration, Environment}
import play.api.i18n.I18nSupport
import play.api.libs.json.Json
import play.api.mvc.{ControllerComponents, RequestHeader}
import services.document.DocumentService
import scala.concurrent.{ExecutionContext, Future}

@Singleton
class WorkspaceController @Inject() (
  val components: ControllerComponents,
  val contributions: ContributionService,
  val users: UserService,
  val config: Configuration,
  val silhouette: Silhouette[Security.Env],
  implicit val documents: DocumentService,
  implicit val ctx: ExecutionContext,
  implicit val env: Environment,
  implicit val webjars: WebJarsUtil
) extends BaseController(components, config, users) with I18nSupport with HasPrettyPrintJSON {

  
  def workspace(usernameInPath: String) = silhouette.UserAwareAction.async { implicit request =>    
    // If the user is logged in & the name in the path == username it's the profile owner
    val isProfileOwner = request.identity match {
      case Some(userWithRoles) => userWithRoles.username.equalsIgnoreCase(usernameInPath)
      case None => false
    }
    
    if (isProfileOwner)
      Future.successful(Ok(views.html.my.workspace()))
    else
      renderPublicProfile(usernameInPath, request.identity)
  }

  def activityFeed(usernameInPath: String) = silhouette.UserAwareAction.async { implicit request =>
    val loggedInAs = request.identity.map(_.username)
    contributions.getUserActivityFeed(Seq(usernameInPath), loggedInAs).map { response => 
      jsonOk(Json.toJson(response))
    } 
  }
  
} 
Example 90
Source File: AccountInfoController.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package controllers.my.account

import com.mohiva.play.silhouette.api.Silhouette
import controllers.{BaseController, HasPrettyPrintJSON, Security}
import javax.inject.{Inject, Singleton}
import play.api.Configuration
import play.api.libs.json.Json
import play.api.mvc.ControllerComponents
import scala.concurrent.{Future, ExecutionContext}
import services.contribution.ContributionService
import services.document.DocumentService
import services.user.UserService
import storage.uploads.Uploads

@Singleton
class AccountInfoController @Inject() (
    val components: ControllerComponents,
    val contributions: ContributionService,
    val documents: DocumentService,
    val silhouette: Silhouette[Security.Env],
    val users: UserService,
    val uploads: Uploads,
    val config: Configuration,
    implicit val ctx: ExecutionContext
  ) extends BaseController(components, config, users)
      with HasPrettyPrintJSON {

  
  def getCollaborators(username: String) = Action.async { implicit request =>
    contributions.getTopCollaborators(username).map { tuples => 
      val json = tuples.map(t => Json.obj("username" -> t._1, "edits" -> t._2)) 
      jsonOk(Json.toJson(json))
    }    
  }

} 
Example 91
Source File: RestoreController.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package controllers.my.settings

import akka.actor.ActorSystem
import com.mohiva.play.silhouette.api.Silhouette
import controllers.{HasUserService, HasConfig, Security }
import controllers.document.{BackupReader, HasBackupValidation}
import java.io.File
import javax.inject.Inject
import services.annotation.AnnotationService
import services.document.DocumentService
import services.user.Roles._
import services.user.UserService
import play.api.{Configuration, Logger}
import play.api.i18n.{I18nSupport, MessagesApi}
import play.api.mvc.{AbstractController, ControllerComponents}
import scala.concurrent.{ExecutionContext, Future}
import storage.db.DB
import transform.tiling.TilingService

class RestoreController @Inject() (
  val components: ControllerComponents,
  val config: Configuration,
  val users: UserService,
  val silhouette: Silhouette[Security.Env],
  implicit val annotations: AnnotationService,
  implicit val db: DB,
  implicit val documents: DocumentService,
  implicit val tiling: TilingService,
  implicit val ctx: ExecutionContext,
  implicit val system: ActorSystem
) extends AbstractController(components) 
    with HasUserService 
    with HasConfig
    with I18nSupport
    with BackupReader {
  
  def index() = silhouette.SecuredAction { implicit request =>
    Ok(views.html.my.settings.restore(request.identity))
  }

  def restore() = silhouette.SecuredAction.async { implicit request =>
    request.body.asMultipartFormData.map { tempfile =>
      tempfile.file("backup") match {
       
        case Some(filepart) =>
          // Forces the owner of the backup to the currently logged in user
          restoreBackup(
            filepart.ref.path.toFile,
            runAsAdmin = false,
            forcedOwner = Some(request.identity.username)
          ).map { _ => 
            Redirect(routes.RestoreController.index).flashing("success" -> "The document was restored successfully.") 
          }.recover { 
            
            case e: HasBackupValidation.InvalidSignatureException =>
              Redirect(routes.RestoreController.index).flashing("error" -> "The authenticity of your backup could not be verified.")
              
            case t: Throwable =>
              t.printStackTrace()
              Redirect(routes.RestoreController.index).flashing("error" -> "There was an error restoring your document.") 
          }
          
        case None =>
          Logger.warn("Personal document restore POST without file attached")
          Future.successful(BadRequest)        
      }
    }.getOrElse {
      Logger.warn("Personal document restore POST without form data")
      Future.successful(BadRequest)
    }
  }

} 
Example 92
Source File: AccountSettingsController.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package controllers.my.settings

import com.mohiva.play.silhouette.api.{Silhouette, LoginInfo}
import controllers.{HasUserService, HasConfig, Security}
import javax.inject.Inject
import services.announcement.AnnouncementService
import services.annotation.AnnotationService
import services.contribution.ContributionService
import services.user.Roles._
import services.user.UserService
import services.upload.UploadService
import services.document.DocumentService
import org.webjars.play.WebJarsUtil
import play.api.Configuration
import play.api.data.Form
import play.api.data.Forms._
import play.api.i18n.I18nSupport
import play.api.mvc.{AbstractController, ControllerComponents}
import scala.concurrent.{Await, ExecutionContext, Future}
import scala.concurrent.duration._
import controllers.HasAccountRemoval

case class AccountSettingsData(
  email  : String,
  name   : Option[String],
  bio    : Option[String],
  website: Option[String])

class AccountSettingsController @Inject() (
  val components: ControllerComponents,
  val config: Configuration,
  val silhouette: Silhouette[Security.Env],
  implicit val announcements: AnnouncementService,
  implicit val annotations: AnnotationService,
  implicit val contributions: ContributionService,
  implicit val ctx: ExecutionContext,
  implicit val documents: DocumentService,
  implicit val uploads: UploadService,
  implicit val users: UserService,
  implicit val webjars: WebJarsUtil
) extends AbstractController(components) with HasUserService with HasConfig with HasAccountRemoval with I18nSupport {

  val accountSettingsForm = Form(
    mapping(
      "email" -> email,
      "name" -> optional(text(maxLength=80)),
      "bio" -> optional(text(maxLength=256)),
      "website" -> optional(text(maxLength=256))
    )(AccountSettingsData.apply)(AccountSettingsData.unapply)
  )

  def index() = silhouette.SecuredAction { implicit request =>
    val u = request.identity
    
    val form = accountSettingsForm.fill(AccountSettingsData(
      users.decryptEmail(u.email),
      u.realName,
      u.bio,
      u.website))
    
    Ok(views.html.my.settings.account(form, u))
  }

  def updateAccountSettings() = silhouette.SecuredAction.async { implicit request =>
    accountSettingsForm.bindFromRequest.fold(
      formWithErrors =>
        Future.successful(BadRequest(views.html.my.settings.account(formWithErrors, request.identity))),

      f =>
        users.updateUserSettings(request.identity.username, f.email, f.name, f.bio, f.website)
          .map { success =>
            if (success)
              Redirect(routes.AccountSettingsController.index).flashing("success" -> "Your settings have been saved.")
            else 
              Redirect(routes.AccountSettingsController.index).flashing("error" -> "There was an error while saving your settings.")
          }.recover { case t:Throwable => {
            t.printStackTrace()
            Redirect(routes.AccountSettingsController.index).flashing("error" -> "There was an error while saving your settings.")
          }}
    )
  }
  
  def deleteAccount() = silhouette.SecuredAction.async { implicit request =>
    deleteUserAccount(request.identity.username).flatMap { _ =>
      silhouette.env.authenticatorService.discard(
        request.authenticator,
        Redirect(controllers.landing.routes.LandingController.index))
    }
  }

} 
Example 93
Source File: PasswordSettingsController.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package controllers.my.settings

import com.mohiva.play.silhouette.api.Silhouette
import controllers.{ HasConfig, HasUserService, Security }
import javax.inject.Inject
import services.user.UserService
import services.user.Roles._
import play.api.Configuration
import play.api.data.Form
import play.api.data.Forms._
import play.api.data.validation._
import play.api.i18n.{ I18nSupport, MessagesApi }
import play.api.mvc.{AbstractController, ControllerComponents}
import scala.concurrent.{ ExecutionContext, Future }

case class PasswordSettingsData(currentPassword: String, newPassword: String, verifyPassword: String)

class PasswordSettingsController @Inject() (
    val components: ControllerComponents,
    val config: Configuration,
    val users: UserService,
    val silhouette: Silhouette[Security.Env],
    implicit val ctx: ExecutionContext
  ) extends AbstractController(components) with HasConfig with HasUserService with I18nSupport {

  private val matchingPasswords: Constraint[PasswordSettingsData] = Constraint("constraints.valid") { d =>
    if (d.newPassword == d.verifyPassword) Valid else Invalid("Passwords must match")
  }

  val passwordSettingsForm = Form(
    mapping(
      "current" -> nonEmptyText,
      "new" -> nonEmptyText,
      "verify" -> nonEmptyText
    )(PasswordSettingsData.apply)(PasswordSettingsData.unapply).verifying(matchingPasswords)
  )

  def index() = silhouette.SecuredAction { implicit request =>
    Ok(views.html.my.settings.password(passwordSettingsForm, request.identity))
  }

  def updatePassword() = silhouette.SecuredAction.async { implicit request =>
    passwordSettingsForm.bindFromRequest.fold(
      formWithErrors =>
        Future.successful(BadRequest(views.html.my.settings.password(formWithErrors, request.identity))),

      f => {
        users.updatePassword(request.identity.username, f.currentPassword, f.newPassword)
          .map { _ match {
            case Right(_) =>
              Redirect(routes.PasswordSettingsController.index).flashing("success" -> "Your password has been updated.")
            case Left(errorMessage) =>
              Redirect(routes.PasswordSettingsController.index).flashing("error" -> errorMessage)
          }}.recover { case t:Throwable => {
            t.printStackTrace()
            Redirect(routes.PasswordSettingsController.index).flashing("error" -> "There was an error while updating your password.")
          }}
      }
    )
  }

} 
Example 94
Source File: MapController.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package controllers.document.map

import com.mohiva.play.silhouette.api.Silhouette
import controllers.{BaseOptAuthController, HasVisitLogging, Security}
import javax.inject.{Inject, Singleton}
import services.document.DocumentService
import services.annotation.AnnotationService
import services.user.UserService
import services.user.Roles._
import services.visit.VisitService
import org.webjars.play.WebJarsUtil
import play.api.Configuration
import play.api.mvc.ControllerComponents
import play.api.i18n.I18nSupport
import scala.concurrent.{ExecutionContext, Future}

@Singleton
class MapController @Inject() (
    val components: ControllerComponents,
    val config: Configuration,
    val annotations: AnnotationService,
    val document: DocumentService,
    val users: UserService,
    val silhouette: Silhouette[Security.Env],
    implicit val visitService: VisitService,
    implicit val ctx: ExecutionContext,
    implicit val webjars: WebJarsUtil
  ) extends BaseOptAuthController(components, config, document, users) with HasVisitLogging with I18nSupport {

  def showMap(documentId: String) = silhouette.UserAwareAction.async { implicit request =>
    documentReadResponse(documentId, request.identity,  { case (doc, accesslevel) =>
      logDocumentView(doc.document, None, accesslevel)
      annotations.countByDocId(documentId).map { documentAnnotationCount =>
        Ok(views.html.document.map.index(doc, request.identity, accesslevel, documentAnnotationCount))
      }
    })
  }

} 
Example 95
Source File: StatsController.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package controllers.document.stats

import com.mohiva.play.silhouette.api.Silhouette
import controllers.{BaseOptAuthController, Security, HasVisitLogging, HasPrettyPrintJSON}
import java.io.{ByteArrayOutputStream, PrintWriter}
import javax.inject.{Inject, Singleton}
import kantan.csv._
import kantan.csv.ops._
import kantan.csv.CsvConfiguration.{Header, QuotePolicy}
import kantan.csv.engine.commons._
import services.annotation.AnnotationService
import services.document.DocumentService
import services.user.UserService
import services.user.Roles._
import services.visit.VisitService
import org.webjars.play.WebJarsUtil
import play.api.Configuration
import play.api.mvc.{AnyContent, Request, Result, ControllerComponents}
import play.api.libs.json._
import play.api.libs.functional.syntax._
import play.api.i18n.I18nSupport
import plugins.PluginRegistry
import scala.concurrent.{ExecutionContext, Future}

@Singleton
class StatsController @Inject() (
  val components: ControllerComponents,
  val config: Configuration,
  val documents: DocumentService,
  val annotations: AnnotationService,
  val users: UserService,
  val silhouette: Silhouette[Security.Env],
  implicit val visitService: VisitService,
  implicit val webjars: WebJarsUtil,
  implicit val ctx: ExecutionContext
) extends BaseOptAuthController(components, config, documents, users) 
    with HasVisitLogging 
    with HasPrettyPrintJSON 
    with I18nSupport {
  
  private val CSV_CONFIG = CsvConfiguration(',', '"', QuotePolicy.WhenNeeded, Header.None)
    
  implicit val tuple2Writes: Writes[Tuple2[String, Long]] = (
    (JsPath \ "value").write[String] and
    (JsPath \ "count").write[Long]
  )(t => (t._1, t._2))
  
  private def toCSV(stats: Seq[(String, Long)]): String = {
    val out = new ByteArrayOutputStream()
    val writer = out.asCsvWriter[(String, Long)](CSV_CONFIG)
    stats.foreach(writer.write(_))
    writer.close()
    new String(out.toByteArray, "UTF-8")
  }
  
  def showDocumentStats(documentId: String, tab: Option[String]) = silhouette.UserAwareAction.async { implicit request =>
    documentReadResponse(documentId, request.identity,  { case (doc, accesslevel) =>
      logDocumentView(doc.document, None, accesslevel)      
      tab.map(_.toLowerCase) match {
        case Some(t) if t == "activity" =>  
          val plugins = PluginRegistry.listConfigs("document.stats.activity")
          Future.successful(Ok(views.html.document.stats.activity(doc, request.identity, accesslevel, plugins)))
          
        case Some(t) if t == "entities" =>
          val plugins = PluginRegistry.listConfigs("document.stats.entities")
          Future.successful(Ok(views.html.document.stats.entities(doc, request.identity, accesslevel, plugins)))
          
        case Some(t) if t == "tags" =>
          val plugins = PluginRegistry.listConfigs("document.stats.tags")
          Future.successful(Ok(views.html.document.stats.tags(doc, request.identity, accesslevel, plugins)))
          
        case _ =>
          val plugins = PluginRegistry.listConfigs("document.stats.activity")
          Future.successful(Ok(views.html.document.stats.activity(doc, request.identity, accesslevel, plugins)))
      }
    })
  }
  
  private def getTags(documentId: String)(action: (Seq[(String, Long)], Request[AnyContent]) => Result) =
    silhouette.UserAwareAction.async { implicit request =>
      documentReadResponse(documentId, request.identity,  { case (doc, accesslevel) =>
          annotations.getTagStats(documentId).map { buckets =>
            action(buckets, request.request)
          }
        }
      )
    }
  
  def getTagsAsJSON(documentId: String) = getTags(documentId) { case (buckets, request) =>
    jsonOk(Json.toJson(buckets))(request)
  }
  
  def getTagsAsCSV(documentId: String) = getTags(documentId) { case(buckets, request) =>
    Ok(toCSV(buckets)).withHeaders(CONTENT_DISPOSITION -> { s"attachment; filename=${documentId}_tags.csv" })
  }

} 
Example 96
Source File: DiscussionController.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package controllers.document.discussion

import com.mohiva.play.silhouette.api.Silhouette
import controllers.{BaseAuthController, Security}
import javax.inject.{Inject, Singleton}
import services.document.DocumentService
import services.user.UserService
import services.user.Roles._
import org.webjars.play.WebJarsUtil
import play.api.Configuration
import play.api.mvc.ControllerComponents
import play.api.i18n.I18nSupport
import scala.concurrent.ExecutionContext

@Singleton
class DiscussionController @Inject() (
    val components: ControllerComponents,
    val config: Configuration,
    val documents: DocumentService,
    val users: UserService,
    val silhouette: Silhouette[Security.Env],
    implicit val webjars: WebJarsUtil,
    implicit val ctx: ExecutionContext
  ) extends BaseAuthController(components, config, documents, users) with I18nSupport {

  def showDiscussionBoard(documentId: String) = silhouette.SecuredAction.async { implicit request =>
    documentResponse(documentId, request.identity, { case (doc, accesslevel) =>
      Ok(views.html.document.discussion.index(doc, Some(request.identity), accesslevel)) })
  }

} 
Example 97
Source File: PlayRouter.scala    From caliban   with Apache License 2.0 5 votes vote down vote up
package caliban

import akka.stream.Materializer
import play.api.mvc.{ ActionBuilder, AnyContent, ControllerComponents, PlayBodyParsers, Request, Results }
import play.api.routing.Router.Routes
import play.api.routing.SimpleRouter
import play.api.routing.sird._
import zio.Runtime
import zio.duration.Duration
import scala.concurrent.ExecutionContext

case class PlayRouter[R, E](
  interpreter: GraphQLInterpreter[R, E],
  controllerComponents: ControllerComponents,
  playground: Boolean = true,
  allowGETRequests: Boolean = true,
  subscriptions: Boolean = true,
  skipValidation: Boolean = false,
  enableIntrospection: Boolean = true,
  keepAliveTime: Option[Duration] = None
)(implicit runtime: Runtime[R], materializer: Materializer)
    extends SimpleRouter
    with PlayAdapter {

  override val actionBuilder: ActionBuilder[Request, AnyContent] = controllerComponents.actionBuilder
  override val parse: PlayBodyParsers                            = controllerComponents.parsers
  implicit val ec: ExecutionContext                              = controllerComponents.executionContext

  override def routes: Routes = {
    case POST(p"/api/graphql") => makePostAction(interpreter, skipValidation, enableIntrospection)
    case GET(
        p"/api/graphql" ? q_o"query=$query" & q_o"variables=$variables" & q_o"operationName=$operation" & q_o"extensions=$extensions"
        ) if allowGETRequests =>
      makeGetAction(interpreter, skipValidation, enableIntrospection)(query, variables, operation, extensions)
    case GET(p"/ws/graphql") if subscriptions =>
      makeWebSocket(interpreter, skipValidation, enableIntrospection, keepAliveTime)
    case GET(p"/graphiql") if playground =>
      actionBuilder(
        Results.Ok
          .sendResource("graphiql.html")(controllerComponents.executionContext, controllerComponents.fileMimeTypes)
      )
  }

} 
Example 98
Source File: IzanamiController.scala    From izanami   with Apache License 2.0 5 votes vote down vote up
package controllers

import akka.actor.ActorSystem
import controllers.actions.SecuredAction
import env.Env
import izanami.scaladsl.Proxy
import play.api.libs.json.Json
import play.api.mvc.{AbstractController, ControllerComponents}

class IzanamiController(env: Env, proxy: Proxy, SecuredAction: SecuredAction, val cc: ControllerComponents)(
    implicit system: ActorSystem
) extends AbstractController(cc) {

  import cats._
  import cats.implicits._
  import system.dispatcher

  def izanamiProxy() = SecuredAction.async { req =>
    proxy
      .statusAndJsonResponse(
        Json.obj("userId" -> req.userId).some,
        req.userId.some
      )
      .map {
        case (status, response) => Status(status)(response)
      }
  }

  def markDisplayed(experiment: String) = SecuredAction.async { req =>
    proxy.markVariantDisplayed(experiment, req.userId).map {
      case (status, response) => Status(status)(response)
    }
  }

  def markWon(experiment: String) = SecuredAction.async { req =>
    proxy.markVariantWon(experiment, req.userId).map {
      case (status, response) => Status(status)(response)
    }
  }

} 
Example 99
Source File: MeController.scala    From izanami   with Apache License 2.0 5 votes vote down vote up
package controllers

import akka.actor.ActorSystem
import akka.http.scaladsl.util.FastFuture
import controllers.actions.SecuredAction
import domains.me.MeService
import env.Env
import izanami.scaladsl.FeatureClient
import play.api.libs.json.Json
import play.api.mvc.{AbstractController, ControllerComponents}

import scala.concurrent.Future

class MeController(env: Env,
                   meService: MeService[Future],
                   featureClient: FeatureClient,
                   SecuredAction: SecuredAction,
                   cc: ControllerComponents)(
    implicit system: ActorSystem
) extends AbstractController(cc) {

  import cats._
  import cats.implicits._
  import system.dispatcher
  import domains.me.Me._

  def me() = SecuredAction.async { implicit req =>
    meService.get(req.userId).map { me =>
      Ok(Json.toJson(me))
    }
  }

  def addTvShow(id: String) = SecuredAction.async { implicit req =>
    meService.addTvShow(req.userId, id).map { me =>
      Ok(Json.toJson(me))
    }
  }

  def removeTvShow(id: String) = SecuredAction.async { implicit req =>
    meService.removeTvShow(req.userId, id).map { me =>
      Ok(Json.toJson(me))
    }
  }

  def markEpisode(showId: String, episodeId: String, watched: Boolean) = SecuredAction.async { implicit req =>
    meService.markEpisode(req.userId, showId, episodeId, watched).map { me =>
      Ok(Json.toJson(me))
    }
  }

  def markSeason(showId: String, season: Int, watched: Boolean) = SecuredAction.async { implicit req =>
    featureClient.featureOrElseAsync("mytvshows:season:markaswatched") {
      meService.markSeason(req.userId, showId, season, watched).map { me =>
        Ok(Json.toJson(me))
      }
    } {
      FastFuture.successful(BadRequest(Json.obj()))
    }
  }

} 
Example 100
Source File: HomeController.scala    From izanami   with Apache License 2.0 5 votes vote down vote up
package controllers

import env.{AppConfig, Env}
import play.api.libs.json.{JsError, Json}
import play.api.mvc.{AbstractController, ControllerComponents, Cookie, Cookies}

case class LoginForm(email: String)
object LoginForm {
  implicit val format = Json.format[LoginForm]
}

class HomeController(env: Env, config: AppConfig, val cc: ControllerComponents) extends AbstractController(cc) {

  def index() = Action {
    config.front match {
      case "react" =>
        Ok(views.html.index(env))
      case _ =>
        Ok(views.html.indexangular(env))
    }
  }

  def indexOtherRoutes(path: String) = index()

  def login() = Action(parse.json) { req =>
    req.body
      .validate[LoginForm]
      .fold(
        e => BadRequest(JsError.toJson(e)),
        form => Ok(Json.obj()).withCookies(Cookie("clientId", form.email))
      )

  }

} 
Example 101
Source File: SearchController.scala    From izanami   with Apache License 2.0 5 votes vote down vote up
package controllers

import akka.actor.ActorSystem
import akka.stream.scaladsl.{GraphDSL, Interleave, Sink, Source}
import akka.stream.{ActorMaterializer, SourceShape}
import controllers.actions.SecuredAuthContext
import domains.abtesting.ExperimentService
import domains.config.ConfigService
import domains.feature.FeatureService
import domains.script.GlobalScriptService
import domains.configuration.GlobalContext
import play.api.libs.json.{JsArray, JsValue, Json}
import play.api.mvc.{AbstractController, ActionBuilder, AnyContent, ControllerComponents}
import store.Query
import zio.{Runtime, ZIO}
import libs.http.HttpContext

class SearchController(AuthAction: ActionBuilder[SecuredAuthContext, AnyContent], cc: ControllerComponents)(
    implicit system: ActorSystem,
    R: HttpContext[GlobalContext]
) extends AbstractController(cc) {

  import libs.http._

  def search(pattern: String, features: Boolean, configs: Boolean, experiments: Boolean, scripts: Boolean) =
    AuthAction.asyncTask[GlobalContext] { ctx =>
      val query: Query = Query.oneOf(ctx.authorizedPatterns).and(pattern.split(",").toList)

      for {
        featuresRes <- if (features)
                        FeatureService
                          .findByQuery(query, 1, 10)
                          .map(_.results.map(value => Json.obj("type" -> "features", "id" -> Json.toJson(value.id))))
                          .map(value => Source(value.toList))
                      else ZIO.succeed(Source.empty[JsValue])

        configsRes <- if (configs)
                       ConfigService
                         .findByQuery(query, 1, 10)
                         .map(
                           _.results.map(value => Json.obj("type" -> "configurations", "id" -> Json.toJson(value.id)))
                         )
                         .map(value => Source(value.toList))
                     else ZIO.succeed(Source.empty[JsValue])

        experimentsRes <- if (experiments)
                           ExperimentService
                             .findByQuery(query, 1, 10)
                             .map(
                               _.results.map(value => Json.obj("type" -> "experiments", "id" -> Json.toJson(value.id)))
                             )
                             .map(value => Source(value.toList))
                         else ZIO.succeed(Source.empty[JsValue])

        scriptsRes <- if (scripts)
                       GlobalScriptService
                         .findByQuery(query, 1, 10)
                         .map(_.results.map(value => Json.obj("type" -> "scripts", "id" -> Json.toJson(value.id))))
                         .map(value => Source(value.toList))
                     else ZIO.succeed(Source.empty[JsValue])

        res <- ZIO.fromFuture { implicit ec =>
                val all = Source.fromGraph(GraphDSL.create() { implicit builder =>
                  import GraphDSL.Implicits._

                  val interleave = builder.add(Interleave[JsValue](4, 1))
                  featuresRes ~> interleave.in(0)
                  configsRes ~> interleave.in(1)
                  experimentsRes ~> interleave.in(2)
                  scriptsRes ~> interleave.in(3)

                  SourceShape(interleave.out)
                })
                all.take(10).runWith(Sink.seq) map { jsons =>
                  Ok(JsArray(jsons))
                }
              }
      } yield res
    }

} 
Example 102
Source File: EventsController.scala    From izanami   with Apache License 2.0 5 votes vote down vote up
package controllers

import akka.actor.ActorSystem
import controllers.actions.SecuredAuthContext
import domains.Domain.Domain
import domains.events.{EventStore, EventStoreContext}
import play.api.libs.EventSource
import play.api.libs.EventSource.{EventDataExtractor, EventIdExtractor, EventNameExtractor}
import play.api.libs.json.{JsString, Json}
import play.api.mvc.{AbstractController, ActionBuilder, AnyContent, ControllerComponents}
import libs.http.HttpContext
import akka.stream.scaladsl.Flow
import scala.util.Success
import scala.util.Failure
import libs.logs.IzanamiLogger
import java.time.LocalDateTime
import play.api.libs.json.JsValue
import scala.concurrent.duration.DurationDouble
import domains.auth.AuthInfo
import domains.Key

class EventsController(system: ActorSystem,
                       AuthAction: ActionBuilder[SecuredAuthContext, AnyContent],
                       cc: ControllerComponents)(implicit r: HttpContext[EventStoreContext])
    extends AbstractController(cc) {

  import libs.http._
  import domains.events.Events._
  import system.dispatcher

  private implicit val nameExtractor =
    EventNameExtractor[IzanamiEvent](_ => None) //Some(event.`type`))
  private implicit val idExtractor = EventIdExtractor[IzanamiEvent](event => Some(s"${event._id}")) //Some(event.key.key))
  private implicit val dataExtractor =
    EventDataExtractor[IzanamiEvent](event => Json.stringify(event.toJson))

  def allEvents(patterns: String, domains: String) =
    events(domains.split(",").toIndexedSeq, patterns)

  def eventsForADomain(domain: String, patterns: String) =
    events(domain.split(",").toIndexedSeq, patterns)

  val logEvent = Flow[IzanamiEvent].map { event =>
    event
  }

  case class KeepAliveEvent() extends IzanamiEvent {
    val _id: Long                          = 0
    val domain: Domain                     = domains.Domain.Unknown
    val authInfo: Option[AuthInfo.Service] = None
    val key: Key                           = Key("na")
    def timestamp: LocalDateTime           = LocalDateTime.now()
    val `type`: String                     = "KEEP_ALIVE"
    val payload: JsValue                   = Json.obj()
  }

  val keepAlive = Flow[IzanamiEvent].keepAlive(30.seconds, () => KeepAliveEvent())

  // TODO abilitations
  private def events[T <: IzanamiEvent](domains: Seq[String], patterns: String) =
    AuthAction.asyncTask[EventStoreContext] { ctx =>
      val allPatterns: Seq[String] = ctx.authorizedPatterns ++ patterns
        .split(",")
        .toList

      val lastEventId = ctx.request.headers.get("Last-Event-ID").map(_.toLong)
      val allDomains  = domains.map(JsString).flatMap(_.validate[Domain].asOpt)

      EventStore
        .events(allDomains, allPatterns, lastEventId)
        .map { source =>
          val eventSource = (source via keepAlive via logEvent via EventSource.flow).watchTermination() { (_, fDone) =>
            fDone.onComplete {
              case Success(_) =>
                IzanamiLogger.debug("SSE disconnected")
              case Failure(e) =>
                IzanamiLogger.error("Error during SSE ", e)
            }
            fDone
          }
          Ok.chunked(eventSource).as("text/event-stream")
        }
    }

} 
Example 103
Source File: OAuthController.scala    From izanami   with Apache License 2.0 5 votes vote down vote up
package controllers

import akka.util.ByteString
import com.auth0.jwt.algorithms.Algorithm
import controllers.dto.error.ApiErrors
import domains.auth.{OAuthModule, OAuthServiceModule, Oauth2Service}
import domains.user.User
import env.{Env, Oauth2Config}
import play.api.libs.json.Json
import play.api.mvc.{AbstractController, ControllerComponents, Cookie}
import zio.{Runtime, ZIO}
import libs.http.HttpContext

class OAuthController(_env: Env, mayBeOauth2Config: Option[Oauth2Config], cc: ControllerComponents)(
    implicit R: HttpContext[OAuthServiceModule]
) extends AbstractController(cc) {

  import libs.http._

  lazy val _config = _env.izanamiConfig.filter match {
    case env.Default(config) => config
    case _                   => throw new RuntimeException("Wrong config")
  }
  lazy val algorithm: Algorithm = Algorithm.HMAC512(_config.sharedKey)

  def appLoginPage() = Action { implicit request =>
    mayBeOauth2Config match {
      case Some(openIdConnectConfig) =>
        val clientId     = openIdConnectConfig.clientId
        val responseType = "code"
        val scope        = openIdConnectConfig.scope.map(s => s"scope=${s}&").getOrElse("")
        val claims       = Option(openIdConnectConfig.claims).filterNot(_.isEmpty).map(v => s"claims=$v&").getOrElse("")
        val queryParam   = if (openIdConnectConfig.useCookie) "" else s"?desc=izanami"
        val redirectUri = if (_env.baseURL.startsWith("http")) {
          s"${_env.baseURL}/${controllers.routes.OAuthController.appCallback().url}${queryParam}"
        } else {
          s"${controllers.routes.OAuthController.appCallback().absoluteURL()}${queryParam}"
        }
        val loginUrl =
          s"${openIdConnectConfig.loginUrl}?${scope}&${claims}client_id=$clientId&response_type=$responseType&redirect_uri=$redirectUri"
        Redirect(loginUrl)
      case None => BadRequest(Json.toJson(ApiErrors.error("Open Id Connect module not configured")))
    }
  }

  def appLogout() = Action { req =>
    val redirectToOpt: Option[String] = req.queryString.get("redirectTo").map(_.last)
    redirectToOpt match {
      case Some(redirectTo) =>
        Redirect(redirectTo).discardingCookies()
      case _ =>
        BadRequest(Json.toJson(ApiErrors.error("Missing parameters")))
    }
  }

  def appCallback() = Action.asyncZio[OAuthServiceModule] { implicit ctx =>
    mayBeOauth2Config match {
      case Some(openIdConnectConfig) =>
        Oauth2Service
          .paCallback(_env.baseURL, openIdConnectConfig)
          .map { user =>
            Redirect(controllers.routes.HomeController.index())
              .withCookies(Cookie(name = _env.cookieName, value = User.buildToken(user, _config.issuer, algorithm)))
          }
          .mapError { err =>
            BadRequest(Json.toJson(ApiErrors.fromErrors(err.toList)))
          }

      case None => ZIO.succeed(BadRequest(Json.toJson(ApiErrors.error("Open Id Connect module not configured"))))
    }
  }

} 
Example 104
Source File: BackOfficeController.scala    From izanami   with Apache License 2.0 5 votes vote down vote up
package controllers

import ch.qos.logback.classic.{Level, LoggerContext}
import controllers.actions.SecuredAuthContext
import domains.user.User
import org.slf4j.LoggerFactory
import play.api.libs.json.{JsArray, Json}
import play.api.mvc.{AbstractController, ActionBuilder, AnyContent, ControllerComponents}

class BackOfficeController(AuthAction: ActionBuilder[SecuredAuthContext, AnyContent], cc: ControllerComponents)
    extends AbstractController(cc) {

  def changeLogLevel(name: String, newLevel: Option[String]) = AuthAction { ctx =>
    if (isAdmin(ctx)) {
      val loggerContext =
        LoggerFactory.getILoggerFactory.asInstanceOf[LoggerContext]
      val _logger = loggerContext.getLogger(name)
      val oldLevel =
        Option(_logger.getLevel).map(_.levelStr).getOrElse(Level.OFF.levelStr)
      _logger.setLevel(newLevel.map(v => Level.valueOf(v)).getOrElse(Level.ERROR))
      Ok(Json.obj("name" -> name, "oldLevel" -> oldLevel, "newLevel" -> _logger.getLevel.levelStr))
    } else {
      Unauthorized
    }
  }

  def getLogLevel(name: String) = AuthAction { ctx =>
    if (isAdmin(ctx)) {
      val loggerContext =
        LoggerFactory.getILoggerFactory.asInstanceOf[LoggerContext]
      val _logger = loggerContext.getLogger(name)
      Ok(Json.obj("name" -> name, "level" -> _logger.getLevel.levelStr))
    } else {
      Unauthorized
    }
  }

  def getAllLoggers() = AuthAction { ctx =>
    if (isAdmin(ctx)) {
      import scala.jdk.CollectionConverters._
      val loggerContext =
        LoggerFactory.getILoggerFactory.asInstanceOf[LoggerContext]
      val rawLoggers = loggerContext.getLoggerList.asScala.toIndexedSeq
      val loggers = JsArray(rawLoggers.map(logger => {
        val level: String =
          Option(logger.getLevel).map(_.levelStr).getOrElse("OFF")
        Json.obj("name" -> logger.getName, "level" -> level)
      }))
      Ok(loggers)
    } else {
      Unauthorized
    }
  }

  private def isAdmin(ctx: SecuredAuthContext[AnyContent]) =
    ctx.auth.exists {
      case u: User => u.admin
      case _       => false
    }

} 
Example 105
Source File: HealthCheckController.scala    From izanami   with Apache License 2.0 5 votes vote down vote up
package controllers

import controllers.actions.AuthContext
import controllers.dto.error.ApiErrors
import domains.configuration.GlobalContext
import play.api.libs.json.Json
import play.api.mvc.{AbstractController, ActionBuilder, AnyContent, ControllerComponents}
import store.Healthcheck
import libs.http.HttpContext

class HealthCheckController(
    AuthAction: ActionBuilder[AuthContext, AnyContent],
    cc: ControllerComponents
)(implicit R: HttpContext[GlobalContext])
    extends AbstractController(cc) {

  import libs.http._

  def check() = AuthAction.asyncZio[GlobalContext] { _ =>
    Healthcheck
      .check()
      .map(_ => Ok(Json.obj()))
      .mapError { ApiErrors.toHttpResult }
  }

}