play.api.Logger Scala Examples

The following examples show how to use play.api.Logger. 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: DateTimeTools.scala    From pertax-frontend   with Apache License 2.0 9 votes vote down vote up
package util

import com.google.inject.{Inject, Singleton}
import org.joda.time.format.{DateTimeFormat, DateTimeFormatter}
import org.joda.time.{DateTime, _}
import play.api.Logger
import uk.gov.hmrc.time.CurrentTaxYear

import scala.util.{Failure, Success, Try}

import java.time.{LocalDateTime => JavaLDT}

object DateTimeTools extends CurrentTaxYear {

  //Timezone causing problem on dev server
  val defaultTZ = DateTimeZone.forID("Europe/London")
  val unixDateFormat = "yyyy-MM-dd"
  val unixDateTimeFormat = "yyyy-MM-dd'T'HH:mm:ss"
  val humanDateFormat = "dd MMMMM yyyy"

  //Returns for example 1516 in March 2016
  def previousAndCurrentTaxYear = previousAndCurrentTaxYearFromGivenYear(current.currentYear)

  def previousAndCurrentTaxYearFromGivenYear(year: Int) = {
    def y = year

    (y - 1).toString.takeRight(2) + (y).toString.takeRight(2)
  }

  private def formatter(pattern: String): DateTimeFormatter = DateTimeFormat.forPattern(pattern).withZone(defaultTZ)

  def short(dateTime: LocalDate) = formatter("dd/MM/yyy").print(dateTime)

  def asHumanDateFromUnixDate(unixDate: String): String =
    Try(DateTimeFormat.forPattern(humanDateFormat).print(DateTime.parse(unixDate))) match {
      case Success(v) => v
      case Failure(e) => {
        Logger.warn("Invalid date parse in DateTimeTools.asHumanDateFromUnixDate: " + e)
        unixDate
      }
    }

  def toPaymentDate(dateTime: JavaLDT): LocalDate =
    new LocalDate(dateTime.getYear, dateTime.getMonthValue, dateTime.getDayOfMonth)

  override def now: () => DateTime = DateTime.now
}

@Singleton
class DateTimeTools @Inject()() {

  def showSendTaxReturnByPost = {

    val start = new DateTime(s"${DateTime.now().getYear}-11-01T00:00:00Z")
    val end = new DateTime(s"${DateTime.now().getYear + 1}-01-31T23:59:59Z")
    !DateTime.now().isAfter(start) && DateTime.now().isBefore(end)
  }
} 
Example 2
Source File: PreferencesFrontendService.scala    From pertax-frontend   with Apache License 2.0 6 votes vote down vote up
package services

import com.kenshoo.play.metrics.Metrics
import config.ConfigDecorator
import controllers.auth.requests.UserRequest
import com.google.inject.{Inject, Singleton}
import metrics.HasMetrics
import models.{ActivatePaperlessActivatedResponse, ActivatePaperlessNotAllowedResponse, ActivatePaperlessRequiresUserActionResponse, ActivatePaperlessResponse}
import play.api.Mode.Mode
import play.api.i18n.{I18nSupport, Messages, MessagesApi}
import play.api.libs.json.{JsObject, Json}
import play.api.{Configuration, Environment, Logger}
import uk.gov.hmrc.play.bootstrap.http.DefaultHttpClient
import uk.gov.hmrc.crypto.PlainText
import uk.gov.hmrc.play.bootstrap.config.ServicesConfig
import uk.gov.hmrc.play.bootstrap.filters.frontend.crypto.SessionCookieCrypto
import uk.gov.hmrc.play.partials.HeaderCarrierForPartialsConverter
import util.Tools

import scala.concurrent.{ExecutionContext, Future}

@Singleton
class PreferencesFrontendService @Inject()(
  environment: Environment,
  runModeConfiguration: Configuration,
  val simpleHttp: DefaultHttpClient,
  val messagesApi: MessagesApi,
  val metrics: Metrics,
  val configDecorator: ConfigDecorator,
  val sessionCookieCrypto: SessionCookieCrypto,
  val tools: Tools,
  servicesConfig: ServicesConfig)(implicit ec: ExecutionContext)
    extends HeaderCarrierForPartialsConverter with HasMetrics with I18nSupport {

  val mode: Mode = environment.mode
  val preferencesFrontendUrl = servicesConfig.baseUrl("preferences-frontend")

  override def crypto: String => String = cookie => cookie
  def getPaperlessPreference()(implicit request: UserRequest[_]): Future[ActivatePaperlessResponse] = {

    def absoluteUrl = configDecorator.pertaxFrontendHost + request.uri

    def activatePaperless: Future[ActivatePaperlessResponse] =
      withMetricsTimer("get-activate-paperless") { timer =>
        val url =
          s"$preferencesFrontendUrl/paperless/activate?returnUrl=${tools.encryptAndEncode(absoluteUrl)}&returnLinkText=${tools
            .encryptAndEncode(Messages("label.continue"))}" //TODO remove ref to Messages
        simpleHttp.PUT[JsObject, ActivatePaperlessResponse](url, Json.obj("active" -> true)) map {

          case ActivatePaperlessActivatedResponse =>
            timer.completeTimerAndIncrementSuccessCounter()
            ActivatePaperlessActivatedResponse

          case response: ActivatePaperlessRequiresUserActionResponse =>
            timer.completeTimerAndIncrementSuccessCounter()
            response

          case ActivatePaperlessNotAllowedResponse =>
            timer.completeTimerAndIncrementFailedCounter()
            ActivatePaperlessNotAllowedResponse
        } recover {
          case e =>
            timer.completeTimerAndIncrementFailedCounter()
            Logger.warn("Error getting paperless preference record from preferences-frontend-service", e)
            ActivatePaperlessNotAllowedResponse
        }
      }

    if (request.isGovernmentGateway) {
      activatePaperless
    } else {
      Future.successful(ActivatePaperlessNotAllowedResponse)
    }
  }

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

import com.google.inject.Inject
import controllers.auth.SessionAuditor._
import controllers.auth.requests.AuthenticatedRequest
import play.api.Logger
import play.api.libs.json.{Format, Json}
import play.api.mvc.Result
import uk.gov.hmrc.auth.core.retrieve.Credentials
import uk.gov.hmrc.auth.core.{ConfidenceLevel, Enrolment}
import uk.gov.hmrc.domain.{Nino, SaUtr}
import uk.gov.hmrc.http.HeaderCarrier
import uk.gov.hmrc.play.audit.http.connector.AuditConnector
import uk.gov.hmrc.play.audit.http.connector.AuditResult.{Failure, Success}
import uk.gov.hmrc.play.audit.model.ExtendedDataEvent
import util.AuditServiceTools

import scala.concurrent.{ExecutionContext, Future}

private[auth] class SessionAuditor @Inject()(auditConnector: AuditConnector)(implicit ec: ExecutionContext)
    extends AuditTags {

  val logger = Logger(this.getClass)

  def auditOnce[A](request: AuthenticatedRequest[A], result: Result)(implicit hc: HeaderCarrier): Future[Result] =
    request.session.get(sessionKey) match {
      case None =>
        logger.info(request.profile.toString)

        val eventDetail = UserSessionAuditEvent(request)

        val sendAuditEvent = auditConnector
          .sendExtendedEvent(
            ExtendedDataEvent(
              auditSource = AuditServiceTools.auditSource,
              auditType = auditType,
              detail = Json.toJson(eventDetail),
              tags = buildTags(request))
          )
          .recover {
            case e: Exception =>
              Logger.warn(s"Unable to audit: ${e.getMessage}")
              Failure("UserSessionAuditor.auditOncePerSession exception occurred whilst auditing", Some(e))
          }

        sendAuditEvent.map {
          case Success => result.addingToSession(sessionKey -> "true")(request)
          case _       => result
        }

      case _ => Future.successful(result)
    }
}

object SessionAuditor {

  val sessionKey = "sessionAudited"
  val auditType = "user-session-visit"

  case class UserSessionAuditEvent(
    nino: Option[Nino],
    credentials: Credentials,
    confidenceLevel: ConfidenceLevel,
    name: Option[String],
    saUtr: Option[SaUtr],
    allEnrolments: Set[Enrolment])

  object UserSessionAuditEvent {

    def apply[A](request: AuthenticatedRequest[A]): UserSessionAuditEvent = {
      val nino = request.nino
      val credentials = request.credentials
      val confidenceLevel = request.confidenceLevel
      val name = request.name map (_.toString)
      val saUtr = request.saEnrolment map (_.saUtr)
      val enrolments = request.enrolments

      UserSessionAuditEvent(nino, credentials, confidenceLevel, name, saUtr, enrolments)
    }

    implicit val credentialsFormats = Json.format[Credentials]
    implicit val formats: Format[UserSessionAuditEvent] = Json.format[UserSessionAuditEvent]
  }

} 
Example 4
Source File: ActivatePaperlessResponse.scala    From pertax-frontend   with Apache License 2.0 5 votes vote down vote up
package models

import play.api.Logger
import play.api.http.Status._
import uk.gov.hmrc.http.{HttpReads, HttpResponse}

sealed trait ActivatePaperlessResponse
case object ActivatePaperlessActivatedResponse extends ActivatePaperlessResponse
case object ActivatePaperlessNotAllowedResponse extends ActivatePaperlessResponse
case class ActivatePaperlessRequiresUserActionResponse(redirectUrl: String) extends ActivatePaperlessResponse

object ActivatePaperlessResponse {

  implicit lazy val httpReads: HttpReads[ActivatePaperlessResponse] =
    new HttpReads[ActivatePaperlessResponse] {
      override def read(method: String, url: String, response: HttpResponse): ActivatePaperlessResponse =
        response.status match {
          case r if r >= 200 && r < 300 =>
            ActivatePaperlessActivatedResponse

          case PRECONDITION_FAILED =>
            val redirectUrl = (response.json \ "redirectUserTo")
            Logger.warn(
              "Precondition failed when getting paperless preference record from preferences-frontend-service")
            ActivatePaperlessRequiresUserActionResponse(redirectUrl.as[String])

          case r =>
            Logger.warn(s"Unexpected $r response getting paperless preference record from preferences-frontend-service")
            ActivatePaperlessNotAllowedResponse
        }
    }

} 
Example 5
Source File: AddressLookupService.scala    From pertax-frontend   with Apache License 2.0 5 votes vote down vote up
package services

import com.kenshoo.play.metrics.Metrics
import config.ConfigDecorator
import com.google.inject.{Inject, Singleton}
import metrics._
import models.addresslookup.RecordSet
import play.api.Mode.Mode
import play.api.{Configuration, Environment, Logger}
import services.http.SimpleHttp
import uk.gov.hmrc.http.{HeaderCarrier, HttpResponse}
import uk.gov.hmrc.play.bootstrap.config.ServicesConfig
import util._

import scala.concurrent.Future

sealed trait AddressLookupResponse

final case class AddressLookupSuccessResponse(addressList: RecordSet) extends AddressLookupResponse
final case class AddressLookupUnexpectedResponse(r: HttpResponse) extends AddressLookupResponse
final case class AddressLookupErrorResponse(cause: Exception) extends AddressLookupResponse

@Singleton
class AddressLookupService @Inject()(
  environment: Environment,
  configuration: Configuration,
  configDecorator: ConfigDecorator,
  val simpleHttp: SimpleHttp,
  val metrics: Metrics,
  val tools: Tools,
  servicesConfig: ServicesConfig)
    extends HasMetrics {

  val mode: Mode = environment.mode
  val runModeConfiguration: Configuration = configuration
  lazy val addressLookupUrl = servicesConfig.baseUrl("address-lookup")

  def lookup(postcode: String, filter: Option[String] = None)(
    implicit hc: HeaderCarrier): Future[AddressLookupResponse] =
    withMetricsTimer("address-lookup") { t =>
      val hn = tools.urlEncode(filter.getOrElse(""))
      val pc = postcode.replaceAll(" ", "")
      val newHc = hc.withExtraHeaders("X-Hmrc-Origin" -> configDecorator.origin)

      simpleHttp.get[AddressLookupResponse](s"$addressLookupUrl/v1/gb/addresses.json?postcode=$pc&filter=$hn")(
        onComplete = {
          case r if r.status >= 200 && r.status < 300 =>
            t.completeTimerAndIncrementSuccessCounter()
            AddressLookupSuccessResponse(RecordSet.fromJsonAddressLookupService(r.json))

          case r =>
            t.completeTimerAndIncrementFailedCounter()
            Logger.warn(s"Unexpected ${r.status} response getting address record from address lookup service")
            AddressLookupUnexpectedResponse(r)
        },
        onError = {
          case e =>
            t.completeTimerAndIncrementFailedCounter()
            Logger.warn("Error getting address record from address lookup service", e)
            AddressLookupErrorResponse(e)
        }
      )(newHc)
    }
} 
Example 6
Source File: TaxCalculationService.scala    From pertax-frontend   with Apache License 2.0 5 votes vote down vote up
package services

import com.kenshoo.play.metrics.Metrics
import com.google.inject.{Inject, Singleton}
import metrics._
import models.{TaxCalculation, TaxYearReconciliation}
import play.api.Mode.Mode
import play.api.http.Status._
import play.api.{Configuration, Environment, Logger}
import services.http.SimpleHttp
import uk.gov.hmrc.domain.Nino
import uk.gov.hmrc.http.{HeaderCarrier, HttpResponse}
import uk.gov.hmrc.play.bootstrap.config.ServicesConfig
import uk.gov.hmrc.play.bootstrap.http.HttpClient

import scala.concurrent.{ExecutionContext, Future}
import scala.util.control.NonFatal

sealed trait TaxCalculationResponse
case class TaxCalculationSuccessResponse(taxCalculation: TaxCalculation) extends TaxCalculationResponse
case object TaxCalculationNotFoundResponse extends TaxCalculationResponse
case class TaxCalculationUnexpectedResponse(r: HttpResponse) extends TaxCalculationResponse
case class TaxCalculationErrorResponse(cause: Exception) extends TaxCalculationResponse
@Singleton
class TaxCalculationService @Inject()(
  environment: Environment,
  configuration: Configuration,
  val simpleHttp: SimpleHttp,
  val metrics: Metrics,
  val http: HttpClient,
  servicesConfig: ServicesConfig)(implicit ec: ExecutionContext)
    extends HasMetrics {
  val mode: Mode = environment.mode
  val runModeConfiguration: Configuration = configuration
  lazy val taxCalcUrl = servicesConfig.baseUrl("taxcalc")

  
  def getTaxCalculation(nino: Nino, year: Int)(implicit hc: HeaderCarrier): Future[TaxCalculationResponse] =
    withMetricsTimer("get-taxcalc-summary") { t =>
      simpleHttp.get[TaxCalculationResponse](s"$taxCalcUrl/taxcalc/$nino/taxSummary/$year")(
        onComplete = {

          case r if r.status >= 200 && r.status < 300 =>
            Logger.debug(r.body)
            t.completeTimerAndIncrementSuccessCounter()
            TaxCalculationSuccessResponse(r.json.as[TaxCalculation])

          case r if r.status == NOT_FOUND =>
            Logger.debug(r.body)
            t.completeTimerAndIncrementSuccessCounter()
            TaxCalculationNotFoundResponse

          case r =>
            Logger.debug(r.body)
            t.completeTimerAndIncrementFailedCounter()
            Logger.debug(s"Unexpected ${r.status} response getting tax calculation from tax-calculation-service")
            TaxCalculationUnexpectedResponse(r)
        },
        onError = { e =>
          Logger.debug(e.toString)
          t.completeTimerAndIncrementFailedCounter()
          Logger.warn("Error getting tax calculation from tax-calculation-service", e)
          TaxCalculationErrorResponse(e)
        }
      )
    }

  def getTaxYearReconciliations(nino: Nino)(
    implicit headerCarrier: HeaderCarrier): Future[List[TaxYearReconciliation]] =
    http
      .GET[List[TaxYearReconciliation]](s"$taxCalcUrl/taxcalc/$nino/reconciliations")
      .recover {
        case NonFatal(e) =>
          Logger.debug(s"An exception was thrown by taxcalc reconciliations: ${e.getMessage}")
          Nil
      }
} 
Example 7
Source File: IdentityVerificationFrontendService.scala    From pertax-frontend   with Apache License 2.0 5 votes vote down vote up
package services

import com.kenshoo.play.metrics.Metrics
import com.google.inject.{Inject, Singleton}
import metrics.HasMetrics
import play.api.Mode.Mode
import play.api.http.Status._
import play.api.{Configuration, Environment, Logger}
import services.http.SimpleHttp
import uk.gov.hmrc.http.{HeaderCarrier, HttpResponse}
import uk.gov.hmrc.play.bootstrap.config.ServicesConfig

import scala.concurrent.Future

trait IdentityVerificationResponse
case class IdentityVerificationSuccessResponse(result: String) extends IdentityVerificationResponse
case object IdentityVerificationNotFoundResponse extends IdentityVerificationResponse
case class IdentityVerificationUnexpectedResponse(r: HttpResponse) extends IdentityVerificationResponse
case class IdentityVerificationErrorResponse(cause: Exception) extends IdentityVerificationResponse

object IdentityVerificationSuccessResponse {
  val Success = "Success"
  val Incomplete = "Incomplete"
  val FailedMatching = "FailedMatching"
  val InsufficientEvidence = "InsufficientEvidence"
  val LockedOut = "LockedOut"
  val UserAborted = "UserAborted"
  val Timeout = "Timeout"
  val TechnicalIssue = "TechnicalIssue"
  val PrecondFailed = "PreconditionFailed"
}
@Singleton
class IdentityVerificationFrontendService @Inject()(
  environment: Environment,
  configuration: Configuration,
  val simpleHttp: SimpleHttp,
  val metrics: Metrics,
  servicesConfig: ServicesConfig)
    extends HasMetrics {

  val mode: Mode = environment.mode
  val runModeConfiguration: Configuration = configuration
  lazy val identityVerificationFrontendUrl: String = servicesConfig.baseUrl("identity-verification-frontend")

  def getIVJourneyStatus(journeyId: String)(implicit hc: HeaderCarrier): Future[IdentityVerificationResponse] =
    withMetricsTimer("get-iv-journey-status") { t =>
      simpleHttp.get[IdentityVerificationResponse](
        s"$identityVerificationFrontendUrl/mdtp/journey/journeyId/$journeyId")(
        onComplete = {
          case r if r.status >= 200 && r.status < 300 =>
            t.completeTimerAndIncrementSuccessCounter()
            val result = List((r.json \ "journeyResult").asOpt[String], (r.json \ "result").asOpt[String]).flatten.head //FIXME - dont use head
            IdentityVerificationSuccessResponse(result)

          case r if r.status == NOT_FOUND =>
            t.completeTimerAndIncrementFailedCounter()
            Logger.warn("Unable to get IV journey status from identity-verification-frontend-service")
            IdentityVerificationNotFoundResponse

          case r =>
            t.completeTimerAndIncrementFailedCounter()
            Logger.warn(
              s"Unexpected ${r.status} response getting IV journey status from identity-verification-frontend-service")
            IdentityVerificationUnexpectedResponse(r)
        },
        onError = {
          case e =>
            t.completeTimerAndIncrementFailedCounter()
            Logger.warn("Error getting IV journey status from identity-verification-frontend-service", e)
            IdentityVerificationErrorResponse(e)
        }
      )

    }
} 
Example 8
Source File: LifetimeAllowanceService.scala    From pertax-frontend   with Apache License 2.0 5 votes vote down vote up
package services

import com.kenshoo.play.metrics.Metrics
import com.google.inject.{Inject, Singleton}
import metrics.HasMetrics
import models.LtaProtections
import play.api.Mode.Mode
import play.api.{Configuration, Environment, Logger}
import services.http.SimpleHttp
import uk.gov.hmrc.domain.Nino
import uk.gov.hmrc.http.{HeaderCarrier, HttpReads}
import uk.gov.hmrc.play.bootstrap.config.ServicesConfig

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
@Singleton
class LifetimeAllowanceService @Inject()(
  environment: Environment,
  configuration: Configuration,
  val simpleHttp: SimpleHttp,
  val metrics: Metrics,
  servicesConfig: ServicesConfig)
    extends HasMetrics {

  val mode: Mode = environment.mode
  val runModeConfiguration: Configuration = configuration
  lazy val lifetimeAllowanceUrl = servicesConfig.baseUrl("pensions-lifetime-allowance")

  def getCount(nino: Nino)(implicit hc: HeaderCarrier, rds: HttpReads[LtaProtections]): Future[Option[Int]] =
    withMetricsTimer("has-lta-response") { t =>
      simpleHttp.get[Option[Int]](
        lifetimeAllowanceUrl + s"/protect-your-lifetime-allowance/individuals/$nino/protections/count")(
        onComplete = {
          case r if r.status >= 200 && r.status < 300 =>
            t.completeTimerAndIncrementSuccessCounter()
            Some((r.json.as[LtaProtections]).count)

          case r =>
            t.completeTimerAndIncrementFailedCounter()
            Logger.warn(
              s"Unexpected ${r.status} response getting lifetime allowance protections count from LTA service")
            None
        },
        onError = {
          case e =>
            t.completeTimerAndIncrementFailedCounter()
            Logger.warn("Error getting lifetime allowance protections count from LTA service", e)
            None
        }
      )
    }

  def hasLtaProtection(nino: Nino)(implicit hc: HeaderCarrier, rds: HttpReads[LtaProtections]): Future[Boolean] =
    getCount(nino) map {
      case (Some(0) | None) => false
      case _                => true
    }
} 
Example 9
Source File: EnrolmentStoreCachingService.scala    From pertax-frontend   with Apache License 2.0 5 votes vote down vote up
package services

import com.google.inject.Inject
import connectors.EnrolmentsConnector
import models.{NonFilerSelfAssessmentUser, NotEnrolledSelfAssessmentUser, SelfAssessmentUserType, WrongCredentialsSelfAssessmentUser}
import play.api.Logger
import uk.gov.hmrc.domain.SaUtr
import uk.gov.hmrc.http.HeaderCarrier

import scala.concurrent.{ExecutionContext, Future}

class EnrolmentStoreCachingService @Inject()(
  val sessionCache: LocalSessionCache,
  enrolmentsConnector: EnrolmentsConnector) {

  private def addSaUserTypeToCache(
    user: SelfAssessmentUserType)(implicit hc: HeaderCarrier, ec: ExecutionContext): Future[SelfAssessmentUserType] =
    sessionCache.cache[SelfAssessmentUserType](SelfAssessmentUserType.cacheId, user).map(_ => user)

  def getSaUserTypeFromCache(
    saUtr: SaUtr)(implicit hc: HeaderCarrier, ec: ExecutionContext): Future[SelfAssessmentUserType] =
    sessionCache.fetchAndGetEntry[SelfAssessmentUserType](SelfAssessmentUserType.cacheId).flatMap {

      case Some(user) => Future.successful(user)

      case _ =>
        enrolmentsConnector
          .getUserIdsWithEnrolments(saUtr.utr)
          .flatMap[SelfAssessmentUserType](
            (response: Either[String, Seq[String]]) =>
              response.fold(
                error => {
                  Logger.warn(error)
                  addSaUserTypeToCache(NonFilerSelfAssessmentUser)
                },
                ids =>
                  if (ids.nonEmpty) {
                    addSaUserTypeToCache(WrongCredentialsSelfAssessmentUser(saUtr))
                  } else {
                    addSaUserTypeToCache(NotEnrolledSelfAssessmentUser(saUtr))
                }
            )
          )
    }

} 
Example 10
Source File: TaiService.scala    From pertax-frontend   with Apache License 2.0 5 votes vote down vote up
package services

import com.kenshoo.play.metrics.Metrics
import com.google.inject.{Inject, Singleton}
import metrics._
import models._
import play.api.Mode.Mode
import play.api.http.Status._
import play.api.{Configuration, Environment, Logger}
import services.http.SimpleHttp
import uk.gov.hmrc.domain.Nino
import uk.gov.hmrc.http.{HeaderCarrier, HttpResponse}
import uk.gov.hmrc.play.bootstrap.config.ServicesConfig

import scala.concurrent.Future

sealed trait TaxComponentsResponse
case class TaxComponentsSuccessResponse(taxComponents: TaxComponents) extends TaxComponentsResponse
case object TaxComponentsUnavailableResponse extends TaxComponentsResponse
case class TaxComponentsUnexpectedResponse(r: HttpResponse) extends TaxComponentsResponse
case class TaxComponentsErrorResponse(cause: Exception) extends TaxComponentsResponse
@Singleton
class TaiService @Inject()(
  environment: Environment,
  runModeConfiguration: Configuration,
  val simpleHttp: SimpleHttp,
  val metrics: Metrics,
  servicesConfig: ServicesConfig)
    extends HasMetrics {

  val mode: Mode = environment.mode
  lazy val taiUrl = servicesConfig.baseUrl("tai")

  
  def taxComponents(nino: Nino, year: Int)(implicit hc: HeaderCarrier): Future[TaxComponentsResponse] =
    withMetricsTimer("get-tax-components") { t =>
      simpleHttp.get[TaxComponentsResponse](s"$taiUrl/tai/$nino/tax-account/$year/tax-components")(
        onComplete = {
          case r if r.status >= 200 && r.status < 300 =>
            t.completeTimerAndIncrementSuccessCounter()
            TaxComponentsSuccessResponse(TaxComponents.fromJsonTaxComponents(r.json))

          case r if r.status == NOT_FOUND | r.status == BAD_REQUEST =>
            t.completeTimerAndIncrementSuccessCounter()
            Logger.warn("Unable to find tax components from the tai-service")
            TaxComponentsUnavailableResponse

          case r =>
            t.completeTimerAndIncrementFailedCounter()
            Logger.warn(s"Unexpected ${r.status} response getting tax components from the tai-service")
            TaxComponentsUnexpectedResponse(r)
        },
        onError = {
          case e =>
            t.completeTimerAndIncrementFailedCounter()
            Logger.error("Error getting tax components from the tai-service", e)
            TaxComponentsErrorResponse(e)
        }
      )
    }
} 
Example 11
Source File: MessageFrontendService.scala    From pertax-frontend   with Apache License 2.0 5 votes vote down vote up
package services.partials

import com.google.inject.{Inject, Singleton}
import com.kenshoo.play.metrics.Metrics
import metrics.HasMetrics
import models.MessageCount
import play.api.Mode.Mode
import play.api.mvc.RequestHeader
import play.api.{Configuration, Environment, Logger}
import uk.gov.hmrc.http.HeaderCarrier
import uk.gov.hmrc.play.bootstrap.config.ServicesConfig
import uk.gov.hmrc.play.bootstrap.filters.frontend.crypto.SessionCookieCrypto
import uk.gov.hmrc.play.bootstrap.http.HttpClient
import uk.gov.hmrc.play.partials.HtmlPartial
import util.EnhancedPartialRetriever

import scala.concurrent.{ExecutionContext, Future}

@Singleton
class MessageFrontendService @Inject()(
  environment: Environment,
  runModeConfiguration: Configuration,
  override val http: HttpClient,
  val metrics: Metrics,
  val sessionCookieCrypto: SessionCookieCrypto,
  servicesConfig: ServicesConfig)(implicit executionContext: ExecutionContext)
    extends EnhancedPartialRetriever(sessionCookieCrypto) with HasMetrics {

  val mode: Mode = environment.mode

  lazy val messageFrontendUrl: String = servicesConfig.baseUrl("message-frontend")

  def getMessageListPartial(implicit request: RequestHeader): Future[HtmlPartial] =
    loadPartial(messageFrontendUrl + "/messages")

  def getMessageDetailPartial(messageToken: String)(implicit request: RequestHeader): Future[HtmlPartial] =
    loadPartial(messageFrontendUrl + "/messages/" + messageToken)

  def getMessageInboxLinkPartial(implicit request: RequestHeader): Future[HtmlPartial] =
    loadPartial(
      messageFrontendUrl + "/messages/inbox-link?messagesInboxUrl=" + controllers.routes.MessageController
        .messageList())

  def getUnreadMessageCount(implicit request: RequestHeader): Future[Option[Int]] =
    loadJson(messageFrontendUrl + "/messages/count?read=No").map(_.map(_.count))

  private def loadJson(url: String)(implicit hc: HeaderCarrier): Future[Option[MessageCount]] =
    withMetricsTimer("load-json") { t =>
      http.GET[Option[MessageCount]](url) recover {
        case e =>
          t.completeTimerAndIncrementFailedCounter()
          Logger.warn(s"Failed to load json", e)
          None
      }
    }
} 
Example 12
Source File: PaymentsController.scala    From pertax-frontend   with Apache License 2.0 5 votes vote down vote up
package controllers

import config.ConfigDecorator
import connectors.PayApiConnector
import controllers.auth.{AuthJourney, WithBreadcrumbAction}
import error.RendersErrors
import com.google.inject.Inject
import models.{NonFilerSelfAssessmentUser, PaymentRequest, SelfAssessmentUser}
import org.joda.time.DateTime
import play.api.Logger
import play.api.mvc.{Action, AnyContent, MessagesControllerComponents}
import uk.gov.hmrc.renderer.TemplateRenderer
import uk.gov.hmrc.time.CurrentTaxYear
import util.LocalPartialRetriever

import scala.concurrent.ExecutionContext

class PaymentsController @Inject()(
  val payApiConnector: PayApiConnector,
  authJourney: AuthJourney,
  withBreadcrumbAction: WithBreadcrumbAction,
  cc: MessagesControllerComponents)(
  implicit partialRetriever: LocalPartialRetriever,
  configDecorator: ConfigDecorator,
  val templateRenderer: TemplateRenderer,
  ec: ExecutionContext)
    extends PertaxBaseController(cc) with CurrentTaxYear with RendersErrors {

  override def now: () => DateTime = () => DateTime.now()

  def makePayment: Action[AnyContent] =
    (authJourney.authWithPersonalDetails andThen withBreadcrumbAction.addBreadcrumb(baseBreadcrumb)).async {
      implicit request =>
        if (request.isSa) {
          request.saUserType match {
            case saUser: SelfAssessmentUser => {
              val paymentRequest = PaymentRequest(configDecorator, saUser.saUtr.toString())
              for {
                response <- payApiConnector.createPayment(paymentRequest)
              } yield {
                response match {
                  case Some(createPayment) => Redirect(createPayment.nextUrl)
                  case None                => error(BAD_REQUEST)
                }
              }
            }
            case NonFilerSelfAssessmentUser => {
              Logger.warn("User had no sa account when one was required")
              futureError(INTERNAL_SERVER_ERROR)
            }
          }
        } else {
          Logger.warn("User had no sa account when one was required")
          futureError(INTERNAL_SERVER_ERROR)
        }
    }
} 
Example 13
Source File: EnhancedPartialRetriever.scala    From pertax-frontend   with Apache License 2.0 5 votes vote down vote up
package util

import com.google.inject.Inject
import metrics.HasMetrics
import play.api.Logger
import uk.gov.hmrc.http.{HeaderCarrier, HttpException, HttpGet}
import uk.gov.hmrc.play.bootstrap.filters.frontend.crypto.SessionCookieCrypto
import uk.gov.hmrc.play.partials.HtmlPartial._
import uk.gov.hmrc.play.partials.{HeaderCarrierForPartialsConverter, HtmlPartial}

import scala.concurrent.{ExecutionContext, Future}


abstract class EnhancedPartialRetriever @Inject()(sessionCookieCrypto: SessionCookieCrypto)(
  implicit executionContext: ExecutionContext)
    extends HeaderCarrierForPartialsConverter with HasMetrics {

  def http: HttpGet

  override def crypto: String => String = cookie => cookie

  def loadPartial(url: String)(implicit hc: HeaderCarrier): Future[HtmlPartial] =
    withMetricsTimer("load-partial") { timer =>
      http.GET[HtmlPartial](url) map {
        case partial: HtmlPartial.Success =>
          timer.completeTimerAndIncrementSuccessCounter()
          partial
        case partial: HtmlPartial.Failure =>
          timer.completeTimerAndIncrementFailedCounter()
          partial
      } recover {
        case e =>
          timer.completeTimerAndIncrementFailedCounter()
          Logger.warn(s"Failed to load partial", e)
          e match {
            case ex: HttpException =>
              HtmlPartial.Failure(Some(ex.responseCode))
            case _ =>
              HtmlPartial.Failure(None)
          }
      }

    }
} 
Example 14
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 15
Source File: CompaniesConfiguration.scala    From crm-seed   with Apache License 2.0 5 votes vote down vote up
package com.dataengi.crm.configurations

import com.google.inject.{Inject, Singleton}
import com.dataengi.crm.common.extensions.awaits._
import com.dataengi.crm.common.extensions.logging._
import play.api.{Configuration, Logger}
import scalty.types._
import cats.instances.all._
import com.dataengi.crm.identities.services.CompaniesService

import scala.concurrent.ExecutionContext

@Singleton
class CompaniesConfiguration @Inject()(configuration: Configuration, companiesService: CompaniesService, implicit val executionContext: ExecutionContext) {

  def loadRootCompany: Unit = {
    val addRootCompanyOr = for {
      rootCompanyOpt <- companiesService.findOption(CompaniesConfiguration.RootCompanyName)
      rootCompanyId <- rootCompanyOpt match {
        case Some(company) =>
          Logger.info(s"[com.dataengi.crm.identities-initiation][load-root-company] $company already exists")
          company.id.get.toOr
        case None =>
          Logger.info(s"[com.dataengi.crm.identities-initiation][load-root-company] creating ${CompaniesConfiguration.RootCompanyName}")
          companiesService.create(CompaniesConfiguration.RootCompanyName)

      }
    } yield rootCompanyId

    val addRootCompanyResult = addRootCompanyOr.await()
    Logger.info(s"[com.dataengi.crm.identities-initiation][load-root-company] ${addRootCompanyResult.logResult}")
  }

}

object CompaniesConfiguration {
  val RootCompanyName = "ROOT_COMPANY"
} 
Example 16
Source File: IdentitiesInitiation.scala    From crm-seed   with Apache License 2.0 5 votes vote down vote up
package com.dataengi.crm.identities.modules

import cats.instances.all._
import com.dataengi.crm.common.context.types._
import com.dataengi.crm.common.extensions.awaits._
import com.dataengi.crm.common.extensions.logging._
import com.dataengi.crm.configurations.{CompaniesConfiguration, RolesConfiguration, RootConfiguration}
import com.google.inject.{Inject, Singleton}
import play.api.Logger
import com.dataengi.crm.identities.daos.PasswordInfoDAO
import com.dataengi.crm.identities.services.{CompaniesService, RolesService}
import com.dataengi.crm.identities.modules.InitiationErrors._
import com.dataengi.crm.identities.repositories.UsersRepository

import scala.concurrent.ExecutionContext

@Singleton
class IdentitiesInitiation @Inject()(usersRepository: UsersRepository,
                                     passwordInfoDAO: PasswordInfoDAO,
                                     companiesService: CompaniesService,
                                     rolesService: RolesService,
                                     rolesConfiguration: RolesConfiguration,
                                     companiesConfiguration: CompaniesConfiguration,
                                     rootConfiguration: RootConfiguration,
                                     implicit val executionContext: ExecutionContext) {

  companiesConfiguration.loadRootCompany
  rolesConfiguration.loadBaseRoles

  val addRootUserResult: Or[Long] = for {
    rootCompany <- companiesService.findOption(CompaniesConfiguration.RootCompanyName).toOrWithLeft(RootCompanyNotFound)
    rootRole    <- rolesService.findOption(RolesConfiguration.Root).toOrWithLeft(RootRoleNotFound)
    rootUserOpt <- usersRepository.find(rootConfiguration.rootLoginInfo)
    saveRootUserResult <- rootUserOpt match {
      case Some(user) =>
        Logger.info(s"[com.dataengi.crm.identities-initiation][add-root] updating root user ${rootConfiguration.rootLoginInfo}")
        usersRepository
          .update(user.id.get, rootConfiguration.createRootUser(rootCompany, rootRole))
          .map(result => user.id.get)
      case None =>
        Logger.info(s"[com.dataengi.crm.identities-initiation][add-root] creating root user ${rootConfiguration.rootLoginInfo}")
        usersRepository.add(rootConfiguration.createRootUser(rootCompany, rootRole))
    }
    savePasswordInfoResult <- passwordInfoDAO.add(rootConfiguration.rootLoginInfo, rootConfiguration.rootPasswordInfo).toOr
  } yield saveRootUserResult

  val result = addRootUserResult.await()

  Logger.info(s"[com.dataengi.crm.identities-initiation][add-root] ${result.logResult}")

} 
Example 17
Source File: TablesInitiation.scala    From crm-seed   with Apache License 2.0 5 votes vote down vote up
package com.dataengi.crm.identities.slick.tables

import java.io.{File, FileWriter}

import play.api.{Configuration, Logger}
import play.api.db.slick.HasDatabaseConfigProvider
import slick.lifted.TableQuery
import com.dataengi.crm.common.context.types._
import com.dataengi.crm.common.extensions.awaits._
import com.dataengi.crm.common.extensions.logging._

import scala.concurrent.ExecutionContext

trait TablesInitiation extends HasDatabaseConfigProvider[slick.jdbc.JdbcProfile] {

  implicit val executionContext: ExecutionContext

  val configuration: Configuration

  val DDLTag: String = super.getClass.getSimpleName

  def printMigrationDDL(tables: List[slick.lifted.TableQuery[_ <: slick.relational.RelationalProfile#Table[_]]]) = {
    val allowPrintDDL = configuration.getOptional[Boolean]("play.db.ddl.print").getOrElse(false)
    Logger.info(s"[initiate-table][print-ddl] allowPrintDDL=$allowPrintDDL")
    if (allowPrintDDL) {
      createDDL(tables, DDLTag)
    }
  }

  private def createDDL(tables: List[TableQuery[_ <: slick.relational.RelationalProfile#Table[_]]], DDLPath: String) = {
    import profile.api._
    val schema    = tables.map(_.schema).reduce(_ ++ _)
    val directory = new File(s"./db/statements/${DDLPath}/")
    if (!directory.exists()) directory.mkdirs()
    val migrationFile = new File(directory.getPath + "/migration_ddl.sql")
    val writer        = new FileWriter(migrationFile.getAbsoluteFile)
    writer.write("# --- !Ups\n\n")
    schema.createStatements.foreach { s =>
      writer.write(s + ";\n")
    }
    writer.write("\n\n# --- !Downs\n\n")
    schema.dropStatements.foreach { s =>
      writer.write(s + ";\n")
    }
    writer.close()
  }

  def createTables(tables: List[slick.lifted.TableQuery[_ <: slick.relational.RelationalProfile#Table[_]]]) = {
    import profile.api._
    val allowCreateTables     = configuration.getOptional[Boolean]("play.db.create.dynamic").getOrElse(false)
    val printStatementsTables = configuration.getOptional[Boolean]("play.db.print.statements").getOrElse(false)
    Logger.info(s"[initiate-table][create] allowCreateTables=$allowCreateTables")
    if (allowCreateTables) {
      val schema             = tables.map(_.schema).reduce(_ ++ _)
      val schemaCreateResult = db.run(schema.create).toOr.await()
      if (printStatementsTables) Logger.info(s"[initiate-table][${DDLTag}] create query: ${schema.create.statements}")
      if (!List("already exist", "not found").exists(schemaCreateResult.logResult.contains)) {
        Logger.info(s"[initiate-table][${DDLTag}] create tables: ${schemaCreateResult.logResult}")
      }
    }
  }

} 
Example 18
Source File: KBModule.scala    From daf-semantics   with Apache License 2.0 5 votes vote down vote up
package modules

import javax.inject._

import play.api.inject.ApplicationLifecycle
import play.api.mvc._

import scala.concurrent.Future
import com.google.inject.ImplementedBy
import play.api.Play
import play.api.Application
import play.api.Environment
import play.api.Configuration
import scala.concurrent.ExecutionContext
import play.api.Logger
import it.almawave.linkeddata.kb.utils.ConfigHelper
import it.almawave.linkeddata.kb.repo._
import scala.concurrent.ExecutionContext.Implicits.global
import java.nio.file.Paths
import play.api.Mode
import java.io.File
import it.almawave.linkeddata.kb.repo.RDFRepository
import com.typesafe.config.ConfigFactory

@ImplementedBy(classOf[KBModuleBase])
trait KBModule

@Singleton
class KBModuleBase @Inject() (lifecycle: ApplicationLifecycle) extends KBModule {

  // TODO: SPI per dev / prod
  val kbrepo = RDFRepository.memory()

  val logger = Logger.underlyingLogger

  // when application starts...
  @Inject
  def onStart(
    env: Environment,
    configuration: Configuration)(implicit ec: ExecutionContext) {

    // get configs
    val app_type = configuration.underlying.getString("app.type")

    val data_dir = app_type match {
      case "dev"  => "./dist/data"
      case "prod" => "./data"
    }
    logger.debug(s"app_type: ${app_type}")
    logger.debug(s"data_dir: ${data_dir}")

    // starting VocabularyAPI service
    var conf_voc = ConfigFactory.parseFile(new File("./conf/semantic_repository.conf").getAbsoluteFile)
    conf_voc = ConfigHelper.injectParameters(conf_voc, ("data_dir", data_dir))

    kbrepo.configuration(conf_voc)

    logger.info("KBModule.START....")
    logger.debug("KBModule using configuration:\n" + ConfigHelper.pretty(conf_voc))

    println("KBModule using configuration:\n" + ConfigHelper.pretty(conf_voc))

    // this is needed for ensure proper connection(s) etc
    kbrepo.start()

    

    // CHECK the initial (total) triples count
    var triples = kbrepo.store.size()

    logger.info(s"KBModule> ${triples} triples loaded")

  }

  // when application stops...
  lifecycle.addStopHook({ () =>

    Future.successful {

      // this is useful for saving files, closing connections, release indexes, etc
      kbrepo.stop()
      logger.info("KBModule.STOP....")

    }

  })

} 
Example 19
Source File: CitizenDetailsService.scala    From nisp-frontend   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.nisp.services

import javax.inject.Inject
import play.api.Logger
import play.api.http.Status
import uk.gov.hmrc.domain.Nino
import uk.gov.hmrc.nisp.connectors.CitizenDetailsConnector
import uk.gov.hmrc.nisp.models.citizen.{Address, Citizen, CitizenDetailsError, CitizenDetailsResponse, MCI_EXCLUSION, NOT_FOUND, TECHNICAL_DIFFICULTIES}
import uk.gov.hmrc.play.http.logging.MdcLoggingExecutionContext._

import scala.concurrent.Future
import uk.gov.hmrc.http.{BadRequestException, HeaderCarrier, NotFoundException, Upstream4xxResponse}

class CitizenDetailsService @Inject()(citizenDetailsConnector: CitizenDetailsConnector) {

  def retrievePerson(nino: Nino)(implicit hc: HeaderCarrier): Future[Either[CitizenDetailsError, CitizenDetailsResponse]] = {
    citizenDetailsConnector.connectToGetPersonDetails(nino) map ( citizen => Right(citizen)) recover {
      case ex: Upstream4xxResponse if ex.upstreamResponseCode == Status.LOCKED =>
        Logger.warn(s"MCI Exclusion for $nino", ex)
        Left(MCI_EXCLUSION)
      case ex: BadRequestException =>
        Logger.error(s"Citizen Details: BadRequest for $nino", ex)
        Left(TECHNICAL_DIFFICULTIES)
      case ex: NotFoundException =>
        Logger.error(s"Citizen Details: NotFound for $nino", ex)
        Left(NOT_FOUND)
    }
  }
} 
Example 20
Source File: NispFrontendController.scala    From nisp-frontend   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.nisp.controllers

import play.api.mvc.{Request, Result}
import play.api.{Logger, PlayException}
import uk.gov.hmrc.nisp.config.wiring.NispFormPartialRetriever
import uk.gov.hmrc.nisp.config.{ApplicationGlobal, ApplicationGlobalTrait, LocalTemplateRenderer}
import uk.gov.hmrc.play.frontend.controller.FrontendController
import uk.gov.hmrc.play.partials.CachedStaticHtmlPartialRetriever
import uk.gov.hmrc.renderer.TemplateRenderer

trait NispFrontendController extends FrontendController {
  val logger: Logger = Logger(this.getClass)

  implicit val cachedStaticHtmlPartialRetriever: CachedStaticHtmlPartialRetriever
  implicit val formPartialRetriever: uk.gov.hmrc.play.partials.FormPartialRetriever = NispFormPartialRetriever
  implicit val templateRenderer: TemplateRenderer = LocalTemplateRenderer

  val applicationGlobal: ApplicationGlobalTrait = ApplicationGlobal

  def onError(ex: Exception)(implicit request: Request[_]): Result = {
    logger.error(
      """
        |
        |! %sInternal server error, for (%s) [%s] ->
        | """.stripMargin.format(ex match {
        case p: PlayException => "@" + p.id + " - "
        case _ => ""
      }, request.method, request.uri),
      ex
    )
    InternalServerError(applicationGlobal.internalServerErrorTemplate)
  }

} 
Example 21
Source File: LandingController.scala    From nisp-frontend   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.nisp.controllers

import play.api.Logger
import play.api.Play.current
import play.api.i18n.Messages.Implicits._
import play.api.mvc.{Action, AnyContent}
import uk.gov.hmrc.nisp.config.ApplicationConfig
import uk.gov.hmrc.nisp.config.wiring.{CitizenDetailsConnector, IdentityVerificationConnector, NispAuthConnector}
import uk.gov.hmrc.nisp.connectors.{IdentityVerificationConnector, IdentityVerificationSuccessResponse}
import uk.gov.hmrc.nisp.controllers.auth.{AuthAction, VerifyAuthActionImpl}
import uk.gov.hmrc.nisp.controllers.partial.PartialRetriever
import uk.gov.hmrc.nisp.services.CitizenDetailsService
import uk.gov.hmrc.nisp.views.html.iv.failurepages.{locked_out, not_authorised, technical_issue, timeout}
import uk.gov.hmrc.nisp.views.html.{identity_verification_landing, landing}
import uk.gov.hmrc.play.frontend.controller.UnauthorisedAction

import scala.concurrent.ExecutionContext.Implicits._
import scala.concurrent.Future

object LandingController extends LandingController with PartialRetriever {
  override val applicationConfig: ApplicationConfig = ApplicationConfig
  override val identityVerificationConnector: IdentityVerificationConnector = IdentityVerificationConnector
  override val verifyAuthAction: AuthAction = new VerifyAuthActionImpl(
    new NispAuthConnector,
    new CitizenDetailsService(CitizenDetailsConnector))
}

trait LandingController extends NispFrontendController {
  val identityVerificationConnector: IdentityVerificationConnector
  val applicationConfig: ApplicationConfig
  val verifyAuthAction: AuthAction

  def show: Action[AnyContent] = UnauthorisedAction(
    implicit request =>
      if (applicationConfig.identityVerification) {
        Ok(identity_verification_landing()).withNewSession
      } else {
        Ok(landing()).withNewSession
      }
  )

  def verifySignIn: Action[AnyContent] = verifyAuthAction {
    implicit request =>
      Redirect(routes.StatePensionController.show())
  }

  def showNotAuthorised(journeyId: Option[String]): Action[AnyContent] = UnauthorisedAction.async { implicit request =>
    val result = journeyId map { id =>

      import IdentityVerificationSuccessResponse._

      val identityVerificationResult = identityVerificationConnector.identityVerificationResponse(id)
      identityVerificationResult map {
        case IdentityVerificationSuccessResponse(FailedMatching) => not_authorised()
        case IdentityVerificationSuccessResponse(InsufficientEvidence) => not_authorised()
        case IdentityVerificationSuccessResponse(TechnicalIssue) => technical_issue()
        case IdentityVerificationSuccessResponse(LockedOut) => locked_out()
        case IdentityVerificationSuccessResponse(Timeout) => timeout()
        case IdentityVerificationSuccessResponse(Incomplete) => not_authorised()
        case IdentityVerificationSuccessResponse(IdentityVerificationSuccessResponse.PreconditionFailed) => not_authorised()
        case IdentityVerificationSuccessResponse(UserAborted) => not_authorised()
        case IdentityVerificationSuccessResponse(FailedIV) => not_authorised()
        case response => Logger.warn(s"Unhandled Response from Identity Verification: $response"); technical_issue()
      }
    } getOrElse Future.successful(not_authorised(showFirstParagraph = false))

    result.map {
      Ok(_).withNewSession
    }
  }
} 
Example 22
Source File: ExclusionController.scala    From nisp-frontend   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.nisp.controllers

import play.api.Play.current
import play.api.i18n.Messages.Implicits._
import play.api.mvc.{Action, AnyContent}
import play.api.{Logger, Play}
import uk.gov.hmrc.nisp.config.wiring.{NationalInsuranceService, StatePensionService}
import uk.gov.hmrc.nisp.controllers.auth.{AuthDetails, ExcludedAuthAction, ExcludedAuthActionImpl}
import uk.gov.hmrc.nisp.controllers.partial.PartialRetriever
import uk.gov.hmrc.nisp.models.enums.Exclusion
import uk.gov.hmrc.nisp.services._
import uk.gov.hmrc.nisp.views.html._

object ExclusionController extends ExclusionController with PartialRetriever with NispFrontendController {
  override val statePensionService: StatePensionService = StatePensionService
  override val authenticate: ExcludedAuthActionImpl = Play.current.injector.instanceOf[ExcludedAuthActionImpl]
  override val nationalInsuranceService: NationalInsuranceService = NationalInsuranceService
}

trait ExclusionController extends NispFrontendController {

  val statePensionService: StatePensionService
  val nationalInsuranceService: NationalInsuranceService
  val authenticate: ExcludedAuthAction

  def showSP: Action[AnyContent] = authenticate.async {
    implicit request =>
      implicit val authDetails: AuthDetails = request.authDetails

      val statePensionF = statePensionService.getSummary(request.nino)
      val nationalInsuranceF = nationalInsuranceService.getSummary(request.nino)

      for (
        statePension <- statePensionF;
        nationalInsurance <- nationalInsuranceF
      ) yield {
        statePension match {
          case Right(sp) if sp.reducedRateElection =>
            Ok(excluded_sp(Exclusion.MarriedWomenReducedRateElection, Some(sp.pensionAge), Some(sp.pensionDate), false, None))
          case Left(exclusion) =>
            if (exclusion.exclusion == Exclusion.Dead)
              Ok(excluded_dead(Exclusion.Dead, exclusion.pensionAge))
            else if (exclusion.exclusion == Exclusion.ManualCorrespondenceIndicator)
              Ok(excluded_mci(Exclusion.ManualCorrespondenceIndicator, exclusion.pensionAge))
            else {
              Ok(excluded_sp(exclusion.exclusion, exclusion.pensionAge, exclusion.pensionDate, nationalInsurance.isRight, exclusion.statePensionAgeUnderConsideration))
            }
          case _ =>
            Logger.warn("User accessed /exclusion as non-excluded user")
            Redirect(routes.StatePensionController.show())
        }
      }
  }

  def showNI: Action[AnyContent] = authenticate.async {
    implicit request =>
      implicit val authDetails: AuthDetails = request.authDetails
      nationalInsuranceService.getSummary(request.nino).map {
        case Left(exclusion) =>
          if (exclusion == Exclusion.Dead) {
            Ok(excluded_dead(Exclusion.Dead, None))
          }
          else if (exclusion == Exclusion.ManualCorrespondenceIndicator) {
            Ok(excluded_mci(Exclusion.ManualCorrespondenceIndicator, None))
          } else {
            Ok(excluded_ni(exclusion))
          }
        case _ =>
          Logger.warn("User accessed /exclusion/nirecord as non-excluded user")
          Redirect(routes.NIRecordController.showGaps())
      }
  }
} 
Example 23
Source File: NispFrontendControllerSpec.scala    From nisp-frontend   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.nisp.controllers

import org.slf4j.{Logger => Slf4JLogger}
import org.mockito.Mockito.{verify, when}
import org.mockito.ArgumentMatchers._
import org.scalatest.mock.MockitoSugar
import org.scalatestplus.play.OneAppPerSuite
import play.api.Logger
import play.api.http.Status
import play.api.mvc.Result
import play.api.test.FakeRequest
import uk.gov.hmrc.nisp.config.{ApplicationGlobal, ApplicationGlobalTrait}
import uk.gov.hmrc.nisp.helpers.{MockApplicationGlobal, MockCachedStaticHtmlPartialRetriever}
import uk.gov.hmrc.nisp.utils.MockTemplateRenderer
import uk.gov.hmrc.play.test.UnitSpec
import uk.gov.hmrc.renderer.TemplateRenderer

class NispFrontendControllerSpec extends UnitSpec with MockitoSugar with OneAppPerSuite {

  val mockLogger: Slf4JLogger = mock[Slf4JLogger]
  when(mockLogger.isErrorEnabled).thenReturn(true)

  def controller = new NispFrontendController {
    override val logger = new Logger(mockLogger)
    val cachedStaticHtmlPartialRetriever = MockCachedStaticHtmlPartialRetriever
    override implicit val templateRenderer: TemplateRenderer = MockTemplateRenderer
    override  val applicationGlobal:ApplicationGlobalTrait = MockApplicationGlobal
  }

  implicit val request = FakeRequest()

  "onError" should {
    "should log error details" in {
      val result: Result =  controller.onError(new Exception())
      verify(mockLogger).error(anyString(), any[Exception])
    }

    "should return an Internal Server Error (500)" in {
      val result: Result =  controller.onError(new Exception())
      status(result) shouldBe Status.INTERNAL_SERVER_ERROR
    }
  }

} 
Example 24
Source File: WithSecurityInfoApiListingCache.scala    From daf   with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
package modules

import io.swagger.config._
import io.swagger.models.Swagger
import io.swagger.models.auth.{BasicAuthDefinition, SecuritySchemeDefinition}
import play.api.Logger
import play.modules.swagger.PlayReader

import scala.collection.JavaConverters._

@SuppressWarnings(
  Array(
    "org.wartremover.warts.Null",
    "org.wartremover.warts.Var"
  )
)
object WithSecurityInfoApiListingCache {
  var cache: Option[Swagger] = None

  def listing(docRoot: String, host: String): Option[Swagger] = {
    Logger("swagger").debug("Loading API metadata")

    val scanner = ScannerFactory.getScanner
    val classes: java.util.Set[Class[_]] = scanner.classes()
    val reader = new PlayReader(null)
    var swagger = reader.read(classes)

    scanner match {
      case config: SwaggerConfig =>
        swagger = config.configure(swagger)
      case _ =>
      // no config, do nothing
    }
    val cache = Some(swagger)
    cache.fold(())(_.setHost(null))
    cache.fold(())(_.setSecurityDefinitions(Map[String, SecuritySchemeDefinition]("basicAuth" -> new BasicAuthDefinition()).asJava))
    cache
  }
} 
Example 25
Source File: WithSecurityInfoApiHelpController.scala    From daf   with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
package controllers

import io.swagger.config.FilterFactory
import io.swagger.core.filter.SpecFilter
import io.swagger.models.Swagger
import _root_.modules.WithSecurityInfoApiListingCache
import play.api.Logger
import play.api.mvc.RequestHeader

import scala.collection.JavaConverters._

@SuppressWarnings(
  Array(
    "org.wartremover.warts.ImplicitParameter"
  )
)
class WithSecurityInfoApiHelpController extends ApiHelpController {
  override protected def getResourceListing(host: String)(implicit requestHeader: RequestHeader): Swagger = {
    Logger("swagger").debug("ApiHelpInventory.getRootResources")
    val docRoot = ""
    val queryParams = for ((key, value) <- requestHeader.queryString) yield {
      (key, value.toList.asJava)
    }
    val cookies = (for (cookie <- requestHeader.cookies) yield {
      (cookie.name, cookie.value)
    }).toMap
    val headers = for ((key, value) <- requestHeader.headers.toMap) yield {
      (key, value.toList.asJava)
    }

    val f = new SpecFilter
    val l: Option[Swagger] = WithSecurityInfoApiListingCache.listing(docRoot, host)

    val specs: Swagger = l match {
      case Some(m) => m
      case _ => new Swagger()
    }

    val hasFilter = Option(FilterFactory.getFilter)
    hasFilter match {
      case Some(_) => f.filter(specs, FilterFactory.getFilter, queryParams.asJava, cookies.asJava, headers.asJava)
      case None => specs
    }
  }

  override protected def getApiListing(resourceName: String, host: String)(implicit requestHeader: RequestHeader): Swagger = {
    Logger("swagger").debug("ApiHelpInventory.getResource(%s)".format(resourceName))
    val docRoot = ""
    val f = new SpecFilter
    val queryParams = requestHeader.queryString.map {case (key, value) => key -> value.toList.asJava}
    val cookies = requestHeader.cookies.map {cookie => cookie.name -> cookie.value}.toMap.asJava
    val headers = requestHeader.headers.toMap.map {case (key, value) => key -> value.toList.asJava}
    val pathPart = resourceName

    val l: Option[Swagger] = WithSecurityInfoApiListingCache.listing(docRoot, host)
    val specs: Swagger = l match {
      case Some(m) => m
      case _ => new Swagger()
    }
    val hasFilter = Option(FilterFactory.getFilter)

    val clone = hasFilter match {
      case Some(_) => f.filter(specs, FilterFactory.getFilter, queryParams.asJava, cookies, headers.asJava)
      case None => specs
    }
    clone.setPaths(clone.getPaths.asScala.filterKeys(_.startsWith(pathPart)).asJava)
    clone
  }
} 
Example 26
Source File: KyloApiClient.scala    From daf   with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
package it.gov.daf.securitymanager.service

import com.google.inject.Inject
import it.gov.daf.securitymanager.service.utilities.ConfigReader
import play.api.Logger
import play.api.libs.json.{JsUndefined, JsValue, Json}
import play.api.libs.ws.{WSAuthScheme, WSClient}
import security_manager.yaml.{Error, Success}

import scala.concurrent.Future

class KyloApiClient @Inject()(wSClient: WSClient){

  import play.api.libs.concurrent.Execution.Implicits._

  def createCategory(name: String):Future[Either[Error,Success]]= {

    val jsonRequest: JsValue = Json.parse(
                                        s"""{
                                           "id": null,
                                           "name": "$name",
                                           "description": null,
                                           "icon": null,
                                           "iconColor": null,
                                           "userFields": [],
                                           "userProperties": [],
                                           "relatedFeedSummaries": [],
                                           "securityGroups": [],
                                           "roleMemberships": [],
                                           "feedRoleMemberships": [],
                                           "owner": null,
                                           "systemName": "$name"
                                    }""")

    Logger.logger.debug("createCategory: "+ jsonRequest.toString())

    val response = wSClient.url(ConfigReader.kyloUrl + "/proxy/v1/feedmgr/categories")
                    .withHeaders("Accept" -> "application/json")
                    .withAuth(ConfigReader.kyloUser,ConfigReader.kyloUserPwd,WSAuthScheme.BASIC)
                    .post(jsonRequest)

    response.map{response =>

      if( response.status != 200 )
        Left( Error(Option(0),Some("Error in during kylo category creation: bad http code"+response.status),None) )
      else{
        Logger.logger.debug("RESPONSE:"+response.json)
        val result = response.json \ "id"
        if( result.isInstanceOf[JsUndefined] )
          Left( Error(Option(0),Some("Error in during kylo category creation"),None) )
        else
          Right( Success(Some("Category created"), Some("ok")) )
      }

    }

  }


} 
Example 27
Source File: UriDataset.scala    From daf   with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
package it.gov.daf.catalogmanager.utilities.uri

import catalog_manager.yaml.MetaCatalog
import com.typesafe.config.ConfigFactory
import it.gov.daf.catalogmanager.utilities.datastructures.DatasetType
import play.api.Logger

import scala.util.{Failure, Success, Try}

case class UriDataset(
                       domain: String = "NO_DOMAIN",
                       typeDs: DatasetType.Value = DatasetType.RAW,
                       groupOwn: String = "NO_groupOwn",
                       owner: String = "NO_owner",
                       theme: String = "NO_theme",
                       subtheme :String = "NO_theme",
                       nameDs: String = "NO_nameDs") {

  val config = ConfigFactory.load()

  def getUri(): String = {
    domain + "://" + "dataset/" + typeDs + "/" + groupOwn + "/" + owner + "/" + theme + "/" + subtheme + "/" + nameDs
  }


  def getUrl(): String = {

    val basePath = config.getString("Inj-properties.hdfsBasePath")
    val baseDataPath = config.getString("Inj-properties.dataBasePath")
    typeDs match {
      case DatasetType.STANDARD => basePath + baseDataPath + "/" + typeDs + "/" + theme + "/" + subtheme + "/" + groupOwn + "/" + nameDs
      case DatasetType.ORDINARY => basePath + baseDataPath + "/" + typeDs + "/" + owner + "/" + theme + "/" + subtheme + "/" + groupOwn + "/" + nameDs
      case DatasetType.RAW => basePath + baseDataPath + "/" + typeDs + "/" + owner + "/" + theme + "/" + subtheme + "/" + groupOwn + "/" + nameDs
      case _ => "-1"
    }
  }
}


object UriDataset  {
  def apply(uri: String): UriDataset = {
    Try {
      val uri2split = uri.split("://")
      val uriParts = uri2split(1).split("/")
      new UriDataset(
        domain = uri2split(0),
        typeDs = DatasetType.withNameOpt(uriParts(1)).get,
        groupOwn = uriParts(2),
        owner = uriParts(3),
        theme = uriParts(4),
        subtheme = uriParts(5),
        nameDs = uriParts(6))
    } match {
      case Success(s) => s
      case Failure(err) =>
        Logger.error("Error while creating uri: " + uri + " - " + err.getMessage)
        UriDataset()
    }

  }

  def convertToUriDataset(schema: MetaCatalog): UriDataset =  {

      val typeDs = if (schema.operational.is_std)
        DatasetType.STANDARD
      else
        DatasetType.ORDINARY
      new UriDataset(
        domain = "daf",
        typeDs = typeDs,
        groupOwn = schema.operational.group_own,
        owner = schema.dcatapit.owner_org.get,
        theme  = schema.operational.theme,
        subtheme = schema.operational.subtheme,
        nameDs = schema.dataschema.avro.name
      )

  }

} 
Example 28
Source File: TableOfContentController.scala    From play-table-of-contents   with MIT License 5 votes vote down vote up
package controllers

import java.net.URL
import javax.inject.Inject

import context.MyExecutionContext
import models.ReadmeForm
import play.api.Logger
import play.api.data.Form
import play.api.data.Forms._
import play.api.mvc._
import readme.TableOfContentHelper
import util.HtmlUtil

import scala.concurrent.Future

class TableOfContentController @Inject()(ec: MyExecutionContext, cc: ControllerComponents)
    extends AbstractController(cc) {

  val logger = Logger(this.getClass)

  implicit val xc: MyExecutionContext = ec

  val userForm = Form(
    mapping(
      "description" -> text,
      "github_url"  -> text
    )(ReadmeForm.apply)(ReadmeForm.unapply)
  )

  val startContent: String =
    """Example :
    |# Title 1
    |## Title 2
    |### Title 3""".stripMargin('|')

  def readme = Action {
    Ok(HtmlUtil.prettify(views.html.readme(startContent)))
  }

  
  private def getGithubReadmeUrl(url: String): String = {
    val githubUrl    = new URL(url)
    val path         = githubUrl.getPath.substring(1)
    val endIndex     = path.indexOf("/", path.indexOf("/") + 1)
    val userNproject = if (endIndex == -1) path else path.substring(0, endIndex)
    s"https://raw.githubusercontent.com/${userNproject}/master/README.md"
  }

  private def readContentFromUrl(mdUrl: String): Future[String] = Future {
    val f = scala.io.Source.fromURL(mdUrl)
    try f.mkString
    finally f.close()
  }

} 
Example 29
Source File: PredefinedTag.scala    From smui   with Apache License 2.0 5 votes vote down vote up
package models

import java.io.InputStream
import java.sql.Connection

import play.api.Logger
import play.api.libs.json.{Json, OFormat}

case class PredefinedTag(property: Option[String],
                         value: String,
                         solrIndexName: Option[String],
                         exported: Option[Boolean]) {

}

object PredefinedTag {

  val logger = Logger(getClass)

  implicit val jsonFormat: OFormat[PredefinedTag] = Json.format[PredefinedTag]

  def fromStream(stream: InputStream): Seq[PredefinedTag] = {
    try {
      Json.parse(stream).as[Seq[PredefinedTag]]
    } finally {
      stream.close()
    }
  }

  def updateInDB(predefinedTags: Seq[PredefinedTag])(implicit connection: Connection): (Seq[InputTagId], Seq[InputTag]) = {
    val indexIdsByName = SolrIndex.listAll.map(i => i.name -> i.id).toMap
    val tagsInDBByContent = InputTag.loadAll().map(t => t.tagContent -> t).toMap

    val newTags = predefinedTags.map { tag =>
      TagContent(tag.solrIndexName.flatMap(indexIdsByName.get), tag.property, tag.value) -> tag
    }.toMap

    val toDelete = tagsInDBByContent.filter { case (content, tag) => tag.predefined && !newTags.contains(content) }.map(_._2.id).toSeq
    val toInsert = newTags.filter(t => !tagsInDBByContent.contains(t._1)).map { case (tc, t) =>
      InputTag.create(tc.solrIndexId, t.property, t.value, t.exported.getOrElse(true), predefined = true)
    }.toSeq

    InputTag.insert(toInsert: _*)
    InputTag.deleteByIds(toDelete)
    if (toDelete.nonEmpty || toInsert.nonEmpty) {
      logger.info(s"Inserted ${toInsert.size} new predefined tags into the DB and deleted ${toDelete.size} no longer existing predefined tags.")
    }

    (toDelete, toInsert)
  }

} 
Example 30
Source File: AuthenticationFilter.scala    From maha   with Apache License 2.0 5 votes vote down vote up
// Copyright 2018, Oath Inc.
// Licensed under the terms of the Apache License 2.0. Please see LICENSE file in project root for terms.
package filter
import akka.stream.Materializer
import com.google.common.base.Charsets
import com.google.common.hash.Hashing
import com.yahoo.maha.core.auth.{AuthValidator, ValidationResult}
import play.api.Logger
import play.api.mvc._

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

class AuthenticationFilter(authValidator: AuthValidator)(implicit val mat: Materializer) extends Filter {

  private val routesWhichRequireAuth : Set[String] = Set("/segments", "/overlord/workers", "/lookups", "/kill/segments")

  def apply(nextFilter: RequestHeader => Future[Result])
           (requestHeader: RequestHeader): Future[Result] = {

    if(routesWhichRequireAuth.contains(requestHeader.path)) {
      Try {
        val result: ValidationResult = authValidator.validate(requestHeader)
        result
      } match {
        case Success(result) =>
          val requestHeaderWithId = requestHeader.copy(tags = requestHeader.tags + ("X-Request-Id" -> generateRequestId(requestHeader))
            + ("userId" -> result.user.getOrElse("Authorized User")))
          nextFilter(requestHeaderWithId)
        case Failure(e) =>
          Logger.error(s"Exception while authenticating user", e)
          val result: Result = authValidator.handleAuthFailure(requestHeader)
          Future.successful(result)
      }
    } else {
      Logger.debug(s"no auth required for path : ${requestHeader.path}")
      nextFilter(requestHeader)
    }
  }

  private def generateRequestId(requestHeader: RequestHeader): String = {
    return s" ${Hashing.goodFastHash(128).newHasher.putString(requestHeader.path + requestHeader.queryString, Charsets.UTF_8).hash.asLong}-${System.nanoTime}"
  }

} 
Example 31
Source File: ObligationsService.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package v1.services

import cats.data.EitherT
import cats.implicits._
import javax.inject.{Inject, Singleton}
import play.api.Logger
import uk.gov.hmrc.http.HeaderCarrier
import utils.{EndpointLogContext, Logging}
import v1.connectors.ObligationsConnector
import v1.models.errors._
import v1.models.request.obligations.ObligationsRequest
import v1.models.response.obligations.ObligationsResponse
import v1.support.DesResponseMappingSupport

import scala.concurrent.{ExecutionContext, Future}

@Singleton
class ObligationsService @Inject()(connector: ObligationsConnector) extends DesResponseMappingSupport with Logging {

  def retrieveObligations(request: ObligationsRequest)(
    implicit hc: HeaderCarrier,
    ec: ExecutionContext,
    logContext: EndpointLogContext): Future[ServiceOutcome[ObligationsResponse]] = {

    val result = for {
      desResponseWrapper <- EitherT(connector.retrieveObligations(request)).leftMap(mapDesErrors(desErrorMap))
    } yield desResponseWrapper

    result.value
  }

  private def desErrorMap: Map[String, MtdError] =
    Map(
      "INVALID_IDTYPE" -> DownstreamError,
      "INVALID_IDNUMBER" -> VrnFormatErrorDes,
      "INVALID_STATUS" -> InvalidStatusErrorDes,
      "INVALID_REGIME" -> DownstreamError,
      "INVALID_DATE_FROM" -> InvalidDateFromErrorDes,
      "INVALID_DATE_TO" -> InvalidDateToErrorDes,
      "INVALID_DATE_RANGE" -> RuleOBLDateRangeTooLargeError,
      "NOT_FOUND_BP_KEY" -> {
        Logger.warn("[ObligationsService] [desErrorMap] - Backend returned NOT_FOUND_BPKEY error")
        DownstreamError
      },
      "NOT_FOUND" -> LegacyNotFoundError,
      "SERVICE_ERROR" -> DownstreamError,
      "SERVICE_UNAVAILABLE" -> DownstreamError
    )
} 
Example 32
Source File: AuditService.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package v1.services

import javax.inject.{Inject, Singleton}
import play.api.libs.json.{Json, Writes}
import play.api.{Configuration, Logger}
import uk.gov.hmrc.http.HeaderCarrier
import uk.gov.hmrc.play.audit.AuditExtensions
import uk.gov.hmrc.play.audit.http.connector.{AuditConnector, AuditResult}
import uk.gov.hmrc.play.audit.model.ExtendedDataEvent
import uk.gov.hmrc.play.bootstrap.config.AppName
import v1.models.audit.AuditEvent

import scala.concurrent.{ExecutionContext, Future}

@Singleton
class AuditService @Inject()(auditConnector: AuditConnector,
                             appNameConfiguration: Configuration) {

  val logger: Logger = Logger(this.getClass)

  def auditEvent[T](event: AuditEvent[T])(implicit hc: HeaderCarrier, ec: ExecutionContext, writer: Writes[T]): Future[AuditResult] = {

    val eventTags = AuditExtensions.auditHeaderCarrier(hc).toAuditTags() +
      ("transactionName" -> event.transactionName)

    val dataEvent = ExtendedDataEvent(
      auditSource = AppName.fromConfiguration(appNameConfiguration),
      auditType = event.auditType,
      detail = Json.toJson(event.detail),
      tags = eventTags
    )
    logger.info(s"Audit event :- dataEvent.tags :: ${dataEvent.tags} --  auditSource:: ${dataEvent.auditSource}" +
      s" --- detail :: ${dataEvent.detail}")
    auditConnector.sendExtendedEvent(dataEvent)
  }
} 
Example 33
Source File: BaseNrsConnector.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package v1.connectors

import java.util.concurrent.TimeoutException

import config.AppConfig
import play.api.Logger
import play.api.libs.json.{Json, Writes}
import play.api.libs.ws.WSClient
import uk.gov.hmrc.http.HeaderCarrier
import v1.connectors.httpparsers.WsReads

import scala.concurrent.{ExecutionContext, Future}

trait BaseNrsConnector {
  val ws: WSClient
  val appConfig: AppConfig

  val logger = Logger(this.getClass)

  private[connectors] def nrsHeaderCarrier(implicit hc: HeaderCarrier): HeaderCarrier =
    hc.withExtraHeaders(
      "X-API-Key" -> appConfig.nrsApiKey,
      "User-Agent" -> appConfig.appName
    )

  def nrsPost[Body: Writes, Resp](body: Body, uri: NrsUri[Resp], defaultResult: NrsOutcome[Resp])(implicit ec: ExecutionContext,
                                                                                      hc: HeaderCarrier,
                                                                                      wsReads: WsReads[NrsOutcome[Resp]]): Future[NrsOutcome[Resp]] = {

    def doPost(implicit hc: HeaderCarrier): Future[NrsOutcome[Resp]] = {

      ws.url(s"${appConfig.nrsBaseUrl}/${uri.value}")
        .withHttpHeaders(hc.headers: _*)
        .withRequestTimeout(appConfig.nrsMaxTimeout)
        .post(Json.toJson(body))
        .map(wsReads.wsRead(_, defaultResult)).recover {
        case e: TimeoutException =>
          logger.warn(s"[NrsConnector][nrsPost] - NRS Call timed out - $e")
          defaultResult
      }
    }

    doPost(nrsHeaderCarrier(hc))
  }

} 
Example 34
Source File: BaseDesConnector.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package v1.connectors

import config.AppConfig
import play.api.Logger
import play.api.libs.json.Writes
import uk.gov.hmrc.http.logging.Authorization
import uk.gov.hmrc.http.{HeaderCarrier, HttpReads}
import uk.gov.hmrc.play.bootstrap.http.HttpClient

import scala.concurrent.{ExecutionContext, Future}

trait BaseDesConnector {
  val http: HttpClient
  val appConfig: AppConfig

  val logger = Logger(this.getClass)

  private[connectors] def desHeaderCarrier(implicit hc: HeaderCarrier): HeaderCarrier =
    hc.copy(authorization = Some(Authorization(s"Bearer ${appConfig.desToken}")))
      .withExtraHeaders("Environment" -> appConfig.desEnv)

  private[connectors] def desPostHeaderCarrier(implicit hc: HeaderCarrier): HeaderCarrier =
    hc.copy(authorization = Some(Authorization(s"Bearer ${appConfig.desToken}")))
      .withExtraHeaders("Environment" -> appConfig.desEnv,
        "Accept" -> "application/json",
        "OriginatorID" -> "MDTP")

  def post[Body: Writes, Resp](body: Body, uri: DesUri[Resp])(implicit ec: ExecutionContext,
                                                              hc: HeaderCarrier,
                                                              httpReads: HttpReads[DesOutcome[Resp]]): Future[DesOutcome[Resp]] = {

    def doPost(implicit hc: HeaderCarrier): Future[DesOutcome[Resp]] = {
      http.POST(s"${appConfig.desBaseUrl}/${uri.value}", body)
    }

    doPost(desPostHeaderCarrier(hc))
  }

  def get[Resp](uri: DesUri[Resp])(implicit ec: ExecutionContext,
                                   hc: HeaderCarrier,
                                   httpReads: HttpReads[DesOutcome[Resp]]): Future[DesOutcome[Resp]] = {

    def doGet(implicit hc: HeaderCarrier): Future[DesOutcome[Resp]] =
      http.GET(s"${appConfig.desBaseUrl}/${uri.value}")

    doGet(desHeaderCarrier(hc))
  }

  def get[Resp](uri: DesUri[Resp], queryParams: Seq[(String, String)])(implicit ec: ExecutionContext,
                                                                       hc: HeaderCarrier,
                                                                       httpReads: HttpReads[DesOutcome[Resp]]): Future[DesOutcome[Resp]] = {

    def doGet(implicit hc: HeaderCarrier): Future[DesOutcome[Resp]] = {
      http.GET(s"${appConfig.desBaseUrl}/${uri.value}", queryParams)
    }

    doGet(desHeaderCarrier(hc))
  }

} 
Example 35
Source File: StandardDesHttpParser.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package v1.connectors.httpparsers

import play.api.Logger
import play.api.http.Status._
import play.api.libs.json.Reads
import uk.gov.hmrc.http.{HttpReads, HttpResponse}
import v1.connectors.DesOutcome
import v1.models.errors.{ConnectorError, DownstreamError, OutboundError}
import v1.models.outcomes.ResponseWrapper

object StandardDesHttpParser extends HttpParser {

  case class SuccessCode(status: Int) extends AnyVal

  val logger = Logger(getClass)

  // Return Right[DesResponse[Unit]] as success response has no body - no need to assign it a value
  implicit def readsEmpty(implicit successCode: SuccessCode = SuccessCode(NO_CONTENT),
                          connectorError: ConnectorError): HttpReads[DesOutcome[Unit]] =
    (_: String, url: String, response: HttpResponse) => doRead(url, response) { correlationId =>
      Right(ResponseWrapper(correlationId, ()))
    }

  implicit def reads[A: Reads](implicit successCode: SuccessCode = SuccessCode(OK),
                               connectorError: ConnectorError): HttpReads[DesOutcome[A]] =
    (_: String, url: String, response: HttpResponse) => doRead(url, response) { correlationId =>
      response.validateJson[A] match {
        case Some(ref) => Right(ResponseWrapper(correlationId, ref))
        case None => Left(ResponseWrapper(correlationId, OutboundError(DownstreamError)))
      }
    }

  private def doRead[A](url: String, response: HttpResponse,
                       )(successOutcomeFactory: String => DesOutcome[A])(
    implicit successCode: SuccessCode, connectorError: ConnectorError): DesOutcome[A] = {

    val correlationId = retrieveCorrelationId(response)

    if (response.status != successCode.status) {
      logger.info(
        "[StandardDesHttpParser][read] - " +
          s"Error response received from DES with status: ${response.status} and body\n" +
          s"${response.body} and correlationId: $correlationId when calling $url - " +
          s"vrn: ${connectorError.vrn}, requestId: ${connectorError.requestId}")
    }
    response.status match {
      case successCode.status =>
        logger.info(
          "[StandardDesHttpParser][read] - " +
            s"Success response received from DES with correlationId: $correlationId when calling $url")
        successOutcomeFactory(correlationId)
      case BAD_REQUEST | NOT_FOUND | FORBIDDEN | CONFLICT | UNPROCESSABLE_ENTITY => Left(ResponseWrapper(correlationId, parseErrors(response)))
      case _                                                                     => Left(ResponseWrapper(correlationId, OutboundError(DownstreamError)))
    }
  }
} 
Example 36
Source File: StandardNrsWsParser.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package v1.connectors.httpparsers

import play.api.Logger
import play.api.http.Status._
import play.api.libs.json.Reads
import play.api.libs.ws.WSResponse
import v1.connectors.NrsOutcome
import v1.models.nrs.response.NrsError

trait WsReads[A] {
  def wsRead(response: WSResponse, defaultResult: A): A
}

object StandardNrsWsParser extends WsParser {

  val logger = Logger(getClass)

  case class SuccessCode(status: Int) extends AnyVal

  implicit def nrsReads[A: Reads](implicit successCode: SuccessCode = SuccessCode(ACCEPTED)): WsReads[NrsOutcome[A]] =
    (response: WSResponse, defaultResult: NrsOutcome[A]) => doRead(response, defaultResult) { response =>
      response.validateJson[A] match {
        case Some(ref) => Right(ref)
        case None => Left(NrsError)
      }
    }

  private def doRead[A](response: WSResponse, defaultResult: NrsOutcome[A])(successOutcomeFactory: WSResponse => NrsOutcome[A])(
    implicit successCode: SuccessCode): NrsOutcome[A] = {

    if (response.status!=successCode.status){
      logger.info("[StandardNrsWsParser][read] - Error response received from NRS " +
        s"with status: ${response.status} and body\n ${response.body}")
    }
    response.status match {
      case successCode.status =>
        logger.info("[StandardNrsWsParser][read] - Success response received from NRS")
        successOutcomeFactory(response)
      case BAD_REQUEST => Left(NrsError)
      case _ => defaultResult
    }
  }
} 
Example 37
Source File: HttpParser.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package v1.connectors.httpparsers

import play.api.Logger
import play.api.libs.json._
import uk.gov.hmrc.http.HttpResponse
import v1.models.errors._

import scala.util.{Success, Try}

trait HttpParser {

  implicit class KnownJsonResponse(response: HttpResponse) {

    def validateJson[T](implicit reads: Reads[T]): Option[T] = {
      Try(response.json) match {
        case Success(json: JsValue) => parseResult(json)
        case _ =>
          Logger.warn("[KnownJsonResponse][validateJson] No JSON was returned")
          None
      }
    }

    def parseResult[T](json: JsValue)(implicit reads: Reads[T]): Option[T] = json.validate[T] match {

      case JsSuccess(value, _) => Some(value)
      case JsError(error) =>
        Logger.warn(s"[KnownJsonResponse][validateJson] Unable to parse JSON: $error")
        None
    }
  }

  def retrieveCorrelationId(response: HttpResponse): String = response.header("CorrelationId").getOrElse("No Correlation ID")

  // Not required while multiple errors are not supported
  //private val multipleErrorReads: Reads[List[DesErrorCode]] = (__ \ "failures").read[List[DesErrorCode]]

  private val bvrErrorReads: Reads[Seq[DesErrorCode]] = {
    implicit val errorIdReads: Reads[DesErrorCode] = (__ \ "id").read[String].map(DesErrorCode(_))
    (__ \ "bvrfailureResponseElement" \ "validationRuleFailures").read[Seq[DesErrorCode]]
  }

  def parseErrors(response: HttpResponse): DesError = {
    val singleError         = response.validateJson[DesErrorCode].map(err => DesErrors(List(err)))
    // FIXME: Legacy VAT can't handle multiple errors so this must be commented out
    //lazy val multipleErrors = response.validateJson(multipleErrorReads).map(errs => DesErrors(errs))
    lazy val bvrErrors      = response.validateJson(bvrErrorReads).map(errs => OutboundError(BVRError, Some(errs.map(_.toMtd))))
    lazy val unableToParseJsonError = {
      Logger.warn(s"unable to parse errors from response: ${response.body}")
      OutboundError(DownstreamError)
    }

    singleError orElse bvrErrors getOrElse unableToParseJsonError
  }

} 
Example 38
Source File: WsParser.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package v1.connectors.httpparsers

import play.api.Logger
import play.api.libs.json.{JsError, JsSuccess, JsValue, Reads}
import play.api.libs.ws.WSResponse

import scala.util.{Success, Try}

trait WsParser {

  implicit class KnownJsonResponse(response: WSResponse) {

    def validateJson[T](implicit reads: Reads[T]): Option[T] = {
      Try(response.json) match {
        case Success(json: JsValue) => parseResult(json)
        case _ =>
          Logger.warn("[KnownJsonResponse][validateJson - NRS] No JSON was returned")
          None
      }
    }

    def parseResult[T](json: JsValue)(implicit reads: Reads[T]): Option[T] = json.validate[T] match {

      case JsSuccess(value, _) => Some(value)
      case JsError(error) =>
        Logger.warn(s"[KnownJsonResponse][validateJson - NRS] Unable to parse JSON: $error")
        None
    }
  }
} 
Example 39
Source File: VersionRoutingMap.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package routing

import com.google.inject.ImplementedBy
import config.{AppConfig, FeatureSwitch}
import definition.Versions.VERSION_1
import javax.inject.Inject
import play.api.Logger
import play.api.routing.Router

// So that we can have API-independent implementations of
// VersionRoutingRequestHandler and VersionRoutingRequestHandlerSpec
// implement this for the specific API...
@ImplementedBy(classOf[VersionRoutingMapImpl])
trait VersionRoutingMap {
  val defaultRouter: Router

  val map: Map[String, Router]

  final def versionRouter(version: String): Option[Router] = map.get(version)
}

// Add routes corresponding to available versions...
case class VersionRoutingMapImpl @Inject()(appConfig: AppConfig,
                                           defaultRouter: Router,
                                           liveRouter: live.Routes,
                                           v1Router: v1.Routes,
                                           v1RouterProd: v1Prod.Routes) extends VersionRoutingMap {

  val featureSwitch = FeatureSwitch(appConfig.featureSwitch)

  val map: Map[String, Router] = Map(
    VERSION_1 ->  {
      if (featureSwitch.refactorEnabled) {
        if (featureSwitch.refactorProdEnabled) {
          Logger.info("[VersionRoutingMap][map] using v1Router - pointing to new packages for Obligations")
          v1RouterProd
        }
        else {
          Logger.info("[VersionRoutingMap][map] using v1Router - pointing to new packages")
          v1Router
        }
      } else {
        Logger.info("[VersionRoutingMap][map] using legacy liveRouter")
        liveRouter
      }
    }
  )
} 
Example 40
Source File: ApiDefinitionFactory.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package definition

import config.{AppConfig, FeatureSwitch}
import javax.inject.{Inject, Singleton}
import play.api.Logger

@Singleton
class ApiDefinitionFactory @Inject()(appConfig: AppConfig) {

  private val readScope = "read:vat"
  private val writeScope = "write:vat"

  lazy val definition: Definition =
    Definition(
      scopes = Seq(
        Scope(
          key = readScope,
          name = "View your VAT information",
          description = "Allow read access to VAT data"
        ),
        Scope(
          key = writeScope,
          name = "Change your VAT information",
          description = "Allow write access to VAT data"
        )
      ),
      api = APIDefinition(
        name = "VAT (MTD)",
        description =
          "An API for providing VAT data",
        context = appConfig.apiGatewayContext,
        categories = Seq("VAT_MTD"),
        versions = Seq(
          APIVersion(
            version = "1.0",
            access = buildWhiteListingAccess(),
            status = buildAPIStatus("1.0"),
            endpointsEnabled = true
          )
        ),
        requiresTrust = None
      )
    )

  private[definition] def buildAPIStatus(version: String): APIStatus = {
    APIStatus.parser.lift(appConfig.apiStatus(version))
      .getOrElse {
        Logger.error(s"[ApiDefinition][buildApiStatus] no API Status found in config.  Reverting to Alpha")
        APIStatus.ALPHA
      }
  }

  private[definition] def buildWhiteListingAccess(): Option[Access] = {
    val featureSwitch = FeatureSwitch(appConfig.featureSwitch)
    if (featureSwitch.isWhiteListingEnabled) Some(Access("PRIVATE", featureSwitch.whiteListedApplicationIds)) else None
  }
} 
Example 41
Source File: VatReturnsOrchestrator.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.vatapi.orchestrators

import javax.inject.Inject

import org.joda.time.DateTime
import play.api.Logger
import play.api.libs.json.JsObject
import uk.gov.hmrc.domain.Vrn
import uk.gov.hmrc.http.HeaderCarrier
import uk.gov.hmrc.vatapi.audit.AuditEvents
import uk.gov.hmrc.vatapi.httpparsers.{EmptyNrsData, NRSData}
import uk.gov.hmrc.vatapi.models.audit.AuditEvent
import uk.gov.hmrc.vatapi.models.{ErrorResult, Errors, InternalServerErrorResult, NRSSubmission, VatReturnDeclaration}
import uk.gov.hmrc.vatapi.resources.AuthRequest
import uk.gov.hmrc.vatapi.resources.wrappers.VatReturnResponse
import uk.gov.hmrc.vatapi.services.{AuditService, NRSService, VatReturnsService}
import uk.gov.hmrc.vatapi.utils.ImplicitDateTimeFormatter

import scala.concurrent.{ExecutionContext, Future}


class VatReturnsOrchestrator @Inject()(
                                        nrsService: NRSService,
                                        vatReturnsService: VatReturnsService,
                                        auditService: AuditService
                                      )(implicit ec: ExecutionContext) extends ImplicitDateTimeFormatter {

  val logger: Logger = Logger(this.getClass)

  def submissionTimestamp: DateTime = DateTime.now()

  def submitVatReturn(vrn: Vrn, vatReturn: VatReturnDeclaration, arn: Option[String])
                     (implicit hc: HeaderCarrier, request: AuthRequest[_]): Future[Either[ErrorResult, VatReturnResponse]] = {

    logger.debug(s"[VatReturnsOrchestrator][submitVatReturn] - Orchestrating calls to NRS and Vat Returns")

    val submission = nrsService.convertToNrsSubmission(vrn, vatReturn)

    nrsService.submit(vrn, submission) flatMap {
      case Left(e) =>
        logger.error(s"[VatReturnsOrchestrator][submitVatReturn] - Error retrieving data from NRS: $e")
        Future.successful(Left(InternalServerErrorResult(Errors.InternalServerError.message)))
      case Right(nrsData) =>
        logger.debug(s"[VatReturnsOrchestrator][submitVatReturn] - Successfully retrieved data from NRS: $nrsData")

        val thisSubmissionTimestamp = submissionTimestamp

        nrsData match {
          case EmptyNrsData =>
            auditService.audit(buildEmptyNrsAudit(vrn, submission, request))
            vatReturnsService.submit(vrn, vatReturn.toDes(thisSubmissionTimestamp, arn)) map {
              response => Right(response withNrsData nrsData.copy(timestamp = thisSubmissionTimestamp.toIsoInstant))
            }
          case _ =>
            auditService.audit(buildNrsAudit(vrn, nrsData, request))

            vatReturnsService.submit(vrn, vatReturn.toDes(thisSubmissionTimestamp, arn)) map {
              response => Right(response withNrsData nrsData.copy(timestamp = thisSubmissionTimestamp.toIsoInstant))
            }
        }
    }
  }

  case class VatReturnOrchestratorResponse(nrs: NRSData, vatReturnResponse: VatReturnResponse)

  private def buildNrsAudit(vrn: Vrn, nrsData: NRSData, request: AuthRequest[_]): AuditEvent[Map[String, String]] =
    AuditEvents.nrsAudit(vrn, nrsData, request.headers.get("Authorization").getOrElse(""))

  private def buildEmptyNrsAudit(vrn: Vrn, submission: NRSSubmission, request: AuthRequest[_]): AuditEvent[JsObject] =
    AuditEvents.nrsEmptyAudit(vrn, submission, request.headers.get("Authorization").getOrElse(""))

} 
Example 42
Source File: resources.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.vatapi

import cats.data.EitherT
import cats.implicits._
import play.api.Logger
import play.api.http.Status
import play.api.libs.json._
import play.api.mvc.Result
import play.api.mvc.Results.InternalServerError
import uk.gov.hmrc.vatapi.models.{AuthorisationErrorResult, ErrorResult, Errors, GenericErrorResult, InternalServerErrorResult, JsonValidationErrorResult, ValidationErrorResult}
import uk.gov.hmrc.vatapi.resources.wrappers.Response

import scala.concurrent.{ExecutionContext, Future}

package object resources {

  type BusinessResult[T] = EitherT[Future, ErrorResult, T]
  val GovTestScenarioHeader = "Gov-Test-Scenario"

  def unhandledResponse(status: Int, logger: Logger): Result = {
    logger.error(s"Unhandled response from DES. Status code: $status. Returning 500 to client.")
    InternalServerError(Json.toJson(Errors.InternalServerError("An internal server error occurred")))
  }

  def handleErrors(errorResult: ErrorResult): VatResult = {
    errorResult match {
      case GenericErrorResult(message) => VatResult.Failure(Status.BAD_REQUEST, Errors.badRequest(message))
      case JsonValidationErrorResult(errors) => VatResult.Failure(Status.BAD_REQUEST,Errors.badRequest(errors))
      case ValidationErrorResult(error) => VatResult.Failure(Status.BAD_REQUEST, Errors.badRequest(error))
      case AuthorisationErrorResult(error) => VatResult.Failure(Status.FORBIDDEN, error)
      case InternalServerErrorResult(error) => VatResult.Failure(Status.INTERNAL_SERVER_ERROR, Errors.InternalServerError(error))
    }
  }

  def validateJson[T](json: JsValue)(implicit reads: Reads[T], ec: ExecutionContext): BusinessResult[T] =
    BusinessResult {
      for {
        errors <- json.validate[T].asEither.left
      } yield JsonValidationErrorResult(errors)
    }

  def validate[T](value: T)(validate: PartialFunction[T, Errors.Error])(implicit ec: ExecutionContext): BusinessResult[T] =
    if (validate.isDefinedAt(value)) BusinessResult.failure(ValidationErrorResult(validate(value)))
    else BusinessResult.success(value)

  def authorise[T](value: T)(auth: PartialFunction[T, Errors.Error])(implicit ec: ExecutionContext): BusinessResult[T] =
    if (auth.isDefinedAt(value)) BusinessResult.failure(AuthorisationErrorResult(Errors.businessError(auth(value))))
    else BusinessResult.success(value)

  def execute[T](torun: Unit => Future[T])(implicit ec: ExecutionContext): BusinessResult[T] =
    BusinessResult {
      for {
        result <- torun(())
      } yield Right(result)
    }

  def fromDes[R <: Response](result: BusinessResult[R]): DesBusinessResult[R] = DesBusinessResult(result)

  object BusinessResult {

    def apply[T](eventuallyErrorOrResult: Future[Either[ErrorResult, T]]): BusinessResult[T] =
      new EitherT(eventuallyErrorOrResult)

    def apply[T](errorOrResult: Either[ErrorResult, T])(implicit ec: ExecutionContext): BusinessResult[T] =
      EitherT.fromEither(errorOrResult)

    def success[T](value: T)(implicit ec: ExecutionContext): BusinessResult[T] = EitherT.fromEither(Right(value))

    def failure[T](error: ErrorResult)(implicit ec: ExecutionContext): BusinessResult[T] = EitherT.fromEither(Left(error))

  }

} 
Example 43
Source File: BaseResource.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.vatapi.resources

import org.joda.time.DateTime
import play.api.Logger
import play.api.mvc.{ActionBuilder, _}
import uk.gov.hmrc.domain.Vrn
import uk.gov.hmrc.play.bootstrap.controller.BackendController
import uk.gov.hmrc.vatapi.auth.{Agent, AuthContext}
import uk.gov.hmrc.vatapi.services.AuthorisationService

import scala.concurrent.{ExecutionContext, Future}
import scala.util.Right

abstract class BaseResource(cc: ControllerComponents) extends BackendController(cc) {
  val authService: AuthorisationService

  val logger: Logger = Logger(this.getClass)

  def AuthAction(vrn: Vrn, nrsRequired: Boolean = false)(implicit ec: ExecutionContext): ActionRefiner[Request, AuthRequest] = new ActionRefiner[Request, AuthRequest] {
    logger.debug(s"[BaseResource][AuthAction] Check MTD VAT authorisation for the VRN : $vrn")

    override def executionContext: ExecutionContext = ec

    override protected def refine[A](request: Request[A]): Future[Either[Result, AuthRequest[A]]] = {
      implicit val ev: Request[A] = request
      nrsRequired match {
        case false =>
          authService.authCheck(vrn) map {
            case Right(authContext) => Right(new AuthRequest(authContext, request))
            case Left(authError) => Left(authError)
          }
        case true =>
          authService.authCheckWithNrsRequirement(vrn) map {
            case Right(authContext) => Right(new AuthRequest(authContext, request))
            case Left(authError) => Left(authError)
          }
      }
    }
  }

  def APIAction(vrn: Vrn, nrsRequired: Boolean = false)(implicit ec: ExecutionContext): ActionBuilder[AuthRequest, AnyContent] = Action andThen AuthAction(vrn, nrsRequired)

  def getRequestDateTimestamp(implicit request: AuthRequest[_]): String = {
    val requestTimestampHeader = "X-Request-Timestamp"
    val requestTimestamp = request.headers.get(requestTimestampHeader) match {
      case Some(timestamp) if timestamp.trim.length > 0 => timestamp.trim
      case _ =>
        logger.warn(s"$requestTimestampHeader header is not passed or is empty in the request.")
        DateTime.now().toString()
    }
    requestTimestamp
  }

  def getArn(implicit request: AuthRequest[_]): Option[String] = {
    request.authContext match {
      case Agent(_, _, _, enrolments) => enrolments.getEnrolment("HMRC-AS-AGENT").flatMap(_.getIdentifier("AgentReferenceNumber")).map(_.value)
      case c: AuthContext => c.agentReference
    }
  }

  def getClientId(implicit request: AuthRequest[_]): String = request.headers.get("X-Client-Id").getOrElse("N/A")

}

class AuthRequest[A](val authContext: AuthContext, request: Request[A]) extends WrappedRequest[A](request) 
Example 44
Source File: Response.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.vatapi.resources.wrappers

import play.api.Logger
import play.api.http.Status
import play.api.libs.json.JsValue
import uk.gov.hmrc.http.HttpResponse
import uk.gov.hmrc.vatapi.models.Errors
import uk.gov.hmrc.vatapi.models.des.DesError
import uk.gov.hmrc.vatapi.models.des.DesErrorCode.{DesErrorCode, _}
import uk.gov.hmrc.vatapi.resources.{AuthRequest, VatResult}
import uk.gov.hmrc.vatapi.utils.pagerDutyLogging.{Endpoint, PagerDutyLogging}

import scala.PartialFunction.{apply => _, _}
import scala.util.{Failure, Success, Try}

object Response {
  val defaultCorrelationId = "No Correlation ID"

  def getCorrelationId(httpResponse: HttpResponse): String =
    httpResponse.header("CorrelationId").getOrElse(defaultCorrelationId)
}

trait Response {

  val logger: Logger = Logger(this.getClass)
  val status: Int = underlying.status

  def underlying: HttpResponse

  def filter[A](pf: PartialFunction[Int, VatResult])(implicit endpoint: Endpoint, request: AuthRequest[A]): VatResult = {
    val statusPrefix: Int = status / 100
    statusPrefix match {
      case 4 | 5 =>
        val message = s"DES error occurred. User type: ${request.authContext.affinityGroup}\n" +
          s"Status code: ${underlying.status}\nBody: ${underlying.body}"

        PagerDutyLogging.logError(endpoint.toLoggerMessage, message, statusPrefix, logger.error(_))

        (pf orElse errorMappings orElse standardErrorMapping) (status)
      case _ => (pf andThen addCorrelationHeader) (status)
    }
  }

  private def addCorrelationHeader(result: VatResult) =
    underlying
      .header("CorrelationId")
      .fold(result)(correlationId => result.withHeaders("X-CorrelationId" -> correlationId))

  def errorMappings: PartialFunction[Int, VatResult] = empty

  private def standardErrorMapping: PartialFunction[Int, VatResult] = {
    case 404 => VatResult.FailureEmptyBody(Status.NOT_FOUND, Errors.NotFound)
    case 500 if errorCodeIsOneOf(SERVER_ERROR) => VatResult.Failure(Status.INTERNAL_SERVER_ERROR, Errors.InternalServerError)
    case 503 if errorCodeIsOneOf(SERVICE_UNAVAILABLE) => VatResult.Failure(Status.INTERNAL_SERVER_ERROR, Errors.InternalServerError)
    case _ => VatResult.Failure(Status.INTERNAL_SERVER_ERROR, Errors.InternalServerError)
  }

  def errorCodeIsOneOf(errorCodes: DesErrorCode*): Boolean = jsonOrError match {
    case Right(json) => json.asOpt[DesError].exists(errorCode => errorCodes.contains(errorCode.code))
    case Left(_) => false
  }

  def jsonOrError: Either[Throwable, JsValue] = {
    Try(underlying.json) match {
      case Success(null) => Left(new RuntimeException)
      case Success(json) => Right(json)
      case Failure(e) => Left(e)
    }
  }

  def getCorrelationId: String = Response.getCorrelationId(underlying)
} 
Example 45
Source File: AuditService.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.vatapi.services

import javax.inject.Inject
import org.joda.time.{DateTime, DateTimeZone}
import play.api.Logger
import play.api.libs.json.{Json, Writes}
import play.api.mvc.Request
import uk.gov.hmrc.http.HeaderCarrier
import uk.gov.hmrc.play.audit.AuditExtensions
import uk.gov.hmrc.play.audit.http.connector.AuditConnector
import uk.gov.hmrc.play.audit.model.ExtendedDataEvent
import uk.gov.hmrc.vatapi.models.audit.AuditEvent
import uk.gov.hmrc.vatapi.resources.BusinessResult

import scala.concurrent.ExecutionContext

class AuditService @Inject()(auditConnector: AuditConnector) {

  val logger: Logger = Logger(this.getClass)

  def audit[T](event: AuditEvent[T])(
    implicit hc: HeaderCarrier,
    fmt: Writes[T],
    request: Request[_],
    ec: ExecutionContext
  ): BusinessResult[Unit] = {

    logger.debug(s"[AuditService][audit] Generating ${event.auditType} audit event for vat-api.")

    val auditEvent =
      ExtendedDataEvent(
        auditSource = "vat-api",
        auditType = event.auditType,
        tags = AuditExtensions.auditHeaderCarrier(hc).toAuditTags(event.transactionName, request.path),
        detail = Json.toJson(event.detail),
        generatedAt = DateTime.now(DateTimeZone.UTC)
      )

    BusinessResult.success(auditConnector.sendExtendedEvent(auditEvent))

  }

} 
Example 46
Source File: NRSService.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.vatapi.services

import java.nio.charset.StandardCharsets
import org.joda.time.DateTime
import java.util.Base64

import javax.inject.Inject
import play.api.Logger
import play.api.libs.json.Json
import uk.gov.hmrc.domain.Vrn
import uk.gov.hmrc.http.HeaderCarrier
import uk.gov.hmrc.vatapi.connectors.NRSConnector
import uk.gov.hmrc.vatapi.httpparsers.NrsSubmissionHttpParser.NrsSubmissionOutcome
import uk.gov.hmrc.vatapi.models.{Metadata, NRSSubmission, SearchKeys, VatReturnDeclaration}
import uk.gov.hmrc.vatapi.resources.AuthRequest

import scala.concurrent.{ExecutionContext, Future}


class NRSService @Inject()(
                            nrsConnector: NRSConnector
                          ) {

  val logger: Logger = Logger(this.getClass)

  def submit(vrn: Vrn, submission: NRSSubmission)(implicit hc: HeaderCarrier, ec: ExecutionContext): Future[NrsSubmissionOutcome] = {
    logger.debug(s"[NRSService][submit] - Submitting payload to NRS")
    nrsConnector.submit(vrn, submission)
  }

  def convertToNrsSubmission(vrn: Vrn, payload: VatReturnDeclaration)(implicit request: AuthRequest[_]): NRSSubmission = {

    val encoder = Base64.getEncoder
    NRSSubmission(
      payload = encoder.encodeToString(Json.toJson(payload).toString.getBytes(StandardCharsets.UTF_8)),
      metadata = Metadata(
        businessId = "vat",
        notableEvent = "vat-return",
        payloadContentType = "application/json",
        payloadSha256Checksum = None,
        userSubmissionTimestamp = DateTime.now(),
        identityData = request.authContext.identityData,
        userAuthToken = request.headers.get("Authorization").get,
        headerData = Json.toJson(request.headers.toMap.map { h => h._1 -> h._2.head }),
        searchKeys = SearchKeys(
          vrn = Some(vrn),
          periodKey = Some(payload.periodKey)
        )
      )
    )
  }
} 
Example 47
Source File: VatApiDefinition.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.vatapi.controllers.definition

import javax.inject.{Inject, Singleton}
import play.api.Logger
import uk.gov.hmrc.vatapi.config.AppContext
import uk.gov.hmrc.vatapi.controllers.definition.APIStatus.APIStatus

@Singleton
class VatApiDefinition @Inject()(appContext: AppContext) {

  lazy val definition: Definition =
    Definition(
      scopes = Seq(
        Scope(
          key = readScope,
          name = "View your VAT information",
          description = "Allow read access to VAT data"
        ),
        Scope(
          key = writeScope,
          name = "Change your VAT information",
          description = "Allow write access to VAT data"
        )
      ),
      api = OldAPIDefinition(
        name = "VAT (MTD)",
        description =
          "An API for providing VAT data",
        context = appContext.apiGatewayRegistrationContext,
        versions = Seq(
          APIVersion(
            version = "1.0",
            status = buildAPIStatus("1.0"),
            endpointsEnabled = true
          )
        ),
        requiresTrust = None
      )
    )
  val logger: Logger = Logger(this.getClass)

  private val readScope = "read:vat"
  private val writeScope = "write:vat"

  private def buildAPIStatus(version: String): APIStatus = {
    appContext.apiStatus(version) match {
      case "ALPHA" => APIStatus.ALPHA
      case "BETA" => APIStatus.BETA
      case "STABLE" => APIStatus.STABLE
      case "DEPRECATED" => APIStatus.DEPRECATED
      case "RETIRED" => APIStatus.RETIRED
      case _ => logger.error(s"[ApiDefinition][buildApiStatus] no API status found in config. Reverting to alpha")
        APIStatus.ALPHA
    }
  }

} 
Example 48
Source File: NrsSubmissionHttpParser.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.vatapi.httpparsers

import play.api.Logger
import play.api.http.Status._
import play.api.libs.json.{Json, Reads, Writes, _}
import uk.gov.hmrc.http.{HttpReads, HttpResponse}


object NrsSubmissionHttpParser {

  val logger: Logger = Logger(this.getClass)

  type NrsSubmissionOutcome = Either[NrsSubmissionFailure, NRSData]

  implicit object NrsSubmissionOutcomeReads extends HttpReads[NrsSubmissionOutcome] {
    override def read(method: String, url: String, response: HttpResponse): NrsSubmissionOutcome = {
      logger.debug(s"[NrsSubmissionHttpParser][#reads] - Reading NRS Response")
      response.status match {
        case BAD_REQUEST =>
          logger.warn(s"[NrsSubmissionHttpParser][#reads] - BAD_REQUEST status from NRS Response")
          Left(NrsError)
        case ACCEPTED =>
          response.json.validate[NRSData].fold(
            invalid => {
              logger.warn(s"[NrsSubmissionHttpParser][#reads] - Error reading NRS Response: $invalid")
              Left(NrsError)
            },
            valid => {
              logger.debug(s"[NrsSubmissionHttpParser][#reads] - Retrieved NRS Data: $valid")
              Right(valid)
            }
          )
        case e =>
          logger.debug(s"[NrsSubmissionHttpParser][#reads] - Retrieved NRS status : $e")
          Right(EmptyNrsData)
      }
    }
  }

}

sealed trait NrsSubmissionFailure

case class NRSData(nrSubmissionId: String,
                   cadesTSignature: String,
                   timestamp: String
                  )

object EmptyNrsData extends NRSData("", "This has been deprecated - DO NOT USE", "")

object NRSData {
  implicit val writes: Writes[NRSData] = Json.writes[NRSData]
  implicit val reads: Reads[NRSData] = {
    (__ \ "nrSubmissionId").read[String].map { id =>
      NRSData.apply(id, "This has been deprecated - DO NOT USE", "")
    }
  }
}

case object NrsError extends NrsSubmissionFailure 
Example 49
Source File: FinancialDataConnector.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.vatapi.connectors

import javax.inject.Inject
import play.api.Logger
import uk.gov.hmrc.domain.Vrn
import uk.gov.hmrc.http.HeaderCarrier
import uk.gov.hmrc.play.bootstrap.http.DefaultHttpClient
import uk.gov.hmrc.vatapi.config.AppContext
import uk.gov.hmrc.vatapi.models.FinancialDataQueryParams
import uk.gov.hmrc.vatapi.resources.wrappers.FinancialDataResponse

import scala.concurrent.{ExecutionContext, Future}

class FinancialDataConnector @Inject()(
                                        override val http: DefaultHttpClient,
                                        override val appContext: AppContext
                                      ) extends BaseConnector {

  private lazy val baseUrl: String = s"${appContext.desUrl}/enterprise/financial-data"
  val logger: Logger = Logger(this.getClass)

  def getFinancialData(vrn: Vrn, params: FinancialDataQueryParams)(implicit hc: HeaderCarrier, ec: ExecutionContext): Future[FinancialDataResponse] = {

    logger.debug(s"[FinancialDataConnector][getFinancialData] Retrieve financial data for VRN $vrn.")

    val queryString = s"dateFrom=${params.from}&dateTo=${params.to}&"
    httpGet[FinancialDataResponse](
      s"$baseUrl/VRN/$vrn/VATC?${queryString}onlyOpenItems=false&includeLocks=false&calculateAccruedInterest=true&customerPaymentInformation=true", FinancialDataResponse)
  }
} 
Example 50
Source File: ObligationsConnector.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.vatapi.connectors

import javax.inject.Inject
import play.api.Logger
import uk.gov.hmrc.domain.Vrn
import uk.gov.hmrc.http.HeaderCarrier
import uk.gov.hmrc.play.bootstrap.http.DefaultHttpClient
import uk.gov.hmrc.vatapi.config.AppContext
import uk.gov.hmrc.vatapi.models.ObligationsQueryParams
import uk.gov.hmrc.vatapi.resources.wrappers.ObligationsResponse

import scala.concurrent.{ExecutionContext, Future}

class ObligationsConnector @Inject()(
                                      override val http: DefaultHttpClient,
                                      override val appContext: AppContext
                                    )(implicit ec: ExecutionContext) extends BaseConnector {

  private val logger: Logger = Logger(this.getClass)

  def get(vrn: Vrn, queryParams: ObligationsQueryParams)(implicit hc: HeaderCarrier): Future[ObligationsResponse] = {
    logger.debug(s"[ObligationsConnector][get] Retrieve obligations for VRN $vrn with the given query parameters.")

    httpGet[ObligationsResponse](appContext.desUrl + s"/enterprise/obligation-data/vrn/$vrn/VATC?${queryParams.queryString}", ObligationsResponse)
  }
} 
Example 51
Source File: NRSConnector.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up

package uk.gov.hmrc.vatapi.connectors

import java.util.concurrent.TimeoutException

import javax.inject.Inject
import play.api.Logger
import play.api.libs.json.{JsValue, Json, Writes}
import play.api.libs.ws.WSClient
import uk.gov.hmrc.domain.Vrn
import uk.gov.hmrc.http._
import uk.gov.hmrc.play.bootstrap.http.DefaultHttpClient
import uk.gov.hmrc.vatapi.config.AppContext
import uk.gov.hmrc.vatapi.httpparsers.EmptyNrsData
import uk.gov.hmrc.vatapi.httpparsers.NrsSubmissionHttpParser.{NrsSubmissionOutcome, NrsSubmissionOutcomeReads}
import uk.gov.hmrc.vatapi.models.NRSSubmission

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


class NRSConnector @Inject()(
                              override val http: DefaultHttpClient,
                              override val appContext: AppContext,
                              ws: WSClient
                            ) extends BaseConnector {

  val logger: Logger = Logger(this.getClass)
  val nrsSubmissionUrl: String => String = vrn => s"${appContext.nrsServiceUrl}/submission"
  val nrsMaxTimeout: Duration = appContext.nrsMaxTimeoutMillis.milliseconds

  private val xApiKeyHeader = "X-API-Key"

  def submit(vrn: Vrn, nrsSubmission: NRSSubmission)(implicit hc: HeaderCarrier, ec: ExecutionContext): Future[NrsSubmissionOutcome] = {

    logger.debug(s"[NRSConnector][submit] - Submission to NRS for 9 box vat return for VRN: $vrn")

    val nrsResponse = {
      val submitUrl = nrsSubmissionUrl(vrn.toString)
      val headers = hc.withExtraHeaders(xApiKeyHeader -> s"${appContext.xApiKey}", "User-Agent" -> appContext.appName).headers

      implicit val nrsWrites = implicitly[Writes[NRSSubmission]]

      ws.url(submitUrl)
        .withHttpHeaders(headers: _*)
        .withRequestTimeout(nrsMaxTimeout)
        .post(Json.toJson(nrsSubmission))
    }

    nrsResponse.map { res =>

      val resJson = Try(res.json) match {
        case Success(json: JsValue) => Some(json)
        case _ => None
      }

      val httpResponse = HttpResponse(
        res.status,
        resJson,
        res.headers,
        None
      )

      Logger.debug(s"[NRSConnector][submit] - NRS Call succeeded")

      NrsSubmissionOutcomeReads.read("", "", httpResponse)

    }.recover {
      case e: TimeoutException => {
        logger.warn(s"[NRSConnector][submit] - NRS Call timed out for VRN: $vrn - $e")
        Right(EmptyNrsData)
      }
    }
  }
} 
Example 52
Source File: MetricsRepoActor.scala    From prometheus-opentsdb-exporter   with Apache License 2.0 5 votes vote down vote up
package actors

import akka.actor._

import play.api.Logger

import models.Metric


object MetricsRepoActor {
  def props(listener: Option[ActorRef] = None): Props = Props(new MetricsRepoActor(listener))
  def name = "metrics-repo"

  sealed trait MetricsRepoMessage
  case class RegisterMetrics(metrics: Seq[Metric]) extends MetricsRepoMessage
  case object GetMetrics extends MetricsRepoMessage
  case object ResetMetrics extends MetricsRepoMessage
  case class MetricsList(metrics: Seq[Metric]) extends MetricsRepoMessage
}

class MetricsRepoActor(listener: Option[ActorRef] = None) extends Actor {
  import actors.MetricsRepoActor._

  private [this] var metricsRepo: Map[String, Metric] = Map.empty

  override def receive = {
    case RegisterMetrics(metrics) =>
      metrics.foreach { metric =>
        Logger.info(s"Registering metric: ${metric.name}")

        val newMetric = metricsRepo.get(metric.name).map { oldMetric =>
          val newQuery = oldMetric.query.copy(mappings = oldMetric.query.mappings ++ metric.query.mappings)
          oldMetric.copy(query = newQuery)
        }.getOrElse(metric)

        metricsRepo = metricsRepo + (newMetric.name -> newMetric)
      }

    case GetMetrics =>
      val metrics = MetricsList(metricsRepo.values.toList)
      sender ! metrics
      listener.foreach(_ ! metrics)

    case ResetMetrics =>
      Logger.info("Resetting metrics.")
      metricsRepo = Map.empty
  }
} 
Example 53
Source File: MetricsRepoService.scala    From prometheus-opentsdb-exporter   with Apache License 2.0 5 votes vote down vote up
package services

import scala.concurrent.duration._

import java.io.{File, FileInputStream}
import javax.inject._

import akka.actor.{ActorNotFound, ActorSystem}
import akka.util.Timeout

import play.api.libs.json._
import play.api.{Configuration, Logger}

import models.Metric
import actors.MetricsRepoActor
import actors.MetricsRepoActor.{RegisterMetrics, ResetMetrics}


@Singleton
class MetricsRepoService @Inject()(
  configuration: Configuration,
  system: ActorSystem
) {
  private implicit val to: Timeout = 5 seconds

  private val metricsDir = configuration.getString("metrics.dir").get

  private implicit val ec = system.dispatcher

  private def getListOfFiles(dir: String):List[File] = {
    val d = new File(dir)
    if (d.exists && d.isDirectory) {
      d.listFiles.filter(_.isFile).toList.sortBy(_.getAbsolutePath)
    } else {
      Logger.warn(s"Metrics dir not found: $dir")
      Logger.info(s"Working dir: ${new File(".").getAbsolutePath}")
      List[File]()
    }
  }

  lazy val metricsRepo = {
    Logger.info(s"Initializing the metrics repo.")
    system.actorSelection(s"${MetricsRepoActor.name}")
      .resolveOne()
      .recover {
        case ActorNotFound(_) =>
          system.actorOf(MetricsRepoActor.props(), MetricsRepoActor.name)
      }
  }

  def reloadMetrics(): Unit = {
    metricsRepo.foreach { mr =>
      Logger.info("Loading metrics definitions.")

      mr ! ResetMetrics

      getListOfFiles(metricsDir).foreach { f =>
        Logger.info(s"Loading metrics definitions from: ${f.getAbsolutePath}")

        Json.parse(new FileInputStream(f)).validate[Seq[Metric]].fold(
          valid = metrics => {
            Logger.info("Metrics definitions parsed and validating. Reloading...")
            mr ! RegisterMetrics(metrics)
          },
          invalid = errors =>
            Logger.error(errors.mkString("\n"))
        )
      }
    }
  }

  reloadMetrics()
} 
Example 54
Source File: CityController.scala    From play-reactive-mongo-db   with MIT License 5 votes vote down vote up
package controllers

import javax.inject._

import models.City
import play.api.Logger
import play.api.libs.json._
import play.api.mvc._
import play.modules.reactivemongo._
import reactivemongo.api.ReadPreference
import reactivemongo.play.json._
import reactivemongo.play.json.collection._
import utils.Errors

import scala.concurrent.{ExecutionContext, Future}



@Singleton
class CityController @Inject()(val reactiveMongoApi: ReactiveMongoApi)(implicit exec: ExecutionContext) extends Controller with MongoController with ReactiveMongoComponents {

  def citiesFuture: Future[JSONCollection] = database.map(_.collection[JSONCollection]("city"))

  def create(name: String, population: Int) = Action.async {
    for {
      cities <- citiesFuture
      lastError <- cities.insert(City(name, population))
    } yield
      Ok("Mongo LastError: %s".format(lastError))
  }

  def createFromJson = Action.async(parse.json) { request =>
    Json.fromJson[City](request.body) match {
      case JsSuccess(city, _) =>
        for {
          cities <- citiesFuture
          lastError <- cities.insert(city)
        } yield {
          Logger.debug(s"Successfully inserted with LastError: $lastError")
          Created("Created 1 city")
        }
      case JsError(errors) =>
        Future.successful(BadRequest("Could not build a city from the json provided. " + Errors.show(errors)))
    }
  }

  def createBulkFromJson = Action.async(parse.json) { request =>
    Json.fromJson[Seq[City]](request.body) match {
      case JsSuccess(newCities, _) =>
        citiesFuture.flatMap { cities =>
          val documents = newCities.map(implicitly[cities.ImplicitlyDocumentProducer](_))

          cities.bulkInsert(ordered = true)(documents: _*).map { multiResult =>
            Logger.debug(s"Successfully inserted with multiResult: $multiResult")
            Created(s"Created ${multiResult.n} cities")
          }
        }
      case JsError(errors) =>
        Future.successful(BadRequest("Could not build a city from the json provided. " + Errors.show(errors)))
    }
  }

  def findByName(name: String) = Action.async {
    // let's do our query
    val futureCitiesList: Future[List[City]] = citiesFuture.flatMap {
      // find all cities with name `name`
      _.find(Json.obj("name" -> name)).
      // perform the query and get a cursor of JsObject
      cursor[City](ReadPreference.primary).
      // Coollect the results as a list
      collect[List]()
    }

    // everything's ok! Let's reply with a JsValue
    futureCitiesList.map { cities =>
      Ok(Json.toJson(cities))
    }
  }
} 
Example 55
Source File: PersonController.scala    From play-reactive-mongo-db   with MIT License 5 votes vote down vote up
package controllers

import javax.inject._

import play.api.Logger
import play.api.libs.functional.syntax._
import play.api.libs.json.Reads._
import play.api.libs.json._
import play.api.mvc._
import play.modules.reactivemongo._
import reactivemongo.api.ReadPreference
import reactivemongo.play.json._
import reactivemongo.play.json.collection.JSONCollection

import scala.concurrent.{ExecutionContext, Future}


@Singleton
class PersonController @Inject()(val reactiveMongoApi: ReactiveMongoApi)(implicit exec: ExecutionContext) extends Controller with MongoController with ReactiveMongoComponents {

  val transformer: Reads[JsObject] =
    Reads.jsPickBranch[JsString](__ \ "name") and
      Reads.jsPickBranch[JsNumber](__ \ "age") and
      Reads.jsPut(__ \ "created", JsNumber(new java.util.Date().getTime())) reduce

  def personsFuture: Future[JSONCollection] = database.map(_.collection[JSONCollection]("persons"))

  def create(name: String, age: Int) = Action.async {
    val json = Json.obj(
      "name" -> name,
      "age" -> age,
      "created" -> new java.util.Date().getTime())

    for {
      persons <- personsFuture
      lastError <- persons.insert(json)
    } yield Ok("Mongo LastError: %s".format(lastError))

  }

  def createFromJson = Action.async(parse.json) { request =>
    request.body.transform(transformer) match {
      case JsSuccess(person, _) =>
      for {
        persons <- personsFuture
        lastError <- persons.insert(person)
      }
      yield {
        Logger.debug(s"Successfully inserted with LastError: $lastError")
        Created("Created 1 person")
      }
      case _ =>
        Future.successful(BadRequest("invalid json"))
    }
  }

  def createBulkFromJson = Action.async(parse.json) { request =>
    //Transformation silent in case of failures.
    val documents = for {
      persons       <- request.body.asOpt[JsArray].toStream
      maybePerson   <- persons.value
      validPerson   <- maybePerson.transform(transformer).asOpt.toList
    } yield validPerson

    for {
      persons <- personsFuture
      multiResult <- persons.bulkInsert(documents = documents, ordered = true)
    } yield {
      Logger.debug(s"Successfully inserted with multiResult: $multiResult")
      Created(s"Created ${multiResult.n} person")
    }
  }

  def findByName(name: String) = Action.async {
    // let's do our query
    val cursor: Future[List[JsObject]] = personsFuture.flatMap{ persons =>
      // find all people with name `name`
      persons.find(Json.obj("name" -> name)).
      // sort them by creation date
      sort(Json.obj("created" -> -1)).
      // perform the query and get a cursor of JsObject
      cursor[JsObject](ReadPreference.primary).collect[List]()
  }

    // everything's ok! Let's reply with a JsValue
    cursor.map { persons =>
      Ok(Json.toJson(persons))
    }
  }
} 
Example 56
Source File: HomeController.scala    From Aton   with GNU General Public License v3.0 5 votes vote down vote up
package controllers

import akka.actor.{ActorRef, ActorSystem}
import com.google.inject.name.Named
import com.google.inject.{Inject, Singleton}
import dao.{DatabaseInitializer, LaboratoryDAO, UserDAO}
import model.{Role, User}
import play.api.{Environment, Logger}
import play.api.i18n.MessagesApi
import services.{LaboratoryService, UserService}
import views.html._

import scala.concurrent.{Await, ExecutionContext}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._


@Singleton
class HomeController @Inject()(databaseInitializer: DatabaseInitializer, laboratoryService : LaboratoryService, @Named("computerChecker") computerChecker: ActorRef, actorSystem: ActorSystem)(implicit userService: UserService, executionContext: ExecutionContext, environment: Environment) extends ControllerWithNoAuthRequired {
  val logger = Logger("HomeController")

  play.Logger.debug("Configuring Computer Checker...")
  actorSystem.scheduler.schedule(0.microseconds,5.minutes, computerChecker,"Execute")
  play.Logger.debug("Computer Checker configured.")

  logger.debug("Initializing database")
  Await.result(databaseInitializer.initialize(), 2.seconds)
  logger.debug("Database initialized")

  def home = AsyncStack { implicit request =>
    play.Logger.debug("Logged user: " + loggedIn)
    implicit val (username: Option[String], isAdmin: Boolean) = loggedIn match {
      case Some(User(usernameString, password, Some(name), role)) => (Some(name), role == Role.Administrator)
      case Some(User(usernameString, password, None, role)) => (Some(usernameString), role == Role.Administrator)
      case _ => (None, false)
    }
    logger.debug("Petición de listar todos los laboratorios con el siguiente request recibida " + request)
    logger.debug("User: " + username + ", is admin: " + isAdmin)
    laboratoryService.listAll.map { _ =>
      Ok(index("Aton"))
    }
  }

  def about = StackAction { implicit request =>
    implicit val (username: Option[String], isAdmin: Boolean) = loggedIn match {
      case Some(User(usernameString, password, Some(name), role)) => (Some(name), role == Role.Administrator)
      case Some(User(usernameString, password, None, role)) => (Some(usernameString), role == Role.Administrator)
      case _ => (None, false)
    }

    Ok//(index(messagesApi("about"),views.html.about()))
  }
} 
Example 57
Source File: Migration.scala    From Cortex   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.thp.cortex.models

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

import play.api.Logger
import play.api.libs.json.{JsNull, JsNumber, JsString, JsValue, Json}

import org.thp.cortex.services.{OrganizationSrv, UserSrv, WorkerSrv}

import org.elastic4play.controllers.Fields
import org.elastic4play.services.Operation._
import org.elastic4play.services.{DatabaseState, IndexType, MigrationOperations, Operation}
import org.elastic4play.utils.Hasher

@Singleton
class Migration @Inject()(userSrv: UserSrv, organizationSrv: OrganizationSrv, workerSrv: WorkerSrv, implicit val ec: ExecutionContext)
    extends MigrationOperations {

  lazy val logger                                = Logger(getClass)
  def beginMigration(version: Int): Future[Unit] = Future.successful(())

  def endMigration(version: Int): Future[Unit] =
    userSrv.inInitAuthContext { implicit authContext ⇒
      organizationSrv
        .create(Fields(Json.obj("name" → "cortex", "description" → "Default organization", "status" → "Active")))
        .transform(_ ⇒ Success(())) // ignore errors (already exist)
    }

  override def indexType(version: Int): IndexType.Value = if (version > 3) IndexType.indexWithoutMappingTypes else IndexType.indexWithMappingTypes

  val operations: PartialFunction[DatabaseState, Seq[Operation]] = {
    case DatabaseState(1) ⇒
      val hasher = Hasher("MD5")
      Seq(
        // add type to analyzer
        addAttribute("analyzer", "type" → JsString("analyzer")),
        renameAttribute("job", "workerDefinitionId", "analyzerDefinitionId"),
        renameAttribute("job", "workerId", "analyzerId"),
        renameAttribute("job", "workerName", "analyzerName"),
        addAttribute("job", "type"          → JsString(WorkerType.analyzer.toString)),
        addAttribute("report", "operations" → JsString("[]")),
        renameEntity("analyzer", "worker"),
        renameAttribute("worker", "workerDefinitionId", "analyzerDefinitionId"),
        addAttribute("worker", "type" → JsString(WorkerType.analyzer.toString)),
        mapEntity("worker") { worker ⇒
          val id = for {
            organizationId ← (worker \ "_parent").asOpt[String]
            name           ← (worker \ "name").asOpt[String]
            tpe            ← (worker \ "type").asOpt[String]
          } yield hasher.fromString(s"${organizationId}_${name}_$tpe").head.toString
          worker + ("_id" → JsString(id.getOrElse("<null>")))
        },
        renameEntity("analyzerConfig", "workerConfig"),
        addAttribute("workerConfig", "type" → JsString(WorkerType.analyzer.toString))
      )

    case DatabaseState(2) ⇒
      Seq(mapEntity("worker") { worker ⇒
        val definitionId = (worker \ "workerDefinitionId").asOpt[String]
        definitionId
          .flatMap(workerSrv.getDefinition(_).toOption)
          .fold {
            logger.warn(s"no definition found for worker ${definitionId.getOrElse(worker)}. You should probably have to disable and re-enable it")
            worker
          } { definition ⇒
            worker +
              ("version"     → JsString(definition.version)) +
              ("author"      → JsString(definition.author)) +
              ("url"         → JsString(definition.url)) +
              ("license"     → JsString(definition.license)) +
              ("command"     → definition.command.fold[JsValue](JsNull)(c ⇒ JsString(c.toString))) +
              ("dockerImage" → definition.dockerImage.fold[JsValue](JsNull)(JsString.apply)) +
              ("baseConfig"  → definition.baseConfiguration.fold[JsValue](JsNull)(JsString.apply))
          }
      })

    case DatabaseState(3) ⇒
      Seq(
        mapEntity("sequence") { seq ⇒
          val oldId   = (seq \ "_id").as[String]
          val counter = (seq \ "counter").as[JsNumber]
          seq - "counter" - "_routing" +
            ("_id"             → JsString("sequence_" + oldId)) +
            ("sequenceCounter" → counter)
        }
      )
  }
} 
Example 58
Source File: Organization.scala    From Cortex   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.thp.cortex.models

import javax.inject.{Inject, Provider, Singleton}

import scala.concurrent.{ExecutionContext, Future}

import play.api.Logger
import play.api.libs.json.{JsNumber, JsObject, JsString, Json}

import org.elastic4play.models.JsonFormat.enumFormat
import org.elastic4play.models.{AttributeDef, BaseEntity, EntityDef, HiveEnumeration, ModelDef, AttributeFormat ⇒ F, AttributeOption ⇒ O}
import org.elastic4play.services.FindSrv

object OrganizationStatus extends Enumeration with HiveEnumeration {
  type Type = Value
  val Active, Locked = Value
  implicit val reads = enumFormat(this)
}

trait OrganizationAttributes { _: AttributeDef ⇒
  val name        = attribute("name", F.stringFmt, "Organization name", O.form)
  val _id         = attribute("_id", F.stringFmt, "Organization name", O.model)
  val description = attribute("description", F.textFmt, "Organization description")
  val status      = attribute("status", F.enumFmt(OrganizationStatus), "Status of the organization", OrganizationStatus.Active)
}

@Singleton
class OrganizationModel @Inject()(
    findSrv: FindSrv,
    userModelProvider: Provider[UserModel],
    workerModelProvider: Provider[WorkerModel],
    implicit val ec: ExecutionContext
) extends ModelDef[OrganizationModel, Organization]("organization", "Organization", "/organization")
    with OrganizationAttributes
    with AuditedModel {

  private lazy val logger      = Logger(getClass)
  lazy val userModel           = userModelProvider.get
  lazy val workerModel         = workerModelProvider.get
  override def removeAttribute = Json.obj("status" → "Locked")

  override def creationHook(parent: Option[BaseEntity], attrs: JsObject): Future[JsObject] =
    Future.successful {
      (attrs \ "name").asOpt[JsString].fold(attrs) { orgName ⇒
        attrs - "name" + ("_id" → orgName)
      }
    }

  private def buildUserStats(organization: Organization): Future[JsObject] = {
    import org.elastic4play.services.QueryDSL._
    findSrv(userModel, "organization" ~= organization.id, groupByField("status", selectCount))
      .map { userStatsJson ⇒
        val (userCount, userStats) = userStatsJson.value.foldLeft((0L, JsObject.empty)) {
          case ((total, s), (key, value)) ⇒
            val count = (value \ "count").as[Long]
            (total + count, s + (key → JsNumber(count)))
        }
        Json.obj("users" → (userStats + ("total" → JsNumber(userCount))))
      }
  }

  private def buildWorkerStats(organization: Organization): Future[JsObject] = {
    import org.elastic4play.services.QueryDSL._
    findSrv(workerModel, withParent(organization), groupByField("status", selectCount))
      .map { workerStatsJson ⇒
        val (workerCount, workerStats) = workerStatsJson.value.foldLeft((0L, JsObject.empty)) {
          case ((total, s), (key, value)) ⇒
            val count = (value \ "count").as[Long]
            (total + count, s + (key → JsNumber(count)))
        }
        Json.obj("workers" → (workerStats + ("total" → JsNumber(workerCount))))
      }
  }

  override def getStats(entity: BaseEntity): Future[JsObject] =
    entity match {
      case organization: Organization ⇒
        for {
          userStats   ← buildUserStats(organization)
          workerStats ← buildWorkerStats(organization)
        } yield userStats ++ workerStats
      case other ⇒
        logger.warn(s"Request caseStats from a non-case entity ?! ${other.getClass}:$other")
        Future.successful(Json.obj())
    }

}

class Organization(model: OrganizationModel, attributes: JsObject)
    extends EntityDef[OrganizationModel, Organization](model, attributes)
    with OrganizationAttributes {
  override def toJson: JsObject = super.toJson + ("name" → JsString(id))
} 
Example 59
Source File: AuditSrv.scala    From Cortex   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.thp.cortex.services

import javax.inject.{Inject, Singleton}

import scala.concurrent.ExecutionContext
import scala.concurrent.duration.FiniteDuration

import play.api.Logger

import akka.actor.{Actor, ActorRef}
import org.thp.cortex.models.JobStatus

import org.elastic4play.models.BaseEntity
import org.elastic4play.services._

object AuditActor {
  case class Register(jobId: String, timeout: FiniteDuration)
  case class Unregister(jobId: String, actorRef: ActorRef)
  case class JobEnded(jobId: String, status: JobStatus.Type)
}

@Singleton
class AuditActor @Inject()(eventSrv: EventSrv, implicit val ec: ExecutionContext) extends Actor {

  import AuditActor._

  object EntityExtractor {
    def unapply(e: BaseEntity) = Some((e.model, e.id, e.routing))
  }
  var registration                    = Map.empty[String, Seq[ActorRef]]
  private[AuditActor] lazy val logger = Logger(getClass)

  override def preStart(): Unit = {
    eventSrv.subscribe(self, classOf[EventMessage])
    super.preStart()
  }

  override def postStop(): Unit = {
    eventSrv.unsubscribe(self)
    super.postStop()
  }

  override def receive: Receive = {
    case Register(jobId, timeout) ⇒
      logger.info(s"Register new listener for job $jobId ($sender)")
      val newActorList = registration.getOrElse(jobId, Nil) :+ sender
      registration += (jobId → newActorList)
      context.system.scheduler.scheduleOnce(timeout, self, Unregister(jobId, sender))

    case Unregister(jobId, actorRef) ⇒
      logger.info(s"Unregister listener for job $jobId ($actorRef)")
      val newActorList = registration.getOrElse(jobId, Nil).filterNot(_ == actorRef)
      registration += (jobId → newActorList)

    case AuditOperation(EntityExtractor(model, id, routing), action, details, authContext, date) ⇒
      if (model.modelName == "job" && action == AuditableAction.Update) {
        logger.info(s"Job $id has be updated (${details \ "status"})")
        val status = (details \ "status").asOpt[JobStatus.Type].getOrElse(JobStatus.InProgress)
        if (status != JobStatus.InProgress) registration.getOrElse(id, Nil).foreach { aref ⇒
          aref ! JobEnded(id, status)
        }
      }
  }
} 
Example 60
Source File: CSRFFilter.scala    From Cortex   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.thp.cortex.services

import javax.inject.{Inject, Provider, Singleton}

import play.api.Logger
import play.api.http.SessionConfiguration
import play.api.libs.crypto.CSRFTokenSigner
import play.filters.csrf.{CSRFFilter ⇒ PCSRFFilter}
import play.api.mvc.RequestHeader
import play.filters.csrf.CSRF.{ErrorHandler ⇒ CSRFErrorHandler, TokenProvider}
import play.filters.csrf.CSRFConfig

import akka.stream.Materializer

object CSRFFilter {
  private[CSRFFilter] lazy val logger = Logger(getClass)

  def shouldProtect(request: RequestHeader): Boolean = {
    val isLogin     = request.uri.startsWith("/api/login")
    val isApi       = request.uri.startsWith("/api")
    val isInSession = request.session.data.nonEmpty
    val check       = !isLogin && isApi && isInSession
    logger.debug(s"[csrf] uri ${request.uri} (isLogin=$isLogin, isApi=$isApi, isInSession=$isInSession): ${if (check) "" else "don't"} check")
    check
  }

}

@Singleton
class CSRFFilter @Inject()(
    config: Provider[CSRFConfig],
    tokenSignerProvider: Provider[CSRFTokenSigner],
    sessionConfiguration: SessionConfiguration,
    tokenProvider: TokenProvider,
    errorHandler: CSRFErrorHandler
)(mat: Materializer)
    extends PCSRFFilter(
      config.get.copy(shouldProtect = CSRFFilter.shouldProtect),
      tokenSignerProvider.get,
      sessionConfiguration,
      tokenProvider,
      errorHandler
    )(mat) 
Example 61
Source File: CortexAuthSrv.scala    From Cortex   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.thp.cortex.services

import javax.inject.{Inject, Singleton}

import scala.collection.immutable
import scala.concurrent.ExecutionContext

import play.api.{Configuration, Logger}

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

object CortexAuthSrv {
  private[CortexAuthSrv] lazy val logger = Logger(getClass)

  def getAuthSrv(authTypes: Seq[String], authModules: immutable.Set[AuthSrv]): Seq[AuthSrv] =
    ("key" +: authTypes.filterNot(_ == "key"))
      .flatMap { authType ⇒
        authModules
          .find(_.name == authType)
          .orElse {
            logger.error(s"Authentication module $authType not found")
            None
          }
      }
}

@Singleton
class CortexAuthSrv @Inject()(
    configuration: Configuration,
    authModules: immutable.Set[AuthSrv],
    userSrv: UserSrv,
    implicit override val ec: ExecutionContext
) extends MultiAuthSrv(
      CortexAuthSrv.getAuthSrv(configuration.getDeprecated[Option[Seq[String]]]("auth.provider", "auth.type").getOrElse(Seq("local")), authModules),
      ec
    ) {

  // Uncomment the following lines if you want to prevent user with key to use password to authenticate
  //  override def authenticate(username: String, password: String)(implicit request: RequestHeader): Future[AuthContext] =
  //    userSrv.get(username)
  //      .transformWith {
  //        case Success(user) if user.key().isDefined ⇒ Future.failed(AuthenticationError("Authentication by password is not permitted for user with key"))
  //        case _: Success[_]                         ⇒ super.authenticate(username, password)
  //        case _: Failure[_]                         ⇒ Future.failed(AuthenticationError("Authentication failure"))
  //      }
} 
Example 62
Source File: ProcessJobRunnerSrv.scala    From Cortex   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.thp.cortex.services

import java.nio.charset.StandardCharsets
import java.nio.file.{Files, Path, Paths}

import akka.actor.ActorSystem
import javax.inject.{Inject, Singleton}
import org.elastic4play.utils.RichFuture
import org.thp.cortex.models._
import play.api.Logger
import play.api.libs.json.Json

import scala.concurrent.duration.FiniteDuration
import scala.concurrent.{ExecutionContext, Future}
import scala.sys.process.{Process, ProcessLogger, _}
import scala.util.Try

@Singleton
class ProcessJobRunnerSrv @Inject()(implicit val system: ActorSystem) {

  lazy val logger = Logger(getClass)

  private val pythonPackageVersionRegex = "^Version: ([0-9]*)\\.([0-9]*)\\.([0-9]*)".r

  def checkCortexUtilsVersion(pythonVersion: String): Option[(Int, Int, Int)] =
    Try {
      (s"pip$pythonVersion" :: "show" :: "cortexutils" :: Nil)
        .lineStream
        .collectFirst {
          case pythonPackageVersionRegex(major, minor, patch) ⇒ (major.toInt, minor.toInt, patch.toInt)
        }
    }.getOrElse(None)

  def run(jobDirectory: Path, command: String, job: Job, timeout: Option[FiniteDuration])(implicit ec: ExecutionContext): Future[Unit] = {
    val baseDirectory = Paths.get(command).getParent.getParent
    val output        = StringBuilder.newBuilder
    logger.info(s"Execute $command in $baseDirectory, timeout is ${timeout.fold("none")(_.toString)}")
    val process = Process(Seq(command, jobDirectory.toString), baseDirectory.toFile)
      .run(ProcessLogger { s ⇒
        logger.info(s"  Job ${job.id}: $s")
        output ++= s
      })
    val execution = Future
      .apply {
        process.exitValue()
        ()
      }
      .map { _ ⇒
        val outputFile = jobDirectory.resolve("output").resolve("output.json")
        if (!Files.exists(outputFile) || Files.size(outputFile) == 0) {
          val report = Json.obj("success" → false, "errorMessage" → output.toString)
          Files.write(outputFile, report.toString.getBytes(StandardCharsets.UTF_8))
        }
        ()
      }
      .recoverWith {
        case error ⇒
          logger.error(s"Execution of command $command failed", error)
          Future.apply {
            val report = Json.obj("success" → false, "errorMessage" → s"${error.getMessage}\n$output")
            Files.write(jobDirectory.resolve("output").resolve("output.json"), report.toString.getBytes(StandardCharsets.UTF_8))
            ()
          }
      }
    timeout.fold(execution)(t ⇒ execution.withTimeout(t, killProcess(process)))
  }

  def killProcess(process: Process): Unit = {
    logger.info("Timeout reached, killing process")
    process.destroy()
  }
} 
Example 63
Source File: MispCtrl.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
import org.elastic4play.controllers.{Authenticated, Fields, FieldsBodyParser, Renderer}
import org.thp.cortex.models.Roles
import org.thp.cortex.services.{MispSrv, WorkerSrv}
import play.api.Logger
import play.api.libs.json.{JsObject, JsValue}
import play.api.mvc._

import scala.concurrent.{ExecutionContext, Future}

class MispCtrl @Inject()(
    mispSrv: MispSrv,
    analyzerSrv: WorkerSrv,
    authenticated: Authenticated,
    fieldsBodyParser: FieldsBodyParser,
    renderer: Renderer,
    components: ControllerComponents,
    implicit val ec: ExecutionContext
) extends AbstractController(components) {

  private[MispCtrl] lazy val logger = Logger(getClass)

  def modules: Action[Fields] = authenticated(Roles.read).async(fieldsBodyParser) { implicit request ⇒
    val (analyzers, analyzerCount) = mispSrv.moduleList
    renderer.toOutput(OK, analyzers, analyzerCount)
  }

  def query: Action[JsValue] = authenticated(Roles.analyze)(parse.json).async { implicit request ⇒
    (request.body \ "module")
      .asOpt[String]
      .fold(Future.successful(BadRequest("Module parameter is not present in request"))) { module ⇒
        request
          .body
          .as[JsObject]
          .fields
          .collectFirst {
            case kv @ (k, _) if k != "module" ⇒ kv
          }
          .fold(Future.successful(BadRequest("Request doesn't contain data to analyze"))) {
            case (mispType, dataJson) ⇒
              dataJson.asOpt[String].fold(Future.successful(BadRequest("Data has invalid type (expected string)"))) { data ⇒
                mispSrv
                  .query(module, mispType, data)
                  .map(Ok(_))
              }
          }
      }
  }
} 
Example 64
Source File: OrganizationCtrl.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.Logger
import play.api.http.Status
import play.api.mvc._

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

import org.elastic4play.{BadRequestError, NotFoundError}
import org.elastic4play.controllers.{Authenticated, Fields, FieldsBodyParser, Renderer}
import org.elastic4play.models.JsonFormat.baseModelEntityWrites
import org.elastic4play.services.JsonFormat.{aggReads, queryReads}
import org.elastic4play.services.{UserSrv ⇒ _, _}

@Singleton
class OrganizationCtrl @Inject()(
    organizationSrv: OrganizationSrv,
    authSrv: AuthSrv,
    auxSrv: AuxSrv,
    userSrv: UserSrv,
    authenticated: Authenticated,
    renderer: Renderer,
    fieldsBodyParser: FieldsBodyParser,
    components: ControllerComponents,
    implicit val ec: ExecutionContext
) extends AbstractController(components)
    with Status {

  private[OrganizationCtrl] lazy val logger = Logger(getClass)

  def create: Action[Fields] = authenticated(Roles.superAdmin).async(fieldsBodyParser) { implicit request ⇒
    organizationSrv
      .create(request.body)
      .map(organization ⇒ renderer.toOutput(CREATED, organization))
  }

  def get(organizationId: String): Action[Fields] = authenticated(Roles.superAdmin, Roles.orgAdmin).async(fieldsBodyParser) { implicit request ⇒
    val withStats = request.body.getBoolean("nstats").getOrElse(false)
    (for {
      userOrganizationId ← if (request.roles.contains(Roles.superAdmin)) Future.successful(organizationId)
      else userSrv.getOrganizationId(request.userId)
      if userOrganizationId == organizationId
      organization          ← organizationSrv.get(organizationId)
      organizationWithStats ← auxSrv(organization, 0, withStats, removeUnaudited = false)
    } yield renderer.toOutput(OK, organizationWithStats))
      .recoverWith { case _: NoSuchElementException ⇒ Future.failed(NotFoundError(s"organization $organizationId not found")) }
  }

  def update(organizationId: String): Action[Fields] = authenticated(Roles.superAdmin).async(fieldsBodyParser) { implicit request ⇒
    if (organizationId == "cortex")
      Future.failed(BadRequestError("Cortex organization can't be updated"))
    else
      organizationSrv.update(organizationId, request.body).map { organization ⇒
        renderer.toOutput(OK, organization)
      }
  }

  def delete(organizationId: String): Action[AnyContent] = authenticated(Roles.superAdmin).async { implicit request ⇒
    if (organizationId == "cortex")
      Future.failed(BadRequestError("Cortex organization can't be removed"))
    else
      organizationSrv
        .delete(organizationId)
        .map(_ ⇒ NoContent)
  }

  def find: Action[Fields] = authenticated(Roles.superAdmin).async(fieldsBodyParser) { implicit 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 withStats              = request.body.getBoolean("nstats").getOrElse(false)
    val (organizations, total) = organizationSrv.find(query, range, sort)
    val organizationWithStats  = auxSrv(organizations, 0, withStats, removeUnaudited = false)
    renderer.toOutput(OK, organizationWithStats, total)
  }

  def stats(): Action[Fields] = authenticated(Roles.superAdmin).async(fieldsBodyParser) { implicit request ⇒
    val query = request.body.getValue("query").fold[QueryDef](QueryDSL.any)(_.as[QueryDef])
    val aggs  = request.body.getValue("stats").getOrElse(throw BadRequestError("Parameter \"stats\" is missing")).as[Seq[Agg]]
    organizationSrv.stats(query, aggs).map(s ⇒ Ok(s))
  }
} 
Example 65
Source File: Module.scala    From Cortex   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.thp.cortex

import java.lang.reflect.Modifier

import com.google.inject.AbstractModule
import net.codingwell.scalaguice.{ScalaModule, ScalaMultibinder}
import play.api.libs.concurrent.AkkaGuiceSupport
import play.api.{Configuration, Environment, Logger, Mode}
import scala.collection.JavaConverters._

import com.google.inject.name.Names
import org.reflections.Reflections
import org.reflections.scanners.SubTypesScanner
import org.reflections.util.ConfigurationBuilder
import org.thp.cortex.models.{AuditedModel, Migration}
import org.thp.cortex.services._

import org.elastic4play.models.BaseModelDef
import org.elastic4play.services.auth.MultiAuthSrv
import org.elastic4play.services.{UserSrv ⇒ EUserSrv, AuthSrv, MigrationOperations}
import org.thp.cortex.controllers.{AssetCtrl, AssetCtrlDev, AssetCtrlProd}
import services.mappers.{MultiUserMapperSrv, UserMapper}

class Module(environment: Environment, configuration: Configuration) extends AbstractModule with ScalaModule with AkkaGuiceSupport {

  private lazy val logger = Logger(s"module")

  override def configure(): Unit = {
    val modelBindings        = ScalaMultibinder.newSetBinder[BaseModelDef](binder)
    val auditedModelBindings = ScalaMultibinder.newSetBinder[AuditedModel](binder)
    val reflectionClasses = new Reflections(
      new ConfigurationBuilder()
        .forPackages("org.elastic4play")
        .addClassLoader(getClass.getClassLoader)
        .addClassLoader(environment.getClass.getClassLoader)
        .forPackages("org.thp.cortex")
        .setExpandSuperTypes(false)
        .setScanners(new SubTypesScanner(false))
    )

    reflectionClasses
      .getSubTypesOf(classOf[BaseModelDef])
      .asScala
      .filterNot(c ⇒ Modifier.isAbstract(c.getModifiers))
      .foreach { modelClass ⇒
        logger.info(s"Loading model $modelClass")
        modelBindings.addBinding.to(modelClass)
        if (classOf[AuditedModel].isAssignableFrom(modelClass)) {
          auditedModelBindings.addBinding.to(modelClass.asInstanceOf[Class[AuditedModel]])
        }
      }

    val authBindings = ScalaMultibinder.newSetBinder[AuthSrv](binder)
    reflectionClasses
      .getSubTypesOf(classOf[AuthSrv])
      .asScala
      .filterNot(c ⇒ Modifier.isAbstract(c.getModifiers) || c.isMemberClass)
      .filterNot(c ⇒ c == classOf[MultiAuthSrv] || c == classOf[CortexAuthSrv])
      .foreach { authSrvClass ⇒
        logger.info(s"Loading authentication module $authSrvClass")
        authBindings.addBinding.to(authSrvClass)
      }

    val ssoMapperBindings = ScalaMultibinder.newSetBinder[UserMapper](binder)
    reflectionClasses
      .getSubTypesOf(classOf[UserMapper])
      .asScala
      .filterNot(c ⇒ Modifier.isAbstract(c.getModifiers) || c.isMemberClass)
      .filterNot(c ⇒ c == classOf[MultiUserMapperSrv])
      .foreach(mapperCls ⇒ ssoMapperBindings.addBinding.to(mapperCls))

    if (environment.mode == Mode.Prod)
      bind[AssetCtrl].to[AssetCtrlProd]
    else
      bind[AssetCtrl].to[AssetCtrlDev]

    bind[EUserSrv].to[UserSrv]
    bind[Int].annotatedWith(Names.named("databaseVersion")).toInstance(models.modelVersion)
    bind[UserMapper].to[MultiUserMapperSrv]

    bind[AuthSrv].to[CortexAuthSrv]
    bind[MigrationOperations].to[Migration]
    bindActor[AuditActor]("audit")
  }
} 
Example 66
Source File: ApplicationTimer.scala    From naptime   with Apache License 2.0 5 votes vote down vote up
package services

import java.time.{Clock, Instant}
import javax.inject._
import play.api.Logger
import play.api.inject.ApplicationLifecycle
import scala.concurrent.Future


@Singleton
class ApplicationTimer @Inject() (clock: Clock, appLifecycle: ApplicationLifecycle) {

  // This code is called when the application starts.
  private val start: Instant = clock.instant
  Logger.info(s"ApplicationTimer demo: Starting application at $start.")

  // When the application starts, register a stop hook with the
  // ApplicationLifecycle object. The code inside the stop hook will
  // be run when the application stops.
  appLifecycle.addStopHook { () =>
    val stop: Instant = clock.instant
    val runningTime: Long = stop.getEpochSecond - start.getEpochSecond
    Logger.info(s"ApplicationTimer demo: Stopping application at ${clock.instant} after ${runningTime}s.")
    Future.successful(())
  }
} 
Example 67
Source File: bakerServiceImpl.scala    From Learn-Scala-Programming   with MIT License 5 votes vote down vote up
package ch15

import akka.NotUsed
import akka.stream.{Attributes, DelayOverflowStrategy}
import akka.stream.scaladsl.{BidiFlow, Flow, Source}
import ch15.model._
import com.lightbend.lagom.scaladsl.api._

import scala.concurrent.duration._
import scala.concurrent.Future

import play.api.Logger

class BakerServiceImpl extends BakerService {

  private val logger = Logger("Baker")

  override def bake: ServiceCall[Source[RawCookies, NotUsed], Source[ReadyCookies, NotUsed]] = ServiceCall { dough =>
    logger.info(s"Baking: $dough")
    Future.successful(dough.via(bakerFlow))
  }

  private val bakerFlow: Flow[RawCookies, ReadyCookies, NotUsed] =
    Baker.bakeFlow.join(Oven.bakeFlow)
}

object Baker {
  private val logger = Logger("BakerFlow")

  def bakeFlow: BidiFlow[RawCookies, RawCookies, ReadyCookies, ReadyCookies, NotUsed] = BidiFlow.fromFlows(inFlow, outFlow)

  private val inFlow = Flow[RawCookies]
    .flatMapConcat(extractFromBox)
    .grouped(Oven.ovenSize)
    .map(_.reduce(_ + _))

  private def outFlow = Flow[ReadyCookies].map { c =>
    logger.info(s"Sending to manager: $c")
    c
  }

  private def extractFromBox(c: RawCookies) = {
    logger.info(s"Extracting: $c")
    Source(List.fill(c.count)(RawCookies(1)))
  }
}

object Oven {
  private val logger = Logger("Oven")

  val ovenSize = 12
  private val bakingTime = 2.seconds

  def bakeFlow: Flow[RawCookies, ReadyCookies, NotUsed] =
    Flow[RawCookies]
      .map(bake)
      .delay(bakingTime, DelayOverflowStrategy.backpressure)
      .addAttributes(Attributes.inputBuffer(1, 1))

  private def bake(c: RawCookies): ReadyCookies = {
    logger.info(s"Baked: $c")
    assert(c.count == ovenSize)
    ReadyCookies(c.count)
  }
} 
Example 68
Source File: BoyServiceImpl.scala    From Learn-Scala-Programming   with MIT License 5 votes vote down vote up
package ch15

import ch15.ShopService._
import ch15.model._
import com.lightbend.lagom.scaladsl.api._
import play.api.Logger

import scala.concurrent.{ExecutionContext, Future}

class BoyServiceImpl(shopService: ShopService)(implicit ec: ExecutionContext)
    extends BoyService {
  private val logger = Logger("Boy")
  override def shop: ServiceCall[ShoppingList, Groceries] =
    ServiceCall(callExtApi)

  private val callExtApi: ShoppingList => Future[Groceries] = list =>
    shopService.order.invoke(Order(list)).map(_.order).recover {
      case th: Throwable =>
        logger.error(th.getMessage, th)
        Groceries(0, 0, 0, 0)
  }
} 
Example 69
Source File: OAuth2AuthProvider.scala    From play-zhewbacca   with MIT License 5 votes vote down vote up
package org.zalando.zhewbacca

import javax.inject.{Inject, Singleton}

import play.api.Logger

import scala.concurrent.{ExecutionContext, Future}


@Singleton
class OAuth2AuthProvider @Inject() (getTokenInfo: (OAuth2Token) => Future[Option[TokenInfo]])(implicit ec: ExecutionContext)
  extends AuthProvider {

  val logger: Logger = Logger("security.OAuth2AuthProvider")

  private val bearerTokenType = "Bearer"

  override def valid(token: Option[OAuth2Token], scope: Scope): Future[AuthResult] =
    token.map(validateToken(_, scope)).getOrElse(Future.successful(AuthTokenEmpty))

  private def validateToken(token: OAuth2Token, scope: Scope): Future[AuthResult] =
    getTokenInfo(token).map(validateTokenInfo(_, token, scope))

  private def validateTokenInfo(tokenInfo: Option[TokenInfo], token: OAuth2Token, scope: Scope): AuthResult = {
    tokenInfo match {
      case Some(tokenInfo @ TokenInfo(`token`.value, thatScope, `bearerTokenType`, _, _, _)) if scope.in(thatScope) =>
        AuthTokenValid(tokenInfo)
      case Some(tokenInfo @ TokenInfo(_, thatScope, tokenType, _, _, _)) =>
        logger.info(s"Token '${token.toSafeString} has insufficient scope or wrong type, token scopes are ${thatScope.names.mkString(", ")}," +
          s"token type is $tokenType")
        AuthTokenInsufficient
      case None =>
        logger.debug(s"Token '${token.toSafeString} is not valid'")
        AuthTokenInvalid
    }
  }
} 
Example 70
Source File: IAMClient.scala    From play-zhewbacca   with MIT License 5 votes vote down vote up
package org.zalando.zhewbacca

import java.util.concurrent.atomic.AtomicInteger
import javax.inject.{Inject, Singleton}

import akka.actor.ActorSystem
import akka.pattern.CircuitBreaker
import org.zalando.zhewbacca.metrics.PluggableMetrics
import play.api.http.Status._
import play.api.libs.ws.WSClient
import play.api.{Configuration, Logger}

import scala.concurrent.duration._
import scala.concurrent.{ExecutionContext, Future}
import scala.util.control.NonFatal

import atmos.dsl._
import atmos.dsl.Slf4jSupport._


@Singleton
class IAMClient @Inject() (
    config: Configuration,
    pluggableMetrics: PluggableMetrics,
    ws: WSClient,
    actorSystem: ActorSystem,
    implicit val ec: ExecutionContext) extends (OAuth2Token => Future[Option[TokenInfo]]) {

  val logger: Logger = Logger("security.IAMClient")

  val METRICS_BREAKER_CLOSED = 0
  val METRICS_BREAKER_OPEN = 1
  val circuitStatus = new AtomicInteger()

  pluggableMetrics.gauge {
    circuitStatus.get
  }

  val authEndpoint: String = config.getOptional[String]("authorisation.iam.endpoint").getOrElse(
    throw new IllegalArgumentException("Authorisation: IAM endpoint is not configured"))

  val breakerMaxFailures: Int = config.getOptional[Int]("authorisation.iam.cb.maxFailures").getOrElse(
    throw new IllegalArgumentException("Authorisation: Circuit Breaker max failures is not configured"))

  val breakerCallTimeout: FiniteDuration = config.getOptional[FiniteDuration]("authorisation.iam.cb.callTimeout").getOrElse(
    throw new IllegalArgumentException("Authorisation: Circuit Breaker call timeout is not configured"))

  val breakerResetTimeout: FiniteDuration = config.getOptional[FiniteDuration]("authorisation.iam.cb.resetTimeout").getOrElse(
    throw new IllegalArgumentException("Authorisation: Circuit Breaker reset timeout is not configured"))

  val breakerMaxRetries: TerminationPolicy = config.getOptional[Int]("authorisation.iam.maxRetries").getOrElse(
    throw new IllegalArgumentException("Authorisation: Circuit Breaker max retries is not configured")).attempts

  val breakerRetryBackoff: FiniteDuration = config.getOptional[FiniteDuration]("authorisation.iam.retry.backoff.duration").getOrElse(
    throw new IllegalArgumentException("Authorisation: Circuit Breaker the duration of exponential backoff is not configured"))

  lazy val breaker: CircuitBreaker = new CircuitBreaker(
    actorSystem.scheduler,
    breakerMaxFailures,
    breakerCallTimeout,
    breakerResetTimeout).onHalfOpen {
    circuitStatus.set(METRICS_BREAKER_OPEN)
  }.onOpen {
    circuitStatus.set(METRICS_BREAKER_OPEN)
  }.onClose {
    circuitStatus.set(METRICS_BREAKER_CLOSED)
  }

  implicit val retryRecover = retryFor { breakerMaxRetries } using {
    exponentialBackoff { breakerRetryBackoff }
  } monitorWith {
    logger.logger onRetrying logNothing onInterrupted logWarning onAborted logError
  }

  override def apply(token: OAuth2Token): Future[Option[TokenInfo]] = {
    breaker.withCircuitBreaker(
      pluggableMetrics.timing(
        retryAsync(s"Calling $authEndpoint") {
          ws.url(authEndpoint).withQueryStringParameters(("access_token", token.value)).get()
        })).map { response =>
        response.status match {
          case OK => Some(response.json.as[TokenInfo])
          case _ => None
        }
      } recover {
        case NonFatal(e) =>
          logger.error(s"Exception occurred during validation of token '${token.toSafeString}': $e")
          None // consider any exception as invalid token
      }
  }

} 
Example 71
Source File: SecurityRule.scala    From play-zhewbacca   with MIT License 5 votes vote down vote up
package org.zalando.zhewbacca

import org.zalando.zhewbacca.TokenInfoConverter._
import play.api.Logger
import play.api.mvc.{RequestHeader, Result, Results}

import scala.concurrent.{ExecutionContext, Future}

trait SecurityRule {
  def isApplicableTo(requestHeader: RequestHeader): Boolean
  def execute(nextFilter: RequestHeader => Future[Result], requestHeader: RequestHeader)(implicit ec: ExecutionContext): Future[Result]
}

abstract class StrictRule(method: String, pathRegex: String) extends SecurityRule {

  private val RequestMatcherRegex = s"^$method $pathRegex$$".r

  def isApplicableTo(requestHeader: RequestHeader): Boolean =
    RequestMatcherRegex.pattern.matcher(s"${requestHeader.method} ${requestHeader.uri}").matches

}

case class ValidateTokenRule(
    authProvider: AuthProvider,
    method: String,
    pathRegex: String,
    scope: Scope) extends StrictRule(method, pathRegex) {

  private[this] val log = Logger(this.getClass)

  override def execute(nextFilter: RequestHeader => Future[Result], requestHeader: RequestHeader)(implicit ec: ExecutionContext): Future[Result] =
    RequestValidator.validate(scope, requestHeader, authProvider).flatMap[Result] {
      case Right(tokenInfo) =>
        log.info(s"Request #${requestHeader.id} authenticated as: ${tokenInfo.userUid}")
        nextFilter(requestHeader.withTokenInfo(tokenInfo))

      case Left(result) =>
        log.info(s"Request #${requestHeader.id} failed auth")
        Future.successful(result)
    }
}


case object DenyAllRule extends DenySecurityRule {
  override def isApplicableTo(requestHeader: RequestHeader): Boolean = true
}

trait DenySecurityRule extends SecurityRule {
  override def execute(nextFilter: RequestHeader => Future[Result], requestHeader: RequestHeader)(implicit ec: ExecutionContext): Future[Result] =
    Future.successful(Results.Forbidden)
} 
Example 72
Source File: RequestValidator.scala    From play-zhewbacca   with MIT License 5 votes vote down vote up
package org.zalando.zhewbacca

import play.api.Logger
import play.api.mvc._

import scala.concurrent.{ExecutionContext, Future}
import scala.util.control.NonFatal

private[zhewbacca] object RequestValidator {

  val logger: Logger = Logger(this.getClass)

  def validate[A](scope: Scope, requestHeader: RequestHeader, authProvider: AuthProvider)(implicit ec: ExecutionContext): Future[Either[Result, TokenInfo]] = {
    authProvider.valid(OAuth2Token.from(requestHeader), scope).map {
      case AuthTokenValid(tokenInfo) => Right(tokenInfo)
      case AuthTokenInvalid => Left(Results.Unauthorized)
      case AuthTokenEmpty => Left(Results.Unauthorized)
      case AuthTokenInsufficient => Left(Results.Forbidden)
    } recover {
      case NonFatal(e) =>
        logger.error(e.getMessage, e)
        logger.debug("Request unauthorized because of failure in Authentication Provider")
        Left(Results.Unauthorized)
    }
  }
} 
Example 73
Source File: SecurityRulesRepository.scala    From play-zhewbacca   with MIT License 5 votes vote down vote up
package org.zalando.zhewbacca

import javax.inject.Inject

import com.typesafe.config.{Config, ConfigFactory}
import play.api.{Configuration, Logger}
import scala.collection.JavaConverters._

import play.api.http.HttpVerbs._
import play.api.mvc.RequestHeader

class SecurityRulesRepository @Inject() (configuration: Configuration, provider: AuthProvider) {

  private val logger = Logger(getClass)

  private val SupportedHttpMethods: Set[String] = Set(GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS)

  private val ConfigKeyMethod = "method"
  private val ConfigKeyPathRegex = "pathRegex"
  private val ConfigKeyScopes = "scopes"
  private val ConfigKeyAllowed = "allowed"
  private val ConfigKeyRules = "rules"

  private val rules: Seq[StrictRule] = load()

  def get(requestHeader: RequestHeader): Option[StrictRule] =
    rules.find(_.isApplicableTo(requestHeader))

  private def load(): Seq[StrictRule] = {
    val securityRulesFileName = configuration.getOptional[String]("authorisation.rules.file").getOrElse("security_rules.conf")
    logger.info(s"Configuration file for security rules: $securityRulesFileName")

    if (configFileExists(securityRulesFileName)) {
      ConfigFactory.load(securityRulesFileName)
        .getConfigList(ConfigKeyRules).asScala
        .map(toRule)
    } else {
      sys.error(s"configuration file $securityRulesFileName for security rules not found")
    }
  }

  private def toRule(config: Config): StrictRule = {
    (getHttpMethod(config), config.getString(ConfigKeyPathRegex), getAllowedFlag(config), getScopeNames(config)) match {
      case (Some(method), pathRegex, Some(true), _) =>
        logger.info(s"Explicitly allowed unauthorized requests for method: '$method' and path regex: '$pathRegex'")
        ExplicitlyAllowedRule(method, pathRegex)

      case (Some(method), pathRegex, Some(false), _) =>
        logger.info(s"Explicitly denied all requests for method: '$method' and path regex: '$pathRegex'")
        ExplicitlyDeniedRule(method, pathRegex)

      case (Some(method), pathRegex, None, Some(scopeNames)) =>
        logger.info(s"Configured required scopes '$scopeNames' for method '$method' and path regex: '$pathRegex'")
        ValidateTokenRule(provider, method, pathRegex, Scope(scopeNames))

      case _ =>
        sys.error(s"Invalid config: $config")
    }
  }

  private def configFileExists(fileName: String): Boolean =
    Option(Thread.currentThread()
      .getContextClassLoader
      .getResource(fileName))
      .isDefined

  private def getHttpMethod(config: Config): Option[String] = {
    if (SupportedHttpMethods(config.getString(ConfigKeyMethod))) {
      Some(config.getString(ConfigKeyMethod))
    } else {
      None
    }
  }

  private def getAllowedFlag(config: Config): Option[Boolean] = {
    if (config.hasPath(ConfigKeyAllowed)) {
      Some(config.getBoolean(ConfigKeyAllowed))
    } else {
      None
    }
  }

  private def getScopeNames(config: Config): Option[Set[String]] = {
    if (config.hasPath(ConfigKeyScopes)) {
      Some(config.getStringList(ConfigKeyScopes).asScala.toSet)
    } else {
      None
    }
  }

} 
Example 74
Source File: ServiceRegistrationModule.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.internal.server

import java.net.URI
import java.util.function.{ Function => JFunction }

import akka.actor.CoordinatedShutdown
import akka.Done
import akka.NotUsed
import com.lightbend.lagom.internal.javadsl.registry.ServiceRegistry
import com.lightbend.lagom.internal.javadsl.registry.ServiceRegistryService
import com.lightbend.lagom.internal.javadsl.server.ResolvedServices
import com.lightbend.lagom.devmode.internal.registry.serviceDnsRecords
import com.typesafe.config.Config
import javax.inject.Inject
import javax.inject.Provider
import javax.inject.Singleton
import play.api.inject.Binding
import play.api.inject.Module
import play.api.Configuration
import play.api.Environment
import play.api.Logger

import scala.compat.java8.FutureConverters.CompletionStageOps
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
import scala.collection.JavaConverters._
import scala.collection.immutable

class ServiceRegistrationModule extends Module {
  override def bindings(environment: Environment, configuration: Configuration): Seq[Binding[_]] = Seq(
    bind[ServiceRegistrationModule.RegisterWithServiceRegistry].toSelf.eagerly(),
    bind[ServiceRegistrationModule.ServiceConfig].toProvider[ServiceRegistrationModule.ServiceConfigProvider]
  )
}

object ServiceRegistrationModule {
  class ServiceConfigProvider @Inject() (config: Config) extends Provider[ServiceConfig] {
    override lazy val get = ServiceConfig(serviceDnsRecords(config))
  }

  case class ServiceConfig(uris: immutable.Seq[URI])

  
  @Singleton
  private class RegisterWithServiceRegistry @Inject() (
      coordinatedShutdown: CoordinatedShutdown,
      resolvedServices: ResolvedServices,
      config: ServiceConfig,
      registry: ServiceRegistry
  )(implicit ec: ExecutionContext) {
    private lazy val logger: Logger = Logger(this.getClass())

    private val locatableServices = resolvedServices.services.filter(_.descriptor.locatableService)

    coordinatedShutdown.addTask(
      CoordinatedShutdown.PhaseBeforeServiceUnbind,
      "unregister-services-from-service-locator-javadsl"
    ) { () =>
      Future
        .sequence(locatableServices.map { service =>
          registry.unregister(service.descriptor.name).invoke().toScala
        })
        .map(_ => Done)
    }

    locatableServices.foreach { service =>
      val c = ServiceRegistryService.of(config.uris.asJava, service.descriptor.acls)
      registry
        .register(service.descriptor.name)
        .invoke(c)
        .exceptionally(new JFunction[Throwable, NotUsed] {
          def apply(t: Throwable) = {
            logger
              .error(s"Service name=[${service.descriptor.name}] couldn't register itself to the service locator.", t)
            NotUsed.getInstance()
          }
        })
    }
  }
} 
Example 75
Source File: LagomPlayModule.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.play

import java.util.{ List => JList }
import java.util.Optional
import javax.inject.Inject

import com.lightbend.lagom.internal.javadsl.registry.ServiceRegistry
import com.lightbend.lagom.internal.javadsl.registry.ServiceRegistryService
import com.lightbend.lagom.devmode.internal.registry.serviceDnsRecords
import com.lightbend.lagom.javadsl.api.ServiceAcl
import com.lightbend.lagom.javadsl.api.ServiceInfo
import com.lightbend.lagom.javadsl.api.transport.Method
import com.typesafe.config.Config
import play.api.inject.ApplicationLifecycle
import play.api.inject.Binding
import play.api.inject.Module
import play.api.Configuration
import play.api.Environment
import play.api.Logger

import scala.collection.JavaConverters._
import scala.compat.java8.FutureConverters._
import scala.util.Success
import scala.util.Try

class LagomPlayModule extends Module {
  private val logger = Logger(this.getClass)

  override def bindings(environment: Environment, config: Configuration): Seq[Binding[_]] = {
    val maybeServiceInfoBinding: Option[Binding[ServiceInfo]] = prepareServiceInfoBinding(config.underlying)
    val playRegistry                                          = bind[PlayRegisterWithServiceRegistry].toSelf.eagerly()

    Seq(
      playRegistry
    ) ++ maybeServiceInfoBinding.toList
  }

  private def prepareServiceInfoBinding(config: Config) = {
    val triedServiceName                   = Try(config.getString("lagom.play.service-name"))
    val triedAcls: Try[JList[_ <: Config]] = Try(config.getConfigList("lagom.play.acls"))

    val warning = "Service setup via 'application.conf' is deprecated. Remove 'lagom.play.service-name' and/or " +
      "'lagom.play.acls' and use 'bindServiceInfo' on your Guice's Module class."

    val maybeServiceInfoBinding = (triedServiceName, triedAcls) match {
      case (Success(serviceName), Success(aclList)) => {
        logger.warn(warning)
        // create a ServiceInfo in case user doesn't see the warning
        val acls = parseAclList(aclList)
        Some(bind[ServiceInfo].toInstance(ServiceInfo.of(serviceName, acls: _*)))
      }
      case (Success(serviceName), _) => {
        logger.warn(warning)
        // create a ServiceInfo in case user doesn't see the warning
        Some(bind[ServiceInfo].toInstance(ServiceInfo.of(serviceName)))
      }
      case (_, Success(_)) => {
        logger.warn(warning)
        // can't create a ServiceInfo because service-name is missing
        None
      }
      case _ => None
    }
    maybeServiceInfoBinding
  }

  private def parseAclList(aclList: JList[_ <: Config]): Seq[ServiceAcl] = {
    aclList.asScala.map { aclConfig =>
      val method = if (aclConfig.hasPath("method")) {
        Optional.of(new Method(aclConfig.getString("method")))
      } else Optional.empty[Method]
      val pathRegex = if (aclConfig.hasPath("path-regex")) {
        Optional.of(aclConfig.getString("path-regex"))
      } else Optional.empty[String]
      new ServiceAcl(method, pathRegex)
    }.toSeq
  }
}

class PlayRegisterWithServiceRegistry @Inject() (
    config: Config,
    serviceInfo: ServiceInfo,
    serviceRegistry: ServiceRegistry,
    applicationLifecycle: ApplicationLifecycle
) {
  val uris = serviceDnsRecords(config)

  private val serviceAcls = serviceInfo.getAcls
  private val service     = ServiceRegistryService.of(uris.asJava, serviceAcls)
  // TODO: fix -> this register operation is registering all ACLs under the microservice name, not under each locatable service name. Will lead to unlocatable.
  serviceRegistry.register(serviceInfo.serviceName()).invoke(service)

  applicationLifecycle.addStopHook(() => serviceRegistry.unregister(serviceInfo.serviceName()).invoke().toScala)
} 
Example 76
Source File: ServiceRegistration.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.devmode.internal.scaladsl.registry

import akka.Done
import akka.actor.CoordinatedShutdown
import com.lightbend.lagom.devmode.internal.registry.serviceDnsRecords
import com.lightbend.lagom.scaladsl.api.ServiceInfo
import com.typesafe.config.Config
import play.api.Logger

import scala.concurrent.ExecutionContext
import scala.util.Failure
import scala.util.Success

import scala.collection._

class ServiceRegistration(
    serviceInfo: ServiceInfo,
    coordinatedShutdown: CoordinatedShutdown,
    config: Config,
    registry: ServiceRegistry
)(implicit ec: ExecutionContext) {
  private val logger: Logger = Logger(this.getClass)

  private val uris = serviceDnsRecords(config)

  coordinatedShutdown.addTask(
    CoordinatedShutdown.PhaseBeforeServiceUnbind,
    "unregister-services-from-service-locator-scaladsl"
  ) { () =>
    registry.unregister(serviceInfo.serviceName).invoke().map(_ => Done)
  }

  registry
    .register(serviceInfo.serviceName)
    .invoke(new ServiceRegistryService(uris, immutable.Seq(serviceInfo.acls.toSeq: _*)))
    .onComplete {
      case Success(_) =>
        logger.debug(s"Service name=[${serviceInfo.serviceName}] successfully registered with service locator.")
      case Failure(e) =>
        logger.error(s"Service name=[${serviceInfo.serviceName}] couldn't register itself to the service locator.", e)
    }
} 
Example 77
Source File: ServiceLocatorSessionProvider.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.internal.persistence.cassandra

import java.net.InetSocketAddress
import java.net.URI

import scala.collection.immutable
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
import scala.concurrent.Promise
import scala.concurrent.duration._
import scala.util.control.NoStackTrace

import akka.actor.ActorSystem
import akka.persistence.cassandra.ConfigSessionProvider
import com.typesafe.config.Config
import play.api.Logger


private[lagom] final class ServiceLocatorSessionProvider(system: ActorSystem, config: Config)
    extends ConfigSessionProvider(system, config) {
  private val log = Logger(getClass)

  override def lookupContactPoints(
      clusterId: String
  )(implicit ec: ExecutionContext): Future[immutable.Seq[InetSocketAddress]] = {
    ServiceLocatorHolder(system).serviceLocatorEventually.flatMap { serviceLocatorAdapter =>
      serviceLocatorAdapter.locateAll(clusterId).map {
        case Nil => throw new NoContactPointsException(s"No contact points for [$clusterId]")
        case uris =>
          log.debug(s"Found Cassandra contact points: $uris")

          // URIs must be all valid
          uris.foreach { uri =>
            require(uri.getHost != null, s"missing host in $uri for Cassandra contact points $clusterId")
            require(uri.getPort != -1, s"missing port in $uri for Cassandra contact points $clusterId")
          }

          uris.map { uri =>
            new InetSocketAddress(uri.getHost, uri.getPort)
          }
      }
    }
  }
}

private[lagom] final class NoContactPointsException(msg: String) extends RuntimeException(msg) with NoStackTrace 
Example 78
Source File: AkkaManagementTrigger.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.internal.akka.management

import akka.Done
import akka.actor.ActorSystem
import akka.actor.CoordinatedShutdown
import akka.actor.ExtendedActorSystem
import akka.management.scaladsl.AkkaManagement
import com.typesafe.config.Config
import play.api.Logger

import scala.concurrent.ExecutionContext
import scala.concurrent.Future


  private[lagom] def forcedStart(requester: String): Future[Done] = {
    if (!enabled) {
      logger.warn(
        s"'lagom.akka.management.enabled' property is set to '$enabledRenderedValue', " +
          s"but Akka Management is being required to start by: '$requester'."
      )
    }

    doStart()
  }

  private def doStart(): Future[Done] = {
    val akkaManagement = AkkaManagement(system.asInstanceOf[ExtendedActorSystem])
    akkaManagement.start().map { _ =>
      // add a task to stop
      coordinatedShutdown.addTask(
        CoordinatedShutdown.PhaseBeforeServiceUnbind,
        "stop-akka-http-management"
      ) { () =>
        akkaManagement.stop()
      }
      Done
    }
  }
} 
Example 79
Source File: CassandraTestServer.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.internal.testkit

import java.nio.file.Files
import java.util.concurrent.TimeUnit

import akka.persistence.cassandra.testkit.CassandraLauncher
import com.google.common.io.MoreFiles
import com.google.common.io.RecursiveDeleteOption
import play.api.Logger
import play.api.inject.ApplicationLifecycle

import scala.concurrent.Future
import scala.util.Try

private[lagom] object CassandraTestServer {
  private val LagomTestConfigResource: String = "lagom-test-embedded-cassandra.yaml"

  private lazy val log = Logger(getClass)

  def run(cassandraDirectoryPrefix: String, lifecycle: ApplicationLifecycle): Int = {

    val cassandraDirectory = Files.createTempDirectory(cassandraDirectoryPrefix)

    // Shut down Cassandra and delete its temporary directory when the application shuts down
    lifecycle.addStopHook { () =>
      import scala.concurrent.ExecutionContext.Implicits.global
      Try(CassandraLauncher.stop())
      // The ALLOW_INSECURE option is required to remove the files on OSes that don't support SecureDirectoryStream
      // See http://google.github.io/guava/releases/snapshot-jre/api/docs/com/google/common/io/MoreFiles.html#deleteRecursively-java.nio.file.Path-com.google.common.io.RecursiveDeleteOption...-
      Future(MoreFiles.deleteRecursively(cassandraDirectory, RecursiveDeleteOption.ALLOW_INSECURE))
    }

    val t0 = System.nanoTime()

    CassandraLauncher.start(
      cassandraDirectory.toFile,
      LagomTestConfigResource,
      clean = false,
      port = 0,
      CassandraLauncher.classpathForResources(LagomTestConfigResource)
    )

    log.debug(s"Cassandra started in ${TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - t0)} ms")

    CassandraLauncher.randomPort
  }
} 
Example 80
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 81
Source File: SelfAssessmentApiDefinition.scala    From self-assessment-api   with Apache License 2.0 5 votes vote down vote up
package router.definition

import config.{AppConfig, FeatureSwitch}
import javax.inject.{Inject, Singleton}
import play.api.Logger
import router.definition.APIStatus.APIStatus
import router.constants.Versions._

@Singleton
class SelfAssessmentApiDefinition @Inject()(appConfig: AppConfig) {

  private val readScope = "read:self-assessment"
  private val writeScope = "write:self-assessment"

  lazy val definition: Definition =
    Definition(
      scopes = Seq(
        Scope(
          key = readScope,
          name = "View your Self Assessment information",
          description = "Allow read access to self assessment data"
        ),
        Scope(
          key = writeScope,
          name = "Change your Self Assessment information",
          description = "Allow write access to self assessment data"
        )
      ),
      api = APIDefinition(
        name = "Self Assessment (MTD)",
        description = "An API for providing self assessment data and obtaining tax calculations",
        context = appConfig.apiGatewayContext,
        versions = Seq(
          APIVersion(
            version = VERSION_1,
            access = buildWhiteListingAccess(),
            status = buildAPIStatus(VERSION_1),
            endpointsEnabled = true),
          APIVersion(
            version = VERSION_2,
            access = buildWhiteListingAccess(),
            status = buildAPIStatus(VERSION_2),
            endpointsEnabled = true)
        ),
        requiresTrust = None
      )
    )

  private[definition] def buildAPIStatus(version: String): APIStatus = {
    appConfig.apiStatus(version) match {
      case "ALPHA" => APIStatus.ALPHA
      case "BETA" => APIStatus.BETA
      case "STABLE" => APIStatus.STABLE
      case "DEPRECATED" => APIStatus.DEPRECATED
      case "RETIRED" => APIStatus.RETIRED
      case _ => Logger.error(s"[ApiDefinition][buildApiStatus] no API Status found in config.  Reverting to Alpha")
        APIStatus.ALPHA
    }
  }

  private[definition] def buildWhiteListingAccess(): Option[Access] = {
    val featureSwitch = FeatureSwitch(appConfig.featureSwitch)
    featureSwitch.isWhiteListingEnabled match {
      case true => Some(Access("PRIVATE", featureSwitch.whiteListedApplicationIds))
      case false => None
    }
  }
} 
Example 82
Source File: Service.scala    From self-assessment-api   with Apache License 2.0 5 votes vote down vote up
package router.services

import play.api.Logger
import play.api.http.HeaderNames.ACCEPT
import router.constants.Versions
import router.errors.{IncorrectAPIVersion, UnsupportedAPIVersion}
import router.httpParsers.SelfAssessmentHttpParser.SelfAssessmentOutcome
import uk.gov.hmrc.http.HeaderCarrier

import scala.concurrent.Future

trait Service {

  private[services] def withApiVersion(pf: PartialFunction[Option[String], Future[SelfAssessmentOutcome]])
                                      (implicit hc: HeaderCarrier): Future[SelfAssessmentOutcome] = {
    pf.orElse[Option[String], Future[SelfAssessmentOutcome]] {
      case Some(_) =>
        Logger.info("request header contains an unsupported api version")
        Future.successful(Left(UnsupportedAPIVersion))
      case None =>
        Logger.info("request header contains an incorrect or empty api version")
        Future.successful(Left(IncorrectAPIVersion))
    }(getAPIVersionFromRequest)
  }

  private[services] def getAPIVersionFromRequest(implicit hc: HeaderCarrier): Option[String] =
    Versions.getFromRequest

  private[services] def convertHeaderToVersion1(implicit hc: HeaderCarrier) = {
    val convertAcceptHeader: PartialFunction[(String, String), (String, String)] = {
      case (ACCEPT, _) => (ACCEPT, "application/vnd.hmrc.1.0+json")
      case header => header
    }
    hc.copy(otherHeaders = hc.otherHeaders.map(convertAcceptHeader))
  }
} 
Example 83
Source File: ApplicationTimer.scala    From play-webpack-typescript-react   with MIT License 5 votes vote down vote up
package services

import java.time.{Clock, Instant}
import javax.inject._
import play.api.Logger
import play.api.inject.ApplicationLifecycle
import scala.concurrent.Future


@Singleton
class ApplicationTimer @Inject()(clock: Clock, appLifecycle: ApplicationLifecycle) {

  // This code is called when the application starts.
  private val start: Instant = clock.instant
  Logger.info(s"ApplicationTimer demo: Starting application at $start.")

  // When the application starts, register a stop hook with the
  // ApplicationLifecycle object. The code inside the stop hook will
  // be run when the application stops.
  appLifecycle.addStopHook { () =>
    val stop: Instant     = clock.instant
    val runningTime: Long = stop.getEpochSecond - start.getEpochSecond
    Logger.info(s"ApplicationTimer demo: Stopping application at ${clock.instant} after ${runningTime}s.")
    Future.successful(())
  }
} 
Example 84
Source File: AthanorClient.scala    From tap   with Apache License 2.0 5 votes vote down vote up
package controllers.external.athanor

import io.heta.tap.data.results.StringListResult
import javax.inject.Inject
import io.heta.tap.util.AppConfig
import play.api.Logger
import play.api.libs.ws.{WSClient, WSRequest, WSResponse}

import scala.concurrent.{ExecutionContext, Future}
import scala.concurrent.duration._ // scalastyle:ignore




class AthanorClient @Inject()(wsClient: WSClient, config: AppConfig)(implicit ec: ExecutionContext) {

  val logger: Logger = Logger(this.getClass)

  val athanorURL= config.getAthanorURL

  def process(text:String,parameter:String,start:Long):Future[StringListResult] = {
    //logger.info(s"Analysing with athanor: $text")

    val url = athanorURL + parameter
    logger.info(s"Analysing with athanor at this url: $url")

    val request: WSRequest = wsClient.url(url)

    val athanorRequest: WSRequest = request
      .withHttpHeaders("Accept" -> "application/json")
      .withRequestTimeout(30000.millis)

    val futureResponse: Future[WSResponse] = athanorRequest.post(text)


    val result: Future[StringListResult] = {
      val decoded = futureResponse.map { response =>
        val res = decodeRepsonse(response)
        val queryTime = (System.currentTimeMillis() - start).toInt
        StringListResult(res,"ok",querytime = queryTime)
      }
      val errMsg = "There was a problem connecting to the Athanor server."
      futureResponse.recover {
        case e: Any => {
          val msg = s"$errMsg: $e"
          logger.error(msg)
          StringListResult(Vector(),msg)
        }
        //case _ => logger.error(errMsg)
      }
      decoded
    }
    result
  }

  case class AthanorMsg(message: String, results: Vector[Vector[String]])

  def decodeRepsonse(response:WSResponse): Vector[Vector[String]] = {
    val resBody = response.body
    if(resBody.nonEmpty && resBody.contains(":[[")) {
      logger.debug("Decoding response: "+ resBody)

      import play.api.libs.functional.syntax._ //scalastyle:ignore
      import play.api.libs.json._ //scalastyle:ignore

      implicit val AMWrites: Writes[AthanorMsg] = (
        (JsPath \ "message").write[String] and
          (JsPath \ "results").write[Vector[Vector[String]]]
        ) (unlift(AthanorMsg.unapply))

      implicit val AMReads: Reads[AthanorMsg] = (
        (JsPath \ "message").read[String] and
          (JsPath \ "results").read[Vector[Vector[String]]]
        ) (AthanorMsg.apply _)

      val athanorMsg:AthanorMsg = response.json.as[AthanorMsg]
      logger.debug("Athanor message: " + athanorMsg.message)
      logger.debug("Athanor results: " + athanorMsg.results)
      athanorMsg.results
    } else {
      logger.error("There was a problem: " + resBody) //TODO If we get to here, we need to return the message to the client!!
      Vector()
    }
  }
} 
Example 85
Source File: GenericHandler.scala    From tap   with Apache License 2.0 5 votes vote down vote up
package controllers.handlers


import io.heta.tap.data.results.StringResult
import play.api.Logger
import play.api.libs.json.{JsValue, Json}

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.reflect.runtime.universe._
import scala.util.Try

trait GenericHandler {

  def queryTime(start:Long):Int = (System.currentTimeMillis() - start).toInt

  def validJson(parameters:Option[String]):Option[JsValue] = parameters.flatMap(p => Try(Json.parse(p)).toOption).map(_.result.get)

  def extractParameter[A:TypeTag](paramName:String,parameters:Option[String]):Option[Any] = {
    val jsParams = validJson(parameters)
    Logger.debug(s"JSON: $jsParams")
    jsParams.flatMap { jp =>
      val result = Try((jp \ paramName).toOption).toOption.flatten
      typeOf[A] match {
        case t if t =:= typeOf[String] => Try(result.map(_.as[String])).toOption.flatten // scalastyle:ignore
        case t if t =:= typeOf[Double] => Try(result.map(_.as[Double])).toOption.flatten // scalastyle:ignore
        case t if t =:= typeOf[Int] => Try(result.map(_.as[Int])).toOption.flatten       // scalastyle:ignore
        case _ => None
      }
    }
  }

  def dummyResult(text:String):Future[StringResult] = Future {
    StringResult("This features is not implemented yet")
  }


} 
Example 86
Source File: BatchAnalysisHandler.scala    From tap   with Apache License 2.0 5 votes vote down vote up
package controllers.handlers

import java.util.UUID

import akka.actor.ActorRef
import akka.pattern.ask
import akka.util.Timeout
import io.heta.tap.analysis.batch.AwsS3Client
import io.heta.tap.analysis.batch.BatchActor.{AnalyseSource, CheckProgress, INIT, ResultMessage}
import io.heta.tap.data.results.BatchResult
import javax.inject.{Inject, Named}
import play.api.Logger

import scala.concurrent.Future
import scala.concurrent.duration._
import scala.util.Success





class BatchAnalysisHandler @Inject()(awsS3Client: AwsS3Client, @Named("batch")batch:ActorRef, @Named("cluAnnotator")cluAnnotator:ActorRef) extends GenericHandler {

  import io.heta.tap.pipelines.materialize.PipelineContext.executor

  val logger: Logger = Logger(this.getClass)

  {
    implicit val timeout: Timeout = 5.seconds
    (batch ? INIT).onComplete{
      case Success(result:Boolean) => if(result) {
        logger.info("BatchActor initialised successfully")
      } else {
        logger.error("There was a problem initialising the BatchActor")
      }
      case scala.util.Failure(exception) => logger.error(exception.getMessage)
    }
  }

  def analyse(parameters:Option[String],start:Long):Future[BatchResult] = {
    logger.info(s"Batch analysis with parameters: $parameters")
    process(parameters) match {
      case Right(futResMsg:Future[ResultMessage]) => futResMsg.map( rm => BatchResult(rm.result,rm.message,(System.currentTimeMillis() - start).toInt))
      case Left(error) => Future(BatchResult("",error.getMessage,(System.currentTimeMillis() - start).toInt))
    }
  }

  def process(parameters:Option[String]): Either[Throwable,Future[ResultMessage]] = try {
    val bucket = extractParameter[String]("s3bucket",parameters)
    if(bucket.nonEmpty) {
      val analysis = extractParameter[String]("analysisType",parameters)
      if (analysis.nonEmpty) sendRequest(ANALYSE,bucket.get.toString,analysis.get.toString)
      else {
        val progress = extractParameter[String]("progressCheck",parameters)
        if (progress.nonEmpty) {
          val batchId = progress.getOrElse("").asInstanceOf[String]
          val uuid = UUID.fromString(batchId)
          sendRequest(PROGRESS,bucket.get.toString,uuid.toString)
        }
        else throw new Exception("ERROR: No valid parameters provided")
      }
    } else throw new Exception("ERROR: No S3 bucket provided")
  } catch {
    case error => Left(error)
  }

  def sendRequest(requestType:RequestType,bucket:String,payLoad:String):Either[Throwable,Future[ResultMessage]] = {
    implicit val timeout: Timeout = 5.seconds

        val request = requestType match {
          case ANALYSE => AnalyseSource(bucket,payLoad,cluAnnotator)
          case PROGRESS => CheckProgress(bucket,payLoad)
        }
        val result = (batch ? request).mapTo[Future[ResultMessage]].flatten
        Right(result)
     // }
     // case None => throw new Exception("No S3 Client Found.")
    //}
  }

  type RequestType = String
  lazy val ANALYSE:RequestType = "analyse"
  lazy val PROGRESS:RequestType = "progress"
} 
Example 87
Source File: ExternalAnalysisHandler.scala    From tap   with Apache License 2.0 5 votes vote down vote up
package controllers.handlers

import javax.inject.Inject
import play.api.Logger
import controllers.external.athanor.AthanorClient
import io.heta.tap.data.results.StringListResult

import scala.concurrent.Future

class ExternalAnalysisHandler @Inject() (athanorClient: AthanorClient) extends GenericHandler {

  val logger: Logger = Logger(this.getClass)

  def analyseWithAthanor(text:Option[String],parameters:Option[String],start:Long):Future[StringListResult] = {
    val inputText = text.getOrElse("")
    val grammar = extractParameter[String]("grammar",parameters)
    //logger.warn(s"grammar |$grammar|")
    val grammarParam = "?grammar=" + grammar.getOrElse("nogrammar")
    logger.debug(s"Creating request with parameter: $grammarParam")
    athanorClient.process(inputText,grammarParam,start)
  }

} 
Example 88
Source File: GraphQlController.scala    From tap   with Apache License 2.0 5 votes vote down vote up
package controllers

import javax.inject.Inject
import models.GraphqlSchema
import models.graphql.GraphqlActions
import play.api.Logger
import play.api.libs.json.{JsObject, JsValue, Json}
import play.api.mvc.{Action, AnyContent, InjectedController, Result}
import sangria.ast.Document
import sangria.execution.{ErrorWithResolver, Executor, QueryAnalysisError}
import sangria.marshalling.playJson.{PlayJsonInputUnmarshallerJObject, PlayJsonResultMarshaller}
import sangria.parser.{QueryParser, SyntaxError}
import sangria.schema.Schema
import views.GraphiqlPage

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.util.{Failure, Success}


class GraphQlController @Inject() (assets: AssetsFinder, gqlSchema: GraphqlSchema, actions: GraphqlActions) extends InjectedController {

  val schema:Schema[GraphqlActions,Unit] = gqlSchema.create

  def graphiql:Action[AnyContent] = Action {
    request => Logger.info("Got Any content request from:" + request.remoteAddress)
    //Ok(views.html.graphiql(assets))
    Ok(GraphiqlPage.render("Explore TAP with GraphiQL"))
  }

  def graphql:Action[JsValue] = Action.async(parse.json) { request =>
    val query = (request.body \ "query").as[String]
    val operation = (request.body \ "operationName").asOpt[String]
    val variables = (request.body \ "variables").asOpt[JsObject].getOrElse(Json.obj())
    Logger.info(s"Query received from ${request.remoteAddress} >>> ${operation.getOrElse("No query")}")
    Logger.info(s"Variables: $variables")
    process(query,operation,variables)
  }

  def process(query:String,name:Option[String],variables:JsObject):Future[Result] = QueryParser.parse(query) match {
    case Success(queryAst) => executeGraphQLQuery(queryAst, name, variables)
    case Failure(error: SyntaxError) => Future.successful(BadRequest(error.getMessage))
    case _ => Future.successful(BadRequest("There was a problem with the request to TAP graphql."))
  }

  def executeGraphQLQuery(query: Document, name: Option[String], vars: JsObject):Future[Result] = {
     Executor.execute(schema, query, actions, operationName = name, variables = vars)
      .map(Ok(_))
      .recover {
        case error: QueryAnalysisError => BadRequest(error.resolveError)
        case error: ErrorWithResolver => InternalServerError(error.resolveError)
      }

  }
} 
Example 89
Source File: ApplicationTimer.scala    From sbt-header   with Apache License 2.0 5 votes vote down vote up
package services

import java.time.{Clock, Instant}
import javax.inject._
import play.api.Logger
import play.api.inject.ApplicationLifecycle
import scala.concurrent.Future


@Singleton
class ApplicationTimer @Inject() (clock: Clock, appLifecycle: ApplicationLifecycle) {

  // This code is called when the application starts.
  private val start: Instant = clock.instant
  Logger.info(s"ApplicationTimer demo: Starting application at $start.")

  // When the application starts, register a stop hook with the
  // ApplicationLifecycle object. The code inside the stop hook will
  // be run when the application stops.
  appLifecycle.addStopHook { () =>
    val stop: Instant = clock.instant
    val runningTime: Long = stop.getEpochSecond - start.getEpochSecond
    Logger.info(s"ApplicationTimer demo: Stopping application at ${clock.instant} after ${runningTime}s.")
    Future.successful(())
  }
} 
Example 90
Source File: WebSocketMessageHandler.scala    From cluster-broccoli   with Apache License 2.0 5 votes vote down vote up
package de.frosner.broccoli.websocket

import javax.inject.Inject

import cats.instances.future._
import cats.syntax.either._
import de.frosner.broccoli.auth.Account
import de.frosner.broccoli.controllers.InstanceController
import de.frosner.broccoli.instances.NomadInstances
import de.frosner.broccoli.services.InstanceService
import de.frosner.broccoli.websocket.IncomingMessage._
import de.frosner.broccoli.websocket.OutgoingMessage._
import play.api.Logger
import play.api.cache.CacheApi

import scala.concurrent.duration._
import scala.concurrent.{ExecutionContext, Future}


  private def cachedMessage(user: Account, messageKey: String)(message: IncomingMessage): Future[OutgoingMessage] = {
    val cacheKey = s"${user.name}.$messageKey"
    cache
      .get[OutgoingMessage](cacheKey)
      .map(Future.successful)
      .getOrElse {
        val result = underlying.processMessage(user)(message)
        result.onSuccess {
          case outgoingMessage =>
            cache.set(cacheKey, outgoingMessage, timeout)
        }
        result
      }
  }

  override def processMessage(user: Account)(incomingMessage: IncomingMessage): Future[OutgoingMessage] =
    incomingMessage match {
      // Only cache side-effect free "get" messages!
      case message @ GetInstanceTasks(instanceId) => cachedMessage(user, instanceId)(message)
      // For all other messages that might trigger side-effects call out to the underlying handler directly
      case message => underlying.processMessage(user)(message)
    }
} 
Example 91
Source File: WebSocketController.scala    From cluster-broccoli   with Apache License 2.0 5 votes vote down vote up
package de.frosner.broccoli.controllers

import javax.inject.Inject

import cats.data.EitherT
import cats.instances.future._
import de.frosner.broccoli.services.WebSocketService.Msg
import de.frosner.broccoli.services._
import de.frosner.broccoli.websocket.{IncomingMessage, OutgoingMessage, WebSocketMessageHandler}
import jp.t2v.lab.play2.auth.BroccoliWebsocketSecurity
import play.api.cache.CacheApi
import play.api.libs.concurrent.Execution.Implicits._
import play.api.libs.iteratee._
import play.api.libs.json._
import play.api.mvc._
import play.api.{Environment, Logger}

import scala.concurrent.Future

case class WebSocketController @Inject()(webSocketService: WebSocketService,
                                         templateService: TemplateService,
                                         instanceService: InstanceService,
                                         aboutService: AboutInfoService,
                                         messageHandler: WebSocketMessageHandler,
                                         override val cacheApi: CacheApi,
                                         override val playEnv: Environment,
                                         override val securityService: SecurityService)
    extends Controller
    with BroccoliWebsocketSecurity {

  protected val log = Logger(getClass)

  def requestToSocket(request: RequestHeader): Future[Either[Result, (Iteratee[Msg, _], Enumerator[Msg])]] =
    withSecurity(request) { (maybeToken, user, request) =>
      val (connectionId, connectionEnumerator) = maybeToken match {
        case Some(token) =>
          (token, webSocketService.newConnection(token, user)) // auth is enabled and we can use the session ID
        case None => webSocketService.newConnection(user) // no session ID available so we generate one
      }
      val connectionLogString = s"$connectionId by $user from ${request.remoteAddress} at $request"
      log.info(s"New connection $connectionLogString")

      // TODO receive string and try json decoding here because I can handle the error better
      val in = Enumeratee.mapM[Msg] { incomingMessage =>
        EitherT
          .fromEither(Json.fromJson[IncomingMessage](incomingMessage).asEither)
          .leftMap[OutgoingMessage] { jsonErrors =>
            log.warn(s"Can't parse a message from $connectionId: $jsonErrors")
            OutgoingMessage.Error(s"Failed to parse message message: $jsonErrors")
          }
          .semiflatMap { incomingMessage =>
            // Catch all exceptions from the message handler and map them to a generic error message to send over the
            // websocket, to prevent the Enumeratee from stopping at the failure, causing the websocket to be closed and
            // preventing all future messages.
            messageHandler.processMessage(user)(incomingMessage).recover {
              case exception =>
                log.error(s"Message handler threw exception for message $incomingMessage: ${exception.getMessage}",
                          exception)
                OutgoingMessage.Error("Unexpected error in message handler")
            }
          }
          .merge
      } transform Iteratee
        .foreach[OutgoingMessage](msg => webSocketService.send(connectionId, Json.toJson(msg)))
        .map { _ =>
          webSocketService.closeConnections(connectionId)
          log.info(s"Closed connection $connectionLogString")
        }

      val aboutEnumerator =
        Enumerator[Msg](Json.toJson(OutgoingMessage.AboutInfoMsg(AboutController.about(aboutService, user))))

      val templateEnumerator = Enumerator[Msg](
        Json.toJson(
          OutgoingMessage.ListTemplates(TemplateController.list(templateService))
        ))

      val instanceEnumerator = Enumerator[Msg](
        Json.toJson(OutgoingMessage.ListInstances(InstanceController.list(None, user, instanceService))))
      (in, aboutEnumerator.andThen(templateEnumerator).andThen(instanceEnumerator).andThen(connectionEnumerator))
    }

  def socket: WebSocket = WebSocket.tryAccept[Msg](requestToSocket)

} 
Example 92
Source File: SecurityController.scala    From cluster-broccoli   with Apache License 2.0 5 votes vote down vote up
package de.frosner.broccoli.controllers

import javax.inject.Inject

import cats.data.{EitherT, OptionT}
import cats.instances.future._
import cats.syntax.either._
import com.mohiva.play.silhouette.api.util.Credentials
import com.mohiva.play.silhouette.impl.providers.CredentialsProvider
import de.frosner.broccoli.services.{SecurityService, WebSocketService}
import jp.t2v.lab.play2.auth.{BroccoliSimpleAuthorization, LoginLogout}
import play.api.{Environment, Logger}
import play.api.cache.CacheApi
import play.api.data.Forms._
import play.api.data._
import play.api.libs.json.Json
import play.api.mvc.{Action, AnyContent, Controller, Results}

import scala.concurrent.Future

case class SecurityController @Inject()(
    override val securityService: SecurityService,
    override val cacheApi: CacheApi,
    override val playEnv: Environment,
    webSocketService: WebSocketService
) extends Controller
    with LoginLogout
    with BroccoliSimpleAuthorization {

  private val log = Logger(getClass)

  import scala.concurrent.ExecutionContext.Implicits.global

  // https://www.playframework.com/documentation/2.5.x/ScalaForms
  val loginForm = Form {
    mapping(
      SecurityController.UsernameFormKey -> text,
      SecurityController.PasswordFormKey -> text
    )(Credentials.apply)(Credentials.unapply)
  }

  def login: Action[AnyContent] = Action.async { implicit request =>
    getSessionId(request).map(id => (id, webSocketService.closeConnections(id))) match {
      case Some((id, true)) => log.info(s"Removing websocket connection of $id due to another login")
      case _                =>
    }
    (for {
      credentials <- EitherT.fromEither[Future](
        loginForm.bindFromRequest().fold(Function.const(Results.BadRequest.asLeft), _.asRight))
      login <- OptionT(securityService.authenticate(credentials)).toRight(Results.Unauthorized)
      result <- EitherT.right(gotoLoginSucceeded(login.providerKey))
      user <- OptionT(resolveUser(login.providerKey)).toRight(Results.Unauthorized)
    } yield {
      val userResult = Results.Ok(Json.toJson(user))
      result.copy(
        header = result.header.copy(
          headers = userResult.header.headers
            .get("Content-Type")
            .map { contentType =>
              result.header.headers.updated("Content-Type", contentType)
            }
            .getOrElse(result.header.headers)
        ),
        body = userResult.body
      )
    }).merge
  }

  def logout = Action.async(parse.empty) { implicit request =>
    gotoLogoutSucceeded.andThen {
      case tryResult =>
        getSessionId(request).map(id => (id, webSocketService.closeConnections(id))) match {
          case Some((id, true))  => log.info(s"Removing websocket connection of $id due to logout")
          case Some((id, false)) => log.info(s"There was no websocket connection for session $id")
          case None              => log.info(s"No session available to logout from")
        }
    }
  }

  def verify = StackAction(parse.empty) { implicit request =>
    Ok(loggedIn.name)
  }

}

object SecurityController {

  val UsernameFormKey = "username"
  val PasswordFormKey = "password"

} 
Example 93
Source File: BroccoliWebsocketSecurity.scala    From cluster-broccoli   with Apache License 2.0 5 votes vote down vote up
package jp.t2v.lab.play2.auth

import de.frosner.broccoli.auth.Account.anonymous
import de.frosner.broccoli.auth.AuthMode
import de.frosner.broccoli.conf
import de.frosner.broccoli.controllers.AuthConfigImpl
import de.frosner.broccoli.services.SecurityService
import jp.t2v.lab.play2.stackc.{RequestAttributeKey, RequestWithAttributes}
import play.api.Logger
import play.api.libs.iteratee.{Enumerator, Iteratee}
import play.api.mvc._

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future

trait BroccoliWebsocketSecurity extends AsyncAuth with AuthConfigImpl {

  self: Controller with AuthConfig =>

  protected def log: Logger

  val securityService: SecurityService

  private[auth] case object AuthKey extends RequestAttributeKey[User]

  def withSecurity[A](req: RequestHeader)(
      f: (Option[AuthenticityToken], User, RequestHeader) => (Iteratee[A, _], Enumerator[A]))
    : Future[Either[Result, (Iteratee[A, _], Enumerator[A])]] =
    securityService.authMode match {
      case AuthMode.Conf =>
        val maybeToken = extractToken(req)
        val tokenString = maybeToken.getOrElse("<session ID missing>")
        val maybeUser = restoreUser(req, scala.concurrent.ExecutionContext.Implicits.global)
        maybeUser
          .recover {
            case exception =>
              log.info(s"Authenticating the following session failed (session probably outdated): $tokenString") // TODO log level
              (None, identity[Result] _) // don't follow IntelliJ's recommendation here!
          }
          .flatMap {
            // TODO do we need the updater here? can we even use cookies or should we authenticate for each new WS connection?
            case (Some(user), updater) =>
              log.info(s"Successfully authenticated session $tokenString of $user") // TODO log level
              Future.successful(Right(f(maybeToken, user, req)))
            case (None, _) =>
              log.info(s"Websocket to ${req.remoteAddress} not established because of missing authentication") // TODO log level
              authenticationFailed(req).map(result => Left(result))
          }
      case AuthMode.None =>
        Future.successful(Right(f(None, anonymous, req)))
    }

  implicit def loggedIn(implicit req: RequestWithAttributes[_]): User = securityService.authMode match {
    case AuthMode.Conf => req.get(AuthKey).get
    case AuthMode.None => anonymous
  }

} 
Example 94
Source File: InstanceStorageSpec.scala    From cluster-broccoli   with Apache License 2.0 5 votes vote down vote up
package de.frosner.broccoli.instances.storage

import de.frosner.broccoli.models._
import org.specs2.mutable.Specification
import play.api.Logger

import scala.util.{Failure, Try}

class InstanceStorageSpec extends Specification {

  "Any instance storage" should {

    def testStorage = new InstanceStorage {
      protected override val log = Logger(getClass)
      protected override def readInstancesImpl: Try[Set[Instance]] = Failure(new Exception())
      override def readInstancesImpl(idFilter: (String) => Boolean): Try[Set[Instance]] = Failure(new Exception())
      override def readInstanceImpl(id: String): Try[Instance] = Failure(new Exception())
      override def deleteInstanceImpl(toDelete: Instance): Try[Instance] = Failure(new Exception())
      override def writeInstanceImpl(instance: Instance): Try[Instance] = Failure(new Exception())
      override def closeImpl(): Unit = {}
    }

    "be closed after closing" in {
      val storage = testStorage
      storage.close()
      storage.isClosed === true
    }

    "not be closed before closing" in {
      testStorage.isClosed === false
    }

    "should not allow readInstances if closed" in {
      val storage = testStorage
      storage.close()
      storage.readInstances should throwA[IllegalStateException]
    }

    "should not allow readInstances(filter) if closed" in {
      val storage = testStorage
      storage.close()
      storage.readInstances(_ => true) should throwA[IllegalStateException]
    }

    "should not allow readInstance if closed" in {
      val storage = testStorage
      storage.close()
      storage.readInstance("id") should throwA[IllegalStateException]
    }

    "should not allow deleteInstance if closed" in {
      val storage = testStorage
      storage.close()
      val instance = Instance(
        id = "1",
        template = Template(
          id = "1",
          template = "\"{{id}} {{age}}\"",
          description = "desc",
          parameterInfos = Map(
            "id" -> ParameterInfo("id", None, None, None, ParameterType.Raw, None),
            "age" -> ParameterInfo("age",
                                   None,
                                   None,
                                   secret = Some(false),
                                   `type` = ParameterType.Integer,
                                   orderIndex = None)
          )
        ),
        parameterValues = Map("id" -> StringParameterValue("Frank"), "age" -> IntParameterValue(50))
      )
      storage.deleteInstance(instance) should throwA[IllegalStateException]
    }

    "should not allow writeInstance if closed" in {
      val storage = testStorage
      storage.close()
      val instance = Instance(
        id = "1",
        template = Template(
          id = "1",
          template = "\"{{id}} {{age}}\"",
          description = "desc",
          parameterInfos = Map(
            "id" -> ParameterInfo("id", None, None, None, ParameterType.Raw, None),
            "age" -> ParameterInfo("age",
                                   None,
                                   None,
                                   secret = Some(false),
                                   `type` = ParameterType.Integer,
                                   orderIndex = None)
          )
        ),
        parameterValues = Map("id" -> StringParameterValue("Frank"), "age" -> IntParameterValue(50))
      )
      storage.writeInstance(instance) should throwA[IllegalStateException]
    }

  }

} 
Example 95
Source File: KubeServiceLocatorServer.scala    From lagom-on-kube   with Apache License 2.0 5 votes vote down vote up
package me.alexray.lagom.kube.discovery

import java.io.Closeable
import java.net.URI
import java.util.{Map => JMap}

import com.lightbend.lagom.gateway.{ServiceGateway, ServiceGatewayConfig, ServiceGatewayFactory}
import me.alexray.lagom.kube.discovery.impl.KubeServiceRegistryModule
import me.alexray.lagom.kube.gateway.{KubeServiceGateway, KubeServiceGatewayConfig, KubeServiceGatewayFactory}
import play.api.Application
import play.api.Logger
import play.api.Mode
import play.api.Play
import play.api.inject.guice.GuiceApplicationBuilder
import play.api.inject.guice.GuiceableModule.fromGuiceModule
import play.core.server.ServerConfig
import play.core.server.ServerProvider
import play.core.server.ServerWithStop

import scala.util.control.NonFatal

class KubeServiceLocatorServer extends Closeable {
  private val logger: Logger = Logger(this.getClass)

  @volatile private var server: ServerWithStop = _
  @volatile private var gateway: KubeServiceGateway = _

  def start(serviceLocatorPort: Int, serviceGatewayPort: Int, unmanagedServices: JMap[String, String]): Unit = synchronized {
    require(server == null, "Service locator is already running on " + server.mainAddress)

    val application = createApplication(KubeServiceGatewayConfig(serviceGatewayPort), unmanagedServices)
    Play.start(application)
    try {
      server = createServer(application, serviceLocatorPort)
    } catch {
      case NonFatal(e) =>
        throw new RuntimeException(s"Unable to start service locator on port $serviceLocatorPort", e)
    }
    try {
      gateway = application.injector.instanceOf[KubeServiceGatewayFactory].start()
    } catch {
      case NonFatal(e) =>
        throw new RuntimeException(s"Unable to start service gateway on port $serviceGatewayPort", e)
    }
    logger.info("Service locator can be reached at " + serviceLocatorAddress)
    logger.info("Service gateway can be reached at " + serviceGatewayAddress)
  }

  private def createApplication(serviceGatewayConfig: KubeServiceGatewayConfig, unmanagedServices: JMap[String, String]): Application = {
    new GuiceApplicationBuilder()
      .overrides(KubeServiceRegistryModule(serviceGatewayConfig, unmanagedServices))
      .build()
  }

  private def createServer(application: Application, port: Int): ServerWithStop = {
    val config = ServerConfig(port = Some(port), mode = Mode.Test)
    val provider = implicitly[ServerProvider]
    provider.createServer(config, application)
  }

  override def close(): Unit = synchronized {
    if (server == null) Logger.logger.debug("Service locator was already stopped")
    else {
      logger.debug("Stopping service locator...")
      server.stop()
      server = null
      logger.info("Service locator stopped")
    }
  }

  def serviceLocatorAddress: URI = {
    // Converting InetSocketAddress into URL is not that simple.
    // Because we know the service locator is running locally, I'm hardcoding the hostname and protocol.
    new URI(s"http://localhost:${server.mainAddress.getPort}")
  }

  def serviceGatewayAddress: URI = {
    new URI(s"http://localhost:${gateway.address.getPort}")
  }
} 
Example 96
Source File: KubeServiceRegistryImpl.scala    From lagom-on-kube   with Apache License 2.0 5 votes vote down vote up
package me.alexray.lagom.kube.discovery.impl

import java.net.URI
import java.util.concurrent.TimeUnit
import javax.inject.{Inject, Named}

import akka.NotUsed
import akka.actor.ActorRef
import akka.pattern.ask
import akka.util.Timeout
import com.lightbend.lagom.internal.javadsl.registry.{RegisteredService, ServiceRegistry, ServiceRegistryService}
import com.lightbend.lagom.javadsl.api.ServiceCall
import com.lightbend.lagom.javadsl.api.transport.NotFound
import org.pcollections.PSequence
import play.api.Logger

import scala.concurrent.Future
import scala.concurrent.duration.Duration
import me.alexray.lagom.kube.discovery.KubeServiceRegistryActor

import scala.language.implicitConversions


class KubeServiceRegistryImpl @Inject() (@Named(KubeServiceRegistryModule.KUBE_SERVICE_REGISTRY_ACTOR) registry: ActorRef)
  extends ServiceRegistry
{
  import me.alexray.lagom.converters.ServiceCallConverter._

  private val logger: Logger = Logger(this.getClass)
  implicit val timeout = Timeout(Duration.create(5, TimeUnit.SECONDS))
  import scala.concurrent.ExecutionContext.Implicits.global

  override def register(name: String): ServiceCall[ServiceRegistryService, NotUsed] = (service: ServiceRegistryService) =>
  {
    logger.debug("register invoked, name=[" + name + "], request=[" + service + "]")
    (registry ? KubeServiceRegistryActor.Register(name, service)).map(_ => NotUsed)
  }

  override def unregister(name: String): ServiceCall[NotUsed, NotUsed] = (request: NotUsed) => {
    logger.debug("unregister invoked, name=[" + name + "], request=[" + request + "]")

    registry ! KubeServiceRegistryActor.Remove(name)

    Future.successful(NotUsed)
  }

  override def lookup(name: String): ServiceCall[NotUsed, URI] = (request: NotUsed) => {
    logger.debug("locate invoked, name=[" + name + "], request=[" + request + "]")

    (registry ? KubeServiceRegistryActor.Lookup(name)).mapTo[Option[URI]].map {
      case Some(uri) =>
        logger.debug("Location of service name=[" + name + "] is " + uri)
        uri
      case None =>
        logger.debug("Service name=[" + name + "] has not been registered")
        throw new NotFound(name)
    }
  }

  override def registeredServices(): ServiceCall[NotUsed, PSequence[RegisteredService]] = (request: NotUsed) => {
    (registry ? KubeServiceRegistryActor.GetRegisteredServices).mapTo[KubeServiceRegistryActor.RegisteredServices].map(_.services)
  }

} 
Example 97
Source File: KubeServiceRegistration.scala    From lagom-on-kube   with Apache License 2.0 5 votes vote down vote up
package me.alexray.lagom.kube.client

import java.net.URI

import akka.actor.ActorSystem
import com.lightbend.lagom.internal.scaladsl.registry.{ServiceRegistry, ServiceRegistryService}
import com.lightbend.lagom.scaladsl.api.ServiceInfo
import play.api.inject.ApplicationLifecycle
import play.api.{Configuration, Logger}

import scala.concurrent.duration._
import scala.concurrent.{ExecutionContext, Future}
import scala.language.postfixOps
import scala.util.{Failure, Success}

class KubeServiceRegistration(serviceInfo: ServiceInfo,
                              lifecycle: ApplicationLifecycle,
                              config: Configuration,
                              registry: ServiceRegistry,
                              actorSystem: ActorSystem)(implicit ec: ExecutionContext)
{

  private val logger: Logger = Logger(this.getClass)
  private val uri = {
    val httpAddress =
      config.getString("service.http.address")
        .getOrElse(config.underlying.getString("play.server.http.address"))
    val httpPort = config.getString("play.server.http.port").get
    val uri = s"http://$httpAddress:$httpPort"
    logger.info(s"uri: $uri")
    URI.create(uri)
  }

  def completeServiceName(name: String): String =
    name + "-" + config.getString("service.instance.suffix").getOrElse("default").hashCode


  lifecycle.addStopHook { () =>
    Future.sequence(serviceInfo.locatableServices.map {
      case (service, _) =>
        registry.unregister(completeServiceName(service)).invoke()
    }).map(_ => ())
  }


  private def heartBeat(): Unit = {
    actorSystem.scheduler.schedule(1 seconds, 1 minutes) {
      logger.debug("register service heartbeat ")
      register()
    }
  }

  private def register(): Unit = {

    serviceInfo.locatableServices.foreach {
      case (service, acls) =>
        registry.register(completeServiceName(service))
          .invoke(ServiceRegistryService(uri, acls))
          .onComplete {
            case Success(_) =>
              logger.info(s"Service name=[$service] successfully registered with service locator.")
            case Failure(e) =>
              logger.error(s"Service name=[$service] couldn't register itself to the service locator.", e)
              logger.info("Service will try to register in 10 seconds with next heartbeat event")
          }
    }

  }

  heartBeat()

} 
Example 98
Source File: MillinerHatSignup.scala    From HAT2.0   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.hatdex.hat.resourceManagement

import org.hatdex.hat.resourceManagement.models.HatSignup
import play.api.cache.AsyncCacheApi
import play.api.http.Status._
import play.api.libs.json.{ JsError, JsSuccess }
import play.api.libs.ws.{ WSClient, WSRequest, WSResponse }
import play.api.{ Configuration, Logger }

import scala.concurrent.duration._
import scala.concurrent.{ ExecutionContext, Future }

trait MillinerHatSignup {
  val logger: Logger
  val ws: WSClient
  val configuration: Configuration
  val schema: String = configuration.get[String]("resourceManagement.millinerAddress") match {
    case address if address.startsWith("https") => "https://"
    case address if address.startsWith("http")  => "http://"
    case _                                      => "https://"
  }

  val millinerAddress: String = configuration.get[String]("resourceManagement.millinerAddress")
    .stripPrefix("http://")
    .stripPrefix("https://")
  val hatSharedSecret: String = configuration.get[String]("resourceManagement.hatSharedSecret")

  val cache: AsyncCacheApi

  def getHatSignup(hatAddress: String)(implicit ec: ExecutionContext): Future[HatSignup] = {
    // Cache the signup information for subsequent calls (For private/public key and database details)
    cache.getOrElseUpdate[HatSignup](s"configuration:$hatAddress") {
      val request: WSRequest = ws.url(s"$schema$millinerAddress/api/manage/configuration/$hatAddress")
        .withVirtualHost(millinerAddress)
        .withHttpHeaders("Accept" -> "application/json", "X-Auth-Token" -> hatSharedSecret)

      val futureResponse: Future[WSResponse] = request.get()
      futureResponse.map { response =>
        response.status match {
          case OK =>
            response.json.validate[HatSignup] match {
              case signup: JsSuccess[HatSignup] =>
                logger.debug(s"Got back configuration: ${signup.value}")
                cache.set(s"configuration:$hatAddress", signup.value, 1.minute)
                signup.value
              case e: JsError =>
                logger.error(s"Parsing HAT configuration failed: $e")
                throw new HatServerDiscoveryException("Fetching HAT configuration failed")
            }
          case _ =>
            logger.error(s"Fetching HAT configuration failed: ${response.body}")
            throw new HatServerDiscoveryException("Fetching HAT configuration failed")
        }
      }
    }
  }

} 
Example 99
Source File: HatServerProviderActor.scala    From HAT2.0   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.hatdex.hat.resourceManagement.actors

import javax.inject.Inject

import akka.actor.{ Props, _ }
import akka.util.Timeout
import org.hatdex.hat.api.service.RemoteExecutionContext
import org.hatdex.hat.utils.ActiveHatCounter
import play.api.libs.concurrent.InjectedActorSupport
import play.api.{ Configuration, Logger }

import scala.collection.mutable
import scala.concurrent.Future
import scala.concurrent.duration._
import scala.util.{ Failure, Success }

class HatServerProviderActor @Inject() (
    hatServerActorFactory: HatServerActor.Factory,
    activeHatcounter: ActiveHatCounter,
    configuration: Configuration)(
    implicit
    val ec: RemoteExecutionContext) extends Actor with InjectedActorSupport {
  private val log = Logger(this.getClass)
  import HatServerProviderActor._

  private val activeServers = mutable.HashMap[String, ActorRef]()
  private implicit val hatServerTimeout: Timeout = configuration.get[FiniteDuration]("resourceManagement.serverProvisioningTimeout")

  def receive: Receive = {
    case HatServerRetrieve(hat) =>
      log.debug(s"Retrieve HAT server $hat for $sender")
      val retrievingSender = sender
      getHatServerActor(hat) map { hatServerActor =>
        log.debug(s"Got HAT server provider actor, forwarding retrieval message with sender $sender $retrievingSender")
        hatServerActor tell (HatServerActor.HatRetrieve(), retrievingSender)
      } onComplete {
        case Success(_) ⇒ ()
        case Failure(e) ⇒ log.warn(s"Error while getting HAT server provider actor: ${e.getMessage}")
      }

    case HatServerStarted(_) =>
      activeHatcounter.increase()

    case HatServerStopped(_) =>
      activeHatcounter.decrease()

    case message =>
      log.debug(s"Received unexpected message $message")
  }

  private def getHatServerActor(hat: String): Future[ActorRef] = {
    doFindOrCreate(hat, hatServerTimeout.duration / 4)
  }

  private val maxAttempts = 3
  private def doFindOrCreate(hat: String, timeout: FiniteDuration, depth: Int = 0): Future[ActorRef] = {
    if (depth >= maxAttempts) {
      log.error(s"HAT server actor for $hat not resolved")
      throw new RuntimeException(s"Can not create actor for $hat and reached max attempts of $maxAttempts")
    }
    val selection = s"/user/hatServerProviderActor/hat:$hat"

    context.actorSelection(selection).resolveOne(timeout) map { hatServerActor =>
      log.debug(s"HAT server actor $selection resolved")
      hatServerActor
    } recoverWith {
      case ActorNotFound(_) =>
        log.debug(s"HAT server actor ($selection) not found, injecting child")
        val hatServerActor = injectedChild(hatServerActorFactory(hat), s"hat:$hat", props = (props: Props) => props.withDispatcher("hat-server-provider-actor-dispatcher"))
        activeServers(hat) = hatServerActor
        log.debug(s"Injected actor $hatServerActor")
        doFindOrCreate(hat, timeout, depth + 1)
    }
  }

}

object HatServerProviderActor {
  case class HatServerRetrieve(hat: String)

  case class HatServerStarted(hat: String)
  case class HatServerStopped(hat: String)
} 
Example 100
Source File: HatDatabaseProvider.scala    From HAT2.0   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.hatdex.hat.resourceManagement

import javax.inject.{ Inject, Singleton }

import com.typesafe.config.{ Config, ConfigFactory }
import org.hatdex.hat.dal.HatDbSchemaMigration
import org.hatdex.hat.resourceManagement.models.HatSignup
import org.hatdex.libs.dal.HATPostgresProfile.api.Database
import play.api.cache.AsyncCacheApi
import play.api.libs.ws.WSClient
import play.api.{ Configuration, Logger }

import scala.concurrent.{ ExecutionContext, Future }
import scala.collection.JavaConverters._
import scala.concurrent.duration.Duration

trait HatDatabaseProvider {
  protected val configuration: Configuration

  def database(hat: String)(implicit ec: ExecutionContext): Future[Database]

  def shutdown(db: Database): Future[Unit] = {
    // Execution context for the future is defined by specifying the executor during initialisation

    db.shutdown
  }

  def update(db: Database)(implicit ec: ExecutionContext): Future[Unit] = {
    new HatDbSchemaMigration(configuration, db, ec).run("hat.schemaMigrations")
  }
}

@Singleton
class HatDatabaseProviderConfig @Inject() (val configuration: Configuration) extends HatDatabaseProvider {
  def database(hat: String)(implicit ec: ExecutionContext): Future[Database] = {
    Future {
      Database.forConfig(s"hat.${hat.replace(':', '.')}.database", configuration.underlying)
    } recoverWith {
      case e =>
        Future.failed(new HatServerDiscoveryException(s"Database configuration for $hat incorrect or unavailable", e))
    }
  }
}

@Singleton
class HatDatabaseProviderMilliner @Inject() (
    val configuration: Configuration,
    val cache: AsyncCacheApi,
    val ws: WSClient) extends HatDatabaseProvider with MillinerHatSignup {
  val logger = Logger(this.getClass)

  def database(hat: String)(implicit ec: ExecutionContext): Future[Database] = {
    getHatSignup(hat) map { signup =>
      val config = signupDatabaseConfig(signup)
      //      val databaseUrl = s"jdbc:postgresql://${signup.databaseServer.get.host}:${signup.databaseServer.get.port}/${signup.database.get.name}"
      //      val executor = AsyncExecutor(hat, numThreads = 3, queueSize = 1000)
      //      Database.forURL(databaseUrl, signup.database.get.name, signup.database.get.password, driver = "org.postgresql.Driver"  )
      Database.forConfig("", config)
    }
  }

  def signupDatabaseConfig(signup: HatSignup): Config = {
    val database = signup.database.get
    val config = Map(
      "dataSourceClass" -> "org.postgresql.ds.PGSimpleDataSource",
      "properties" -> Map[String, String](
        "user" -> database.name,
        "password" -> database.password,
        "databaseName" -> database.name,
        "portNumber" -> signup.databaseServer.get.port.toString,
        "serverName" -> signup.databaseServer.get.host).asJava,
      "numThreads" -> configuration.get[Int]("resourceManagement.hatDBThreads").toString,
      "idleTimeout" -> configuration.get[Duration]("resourceManagement.hatDBIdleTimeout").toMillis.toString).asJava

    ConfigFactory.parseMap(config)
  }
} 
Example 101
Source File: DevHatInitializationModule.scala    From HAT2.0   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.hatdex.hat.modules

import java.util.UUID

import com.typesafe.config.Config
import javax.inject.Inject
import net.codingwell.scalaguice.ScalaModule
import org.hatdex.hat.api.models.{ Owner, Platform }
import org.hatdex.hat.api.service.{ DalExecutionContext, UsersService }
import org.hatdex.hat.authentication.models.HatUser
import org.hatdex.hat.dal.HatDbSchemaMigration
import org.hatdex.hat.resourceManagement.{ HatServer, HatServerProvider }
import play.api.libs.concurrent.AkkaGuiceSupport
import play.api.{ ConfigLoader, Configuration, Logger }

import scala.concurrent.Future

class DevHatInitializationModule extends ScalaModule with AkkaGuiceSupport {

  
  override protected def configure(): Unit = {
    bind[DevHatInitializer].asEagerSingleton()
  }
}

class DevHatInitializer @Inject() (
    configuration: Configuration,
    serverProvider: HatServerProvider,
    usersService: UsersService)(implicit ec: DalExecutionContext) {
  val logger = Logger(this.getClass)

  import DevHatConfig.configLoader

  val devHats = configuration.get[Map[String, DevHatConfig]]("devhats")
  val devHatMigrations = configuration.get[Seq[String]]("devhatMigrations")

  logger.info(s"Initializing HATs: $devHats")
  devHats.values.map(initializeHat)

  def initializeHat(hat: DevHatConfig) = {
    val hatServer: Future[HatServer] = serverProvider.retrieve(hat.domain).map(_.get)

    val eventuallyMigrated = for {
      server ← hatServer
      _ ← new HatDbSchemaMigration(configuration, server.db, ec).run(devHatMigrations)
      _ ← setupCredentials(hat)(server)
    } yield ()

    eventuallyMigrated map { _ =>
      logger.info(s"Database successfully initialized for ${hat.owner}")
    } recover {
      case e =>
        logger.error(s"Database initialisation failed for ${hat.owner}: ${e.getMessage}", e)
    } map { _ =>
      logger.debug(s"Shutting down connection to database for ${hat.owner}")
      //      hatServer.map(_.db.shutdown)
    }
  }

  def setupCredentials(hat: DevHatConfig)(implicit server: HatServer): Future[Unit] = {
    logger.debug(s"Setup credentials for ${hat.owner}")
    val ownerId = UUID.fromString("694dd8ed-56ae-4910-abf1-6ec4887b4c42")
    val platformId = UUID.fromString("6507ae16-13d7-479b-8ebc-65c28fec1634")
    for {
      savedOwner <- usersService.saveUser(HatUser(ownerId, hat.owner, Some(hat.ownerPasswordHash), hat.ownerName, Seq(Owner()), enabled = true))
      savedPlatform <- usersService.saveUser(HatUser(platformId, hat.platform, Some(hat.platformPasswordHash), hat.platformName, Seq(Platform()), enabled = true))
    } yield {
      logger.info(s"Saved owner: $savedOwner")
      logger.info(s"Saved platform: $savedPlatform")
      ()
    }
  }
}

case class DevHatConfig(
    owner: String,
    domain: String,
    ownerName: String,
    ownerPasswordHash: String,
    platform: String,
    platformName: String,
    platformPasswordHash: String,
    database: Config)

object DevHatConfig {
  implicit val configLoader: ConfigLoader[DevHatConfig] = new ConfigLoader[DevHatConfig] {
    def load(rootConfig: Config, path: String): DevHatConfig = {
      val config = ConfigLoader.configurationLoader.load(rootConfig, path)
      DevHatConfig(
        owner = config.get[String]("owner"),
        domain = config.get[String]("domain"),
        ownerName = config.get[String]("ownerName"),
        ownerPasswordHash = config.get[String]("ownerPasswordHash"),
        platform = config.get[String]("platform"),
        platformName = config.get[String]("platformName"),
        platformPasswordHash = config.get[String]("platformPasswordHash"),
        database = config.get[Config]("database"))
    }
  }
} 
Example 102
Source File: SHEModule.scala    From HAT2.0   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.hatdex.hat.modules

import com.google.inject.{ AbstractModule, Provides }
import com.typesafe.config.Config
import net.codingwell.scalaguice.ScalaModule
import org.hatdex.hat.api.models.applications.Version
import org.hatdex.hat.she.models.LambdaFunctionLoader
import org.hatdex.hat.she.service.{ FunctionExecutableRegistry, FunctionExecutionTriggerHandler }
import org.hatdex.hat.utils.FutureTransformations
import play.api.libs.concurrent.AkkaGuiceSupport
import play.api.{ ConfigLoader, Configuration, Logger }

import scala.collection.JavaConverters._
import scala.concurrent.duration._
import scala.concurrent.{ Await, ExecutionContext, Future }

class SHEModule extends AbstractModule with ScalaModule with AkkaGuiceSupport {
  val logger = Logger(this.getClass)

  override def configure() = {
    bind[FunctionExecutionTriggerHandler].asEagerSingleton()
    ()
  }

  implicit val seqFunctionConfigLoader: ConfigLoader[Seq[FunctionConfig]] = new ConfigLoader[Seq[FunctionConfig]] {
    def load(config: Config, path: String): Seq[FunctionConfig] = {
      val configs = config.getConfigList(path).asScala
      logger.info(s"Got SHE function configs: $configs")
      configs.map { config ⇒
        FunctionConfig(
          config.getString("id"),
          Version(config.getString("version")),
          config.getString("baseUrl"),
          config.getString("namespace"),
          config.getString("endpoint"),
          config.getBoolean("experimental"))
      }
    }
  }

  @Provides
  def provideFunctionExecutableRegistry(
    config: Configuration,
    loader: LambdaFunctionLoader)(implicit ec: ExecutionContext): FunctionExecutableRegistry = {

    val includeExperimental: Boolean = config.getOptional[Boolean]("she.beta").getOrElse(false)

    val eventuallyFunctionsLoaded = Future.sequence(
      config.get[Seq[FunctionConfig]]("she.functions")
        .filter(c => !c.experimental || (includeExperimental && c.experimental))
        .map(c ⇒ FutureTransformations.futureToFutureTry(loader.load(c.id, c.version, c.baseUrl, c.namespace, c.endpoint))))

    val functionsLoaded = Await.result(eventuallyFunctionsLoaded, 30.seconds)

    // ignore any functions that failed to load without stopping the whole application
    new FunctionExecutableRegistry(functionsLoaded.filter(_.isSuccess).flatMap(_.toOption))
  }

  case class FunctionConfig(id: String, version: Version, baseUrl: String, namespace: String, endpoint: String, experimental: Boolean)
} 
Example 103
Source File: StaticDataGeneratorService.scala    From HAT2.0   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.hatdex.hat.she.service

import javax.inject.Inject
import org.hatdex.hat.api.service.richData.RichDataService
import org.hatdex.hat.resourceManagement.HatServer
import org.hatdex.hat.she.mappers.{ FacebookProfileStaticDataMapper, FitbitProfileStaticDataMapper, InstagramProfileStaticDataMapper, SpotifyProfileStaticDataMapper, StaticDataEndpointMapper, TwitterProfileStaticDataMapper, UberProfileStaticDataMapper }
import org.hatdex.hat.she.models.StaticDataValues
import play.api.Logger

import scala.concurrent.{ ExecutionContext, Future }

class StaticDataGeneratorService @Inject() ()(
    implicit
    richDataService: RichDataService,
    val ec: ExecutionContext) {

  private val logger = Logger(this.getClass)

  private val staticDataMappers: Seq[(String, StaticDataEndpointMapper)] = Seq(
    "facebook/profile" -> new FacebookProfileStaticDataMapper(),
    "twitter/profile" -> new TwitterProfileStaticDataMapper(),
    "spotify/profile" -> new SpotifyProfileStaticDataMapper(),
    "fitbit/profile" -> new FitbitProfileStaticDataMapper(),
    "instagram/profile" -> new InstagramProfileStaticDataMapper(),
    "uber/profile" -> new UberProfileStaticDataMapper())

  def getStaticData(endpoint: String)(implicit hatServer: HatServer): Future[Seq[StaticDataValues]] = {
    val mappers = staticDataMappers.find(_._1.startsWith(endpoint))

    logger.debug(s"Fetching feed data for ${mappers.map(_._1)}")

    mappers match {
      case Some((_, mapper)) => mapper.staticDataRecords()
      case None =>
        logger.info(s"No static data found for ${mappers.map(_._1)}")
        Future.successful(Seq())
    }
  }
} 
Example 104
Source File: StaticDataEndpointMapper.scala    From HAT2.0   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.hatdex.hat.she.mappers

import java.util.UUID

import org.hatdex.hat.api.models.{ EndpointData, PropertyQuery }
import org.hatdex.hat.api.service.richData.RichDataService
import org.hatdex.hat.resourceManagement.HatServer
import org.hatdex.hat.she.models.StaticDataValues
import play.api.Logger
import play.api.libs.json._

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future

trait StaticDataEndpointMapper extends JodaWrites with JodaReads {
  protected lazy val logger: Logger = Logger(this.getClass)

  def dataQueries(): Seq[PropertyQuery]
  def mapDataRecord(recordId: UUID, content: JsValue, endpoint: String): Seq[StaticDataValues]

  final def staticDataRecords()(
    implicit
    hatServer: HatServer, richDataService: RichDataService): Future[Seq[StaticDataValues]] = {

    val staticData = Future.sequence(dataQueries.map { query =>

      val eventualDataSource: Future[Seq[EndpointData]] = richDataService.propertyData(query.endpoints, query.orderBy,
        orderingDescending = query.ordering.contains("descending"), skip = 0, limit = query.limit, createdAfter = None)(hatServer.db)

      eventualDataSource.map { dataSource => dataSource.map(item => mapDataRecord(item.recordId.get, item.data, item.endpoint)).headOption.getOrElse(Seq()) }
    })

    staticData.map(_.flatten)
  }
} 
Example 105
Source File: FunctionManager.scala    From HAT2.0   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.hatdex.hat.she.controllers

import com.mohiva.play.silhouette.api.Silhouette
import com.mohiva.play.silhouette.api.actions.SecuredRequest
import javax.inject.Inject
import org.hatdex.hat.api.json.RichDataJsonFormats
import org.hatdex.hat.api.models._
import org.hatdex.hat.api.service.applications.ApplicationsService
import org.hatdex.hat.authentication.{ ContainsApplicationRole, HatApiAuthEnvironment, HatApiController, WithRole }
import org.hatdex.hat.she.models.{ FunctionConfiguration, FunctionConfigurationJsonProtocol, FunctionStatus }
import org.hatdex.hat.she.service.{ FunctionExecutionTriggerHandler, FunctionService }
import play.api.Logger
import play.api.libs.json._
import play.api.mvc._

import scala.concurrent.{ ExecutionContext, Future }

class FunctionManager @Inject() (
    components: ControllerComponents,
    silhouette: Silhouette[HatApiAuthEnvironment],
    functionService: FunctionService,
    functionExecutionDispatcher: FunctionExecutionTriggerHandler)(
    implicit
    val ec: ExecutionContext,
    applicationsService: ApplicationsService)
  extends HatApiController(components, silhouette)
  with RichDataJsonFormats
  with FunctionConfigurationJsonProtocol {

  private val logger = Logger(this.getClass)

  def functionList(): Action[AnyContent] = SecuredAction(ContainsApplicationRole(Owner()) || WithRole(Owner(), Platform())).async { implicit request ⇒
    functionService.all(active = false).map { functions ⇒
      Ok(Json.toJson(functions))
    }
  }

  def functionGet(function: String): Action[AnyContent] = SecuredAction(ContainsApplicationRole(Owner()) || WithRole(Owner(), Platform())).async { implicit request ⇒
    logger.debug(s"Get function $function")
    functionService.get(id = function).map { maybeFunction ⇒
      maybeFunction.map { function ⇒
        Ok(Json.toJson(function))
      } getOrElse {
        NotFound(Json.toJson(ErrorMessage("Function Not Found", s"Function $function not found")))
      }
    }
  }

  def functionEnable(function: String): Action[AnyContent] = SecuredAction(ContainsApplicationRole(Owner()) || WithRole(Owner())).async { implicit request ⇒
    functionSetEnabled(function, enabled = true)
  }

  def functionDisable(function: String): Action[AnyContent] = SecuredAction(ContainsApplicationRole(Owner()) || WithRole(Owner())).async { implicit request ⇒
    functionSetEnabled(function, enabled = false)
  }

  protected def functionSetEnabled(function: String, enabled: Boolean)(implicit request: SecuredRequest[HatApiAuthEnvironment, AnyContent]): Future[Result] = {
    logger.debug(s"Enable function $function = $enabled")
    functionService.get(function).flatMap { maybeFunction ⇒
      maybeFunction.map { function ⇒
        functionService.save(function.copy(status = function.status.copy(enabled = enabled)))
          .map(f ⇒ Ok(Json.toJson(f)))
      } getOrElse {
        Future.successful(NotFound(Json.toJson(ErrorMessage("Function Not Found", s"Function $function not found"))))
      }
    }
  }

  def functionTrigger(function: String): Action[AnyContent] = SecuredAction(ContainsApplicationRole(Owner()) || WithRole(Owner(), Platform())).async { implicit request ⇒
    logger.debug(s"Trigger function $function")
    functionService.get(function).flatMap { maybeFunction ⇒
      maybeFunction.map {
        case c: FunctionConfiguration if c.status.available && c.status.enabled ⇒
          functionExecutionDispatcher.trigger(request.dynamicEnvironment.domain, c)(ec)
            .map(_ ⇒ Ok(Json.toJson(SuccessResponse("Function Executed"))))
            .recover {
              case e ⇒
                logger.error(s"Function $function execution errored with ${e.getMessage}", e)
                InternalServerError(Json.toJson(ErrorMessage("Function Execution Failed", s"Function $function execution errored with ${e.getMessage}")))
            }
        case FunctionConfiguration(_, _, _, _, _, FunctionStatus(false, _, _, _)) ⇒
          Future.successful(BadRequest(Json.toJson(ErrorMessage("Function Not Available", s"Function $function not available for execution"))))
        case FunctionConfiguration(_, _, _, _, _, FunctionStatus(true, false, _, _)) ⇒
          Future.successful(BadRequest(Json.toJson(ErrorMessage("Function Not Enabled", s"Function $function not enabled for execution"))))
      } getOrElse {
        Future.successful(NotFound(Json.toJson(ErrorMessage("Function Not Found", s"Function $function not found"))))
      }
    }
  }
} 
Example 106
Source File: EndpointSubscriberService.scala    From HAT2.0   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.hatdex.hat.api.service.monitoring

import org.hatdex.hat.api.models._
import org.hatdex.hat.api.service.richData.JsonDataTransformer
import org.joda.time.DateTime
import play.api.Logger
import play.api.libs.json.Reads._
import play.api.libs.json.{ JsArray, JsValue, Json, _ }

case class EndpointQueryException(message: String = "", cause: Throwable = None.orNull)
  extends Exception(message, cause)

object EndpointSubscriberService {
  private val logger = Logger(this.getClass)

  def matchesBundle(data: EndpointData, bundle: EndpointDataBundle): Boolean = {
    val endpointQueries = bundle.flatEndpointQueries
      .filter(_.endpoint == data.endpoint)

    endpointQueries collectFirst {
      case q if q.filters.isEmpty                             => true
      case q if q.filters.exists(dataMatchesFilters(data, _)) => true
    } getOrElse {
      false
    }
  }

  private implicit val dateReads: Reads[DateTime] = JodaReads.jodaDateReads("yyyy-MM-dd'T'HH:mm:ssZ")

  private def dataMatchesFilters(data: EndpointData, filters: Seq[EndpointQueryFilter]): Boolean = {
    logger.debug("Checking if data matches provided filters")
    filters.exists { f =>
      data.data.transform(JsonDataTransformer.parseJsPath(f.field).json.pick).fold(
        invalid = {
          _ => false
        },
        valid = {
          fieldData =>
            val data = f.transformation map {
              case _: FieldTransformation.Identity =>
                fieldData
              case trans: FieldTransformation.DateTimeExtract =>
                Json.toJson(dateTimeExtractPart(fieldData.as[DateTime](dateReads), trans.part))
              case trans: FieldTransformation.TimestampExtract =>
                Json.toJson(dateTimeExtractPart(new DateTime(fieldData.as[Long] * 1000L), trans.part))
              case trans =>
                throw EndpointQueryException(s"Invalid field transformation `${trans.getClass.getName}` for ongoing tracking")
            } getOrElse {
              fieldData
            }
            f.operator match {
              case op: FilterOperator.In       => jsContains(op.value, data)
              case op: FilterOperator.Contains => jsContains(data, op.value)
              case op: FilterOperator.Between  => jsLessThanOrEqual(op.lower, data) && jsLessThanOrEqual(data, op.upper)
              case op                          => throw EndpointQueryException(s"Invalid match operator `${op.getClass.getName}` for ongoing tracking")
            }

        })
    }
  }

  private def dateTimeExtractPart(d: DateTime, part: String): Int = {
    part match {
      case "milliseconds" => d.getMillisOfSecond
      case "second"       => d.getSecondOfMinute
      case "minute"       => d.getMinuteOfDay
      case "hour"         => d.getHourOfDay
      case "day"          => d.getDayOfMonth
      case "week"         => d.getWeekOfWeekyear
      case "month"        => d.getMonthOfYear
      case "year"         => d.getYear
      case "decade"       => d.getYear / 10
      case "century"      => d.getCenturyOfEra
      case "dow"          => d.getDayOfWeek
      case "doy"          => d.getDayOfYear
      case "epoch"        => (d.getMillis / 1000).toInt
    }
  }

  private def jsContains(contains: JsValue, contained: JsValue): Boolean = {
    (contains, contained) match {
      case (a: JsObject, b: JsObject) => b.fieldSet.subsetOf(a.fieldSet)
      case (a: JsArray, b: JsArray)   => a.value.containsSlice(b.value)
      case (a: JsArray, b: JsValue)   => a.value.contains(b)
      case (a: JsValue, b: JsValue)   => a == b
      case _                          => false
    }
  }

  private def jsLessThanOrEqual(a: JsValue, b: JsValue): Boolean = {
    (a, b) match {
      case (aa: JsNumber, bb: JsNumber) => aa.value <= bb.value
      case (aa: JsString, bb: JsString) => aa.value <= bb.value
      case _                            => false
    }
  }
} 
Example 107
Source File: Analyze.scala    From Mastering-Spark-for-Data-Science   with MIT License 5 votes vote down vote up
package controllers

import java.io.{File, FileInputStream}
import java.util.UUID

import com.typesafe.config.ConfigFactory
import io.gzet.recommender.Audio
import models.Songs
import play.api.Logger
import play.api.mvc._
import svc.{AnalyzerSvc, CassandraDao, SparkSvc}

object Analyze extends Controller {

  val config = ConfigFactory.load()
  val minTime = config.getInt("gzet.min.time")
  val maxTime = config.getInt("gzet.max.time")
  val cassandraHost = config.getString("cassandra.host")
  val cassandraPort = config.getInt("cassandra.port")
  val sampleSize = config.getDouble("gzet.sample.size")
  val minMatch = config.getDouble("gzet.min.match")

  val dao = new CassandraDao(cassandraHost, cassandraPort)
  val analyzer = new AnalyzerSvc()
  val spark = new SparkSvc()

  def index = Action { implicit request =>
    val songs = Songs(dao.getSongs)
    Logger.info(s"Database is currently ${songs.songs.size} songs long")
    Ok(views.html.analyze("Select a wav file to analyze")(songs))
  }

  def submit = Action(parse.multipartFormData) { request =>
    val songs = Songs(dao.getSongs)
    Logger.info(s"Database is currently ${songs.songs.size} songs long")
    if(songs.songs.isEmpty) {
      Redirect(routes.Analyze.index()).flashing("warning" -> s"Library is currently empty. Please index new records")
    } else {
      request.body.file("song").map { upload =>
        val fileName = upload.filename
        Logger.info(s"Processing file $fileName")
        val file = new File(s"/tmp/${UUID.randomUUID()}")
        upload.ref.moveTo(file)
        try {
          val song = process(file)
          if(song.isEmpty) {
            Redirect(routes.Analyze.index()).flashing("warning" -> s"Could not match any record for [$fileName]")
          } else {
            val songName = song.get
            Logger.info(s"Found song [$songName]")
            Redirect(routes.Analyze.index()).flashing("success" -> songName)
          }
        } catch {
          case e: Exception =>
            Redirect(routes.Analyze.index()).flashing("error" -> e.getMessage)
        }
      }.getOrElse {
        Redirect(routes.Analyze.index()).flashing("error" -> "Missing file")
      }
    }
  }

  def process(file: File) = {
    val is = new FileInputStream(file)
    val audio = Audio.processSong(is, minTime, maxTime)
    Logger.info(audio.toString)
    file.delete()
    analyzer.analyze(audio)
  }

} 
Example 108
Source File: ErrorHandler.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
import javax.inject.{ Inject, Provider }
import play.api.{ Configuration, Environment, Logger, OptionalSourceMapper, UsefulException }
import play.api.http.DefaultHttpErrorHandler
import play.api.mvc.RequestHeader
import play.api.mvc.Results._
import play.api.routing.Router
import scala.concurrent.Future

class ErrorHandler @Inject() (
    env: Environment,
    config: Configuration,
    sourceMapper: OptionalSourceMapper,
    router: Provider[Router]
  ) extends DefaultHttpErrorHandler(env, config, sourceMapper, router) {

  override def onProdServerError(request: RequestHeader, exception: UsefulException) =
    Future.successful(InternalServerError(s"An error occurred: ${exception.getMessage}"))

  override def onClientError(request: RequestHeader, statusCode: Int, message: String) = {
    if (statusCode == 413) // Request entity too large
      Future.successful(EntityTooLarge("Could not upload the file - too large"))
    else if (statusCode == 404) // Not Found
      Future.successful(NotFound(views.html.error404()))
    else
      super.onClientError(request, statusCode, message)
  }

} 
Example 109
Source File: ReferenceRewriterImpl.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package services.entity.builtin.importer

import com.sksamuel.elastic4s.ElasticDsl._
import com.sksamuel.elastic4s.searches.RichSearchResponse
import javax.inject.Inject
import play.api.Logger
import scala.concurrent.{ExecutionContext, Future}
import services.entity.builtin.IndexedEntity
import storage.es.ES
import services.annotation.{Annotation, HasAnnotationIndexing}

class ReferenceRewriterImpl @Inject()(implicit ctx: ExecutionContext, es: ES)
  extends ReferenceRewriter with HasAnnotationIndexing {

  private val SCROLL_BATCH_SIZE = 200

  private def reindexBatch(batch: Seq[(Annotation, Long)]): Future[Boolean] = {
    if (batch.isEmpty) {
      Future.successful(true) // If there were no changes detected, this method might be handed an empty list
    } else {
      es.client execute {
        bulk(batch.map { case (annotation, version) =>
          update(annotation.annotationId.toString) in ES.RECOGITO / ES.ANNOTATION doc annotation version version
        })
      } map { ES.logFailures(_) }
    }
  }

  private def updateBatch(response: RichSearchResponse, entitiesAfter: Seq[IndexedEntity], cursor: Long = 0l): Future[Boolean] = {
    val annotations = response.to[(Annotation, Long)].toSeq
    if (annotations.isEmpty) {
      Future.successful(true)
    } else {    
      val changed = annotations.flatMap { case (before, id) =>
        val after = addUnionIds(before, entitiesAfter)

        // Don't make unnecessary updates if the union Id didn't change 
        if (after == before) None
        else Some((after, id))
      }

      reindexBatch(changed).flatMap { success =>
        val rewritten = cursor + annotations.size
        if (rewritten < response.totalHits)
          fetchNextBatch(response.scrollId).flatMap { response =>
            updateBatch(response, entitiesAfter, rewritten)
          }
        else
          Future.successful(success)
      }
    }
  }

  private def fetchNextBatch(scrollId: String): Future[RichSearchResponse] =
    es.client execute {
      searchScroll(scrollId) keepAlive "5m"
    }

  private def fetchFirstBatch(entitiesBefore: Seq[IndexedEntity], entitiesAfter: Seq[IndexedEntity]) = {
    // Potentially, changes can happen for all entity URIs, before and after
    val affectedUris = 
      (entitiesBefore ++ entitiesAfter)
        .flatMap(_.entity.isConflationOf.map(_.uri)).distinct
    
    es.client execute {
      search(ES.RECOGITO / ES.ANNOTATION) query constantScoreQuery {
        nestedQuery("bodies") query {
          should(affectedUris.map { uri =>
            termQuery("bodies.reference.uri" -> uri)
          })
        }
      } version true limit SCROLL_BATCH_SIZE scroll "5m"
    }
  }

  override def rewriteReferencesTo(entitiesBefore: Seq[IndexedEntity], entitiesAfter: Seq[IndexedEntity]): Future[Boolean] =
    for {
      affectedAnnotations <- fetchFirstBatch(entitiesBefore, entitiesAfter)
      success <- updateBatch(affectedAnnotations, entitiesAfter)
    } yield (success)

} 
Example 110
Source File: BaseGeoJSONCrosswalk.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package services.entity.builtin.importer.crosswalks.geojson

import com.vividsolutions.jts.geom.Geometry
import services.HasGeometry
import services.entity.EntityRecord
import play.api.Logger
import play.api.libs.json._
import play.api.libs.functional.syntax._

trait BaseGeoJSONCrosswalk {

  def fromJson[T](record: String, crosswalk: T => EntityRecord)(implicit reads: Reads[T]): Option[EntityRecord] =
    Json.fromJson[T](Json.parse(record)) match {
      case s: JsSuccess[T] => Some(crosswalk(s.get))
      case e: JsError =>
        Logger.warn(e.toString)
        None
    }

}

case class Feature(geometry: Geometry)

object Feature extends HasGeometry {

  implicit val featureReads: Reads[Feature] = (JsPath \ "geometry").read[Geometry].map(Feature(_))

} 
Example 111
Source File: HasBatchImport.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package services.entity.builtin.importer;

import play.api.Logger
import scala.concurrent.{ExecutionContext, Future}
import services.entity.EntityRecord

trait HasBatchImport { 

  def importRecord(record: EntityRecord): Future[Boolean]
  
  // Maximum number of times a gazetteer record or place link update will be retried in case of failure
  private def MAX_RETRIES = 20
  
  // Incremental backoff time (ms) for index retries
  private val BACKOFF_MS = 500
  
  
  def importRecords(records: Seq[EntityRecord], retries: Int = MAX_RETRIES)(implicit ctx: ExecutionContext): Future[Seq[EntityRecord]] =
    records.foldLeft(Future.successful(Seq.empty[EntityRecord])) { case (f, next) =>
      f.flatMap { failed =>
        importRecord(next).map { success =>
          if (success) failed
          else next +: failed
        }
      }
    } flatMap { failedRecords =>      
      if (failedRecords.size > 0 && retries > 0) {
        Logger.warn(s"${failedRecords.size} gazetteer records failed to import - retrying")

        // Start first retry immediately and then increases wait time for each subsequent retry
        val backoff = (MAX_RETRIES - retries) * BACKOFF_MS
        if (backoff > 0) {
          Logger.info(s"Waiting... ${backoff}ms")
          Thread.sleep(backoff)
        }

        importRecords(failedRecords, retries - 1)
      } else if (failedRecords.size > 0) {
        Logger.error(s"${failedRecords.size} gazetteer records failed without recovery")
        failedRecords.foreach(record =>  Logger.error(record.toString))
        Future.successful(failedRecords)
      } else {
        Logger.info(s"Imported ${records.size} records - no failed imports")
        Future.successful(failedRecords)
      }
    }
  
} 
Example 112
Source File: DocumentIdFactory.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package services.document

import collection.JavaConversions._
import org.apache.commons.lang3.RandomStringUtils
import play.api.Logger
import scala.concurrent.Await
import scala.concurrent.duration._
import services.generated.Tables._
import storage.db.DB

object DocumentIdFactory {
  
  // We use random alphanumeric IDs with 14 chars length (because 62^14 should be enough for anyone (TM))  
  val ID_LENGTH = 14
  
  // Utility function to check if an ID exists in the DB
  def existsId(id: String)(implicit db: DB) = {
    def checkExists() = db.query { sql =>
      val count = sql.select(DOCUMENT.ID)
         .from(DOCUMENT)
         .where(DOCUMENT.ID.equal(id))
         .fetchArray()
         .length
      
      count > 0
    }
    
    Await.result(checkExists(), 10.seconds)    
  }
  
  def generateRandomID(retriesLeft: Int = 10)(implicit db: DB): String = {
    
    // Takes a set of strings and returns those that already exist in the DB as doc IDs
    def findIds(ids: Set[String])(implicit db: DB) = db.query { sql =>
      sql.select(DOCUMENT.ID)
         .from(DOCUMENT)
         .where(DOCUMENT.ID.in(ids))
         .fetchArray()
         .map(_.value1).toSet    
    }
    
    // Generate 10 random IDs
    val randomIds = 
      (1 to 10).map(_ => RandomStringUtils.randomAlphanumeric(ID_LENGTH).toLowerCase).toSet

    // Match them all against the database and remove those that already exist
    val idsAlreadyInDB = Await.result(findIds(randomIds), 10.seconds)    
    val uniqueIds = randomIds.filter(id => !idsAlreadyInDB.contains(id))
    
    if (uniqueIds.size > 0) {
      uniqueIds.head
    } else if (retriesLeft > 0) {
      Logger.warn("Failed to generate unique random document ID")
      generateRandomID(retriesLeft - 1)
    } else {
      throw new RuntimeException("Failed to create unique document ID")
    }
  }
  
} 
Example 113
Source File: DumpLoader.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package controllers.admin.authorities

import java.io.{InputStream, File, FileInputStream}
import java.util.zip.GZIPInputStream
import play.api.Logger
import scala.concurrent.{Await, ExecutionContext}
import scala.concurrent.duration._
import services.entity.EntityRecord
import services.entity.builtin.importer.EntityImporter

class DumpLoader {
  
  private def getStream(file: File, filename: String) =
    if (filename.endsWith(".gz"))
      new GZIPInputStream(new FileInputStream(file))
    else
      new FileInputStream(file)
  
  def importDump(file: File, filename: String, crosswalk: InputStream => Seq[EntityRecord], importer: EntityImporter)(implicit ctx: ExecutionContext) = {
    val records = crosswalk(getStream(file, filename))
    Logger.info("Importing " + records.size + " records")
    Await.result(importer.importRecords(records), 60.minute)   
  }
  
} 
Example 114
Source File: StreamLoader.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package controllers.admin.authorities

import akka.stream.{ActorAttributes, ClosedShape, Materializer, Supervision}
import akka.stream.scaladsl._
import akka.util.ByteString
import java.io.InputStream
import services.entity.EntityRecord
import services.entity.builtin.importer.EntityImporter
import play.api.Logger
import play.api.libs.json.Json
import scala.concurrent.{Await, ExecutionContext}
import scala.concurrent.duration._

class StreamLoader(implicit materializer: Materializer) {
  
  private val BATCH_SIZE = 100
  
  private val decider: Supervision.Decider = {    
    case t: Throwable => 
      t.printStackTrace()
      Supervision.Stop    
  }
  
  def importPlaces(is: InputStream, crosswalk: String => Option[EntityRecord], importer: EntityImporter)(implicit ctx: ExecutionContext) = {
    
    val source = StreamConverters.fromInputStream(() => is, 1024)
      .via(Framing.delimiter(ByteString("\n"), maximumFrameLength = Int.MaxValue, allowTruncation = false))
      .map(_.utf8String)
      
    val parser = Flow.fromFunction[String, Option[EntityRecord]](crosswalk)
      .withAttributes(ActorAttributes.supervisionStrategy(decider))
      .grouped(BATCH_SIZE)
      
    val sink = Sink.foreach[Seq[Option[EntityRecord]]] { records =>
      val toImport = records.flatten
      Await.result(importer.importRecords(toImport), 60.minutes)
    }
    
    val graph = RunnableGraph.fromGraph(GraphDSL.create() { implicit builder =>
      
      import GraphDSL.Implicits._
      
      source ~> parser ~> sink
      
      ClosedShape
    }).withAttributes(ActorAttributes.supervisionStrategy(decider))
        
    graph.run()
  }
  
} 
Example 115
Source File: FileUpload.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package controllers.my.directory.create.types

import controllers.my.directory.create.CreateController
import java.util.UUID
import play.api.Logger
import play.api.mvc.AnyContent
import play.api.libs.json._
import play.api.libs.functional.syntax._
import scala.concurrent.Future
import services.{UnsupportedContentTypeException, UnsupportedTextEncodingException}
import services.generated.tables.records.UploadRecord
import services.upload.QuotaExceededException
import services.user.User

case class UploadSuccess(partId: UUID, contentType: String)

object UploadSuccess {

  implicit val uploadSuccessWrites: Writes[UploadSuccess] = (
    (JsPath \ "uuid").write[UUID] and
    (JsPath \ "content_type").write[String]
  )(unlift(UploadSuccess.unapply))

}

trait FileUpload { self: CreateController =>

  protected def storeFile(pendingUpload: UploadRecord, owner: User, body: AnyContent) = {
    val MSG_ERROR = "Something went wrong while storing your file"

    body.asMultipartFormData.map(tempfile => {
      tempfile.file("file").map { f =>
        uploads.insertUploadFilepart(pendingUpload.getId, owner, f).map(_ match {
          case Right(filepart) =>
            // Upload was properly identified and stored
            Ok(Json.toJson(UploadSuccess(filepart.getId, filepart.getContentType)))

          case Left(e: UnsupportedContentTypeException) =>
            BadRequest("Unknown or unsupported file format")
            
          case Left(e: UnsupportedTextEncodingException) =>
            BadRequest("Unknown or unsupported text encoding")
            
          case Left(e: QuotaExceededException) =>
            BadRequest("Not enough space - you only have " + e.remainingSpaceKb / 1024 + " MB remaining")

          case Left(otherFailure) =>
            // For future use
            BadRequest(MSG_ERROR)
        })
      }.getOrElse({
        // POST without a file? Not possible through the UI!
        Logger.warn("Filepart POST without file attached")
        Future.successful(BadRequest(MSG_ERROR))
      })
    }).getOrElse({
      // POST without form data? Not possible through the UI!
      Logger.warn("Filepart POST without form data")
      Future.successful(BadRequest(MSG_ERROR))
    })
  }

} 
Example 116
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 117
Source File: BaseSerializer.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package controllers.document.downloads.serializers

import java.io.File
import play.api.Logger
import scala.concurrent.ExecutionContext
import services.ContentType
import services.annotation.{ Annotation, AnnotationBody, AnnotationService }
import services.document.ExtendedDocumentMetadata
import services.entity.{Entity, EntityRecord, EntityType}
import services.entity.builtin.EntityService
import storage.es.ES
import storage.uploads.Uploads
import controllers.document.downloads.DownloadsController

trait BaseSerializer {

  protected def sortByCharOffset(annotations: Seq[Annotation]) =
    annotations.sortWith { (a, b) =>
      a.anchor.substring(12).toInt < b.anchor.substring(12).toInt
    }

  protected def sortByXY(annotations: Seq[Annotation]) =
    // TODO port nearest-neighbour sorting from Recogito v.1
    annotations
  
  protected def sortByRow(annotations: Seq[Annotation]) =
    annotations.sortWith { (a, b) =>
      a.anchor.substring(4).toInt < b.anchor.substring(4).toInt
    }

  
  protected def sort(annotations: Seq[Annotation]) = {
    val groupedByContentType = annotations.groupBy(_.annotates.contentType)

    groupedByContentType.flatMap { case (cType, a) => cType match {
      case ContentType.TEXT_PLAIN => sortByCharOffset(a)
      case ContentType.IMAGE_UPLOAD | ContentType.IMAGE_IIIF => sortByXY(a)
      case ContentType.DATA_CSV => sortByRow(a)
      case _ => {
        Logger.warn(s"Can't sort annotations of unsupported content type $cType")
        a
      }
    }}
  }
  
  protected def getFirstQuote(a: Annotation): Option[String] = 
    a.bodies.find(_.hasType == AnnotationBody.QUOTE).flatMap(_.value)

  protected def getFirstTranscription(a: Annotation): Option[String] =
    a.bodies.find(_.hasType == AnnotationBody.TRANSCRIPTION).flatMap(_.value)

  protected def getFirstQuoteOrTranscription(a: Annotation): Option[String] =
    Seq(getFirstQuote(a), getFirstTranscription(a)).flatten.headOption

  protected def getFirstEntityBody(a: Annotation): Option[AnnotationBody] = {
    import AnnotationBody._
    a.bodies.find(b => Set(PERSON, PLACE, EVENT).contains(b.hasType))
  }
  
  protected def getCommentBodies(a: Annotation): Seq[AnnotationBody] =
    a.bodies.filter(_.hasType == AnnotationBody.COMMENT)
    
  protected def getTagBodies(a: Annotation): Seq[AnnotationBody] =
    a.bodies.filter(_.hasType == AnnotationBody.TAG)
  
  protected def exportMergedDocument[T](
    doc: ExtendedDocumentMetadata,
    fn: (Seq[Annotation], Seq[Entity], File) => T
  )(implicit entityService: EntityService, annotationService: AnnotationService, uploads: Uploads, ctx: ExecutionContext) = {
    
    val fAnnotations = annotationService.findByDocId(doc.id, 0, ES.MAX_SIZE)
    val fPlaces = entityService.listEntitiesInDocument(doc.id, Some(EntityType.PLACE), 0, ES.MAX_SIZE)
    
    val f = for {
      annotations <- fAnnotations
      places <- fPlaces
    } yield (annotations.map(_._1), places.items.map(_._1.entity))
    
    f.map { case (annotations, places) =>
      scala.concurrent.blocking {
        val documentDir = uploads.getDocumentDir(doc.owner.getUsername, doc.id).get
        fn(annotations, places, documentDir)
      }
    }
  }
    
} 
Example 118
Source File: DB.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package storage.db

import akka.actor.ActorSystem
import com.google.inject.AbstractModule
import java.sql.Connection
import javax.inject.{ Inject, Singleton }
import services.user.UserService
import services.user.Roles
import org.jooq.impl.DSL
import org.jooq.{ SQLDialect, DSLContext }
import play.api.Logger
import play.api.db.Database
import scala.collection.JavaConversions._
import scala.concurrent.{ ExecutionContext, Future }
import scala.io.Source

object DB {

  val CURRENT_SQLDIALECTT = SQLDialect.POSTGRES_9_4

}


  private def initDB(connection: Connection) = {

    // Splitting by ; is not 100% robust - but should be sufficient for our own schema file
    val statement = connection.createStatement

    Source.fromFile("conf/schema.sql", "UTF-8")
      .getLines().map(_.trim)
      .filter(line => !(line.startsWith("--") || line.isEmpty))
      .mkString(" ").split(";")
      .foreach(s => {
        statement.addBatch(s + ";")
      })

    statement.executeBatch()
    statement.close()
  }
  
  private def createDefaultUserIfEmpty() =
    userService.countUsers.map { count =>
      if (count == 0) {
        Logger.warn("#######################################################")
        Logger.warn("# Empty user table - creating default recogito/recogito")
        Logger.warn("#######################################################")
        
        val f = for {
          _ <- userService.insertUser("recogito", "[email protected]", "recogito", false)
          _ <- userService.insertUserRole("recogito", Roles.Admin)
        } yield()
  
        f.map { _ =>
          Logger.warn("# Done. Make sure to remove this user in production!")
          Logger.warn("#######################################################")
        } recover { case t: Throwable => t.printStackTrace() }
      }
    } recover { case t: Throwable =>
      t.printStackTrace()
    }

} 
Example 119
Source File: ES.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package storage.es

import com.sksamuel.elastic4s.{ElasticsearchClientUri, TcpClient}
import com.sksamuel.elastic4s.ElasticDsl._
import com.sksamuel.elastic4s.bulk.RichBulkResponse
import java.io.File
import javax.inject.{Inject, Singleton}
import org.elasticsearch.common.settings.Settings
import org.elasticsearch.common.xcontent.XContentType
import play.api.{Configuration, Logger}
import play.api.inject.ApplicationLifecycle
import scala.io.Source
import scala.concurrent.{Await, Future, ExecutionContext}
import scala.concurrent.duration._
import scala.util.{Try, Success, Failure}



  private def loadMappings(existingMappings: Seq[String] = Seq.empty[String]): Seq[(String, String)] =
    new File("conf/es-mappings").listFiles.toSeq.filter(_.getName.endsWith(".json"))
      .foldLeft(Seq.empty[(Int, (String, String))])((mappings, file)  => {
        val number = file.getName.substring(0, 2).toInt
        val name = file.getName.substring(3, file.getName.lastIndexOf('.'))
        if (existingMappings.contains(name)) {
          mappings
        } else {
          val json = Source.fromFile(file).getLines.mkString("\n")
          mappings :+ (number, (name, json))
        }
      }).sortBy(_._1).map(_._2)
      
  
  def countTotalDocs()(implicit ctx: ExecutionContext): Future[Long] =
    client execute {
      search(ES.RECOGITO) limit 0
    } map { _.totalHits }

} 
Example 120
Source File: PluginRegistry.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package plugins

import com.typesafe.config.{Config, ConfigFactory}
import java.io.File
import play.api.Logger
import scala.concurrent.{ExecutionContext, Future}
import scala.io.Source

object PluginRegistry {
  
  private val PLUGIN_DIR = new File("plugins") 

  Logger.info("Loading plugin configurations:")
  
  private val configs: Seq[(Config, File)] = 
    findFilesRecursive("plugin.conf", PLUGIN_DIR)
      .map { file => 
        val config = ConfigFactory.parseFile(file) 
        val dir = file.getParentFile
        (config, dir)
      }
  
  configs.foreach { case (c, dir) =>
    Logger.info(s"  ${c.getString("extends")}.${c.getString("id")}")
  }
  
  Logger.info(s"${configs.size} configurations found")
  
  
  private def findFilesRecursive(name: String, dir: File): Seq[File] = {
    if (dir.exists) {
      val all = dir.listFiles

      val dirs = all.filter(_.isDirectory)
      val files = all.filter(_.isFile)

      val matchingFiles = files.filter(_.getName == name)

      matchingFiles ++ dirs.flatMap(dir => findFilesRecursive(name, dir))
    } else Seq()
  }
          
  def listConfigs(extensionPoint: String): Seq[Config] =
    configs
      .filter(_._1.getString("extends").equalsIgnoreCase(extensionPoint))
      .map(_._1)

  private def readFile(extensionPoint: String, id: String, filename: String)(implicit ctx: ExecutionContext) =
    scala.concurrent.blocking {
      Future {
        configs.find { case (config, dir) => 
          config.getString("extends").equalsIgnoreCase(extensionPoint) &&
          config.getString("id").equalsIgnoreCase(id)
        } map { case (config, dir) => 
          val file = new File(dir, filename)
          Source.fromFile(file).getLines.mkString("\n")
        }
      }
    }  

  def loadPlugin(extensionPoint: String, id: String)(implicit ctx: ExecutionContext): Future[Option[String]] =
    readFile(extensionPoint, id, "plugin.js")

  def loadCSS(extensionPoint: String, id: String)(implicit ctx: ExecutionContext): Future[Option[String]] =
    readFile(extensionPoint, id, "plugin.css")

} 
Example 121
Source File: SparkSvc.scala    From Mastering-Spark-for-Data-Science   with MIT License 5 votes vote down vote up
package svc

import java.io.StringWriter
import java.net.{HttpURLConnection, URL}

import com.typesafe.config.ConfigFactory
import io.gzet.recommender.Node
import org.apache.commons.io.IOUtils
import play.api.Logger
import play.api.libs.json._

class SparkSvc() {

  val config = ConfigFactory.load()
  val host = config.getString("spark.job.server.host")
  val port = config.getInt("spark.job.server.port")
  val timeout = config.getInt("spark.job.server.timeout")
  val appName = config.getString("spark.job.server.app")
  val context = config.getString("spark.job.server.context")
  val indexJob = config.getString("spark.job.index")
  val playlistJob = config.getString("spark.job.playlist")
  val playlistRecommendJob = config.getString("spark.job.personalized.playlist")

  private def getConnection(endpoint: String, params: Option[String]) = {
    try {
      val url = new URL(endpoint)
      val connection = url.openConnection().asInstanceOf[HttpURLConnection]
      connection.setDoOutput(true)
      connection.setRequestMethod("POST")
      connection.setRequestProperty("Accept", "application/json")
      if(params.isDefined){
        val os = connection.getOutputStream
        os.write(params.get.getBytes())
        os.flush()
        os.close()
      }
      val inputStream = connection.getInputStream
      val writer = new StringWriter()
      IOUtils.copy(inputStream, writer, "UTF-8")
      val ret = writer.toString
      Json.parse(ret)
    } catch {
      case e: Exception =>
        throw new Exception("Job Failed: " + e.getMessage)
    }
  }

  private def parseResponse(json: JsValue) : String = {
    val jobId = (json \ "result" \ "jobId").asOpt[String]
    if(jobId.isDefined){
      s"Job submitted [${jobId.get}]"
    } else {
      val message = (json \ "result" \ "message").asOpt[String]
      if(message.isDefined){
        throw new Exception(s"Job failed: ${message.get}")
      }
      throw new Exception("Could not find Spark job id")
    }
  }

  def index(path: String): String = {
    Logger.info("Submitting INDEX job")
    val url = s"http://$host:$port/jobs?appName=$appName&classPath=$indexJob&context=$context"
    val params = "input.dir=\"" + path + "\""
    val json = getConnection(url, Some(params))
    parseResponse(json)
  }

  def playlist() = {
    Logger.info("Submitting PLAYLIST job")
    val url = s"http://$host:$port/jobs?appName=$appName&classPath=$playlistJob&context=$context"
    val json = getConnection(url, None)
    parseResponse(json)
  }

  def playlist(id: Long) = {
    Logger.info("Submitting RECOMMEND job")
    val url = s"http://$host:$port/jobs?appName=$appName&classPath=$playlistRecommendJob&context=$context&sync=true&timeout=$timeout"
    val params = s"song.id=$id"
    val json: JsValue = getConnection(url, Some(params))
    val array = (json \ "result").as[Array[String]]
    array.map({line =>
      val Array(id, pr, song) = line.split(",").take(3)
      Node(id.toLong, song, pr.toDouble)
    }).toList
  }

} 
Example 122
Source File: Playlist.scala    From Mastering-Spark-for-Data-Science   with MIT License 5 votes vote down vote up
package controllers

import com.typesafe.config.ConfigFactory
import play.api.Logger
import play.api.mvc.{Action, Controller}
import svc.{AnalyzerSvc, CassandraDao, SparkSvc}

object Playlist extends Controller {

  val config = ConfigFactory.load()
  val minTime = config.getInt("gzet.min.time")
  val maxTime = config.getInt("gzet.max.time")
  val cassandraHost = config.getString("cassandra.host")
  val cassandraPort = config.getInt("cassandra.port")
  val sampleSize = config.getDouble("gzet.sample.size")
  val minMatch = config.getDouble("gzet.min.match")

  val dao = new CassandraDao(cassandraHost, cassandraPort)
  val analyzer = new AnalyzerSvc()
  val spark = new SparkSvc()

  def index = Action { implicit request =>
    val playlist = models.Playlist(dao.getNodes)
    Logger.info(s"Database is currently ${playlist.nodes.size} songs long")
    Ok(views.html.playlist(playlist))
  }

  def personalize(id: Long) = Action { implicit request =>
    if(models.Playlist(dao.getNodes).nodes.isEmpty) {
      Redirect(routes.Playlist.index()).flashing("warning" -> s"Could not run personalized page rank on empty indices")
    } else {
      val name = dao.getSongName(id)
      if(name.isEmpty) {
        Redirect(routes.Playlist.index()).flashing("error" -> s"Could not find song for id [$id]")
      } else {
        try {
          Logger.info(s"Running a personalize Page Rank for id [$id] and song [$name]")
          val nodes = spark.playlist(id)
          val playlist = models.Playlist(nodes, name)
          Ok(views.html.playlist(playlist))
        } catch {
          case e: Exception =>
            Redirect(routes.Playlist.index()).flashing("error" -> e.getMessage)
        }
      }
    }
  }

  def submit = Action { implicit request =>
    try {
      dao.dropPlaylist
      val jobId = spark.playlist()
      Redirect(routes.Playlist.index()).flashing("success" -> jobId)
    } catch {
      case e: Exception =>
        Redirect(routes.Playlist.index()).flashing("error" -> e.getMessage)
    }
  }

} 
Example 123
Source File: NERService.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package transform.ner

import akka.actor.ActorSystem
import akka.routing.RoundRobinPool
import javax.inject.{Inject, Singleton}
import org.pelagios.recogito.sdk.PluginEnvironment
import org.pelagios.recogito.sdk.ner.Entity
import play.api.{Configuration, Logger}
import scala.collection.JavaConverters._
import services.annotation.AnnotationService
import services.entity.builtin.EntityService
import services.task.{TaskService, TaskType}
import storage.uploads.Uploads
import transform.WorkerService

@Singleton
class NERService @Inject() (
  annotationService: AnnotationService,
  entityService: EntityService,
  taskService: TaskService,
  uploads: Uploads,
  config: Configuration,
  system: ActorSystem
) extends WorkerService(
  system, uploads,
  NERActor.props(taskService, annotationService, entityService, config), 3  
)

object NERService extends HasTeiNER {

  val TASK_TYPE = TaskType("NER")

  private def getEnvironment(config: Configuration) = {
    // Not the nicest way to handle this - suggestions welcome!
    val userDir = if (System.getProperty("user.dir").contains("/target/universal/stage"))
      System.getProperty("user.dir").replace("/target/universal/stage", "")
    else 
      System.getProperty("user.dir")

    val pluginsDir = s"${userDir}/plugins"

    val asMap = config.entrySet
      .filter(_._1.startsWith("plugins"))
      .toSeq
      .map { case(key, value) =>
        (key -> value.unwrapped.toString)
      }.toMap.asJava

    new PluginEnvironment(pluginsDir, asMap)
  }
  
  
  private[ner] def parseText(text: String, engine: Option[String], config: Configuration): Seq[Entity] = {
    val ner = engine match {
      case Some(identifier) => NERPluginManager.getEngine(identifier).get
      case None => NERPluginManager.getDefaultEngine
    }

    Logger.info(s"Running NER with engine ${ner.getName}")

    val entities = ner.parse(text, getEnvironment(config))
    entities.asScala
  }
     
} 
Example 124
Source File: Index.scala    From Mastering-Spark-for-Data-Science   with MIT License 5 votes vote down vote up
package controllers

import com.typesafe.config.ConfigFactory
import models.{Library, Songs}
import org.apache.commons.lang3.StringUtils
import play.api.Logger
import play.api.data.Form
import play.api.data.Forms._
import play.api.mvc._
import svc.{AnalyzerSvc, CassandraDao, SparkSvc}

object Index extends Controller {

  val config = ConfigFactory.load()
  val minTime = config.getInt("gzet.min.time")
  val maxTime = config.getInt("gzet.max.time")
  val cassandraHost = config.getString("cassandra.host")
  val cassandraPort = config.getInt("cassandra.port")
  val sampleSize = config.getDouble("gzet.sample.size")
  val minMatch = config.getDouble("gzet.min.match")

  val dao = new CassandraDao(cassandraHost, cassandraPort)
  val analyzer = new AnalyzerSvc()
  val spark = new SparkSvc()

  val indexForm: Form[Library] = Form(mapping("path" -> text)(Library.apply)(Library.unapply))

  def index = Action { implicit request =>
    val songs = Songs(dao.getSongs)
    Logger.info(s"Database is currently ${songs.songs.size} songs long")
    Ok(views.html.index(indexForm)(songs))
  }

  def submit = Action { implicit request =>
    indexForm.bindFromRequest.fold(
      errors =>
        Redirect(routes.Index.index()).flashing("error" -> s"Missing path"),
      index =>
        try {
          if(StringUtils.isNotEmpty(index.path)) {
            Logger.info("Dropping database")
            dao.dropSongs
            dao.dropPlaylist
            Logger.info("Submitting job")
            val jobId = spark.index(index.path)
            Redirect(routes.Index.index()).flashing("success" -> jobId)
          } else {
            Redirect(routes.Index.index()).flashing("error" -> s"Missing path")
          }
        } catch {
          case e: Exception =>
            Redirect(routes.Index.index()).flashing("error" -> e.getMessage)
        }
    )
  }
} 
Example 125
Source File: SimHash.scala    From Mastering-Spark-for-Data-Science   with MIT License 5 votes vote down vote up
package io.gzet.story.web.controllers

import io.gzet.story.model.{Article, Duplicate}
import io.gzet.story.util.{HtmlFetcher, Tokenizer}
import io.gzet.story.util.SimhashUtils._
import io.gzet.story.web.SimpleConfig
import io.gzet.story.web.dao.CassandraDao
import org.apache.lucene.analysis.en.EnglishAnalyzer
import play.api.Logger
import play.api.libs.functional.syntax._
import play.api.libs.json._
import play.api.mvc.{Action, Controller}

object SimHash extends Controller with SimpleConfig {

  val dao = new CassandraDao
  val goose = new HtmlFetcher(gooseConnectionTimeout, gooseSocketTimeout)
  val analyzer = new EnglishAnalyzer()

  implicit val articleFormat = {
    val jsonDescription =
      (__ \ "hash").format[Int] and (__ \ "body").format[String] and (__ \ "title").format[String] and (__ \ "url").format[String]

    jsonDescription(Article.apply, unlift(Article.unapply))
  }

  implicit val duplicateFormat = {
    val jsonDescription =
      (__ \ "simhash").format[Int] and (__ \ "body").format[String] and (__ \ "title").format[String] and (__ \ "url").format[String] and (__ \ "related").format[List[Article]]

    jsonDescription(Duplicate.apply, unlift(Duplicate.unapply))
  }

  def fetch = Action { implicit request =>

    val url = request.getQueryString("url").getOrElse("NA")
    Logger.info(s"Fetch article [$url]")

    val article = goose.fetch(url)
    Logger.info(s"Title [${article.title}]")

    val hash = Tokenizer.lucene(article.body, analyzer).mkString(" ").simhash
    Logger.info(s"Hash [$hash]")

    val related = dao.findDuplicates(hash)
    Logger.info(s"${related.size} duplicate(s) found")

    Ok(Json.toJson(Duplicate(
      hash,
      article.body,
      article.title,
      url,
      related
    )))

  }


} 
Example 126
Source File: UserServiceImpl.scala    From scalafiddle-editor   with Apache License 2.0 5 votes vote down vote up
package scalafiddle.server.models.services
import java.util.UUID
import javax.inject.{Inject, Named}

import akka.actor._
import akka.pattern.ask
import akka.util.Timeout
import com.mohiva.play.silhouette.api.LoginInfo
import com.mohiva.play.silhouette.impl.providers.CommonSocialProfile
import play.api.Logger

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.concurrent.duration._
import scala.util.{Success, Try}
import scalafiddle.server._
import scalafiddle.server.models.User

class UserServiceImpl @Inject() (@Named("persistence") persistence: ActorRef) extends UserService {
  implicit val timeout = Timeout(15.seconds)
  val log              = Logger(getClass)

  
  override def save(profile: CommonSocialProfile): Future[User] = {
    log.debug(s"User $profile logged in")
    val user = User(
      UUID.randomUUID().toString,
      profile.loginInfo,
      profile.firstName,
      profile.lastName,
      profile.fullName,
      profile.email,
      profile.avatarURL,
      true
    )
    ask(persistence, AddUser(user)).mapTo[Try[User]].map {
      case Success(u) =>
        u
      case _ =>
        throw new Exception("Unable to save user")
    }
  }

  override def retrieve(loginInfo: LoginInfo): Future[Option[User]] = {
    ask(persistence, FindUserLogin(loginInfo)).mapTo[Try[User]].map {
      case Success(user) =>
        Some(user)
      case _ =>
        None
    }
  }
} 
Example 127
Source File: ApplicationTimer.scala    From play-swagger   with Apache License 2.0 5 votes vote down vote up
package services

import java.time.{ Clock, Instant }
import javax.inject._
import play.api.Logger
import play.api.inject.ApplicationLifecycle
import scala.concurrent.Future


@Singleton
class ApplicationTimer @Inject() (clock: Clock, appLifecycle: ApplicationLifecycle) {

  // This code is called when the application starts.
  private val start: Instant = clock.instant
  Logger.info(s"ApplicationTimer demo: Starting application at $start.")

  // When the application starts, register a stop hook with the
  // ApplicationLifecycle object. The code inside the stop hook will
  // be run when the application stops.
  appLifecycle.addStopHook { () ⇒
    val stop: Instant = clock.instant
    val runningTime: Long = stop.getEpochSecond - start.getEpochSecond
    Logger.info(s"ApplicationTimer demo: Stopping application at ${clock.instant} after ${runningTime}s.")
    Future.successful(())
  }
} 
Example 128
Source File: TaskExecutor.scala    From sundial   with MIT License 5 votes vote down vote up
package service

import javax.inject.Inject
import dao.{ExecutableStateDao, SundialDao}
import model._
import play.api.{Application, Configuration, Logging, Logger}
import service.emr.EmrServiceExecutor

trait SpecificTaskExecutor[
    ExecutableType <: Executable, StateType <: ExecutableState] {

  protected def logger: Logger

  protected def stateDao(
      implicit dao: SundialDao): ExecutableStateDao[StateType]

  def startExecutable(executable: ExecutableType, task: Task)(
      implicit dao: SundialDao): Unit = {
    val state = actuallyStartExecutable(executable, task)
    stateDao.saveState(state)
  }

  def killExecutable(task: Task, reason: String)(
      implicit dao: SundialDao): Unit = {
    stateDao.loadState(task.id).foreach { state =>
      actuallyKillExecutable(state, task, reason)
    }
  }

  def refreshStatus(task: Task)(
      implicit dao: SundialDao): Option[ExecutorStatus] = {
    logger.debug(s"Refreshing task state for task $task")
    stateDao.loadState(task.id).map { state =>
      val newState = actuallyRefreshState(state)
      stateDao.saveState(newState)
      newState.status
    }
  }

  protected def actuallyStartExecutable(executable: ExecutableType, task: Task)(
      implicit dao: SundialDao): StateType

  protected def actuallyKillExecutable(
      state: StateType,
      task: Task,
      reason: String)(implicit dao: SundialDao): Unit

  protected def actuallyRefreshState(state: StateType)(
      implicit dao: SundialDao): StateType

}

class TaskExecutor @Inject()(batchServiceExecutor: BatchServiceExecutor,
                             shellCommandExecutor: ShellCommandExecutor,
                             emrServiceExecutor: EmrServiceExecutor)(
    implicit configuration: Configuration,
    application: Application)
    extends Logging {

  def startExecutable(task: Task)(implicit dao: SundialDao): Unit = {
    task.executable match {
      case e: BatchExecutable => batchServiceExecutor.startExecutable(e, task)
      case e: ShellCommandExecutable =>
        shellCommandExecutor.startExecutable(e, task)
      case e: EmrJobExecutable => emrServiceExecutor.startExecutable(e, task)
      case _                   => logger.warn(s"No Executor found for Task($task)")
    }
  }

  def killExecutable(task: Task, reason: String)(
      implicit dao: SundialDao): Unit = {
    task.executable match {
      case _: BatchExecutable =>
        batchServiceExecutor.killExecutable(task, reason)
      case _: ShellCommandExecutable =>
        shellCommandExecutor.killExecutable(task, reason)
      case _: EmrJobExecutable =>
        emrServiceExecutor.killExecutable(task, reason)
      case _ => logger.warn(s"No Executor found for Task($task)")
    }
  }

  def refreshStatus(task: Task)(
      implicit dao: SundialDao): Option[ExecutorStatus] = {
    logger.debug(s"Refreshing status for task $task")
    task.executable match {
      case _: BatchExecutable        => batchServiceExecutor.refreshStatus(task)
      case _: ShellCommandExecutable => shellCommandExecutor.refreshStatus(task)
      case _: EmrJobExecutable       => emrServiceExecutor.refreshStatus(task)
      case _ => {
        logger.warn(s"No Executor found for Task($task)")
        None
      }
    }
  }
} 
Example 129
Source File: PasswordReset.scala    From cave   with MIT License 5 votes vote down vote up
package controllers

import play.api.Logger
import play.api.data.Form
import play.api.data.Forms._
import play.api.i18n.Messages
import play.api.mvc._

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.util.control.NonFatal

class PasswordReset extends AbstractCaveController {

  val startResetPasswordForm = Form(
    "email" -> email
  )

  val confirmResetPasswordForm = Form(
    tuple(
      "password1" -> text,
      "password2" -> text
    ) verifying(Messages("cave.login.signup.passwordDoesntMatch"), fields => fields match {
      case (password1: String, password2: String) => password1 == password2
    })
  )

  def startResetPassword = Action { implicit request =>
    Ok(views.html.loginscreen.startResetPassword(startResetPasswordForm))
  }

  def handleStartResetPassword = Action.async { implicit request =>
    withCaveClient { client =>
      startResetPasswordForm.bindFromRequest().fold(
        formWithErrors => Future.successful(BadRequest(views.html.loginscreen.startResetPassword(formWithErrors))),
        email => {
          client.Users.postForgotPassword(email) map {
            _ => Redirect(routes.Authentication.login).flashing("success" -> Messages("cave.login.passwordReset.checkYourEmail", email))
          } recover {
            case NonFatal(e) =>
              Logger.error(s"Password reset error for $email", e)
              Redirect(routes.Authentication.login).flashing("error" -> Messages("cave.login.passwordReset.error"))
          }
        }
      )
    }
  }

  def resetPassword(mailToken: String) = Action { implicit request =>
    Ok(views.html.loginscreen.resetPasswordPage(confirmResetPasswordForm, mailToken))
  }

  def handleResetPassword(mailToken: String) = Action.async { implicit request =>
    withCaveClient { client =>
      confirmResetPasswordForm.bindFromRequest().fold(
        formWithErrors => Future.successful(BadRequest(views.html.loginscreen.resetPasswordPage(formWithErrors, mailToken))),
        values => {
          client.Users.postResetPassword(values._1, mailToken) map {
            _ => debug(s"Password changed")
              Redirect(routes.Authentication.login).flashing("success" -> Messages("cave.login.password.reset.success"))
          } recover {
            case NonFatal(e) =>
              Logger.error("Password change error", e)
              Redirect(routes.Authentication.login).flashing("error" -> Messages("cave.login.passwordReset.error"))
          }
        }
      )
    }
  }
} 
Example 130
Source File: PasswordChange.scala    From cave   with MIT License 5 votes vote down vote up
package controllers

import com.gilt.cavellc.errors.FailedRequest
import play.api.Logger
import play.api.data.Form
import play.api.data.Forms._
import play.api.i18n.Messages

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.util.control.NonFatal

class PasswordChange extends AbstractCaveController {

  val passwordChange = Form(
    tuple(
      "newPassword.password1" -> text,
      "newPassword.password2" -> text
    ) verifying(Messages("cave.login.signup.passwordDoesntMatch"), fields => fields match {
      case (password1: String, password2: String) => password1 == password2
    })
  )

  def page = caveAsyncAction { implicit request =>
    Future.successful(Ok(views.html.loginscreen.passwordChange(passwordChange)))
  }

  def handlePasswordChange = caveAsyncAction { implicit request =>
    withCaveClient { client =>
      passwordChange.bindFromRequest().fold(
        formWithErrors => Future.successful(BadRequest(views.html.loginscreen.passwordChange(formWithErrors))),
        values =>
          client.Users.patchInfo(None, None, Some(values._1)) map {
            case user => Redirect(routes.UserProfile.profile()).flashing("success" -> s"${user.firstName}, your password has been changed")
          } recover {
            case error: FailedRequest if error.responseCode == FORBIDDEN =>
              Logger.debug("Your API session token has expired. Please login again.", error)
              Redirect(routes.Authentication.login).flashing("error" -> Messages("cave.login.sessionTokenExpired"))
            case NonFatal(e) =>
              Logger.error("Unable to change password", e)
              InternalServerError(views.html.errorpages.errorPage(Messages("cave.errors.5xx.passwordChange")))
          }
      )
    }
  }
} 
Example 131
Source File: Teams.scala    From cave   with MIT License 5 votes vote down vote up
package controllers

import com.gilt.cavellc.Client
import com.gilt.cavellc.models.{Member, Organization, Role, Team}
import controllers.helpers.{CreateToken, AddUserData}
import controllers.helpers.CaveForms._
import play.api.Logger
import play.api.i18n.Messages

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future

case class TeamData(team: Team, role: Role, members: Seq[Member])

class Teams extends AbstractCaveController {

  def team(organizationName: String, teamName: String) = caveAsyncAction { implicit request =>
    withCaveClient { client =>

      val data = for {
        userOrganizations <- client.Users.getOrganizations()
        organization <- getOrganization(organizationName, client, userOrganizations)
        userTeams <- getUserTeams(userOrganizations, client)
        roleInOrganization <- Future.successful(userOrganizations.filter(_.name == organizationName).head.role)
        roleInTeam <- getRoleInTeam(organizationName, teamName, userTeams, roleInOrganization)
        teamsInOrganization <- getTeamsInOrganization(organizationName, roleInOrganization, client)
        team <- getSelectedTeam(organizationName, teamName, client, roleInTeam)
        membersInTeam <- getMembers(organizationName, teamName, client, organization, roleInTeam, team)
      } yield (organization, team, roleInTeam, membersInTeam.sortBy(_.user.firstName), userOrganizations.sortBy(_.name), userTeams.sortBy(_.userTeam.name), roleInOrganization)

      data map {
        case (Some(org), Some(team), roleInTeam, membersInTeam, userOrganizations, userTeams, roleInOrganization) =>
          val menuData = SideMenuData(userOrganizations, userTeams, Some(org), Some(team), Some(roleInOrganization))
          val teamData = TeamData(team, roleInTeam, membersInTeam)
          val addUserFormWithOrgAndTeam = addUserForm.fill(AddUserData(EMPTY_STRING, organizationName, teamName, EMPTY_STRING))
          val createTokenFormWithOrg = createTokenForm.fill(CreateToken(org.name, Some(team.name), EMPTY_STRING))

          Ok(views.html.teams.team(menuData, teamData, addUserFormWithOrgAndTeam, createTokenFormWithOrg))

        case _ =>
          Logger.warn(s"Team not found $teamName @ $organizationName")
          InternalServerError(views.html.errorpages.errorPage(Messages("cave.errors.5xx.general")))
      }
    }
  }

  private[controllers] def getMembers(organizationName: String, teamName: String, client: Client, organization: Option[Organization], role: Role, team: Option[Team]): Future[Seq[Member]] = {
    if (organization.isDefined && team.isDefined && !Seq(Role.Viewer, Role.Team).contains(role))
      client.Teams.getOrganizationsAndUsersByOrganizationAndTeam(organizationName, teamName).map(_.sortBy(_.user.firstName))
    else
      Future.successful(List.empty)
  }

  private[controllers] def getSelectedTeam(organizationName: String, teamName: String, client: Client, role: Role): Future[Option[Team]] = {
    if (!Seq(Role.Viewer, Role.Team).contains(role))
      client.Teams.getOrganizationsByOrganizationAndTeam(organizationName, teamName)
    else
      Future.successful(Some(Team(teamName, Seq.empty)))
  }
} 
Example 132
Source File: Tokens.scala    From cave   with MIT License 5 votes vote down vote up
package controllers

import controllers.helpers.CaveForms._
import controllers.helpers.{DeleteToken, CreateToken}
import play.api.Logger
import play.api.i18n.Messages
import play.api.mvc.{AnyContent, Request, Result}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future

class Tokens extends AbstractCaveController {
  def create = caveAsyncAction { implicit request =>
    createTokenForm.bindFromRequest().fold(handleFormError, handleCreateToken)
  }

  def delete = caveAsyncAction { implicit request =>
    deleteTokenForm.bindFromRequest().fold(handleFormError, handleDeleteToken)
  }

  private def handleDeleteToken(token: DeleteToken)(implicit request: Request[AnyContent]): Future[Result] = {
    token.teamName match {
      case Some(team) => deleteTeamToken(token, team)
      case _ => deleteOrganizationToken(token)
    }
  }

  private def handleCreateToken(token: CreateToken)(implicit request: Request[AnyContent]): Future[Result] = {
    token.teamName match {
      case Some(team) => createTeamToken(token, team)
      case _ => createOrganizationToken(token)
    }
  }

  private def deleteOrganizationToken(token: DeleteToken)
                                     (implicit request: Request[AnyContent]): Future[Result] = withCaveClient { client =>
    client.Tokens.deleteOrganizationsByOrganizationAndId(token.orgName, token.tokenId) map { result =>
      Logger.debug(s"Deleted organization token $token")
      Redirect(routes.Organizations.organization(token.orgName)).flashing("success" -> Messages("cave.tokens.delete.success"))
    }
  }

  private def createOrganizationToken(token: CreateToken)
                                     (implicit request: Request[AnyContent]): Future[Result] = withCaveClient { client =>
    client.Tokens.postOrganizationsByOrganization(token.orgName, token.description) map { result =>
      Logger.debug(s"Created new organization token $token")
      Redirect(routes.Organizations.organization(token.orgName)).flashing("success" -> Messages("cave.tokens.created.success"))
    }
  }

  private def deleteTeamToken(token: DeleteToken, team: String)
                             (implicit request: Request[AnyContent]): Future[Result] = withCaveClient { client =>
    client.Tokens.deleteOrganizationsAndTeamsByOrganizationAndTeamAndId(token.orgName, team, token.tokenId) map { result =>
      Logger.debug(s"Deleted team token $token")
      Redirect(routes.Teams.team(token.orgName, token.teamName.getOrElse(""))).flashing("success" -> Messages("cave.tokens.delete.success"))
    }
  }

  private def createTeamToken(token: CreateToken, team: String)
                             (implicit request: Request[AnyContent]): Future[Result] = withCaveClient { client =>
    client.Tokens.postOrganizationsAndTeamsByOrganizationAndTeam(token.orgName, team, token.description) map { result =>
      Logger.debug(s"Created new team token $token")
      Redirect(routes.Teams.team(token.orgName, token.teamName.getOrElse(""))).flashing("success" -> Messages("cave.tokens.created.success"))
    }
  }
} 
Example 133
Source File: Registration.scala    From cave   with MIT License 5 votes vote down vote up
package controllers

import play.api.Logger
import play.api.data.Form
import play.api.i18n.Messages
import play.api.mvc._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import play.api.data.Forms._

import scala.util.control.NonFatal

case class SignUpFormData(firstName: String, lastName: String, password1: String, password2: String)

class Registration extends AbstractCaveController {

  val startSignUpForm = Form(
    "email" -> email
  )

  val confirmSignUpForm = Form(
    mapping(
      "firstName" -> text,
      "lastName" -> text,
      "password1" -> text,
      "password2" -> text
    )(SignUpFormData.apply)(SignUpFormData.unapply)
      verifying(Messages("cave.login.signup.passwordDoesntMatch"), fields => fields match {
      case data: SignUpFormData => data.password1 == data.password2
    })
  )

  def startSignUp = Action { implicit request =>
    Ok(views.html.loginscreen.startSignUp(startSignUpForm))
  }

  def handleStartSignUp = Action.async { implicit request =>
    withCaveClient { client =>
      startSignUpForm.bindFromRequest().fold(
        formWithErrors => Future.successful(BadRequest(views.html.loginscreen.startSignUp(formWithErrors))),
        email => {
          client.Users.postRegister(email) map {
            _ => Redirect(routes.Authentication.login).flashing("success" -> Messages("cave.login.signup.checkYourEmail", email))
          } recover {
            case NonFatal(e) =>
              Logger.error("New user registration error", e)
              Redirect(routes.Authentication.login).flashing("error" -> Messages("cave.login.signup.error"))
          }
        }
      )
    }
  }

  def signUp(mailToken: String) = Action { implicit request =>
    Ok(views.html.loginscreen.signUp(confirmSignUpForm, mailToken))
  }

  def handleSignUp(mailToken: String) = Action.async { implicit request =>
    withCaveClient { client =>
      confirmSignUpForm.bindFromRequest().fold(
        formWithErrors => Future.successful(BadRequest(views.html.loginscreen.signUp(formWithErrors, mailToken))),
        formData => {
          client.Users.postConfirm(formData.firstName, formData.lastName, formData.password1, mailToken) map {
            _ => Redirect(routes.Authentication.login).flashing("success" -> Messages("cave.login.signup.youCanLoginNow", email))
          } recover {
            case NonFatal(e) =>
              Logger.error("Registration confirmation error", e)
              Redirect(routes.Authentication.login).flashing("error" -> Messages("cave.login.signup.error"))
          }
        }
      )
    }
  }
}

object Registration extends Registration 
Example 134
Source File: Authentication.scala    From cave   with MIT License 5 votes vote down vote up
package controllers

import com.gilt.cavellc.errors.FailedRequest
import play.api.Logger
import play.api.data.Form
import play.api.data.Forms._
import play.api.i18n.Messages
import play.api.mvc._

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.util.control.NonFatal

class Authentication extends AbstractCaveController {

  val loginForm = Form(mapping("username" -> email, "password" -> text, "landingUrl" -> text)
    (UserLogin.apply)(UserLogin.unapply)
  )

  def login = Action { implicit request =>
    val loginFormWithLandingPage = loginForm.fill(UserLogin(EMPTY_STRING, EMPTY_STRING, request.flash.get("requestedUrl").getOrElse("/")))
    Ok(views.html.loginscreen.signIn(loginFormWithLandingPage))
  }

  def logout = Action.async { implicit request =>
    Future.successful(Redirect(routes.Authentication.login()).withNewSession.flashing(
      "success" -> "You've been logged out"
    ))
  }

  def authenticate = Action.async { implicit request =>
    withCaveClient { client =>
      loginForm.bindFromRequest().fold(
        formWithErrors => Future.successful(BadRequest(views.html.loginscreen.signIn(formWithErrors))),
        loginForm => client.Users.postLogin(loginForm.email, loginForm.password) flatMap {
          case user: com.gilt.cavellc.models.Auth =>
            withExplicitTokenClient(user.token) { signedClient =>
              signedClient.Users.getInfo().flatMap {
                case Some(apiUser) =>
                  Logger.debug(s"Login Succeeded for ${loginForm.email}")
                  val landingUrl: String = if (loginForm.landingUrl.nonEmpty) loginForm.landingUrl else routes.Application.index().url
                  Logger.debug(s"landing url ${loginForm.landingUrl}")
                  Future.successful(Redirect(landingUrl).withSession(
                    "sessionToken" -> user.token,
                    "userName" -> s"${apiUser.firstName} ${apiUser.lastName}"
                  ))
                case _ =>
                  Logger.error(s"Unable to find user details for user: ${loginForm.email}")
                  Future.successful(InternalServerError(views.html.errorpages.errorPage(Messages("cave.login.login.internalError"))))
              }
            }
        } recover {
          case error: FailedRequest if error.responseCode == BAD_REQUEST =>
            Logger.debug(s"Incorrect username or password for user ${loginForm.email}", error)
            Redirect(routes.Authentication.login()).flashing("error" -> Messages("cave.login.login.incorrectUsernameOrPassword"))
          case NonFatal(e) =>
            Logger.error(s"Unable to authenticate user: ${loginForm.email}", e)
            InternalServerError(views.html.errorpages.errorPage(Messages("cave.login.login.internalError")))
        }
      )
    }
  }
}

object Authentication extends Authentication

case class UserLogin(email: String, password: String, landingUrl: String) 
Example 135
Source File: PlayServerOptions.scala    From tapir   with Apache License 2.0 5 votes vote down vote up
package sttp.tapir.server.play

import akka.stream.Materializer
import play.api.Logger
import play.api.libs.Files.{SingletonTemporaryFileCreator, TemporaryFileCreator}
import play.api.mvc._
import sttp.tapir.server.{DecodeFailureHandler, LogRequestHandling, ServerDefaults}

import scala.concurrent.ExecutionContext

case class PlayServerOptions(
    decodeFailureHandler: DecodeFailureHandler,
    logRequestHandling: LogRequestHandling[Logger => Unit],
    temporaryFileCreator: TemporaryFileCreator,
    defaultActionBuilder: ActionBuilder[Request, AnyContent],
    playBodyParsers: PlayBodyParsers
) {

  lazy val logger: Logger = Logger(this.getClass.getPackage.getName)

}

object PlayServerOptions {
  implicit def default(implicit mat: Materializer, ec: ExecutionContext): PlayServerOptions =
    PlayServerOptions(
      ServerDefaults.decodeFailureHandler,
      defaultLogRequestHandling,
      SingletonTemporaryFileCreator,
      DefaultActionBuilder.apply(PlayBodyParsers.apply().anyContent),
      PlayBodyParsers.apply()
    )

  lazy val defaultLogRequestHandling: LogRequestHandling[Logger => Unit] = LogRequestHandling(
    doLogWhenHandled = debugLog,
    doLogAllDecodeFailures = debugLog,
    doLogLogicExceptions = (msg: String, ex: Throwable) => log => log.error(msg, ex),
    noLog = _ => ()
  )

  private def debugLog(msg: String, exOpt: Option[Throwable]): Logger => Unit =
    exOpt match {
      case None     => log => log.debug(msg)
      case Some(ex) => log => log.debug(s"$msg; exception: {}", ex)
    }
} 
Example 136
Source File: AppLogger.scala    From izanami   with Apache License 2.0 5 votes vote down vote up
package libs
import play.api.{Logger, MarkerContext}

object AppLogger {

  private val logger = Logger("application")

  def debug(message: => String)(implicit mc: MarkerContext): Unit =
    logger.debug(message)

  def info(message: => String)(implicit mc: MarkerContext): Unit =
    logger.info(message)

  def error(message: => String)(implicit mc: MarkerContext): Unit =
    logger.error(message)
  def error(message: => String, error: => Throwable)(implicit mc: MarkerContext): Unit =
    logger.error(message, error)
} 
Example 137
Source File: AuthAction.scala    From izanami   with Apache License 2.0 5 votes vote down vote up
package controllers.actions

import akka.http.scaladsl.util.FastFuture
import libs.AppLogger
import play.api.Logger
import play.api.mvc.Results.Unauthorized
import play.api.mvc._

import scala.concurrent.{ExecutionContext, Future}

case class SecuredContext[A](request: Request[A], userId: String) extends WrappedRequest[A](request)

class SecuredAction(val parser: BodyParser[AnyContent])(implicit val executionContext: ExecutionContext)
    extends ActionBuilder[SecuredContext, AnyContent]
    with ActionFunction[Request, SecuredContext] {

  override def invokeBlock[A](request: Request[A], block: (SecuredContext[A]) => Future[Result]): Future[Result] = {

    val maybeUserId = request.cookies.get("clientId")
    maybeUserId match {
      case Some(id) => block(SecuredContext(request, id.value))
      case None =>
        AppLogger.debug("Auth info is empty => Forbidden")
        FastFuture.successful(Unauthorized)
    }
  }
} 
Example 138
Source File: ChatController.scala    From Scala-Reactive-Programming   with MIT License 5 votes vote down vote up
package controllers

import java.net.URI
import javax.inject._
import akka.actor.ActorSystem
import akka.event.Logging
import akka.stream.Materializer
import akka.stream.scaladsl.{BroadcastHub, Flow, Keep, MergeHub, Source}
import play.api.Logger
import play.api.mvc._
import scala.concurrent.{ExecutionContext, Future}

@Singleton
class ChatController @Inject()(cc: ControllerComponents)
                              (implicit actorSystem: ActorSystem,
                               mat: Materializer,
                               executionContext: ExecutionContext,
                               webJarsUtil: org.webjars.play.WebJarsUtil) 
                               extends AbstractController(cc) with RequestMarkerContext {

  private type WSMessage = String

  private val logger = Logger(getClass)

  private implicit val logging = Logging(actorSystem.eventStream, logger.underlyingLogger.getName)

  private val (chatSink, chatSource) = {
    val source = MergeHub.source[WSMessage]
      .log("source")
      .recoverWithRetries(-1, { case _: Exception ⇒ Source.empty })

    val sink = BroadcastHub.sink[WSMessage]
    source.toMat(sink)(Keep.both).run()
  }

  private val userFlow: Flow[WSMessage, WSMessage, _] = {
     Flow.fromSinkAndSource(chatSink, chatSource)
  }

  def index: Action[AnyContent] = Action { implicit request: RequestHeader =>
    val webSocketUrl = routes.ChatController.chat().webSocketURL()
    logger.info(s"index: ")
    Ok(views.html.index(webSocketUrl))
  }

  def chat(): WebSocket = {
    WebSocket.acceptOrResult[WSMessage, WSMessage] {
      case rh if sameOriginCheck(rh) =>
        Future.successful(userFlow).map { flow =>
          Right(flow)
        }.recover {
          case e: Exception =>
            val msg = "Cannot create websocket"
            logger.error(msg, e)
            val result = InternalServerError(msg)
            Left(result)
        }

      case rejected =>
        logger.error(s"Request ${rejected} failed same origin check")
        Future.successful {
          Left(Forbidden("forbidden"))
        }
    }
  }

  private def sameOriginCheck(implicit rh: RequestHeader): Boolean = {
    logger.debug("Checking the ORIGIN ")
    
    rh.headers.get("Origin") match {
      case Some(originValue) if originMatches(originValue) =>
        logger.debug(s"originCheck: originValue = $originValue")
        true

      case Some(badOrigin) =>
        logger.error(s"originCheck: rejecting request because Origin header value ${badOrigin} is not in the same origin")
        false

      case None =>
        logger.error("originCheck: rejecting request because no Origin header found")
        false
    }
  }

  private def originMatches(origin: String): Boolean = {
    try {
      val url = new URI(origin)
      url.getHost == "localhost" &&
        (url.getPort match { case 9000 | 19001 => true; case _ => false })
    } catch {
      case e: Exception => false
    }
  }

} 
Example 139
Source File: SystemStatusService.scala    From HAT2.0   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.hatdex.hat.api.service

import javax.inject.Inject

import org.hatdex.hat.dal.Tables._
import org.hatdex.libs.dal.HATPostgresProfile.api._
import play.api.Logger

import scala.concurrent.Future

class SystemStatusService @Inject() (implicit val ec: DalExecutionContext) {
  val logger = Logger(this.getClass)

  def tableSizeTotal(implicit db: Database): Future[Long] = {
    val sizeQuery = DataTableSize.map(_.totalSize).sum
    db.run(sizeQuery.result).map(_.getOrElse(0L))
  }

  def fileStorageTotal(implicit db: Database): Future[Long] = {
    val sizeQuery = HatFile.filter(_.status.+>>("status") === "Completed")
      .map(_.status.+>>("size").asColumnOf[Long])
      .sum
    db.run(sizeQuery.result).map(_.getOrElse(0L))
  }
}

object SystemStatusService {
  def humanReadableByteCount(bytes: Long, si: Boolean = true): (BigDecimal, String) = {
    val unit = if (si) { 1000 } else { 1024 }
    if (bytes < unit) {
      (bytes, "B")
    }
    else {
      val exp = (Math.log(bytes.toDouble) / Math.log(unit.toDouble)).toInt
      val preLetter = if (si) {
        "kMGTPE"
      }
      else {
        "KMGTPE"
      }
      val preSi = if (si) {
        ""
      }
      else {
        "i"
      }
      val pre = preLetter.substring(exp - 1, exp) + preSi
      val bdbytes = BigDecimal(bytes / Math.pow(unit.toDouble, exp.toDouble))
      (bdbytes, pre + "B")
    }
  }
} 
Example 140
Source File: FileManager.scala    From HAT2.0   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.hatdex.hat.api.service

import javax.inject.Inject

import com.amazonaws.services.s3.AmazonS3
import com.amazonaws.services.s3.model.{ GeneratePresignedUrlRequest, SSEAlgorithm }
import com.google.inject.name.Named
import com.typesafe.config.Config
import org.hatdex.hat.resourceManagement.HatServer
import play.api.{ ConfigLoader, Logger }

import scala.concurrent.Future
import scala.concurrent.duration.FiniteDuration

trait FileManager {
  def getUploadUrl(filename: String, maybeContentType: Option[String])(implicit hatServer: HatServer): Future[String]
  def getContentUrl(filename: String)(implicit hatServer: HatServer): Future[String]
  def getFileSize(fileName: String)(implicit hatServer: HatServer): Future[Long]
  def deleteContents(filename: String)(implicit hatServer: HatServer): Future[Unit]
}

case class AwsS3Configuration(
    bucketName: String,
    accessKeyId: String,
    secretKey: String,
    region: String,
    signedUrlExpiry: FiniteDuration)

object AwsS3Configuration {
  implicit val configLoader: ConfigLoader[AwsS3Configuration] = new ConfigLoader[AwsS3Configuration] {
    def load(rootConfig: Config, path: String): AwsS3Configuration = {
      val config = rootConfig.getConfig(path)
      AwsS3Configuration(
        bucketName = config.getString("bucketName"),
        accessKeyId = config.getString("accessKeyId"),
        secretKey = config.getString("secretKey"),
        region = config.getString("region"),
        signedUrlExpiry = ConfigLoader.finiteDurationLoader.load(config, "signedUrlExpiry"))
    }
  }
}

class FileManagerS3 @Inject() (
    awsS3Configuration: AwsS3Configuration,
    @Named("s3client-file-manager") s3client: AmazonS3)(implicit ec: RemoteExecutionContext) extends FileManager {

  private val logger = Logger(this.getClass)
  private val bucketName = awsS3Configuration.bucketName

  def getUploadUrl(fileName: String, maybeContentType: Option[String])(implicit hatServer: HatServer): Future[String] = {
    val expiration = org.joda.time.DateTime.now().plus(awsS3Configuration.signedUrlExpiry.toMillis)

    val generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, s"${hatServer.domain}/$fileName")
      .withMethod(com.amazonaws.HttpMethod.PUT)
      .withExpiration(expiration.toDate)
      .withSSEAlgorithm(SSEAlgorithm.AES256)

    // TODO: to be replaced with mandatory validated content MIME type in API v2.7
    val generatePresignedUrlRequestWithContent = maybeContentType.map { contentType =>
      generatePresignedUrlRequest.withContentType(contentType)
    }.getOrElse(generatePresignedUrlRequest)

    val url = Future(s3client.generatePresignedUrl(generatePresignedUrlRequestWithContent))
    url.map(_.toString)
  }

  def getContentUrl(fileName: String)(implicit hatServer: HatServer): Future[String] = {
    val expiration = org.joda.time.DateTime.now().plus(awsS3Configuration.signedUrlExpiry.toMillis)

    val generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, s"${hatServer.domain}/$fileName")
      .withMethod(com.amazonaws.HttpMethod.GET)
      .withExpiration(expiration.toDate)

    val url = Future(s3client.generatePresignedUrl(generatePresignedUrlRequest))
    url.map(_.toString)
  }

  def getFileSize(fileName: String)(implicit hatServer: HatServer): Future[Long] = {
    logger.debug(s"Getting file size for $bucketName ${hatServer.domain}/$fileName")
    Future(s3client.getObjectMetadata(bucketName, s"${hatServer.domain}/$fileName"))
      .map { metadata => Option(metadata.getContentLength).getOrElse(0L) }
      .recover { case _ => 0L }
  }

  def deleteContents(fileName: String)(implicit hatServer: HatServer): Future[Unit] = {
    Future(s3client.deleteObject(bucketName, s"${hatServer.domain}/$fileName"))
  }
} 
Example 141
Source File: LogService.scala    From HAT2.0   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.hatdex.hat.api.service

import java.util.UUID

import akka.Done
import javax.inject.Inject
import org.hatdex.hat.api.models.LogRequest
import play.api.Logger

import scala.concurrent.Future

class LogService @Inject() (implicit val ec: DalExecutionContext) {
  val logger = Logger(this.getClass)

  def logAction(hat: String, logDetails: LogRequest, applicationDetails: Option[(String, String)]): Future[Done] = {
    Future {
      val logId = UUID.randomUUID()
      val applicationVersion = applicationDetails.map(a => s"${a._1}@${a._2}").getOrElse("Unknown")
      logger.info(s"[${logDetails.logGroup.getOrElse("STATS")}] [$hat] [$logId] [${logDetails.actionCode}] [$applicationVersion] ${logDetails.message.getOrElse("")}")

      Done
    }
  }
} 
Example 142
Source File: RichBundleService.scala    From HAT2.0   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.hatdex.hat.api.service.richData

import javax.inject.Inject

import org.hatdex.hat.api.json.RichDataJsonFormats
import org.hatdex.hat.api.models._
import org.hatdex.hat.api.service.DalExecutionContext
import org.hatdex.hat.dal.ModelTranslation
import org.hatdex.hat.dal.Tables._
import org.hatdex.libs.dal.HATPostgresProfile.api._
import play.api.Logger
import play.api.libs.json._

import scala.concurrent.Future

class RichBundleService @Inject() (implicit ec: DalExecutionContext) extends RichDataJsonFormats {

  val logger = Logger(this.getClass)

  def saveCombinator(combinatorId: String, combinator: Seq[EndpointQuery])(implicit db: Database): Future[Unit] = {
    val insertQuery = DataCombinators.insertOrUpdate(DataCombinatorsRow(combinatorId, Json.toJson(combinator)))
    db.run(insertQuery).map(_ => ())
  }

  def combinator(combinatorId: String)(implicit db: Database): Future[Option[Seq[EndpointQuery]]] = {
    db.run(DataCombinators.filter(_.combinatorId === combinatorId).result) map { queries =>
      queries.headOption map { q =>
        q.combinator.as[Seq[EndpointQuery]]
      }
    }
  }

  def combinators()(implicit db: Database): Future[Seq[(String, Seq[EndpointQuery])]] = {
    db.run(DataCombinators.result) map { queries =>
      queries map { q =>
        (q.combinatorId, q.combinator.as[Seq[EndpointQuery]])
      }
    }
  }

  def deleteCombinator(combinatorId: String)(implicit db: Database): Future[Unit] = {
    val deleteQuery = DataCombinators.filter(_.combinatorId === combinatorId).delete
    db.run(deleteQuery).map(_ => ())
  }

  def saveBundle(bundle: EndpointDataBundle)(implicit db: Database): Future[Unit] = {
    val insertQuery = DataBundles.insertOrUpdate(DataBundlesRow(bundle.name, Json.toJson(bundle.bundle)))
    db.run(insertQuery).map(_ => ())
  }

  def bundle(bundleId: String)(implicit db: Database): Future[Option[EndpointDataBundle]] = {
    db.run(DataBundles.filter(_.bundleId === bundleId).result)
      .map(_.headOption.map(ModelTranslation.fromDbModel))
  }

  def bundles()(implicit db: Database): Future[Seq[EndpointDataBundle]] = {
    db.run(DataBundles.result)
      .map(_.map(ModelTranslation.fromDbModel))
  }

  def deleteBundle(bundleId: String)(implicit db: Database): Future[Unit] = {
    val deleteQuery = DataBundles.filter(_.bundleId === bundleId).delete
    db.run(deleteQuery).map(_ => ())
  }
} 
Example 143
Source File: DataMigration.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 javax.inject.Inject

import com.mohiva.play.silhouette.api.Silhouette
import org.hatdex.hat.api.json.RichDataJsonFormats
import org.hatdex.hat.api.models._
import org.hatdex.hat.api.service.MigrationService
import org.hatdex.hat.authentication.{ HatApiAuthEnvironment, HatApiController, WithRole }
import play.api.Logger
import play.api.libs.json._
import play.api.mvc._

import scala.concurrent.ExecutionContext

class DataMigration @Inject() (
    components: ControllerComponents,
    silhouette: Silhouette[HatApiAuthEnvironment],
    migrationService: MigrationService)(
    implicit
    val ec: ExecutionContext) extends HatApiController(components, silhouette) with RichDataJsonFormats {

  private val logger = Logger(this.getClass)

  def migrateData(fromSource: String, fromTableName: String, toNamespace: String, toEndpoint: String, includeTimestamp: Boolean): Action[AnyContent] =
    SecuredAction(WithRole(Owner())).async { implicit request =>
      logger.info(s"Migrate data from $fromSource:$fromTableName to $toNamespace/$toEndpoint")
      val eventualCount = migrationService.migrateOldData(
        request.identity.userId, s"$toNamespace/$toEndpoint",
        fromTableName, fromSource,
        None, None, includeTimestamp)

      eventualCount map { count =>
        Ok(Json.toJson(SuccessResponse(s"Migrated $count records")))
      }
    }

} 
Example 144
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 145
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 146
Source File: PasswordInfoService.scala    From HAT2.0   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.hatdex.hat.authentication

import javax.inject.Inject

import com.mohiva.play.silhouette.api.LoginInfo
import com.mohiva.play.silhouette.api.util.PasswordInfo
import com.mohiva.play.silhouette.password.BCryptPasswordHasher
import com.mohiva.play.silhouette.persistence.daos.DelegableAuthInfoDAO
import org.hatdex.hat.api.service.DalExecutionContext
import org.hatdex.hat.resourceManagement.HatServer
import play.api.Logger

import scala.concurrent.Future

class PasswordInfoService @Inject() (userService: AuthUserServiceImpl)(implicit ec: DalExecutionContext)
  extends DelegableAuthInfoDAO[PasswordInfo, HatServer] {

  val logger = Logger(this.getClass)

  def add(loginInfo: LoginInfo, authInfo: PasswordInfo)(implicit hat: HatServer): Future[PasswordInfo] = {
    update(loginInfo, authInfo)
  }

  def find(loginInfo: LoginInfo)(implicit hat: HatServer): Future[Option[PasswordInfo]] = {
    userService.retrieve(loginInfo).map {
      case Some(user) if user.pass.isDefined =>
        Some(PasswordInfo(BCryptPasswordHasher.ID, user.pass.get, salt = None))
      case _ =>
        logger.info("No such user")
        None
    }
  }

  def remove(loginInfo: LoginInfo)(implicit hat: HatServer): Future[Unit] =
    userService.remove(loginInfo)

  def save(loginInfo: LoginInfo, authInfo: PasswordInfo)(implicit hat: HatServer): Future[PasswordInfo] =
    find(loginInfo).flatMap {
      case Some(_) => update(loginInfo, authInfo)
      case None    => add(loginInfo, authInfo)
    }

  def update(loginInfo: LoginInfo, authInfo: PasswordInfo)(implicit hat: HatServer): Future[PasswordInfo] =
    userService.retrieve(loginInfo).map {
      case Some(user) =>
        userService.save(user.copy(pass = Some(authInfo.password)))
        authInfo
      case _ => throw new Exception("PasswordInfoDAO - update : the user must exists to update its password")
    }

} 
Example 147
Source File: LoggingProvider.scala    From HAT2.0   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.hatdex.hat.utils

import com.google.inject.ImplementedBy
import play.api.Logger

@ImplementedBy(classOf[DefaultLoggingProvider])
trait LoggingProvider {
  def logger(clazz: Class[_]): Logger
}

class DefaultLoggingProvider extends LoggingProvider {
  def logger(clazz: Class[_]): Logger = {
    Logger(clazz)
  }
}

class MockLoggingProvider(mockLogger: Logger) extends LoggingProvider {
  def logger(clazz: Class[_]): Logger = {
    mockLogger
  }
} 
Example 148
Source File: LoggingFilter.scala    From HAT2.0   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.hatdex.hat.utils

import javax.inject.{ Inject, Singleton }
import akka.stream.Materializer
import com.nimbusds.jose.JWSObject
import com.nimbusds.jwt.JWTClaimsSet
import play.api.http.HttpErrorHandler
import play.api.mvc.{ Filter, RequestHeader, Result }
import play.api.{ Configuration, Logger }

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

@Singleton
class ActiveHatCounter() {
  // Careful! Mutable state
  private var count: Long = 0

  def get(): Long = count
  def increase(): Unit = this.synchronized(count += 1)
  def decrease(): Unit = this.synchronized(count -= 1)
}

class LoggingFilter @Inject() (
    errorHandler: HttpErrorHandler,
    configuration: Configuration,
    hatCounter: ActiveHatCounter)(
    implicit
    ec: ExecutionContext,
    val mat: Materializer) extends Filter {
  private val logger = Logger("api")

  def apply(nextFilter: RequestHeader => Future[Result])(requestHeader: RequestHeader): Future[Result] = {

    val startTime = System.currentTimeMillis

    nextFilter(requestHeader)
      .recoverWith({
        case e ⇒ errorHandler.onServerError(requestHeader, e)
      })
      .map { result =>
        val active = hatCounter.get()
        val requestTime = System.currentTimeMillis - startTime
        logger.info(s"[${requestHeader.remoteAddress}] [${requestHeader.method}:${requestHeader.host}:${requestHeader.uri}] " +
          s"[${result.header.status}] [$requestTime:ms] [hats:$active] ${tokenInfo(requestHeader)}")

        result.withHeaders("Request-Time" -> requestTime.toString)
      }
  }

  private val authTokenFieldName: String = configuration.get[String]("silhouette.authenticator.fieldName")
  private def tokenInfo(requestHeader: RequestHeader): String = {
    requestHeader.queryString.get(authTokenFieldName).flatMap(_.headOption)
      .orElse(requestHeader.headers.get(authTokenFieldName))
      .flatMap(t ⇒ if (t.isEmpty) { None } else { Some(t) })
      .flatMap(t ⇒ Try(JWSObject.parse(t)).toOption)
      .map(o ⇒ JWTClaimsSet.parse(o.getPayload.toJSONObject))
      .map { claimSet =>
        s"[${Option(claimSet.getStringClaim("application")).getOrElse("api")}@" +
          s"${Option(claimSet.getStringClaim("applicationVersion")).getOrElse("_")}]"
      }
      .getOrElse("[unauthenticated@_]")
  }
} 
Example 149
Source File: Utils.scala    From HAT2.0   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.hatdex.hat.utils

import play.api.Logger

import scala.collection.immutable.HashMap
import scala.concurrent.{ ExecutionContext, Future }
import scala.util.{ Failure, Success, Try }

object Utils {
  def flatten[T](xs: Seq[Try[T]]): Try[Seq[T]] = {
    val (ss: Seq[Success[T]] @unchecked, fs: Seq[Failure[T]] @unchecked) =
      xs.partition(_.isSuccess)

    if (fs.isEmpty) Success(ss map (_.get))
    else Failure[Seq[T]](fs(0).exception) // Only keep the first failure
  }

  // Utility function to return None for empty sequences
  def seqOption[T](seq: Seq[T]): Option[Seq[T]] = {
    if (seq.isEmpty)
      None
    else
      Some(seq)
  }

  def reverseOptionTry[T](a: Option[Try[T]]): Try[Option[T]] = {
    a match {
      case None =>
        Success(None)
      case Some(Success(b)) =>
        Success(Some(b))
      case Some(Failure(e)) =>
        Failure(e)
    }
  }

  def mergeMap[A, B](ms: Iterable[HashMap[A, B]])(f: (B, B) => B): HashMap[A, B] =
    (for (m <- ms; kv <- m) yield kv).foldLeft(HashMap[A, B]()) { (a, kv) =>
      a + (if (a.contains(kv._1)) kv._1 -> f(a(kv._1), kv._2) else kv)
    }

  def time[R](name: String, logger: Logger)(block: => R): R = {
    val t0 = System.nanoTime()
    val result = block // call-by-name
    val t1 = System.nanoTime()
    logger.info(s"[$name] Elapsed time: ${(t1 - t0) / 1000000.0}ms")
    result
  }

  def timeFuture[R](name: String, logger: Logger)(block: => Future[R])(implicit ec: ExecutionContext): Future[R] = {
    val t0 = System.nanoTime()
    block // call-by-name
      .andThen {
        case Success(_) =>
          val t1 = System.nanoTime()
          logger.info(s"[$name] Elapsed time: ${(t1 - t0) / 1000000.0}ms")
      }
  }

} 
Example 150
Source File: Phata.scala    From HAT2.0   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.hatdex.hat.phata.controllers

import com.mohiva.play.silhouette.api.Silhouette
import controllers.{ Assets, AssetsFinder, AssetsFinderProvider }
import javax.inject.Inject
import org.hatdex.hat.api.json.{ HatJsonFormats, RichDataJsonFormats }
import org.hatdex.hat.api.models.EndpointDataBundle
import org.hatdex.hat.api.service.richData.{ RichBundleService, RichDataService }
import org.hatdex.hat.authentication.{ HatApiAuthEnvironment, HatApiController }
import org.hatdex.hat.phata.{ views => phataViews }
import play.api.cache.{ Cached, CachedBuilder }
import play.api.libs.json.Json
import play.api.mvc._
import play.api.{ Configuration, Logger }

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future

class Phata @Inject() (
    components: ControllerComponents,
    assets: Assets,
    assetsFinder: AssetsFinderProvider,
    cached: Cached,
    configuration: Configuration,
    silhouette: Silhouette[HatApiAuthEnvironment],
    bundleService: RichBundleService,
    dataService: RichDataService) extends HatApiController(components, silhouette) with HatJsonFormats with RichDataJsonFormats {

  implicit val af: AssetsFinder = assetsFinder.get

  private val logger = Logger(this.getClass)

  val indefiniteSuccessCaching: CachedBuilder = cached
    .status(req => s"${req.host}${req.path}", 200)
    .includeStatus(404, 600)

  val csp: Map[String, String] = configuration.get[String]("play.filters.headers.contentSecurityPolicy")
    .split(';')
    .map(_.trim)
    .map({ p ⇒
      val splits = p.split(' ')
      splits.head → splits.tail.mkString(" ")
    })
    .toMap

  def rumpelIndex(): EssentialAction = indefiniteSuccessCaching {
    UserAwareAction.async { implicit request =>
      val rumpelConfigScript = s"""var httpProtocol = "${if (request.secure) { "https" } else { "http" }}:";"""

      Future.successful(Ok(phataViews.html.rumpelIndex(rumpelConfigScript, af)))
    }
  }

  def altRumpelIndex(claimToken: String): EssentialAction = {
    logger.debug(s"Current claim token $claimToken")
    assets.at("index.html")
  }

  def profile: Action[AnyContent] = UserAwareAction.async { implicit request =>
    val defaultBundleDefinition = Json.parse(configuration.get[String]("phata.defaultBundle")).as[EndpointDataBundle]
    for {
      bundle <- bundleService.bundle(defaultBundleDefinition.name).map(_.getOrElse(defaultBundleDefinition))
      data <- dataService.bundleData(bundle, None, None, None)
    } yield {
      Ok(Json.toJson(data))
    }
  }

  def hatLogin(name: String, redirectUrl: String) = indefiniteSuccessCaching {
    Action { implicit request =>
      val scheme = if (request.secure) { "https://" } else { "http://" }
      val newRedirectUrl = s"$scheme${request.domain}/#/hatlogin?name=$name&redirect=${redirectUrl}"
      logger.debug(s"Redirect url from ${request.uri}: $newRedirectUrl")
      Redirect(newRedirectUrl)
    }
  }

  //  def remoteAsset(file: String): String = {
  //    val versionedUrl = assets.path(file)
  //    val maybeAssetsUrl = Some("https://rumpel.hubat.net/assets") //configuration.getOptional[String]("assets.url")
  //    maybeAssetsUrl.fold(versionedUrl)(_ + file)
  //  }

} 
Example 151
Source File: HatDataStatsProcessorSpec.scala    From HAT2.0   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.hatdex.hat.api.service.monitoring

import java.util.UUID

import akka.stream.Materializer
import com.google.inject.AbstractModule
import net.codingwell.scalaguice.ScalaModule
import org.hatdex.hat.api.models.{ EndpointData, Owner }
import org.hatdex.hat.api.service.applications.{ TestApplicationProvider, TrustedApplicationProvider }
import org.hatdex.hat.api.service.monitoring.HatDataEventBus.DataCreatedEvent
import org.hatdex.hat.authentication.models.HatUser
import org.hatdex.hat.dal.ModelTranslation
import org.hatdex.hat.resourceManagement.FakeHatConfiguration
import org.joda.time.DateTime
import org.specs2.mock.Mockito
import org.specs2.specification.Scope
import play.api.inject.guice.GuiceApplicationBuilder
import play.api.libs.json.{ JsValue, Json }
import play.api.test.PlaySpecification
import play.api.{ Application, Logger }

class HatDataStatsProcessorSpec extends PlaySpecification with Mockito with HatDataStatsProcessorContext {

  val logger = Logger(this.getClass)

  sequential

  "The `computeInboundStats` method" should {
    "Correctly count numbers of values for simple objects" in {
      val service = application.injector.instanceOf[HatDataStatsProcessor]
      val stats = service.computeInboundStats(simpleDataCreatedEvent)

      import org.hatdex.hat.api.json.DataStatsFormat._
      logger.debug(s"Got back stats: ${Json.prettyPrint(Json.toJson(stats))}")

      stats.logEntry must be equalTo "test item"
      stats.statsType must be equalTo "inbound"
      stats.stats.length must be equalTo 1
      val endpointStats = stats.stats.head
      endpointStats.endpoint must be equalTo "testendpoint"

      endpointStats.propertyStats("field") must equalTo(1)
      endpointStats.propertyStats("date") must equalTo(1)
      endpointStats.propertyStats("date_iso") must equalTo(1)
      endpointStats.propertyStats("anotherField") must equalTo(1)
      endpointStats.propertyStats("object.objectField") must equalTo(1)
      endpointStats.propertyStats("object.objectFieldArray[]") must equalTo(3)
      endpointStats.propertyStats("object.objectFieldObjectArray[].subObjectName") must equalTo(2)
      endpointStats.propertyStats("object.objectFieldObjectArray[].subObjectName2") must equalTo(2)
    }
  }

}

trait HatDataStatsProcessorContext extends Scope {
  import scala.concurrent.ExecutionContext.Implicits.global
  // Setup default users for testing
  val owner = HatUser(UUID.randomUUID(), "hatuser", Some("pa55w0rd"), "hatuser", Seq(Owner()), enabled = true)

  class ExtrasModule extends AbstractModule with ScalaModule {
    override def configure(): Unit = {
      bind[TrustedApplicationProvider].toInstance(new TestApplicationProvider(Seq()))
    }
  }

  lazy val application: Application = new GuiceApplicationBuilder()
    .configure(FakeHatConfiguration.config)
    .overrides(new ExtrasModule)
    .build()

  implicit lazy val materializer: Materializer = application.materializer

  val simpleJson: JsValue = Json.parse(
    """
      | {
      |   "field": "value",
      |   "date": 1492699047,
      |   "date_iso": "2017-04-20T14:37:27+00:00",
      |   "anotherField": "anotherFieldValue",
      |   "object": {
      |     "objectField": "objectFieldValue",
      |     "objectFieldArray": ["objectFieldArray1", "objectFieldArray2", "objectFieldArray3"],
      |     "objectFieldObjectArray": [
      |       {"subObjectName": "subObject1", "subObjectName2": "subObject1-2"},
      |       {"subObjectName": "subObject2", "subObjectName2": "subObject2-2"}
      |     ]
      |   }
      | }
    """.stripMargin)

  val simpleDataCreatedEvent = DataCreatedEvent(
    "testhat.hubofallthings.net",
    ModelTranslation.fromInternalModel(owner).clean,
    DateTime.now(), "test item",
    Seq(
      EndpointData("testendpoint", Option(UUID.randomUUID()), None, None, simpleJson, None)))
} 
Example 152
Source File: FileManagerS3Spec.scala    From HAT2.0   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.hatdex.hat.api.service

import org.hatdex.hat.api.HATTestContext
import org.specs2.concurrent.ExecutionEnv
import org.specs2.mock.Mockito
import play.api.Logger
import play.api.test.PlaySpecification

import scala.concurrent.Future
import scala.concurrent.duration._

class FileManagerS3Spec(implicit ee: ExecutionEnv) extends PlaySpecification with Mockito with FileManagerContext {

  val logger = Logger(this.getClass)

  sequential

  "The `getUploadUrl` method" should {
    "return a signed url for a provided key" in {
      val fileManager = application.injector.instanceOf[FileManager]
      val result: Future[String] = fileManager.getUploadUrl("testFile", None)

      result must startWith("https://hat-storage-test.s3.eu-west-1.amazonaws.com/hat.hubofallthings.net/testFile").await
    }
  }

  "The `getContentUrl` method" should {
    "return a signed url for a provided key" in {
      val fileManager = application.injector.instanceOf[FileManager]
      val result: Future[String] = fileManager.getContentUrl("testFile")

      result must startWith("https://hat-storage-test.s3.eu-west-1.amazonaws.com/hat.hubofallthings.net/testFile").await
    }
  }

  "The `deleteContents` method" should {
    "return quietly when deleting any file" in {
      val fileManager = application.injector.instanceOf[FileManager]
      val result: Future[Unit] = fileManager.deleteContents("deleteFile")

      result must not(throwAn[Exception]).await
      there was one(mockS3client).deleteObject("hat-storage-test", "hat.hubofallthings.net/deleteFile")
    }
  }

  "The `getFileSize` method" should {
    "return 0 for files that do not exist" in {
      val fileManager = application.injector.instanceOf[FileManager]
      val result: Future[Long] = fileManager.getFileSize("nonExistentFile")

      result must equalTo(0L).await(3, 10.seconds)
    }

    "extract file size for files that do exist" in {
      val fileManager = application.injector.instanceOf[FileManager]
      val result: Future[Long] = fileManager.getFileSize("testFile")

      result must equalTo(123456L).await
      there was one(mockS3client).getObjectMetadata("hat-storage-test", "hat.hubofallthings.net/testFile")
    }
  }
}

trait FileManagerContext extends HATTestContext {
  val mockS3client = fileManagerS3Mock.mockS3client
} 
Example 153
Source File: SystemStatusSpec.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.test._
import org.hatdex.hat.api.HATTestContext
import org.hatdex.hat.api.json.HatJsonFormats
import org.hatdex.hat.api.models.{ HatStatus, StatusKind }
import org.specs2.concurrent.ExecutionEnv
import org.specs2.mock.Mockito
import org.specs2.specification.BeforeAll
import play.api.Logger
import play.api.test.{ FakeRequest, PlaySpecification }

import scala.concurrent.Await
import scala.concurrent.duration._

class SystemStatusSpec(implicit ee: ExecutionEnv) extends PlaySpecification with Mockito with HATTestContext with BeforeAll with HatJsonFormats {

  val logger = Logger(this.getClass)

  sequential

  def beforeAll: Unit = {
    Await.result(databaseReady, 60.seconds)
  }

  "The `update` method" should {
    "Return success response after updating HAT database" in {
      val request = FakeRequest("GET", "http://hat.hubofallthings.net")

      val controller = application.injector.instanceOf[SystemStatus]
      val result = controller.update().apply(request)

      status(result) must equalTo(OK)
      (contentAsJson(result) \ "message").as[String] must be equalTo "Database updated"
    }
  }

  "The `status` method" should {
    "Return current utilisation" in {
      val request = FakeRequest("GET", "http://hat.hubofallthings.net")
        .withAuthenticator(owner.loginInfo)

      val controller = application.injector.instanceOf[SystemStatus]
      val result = controller.status().apply(request)

      status(result) must equalTo(OK)
      val stats = contentAsJson(result).as[List[HatStatus]]

      stats.length must be greaterThan 0
      stats.find(_.title == "Previous Login").get.kind must be equalTo StatusKind.Text("Never", None)
      stats.find(_.title == "Owner Email").get.kind must be equalTo StatusKind.Text("[email protected]", None)
      stats.find(_.title == "Database Storage").get.kind must haveClass[StatusKind.Numeric]
      stats.find(_.title == "File Storage").get.kind must haveClass[StatusKind.Numeric]
      stats.find(_.title == "Database Storage Used").get.kind must haveClass[StatusKind.Numeric]
      stats.find(_.title == "File Storage Used").get.kind must haveClass[StatusKind.Numeric]
      stats.find(_.title == "Database Storage Used Share").get.kind must haveClass[StatusKind.Numeric]
      stats.find(_.title == "File Storage Used Share").get.kind must haveClass[StatusKind.Numeric]
    }

    "Return last login information when present" in {
      val authRequest = FakeRequest("GET", "http://hat.hubofallthings.net")
        .withHeaders("username" -> "hatuser", "password" -> "pa55w0rd")

      val authController = application.injector.instanceOf[Authentication]

      val request = FakeRequest("GET", "http://hat.hubofallthings.net")
        .withAuthenticator(owner.loginInfo)

      val controller = application.injector.instanceOf[SystemStatus]

      val result = for {
        _ <- authController.accessToken().apply(authRequest)
        // login twice - the second login is considered "current", not previous
        _ <- authController.accessToken().apply(authRequest)
        r <- controller.status().apply(request)
      } yield r

      status(result) must equalTo(OK)
      val stats = contentAsJson(result).as[List[HatStatus]]

      stats.length must be greaterThan 0
      stats.find(_.title == "Previous Login").get.kind must be equalTo StatusKind.Text("moments ago", None)
    }
  }
} 
Example 154
Source File: HatDataStatsProcessorActor.scala    From HAT2.0   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.hatdex.hat.api.service.monitoring

import javax.inject.Inject
import akka.Done
import akka.actor.Actor
import org.hatdex.hat.api.models.{ DataDebitOperation, DataStats, InboundDataStats, OutboundDataStats, DataDebitEvent ⇒ DataDebitAction }
import org.hatdex.hat.api.service.StatsReporter
import org.hatdex.hat.api.service.monitoring.HatDataEventBus.{ DataCreatedEvent, DataDebitEvent, RichDataDebitEvent, RichDataRetrievedEvent }
import org.hatdex.hat.resourceManagement.{ HatServer, HatServerDiscoveryException, HatServerProvider }
import play.api.Logger

import scala.concurrent.{ ExecutionContext, Future }

class HatDataStatsProcessorActor @Inject() (
    processor: HatDataStatsProcessor) extends Actor {

  private val log = Logger(this.getClass)

  import HatDataEventBus._

  def receive: Receive = {
    case d: DataCreatedEvent       => processBatchedStats(Seq(d))
    case d: RichDataRetrievedEvent => processBatchedStats(Seq(d))
    case d: RichDataDebitEvent     => processBatchedStats(Seq(d))
    case d: DataDebitEvent         => processBatchedStats(Seq(d))
    case d: Seq[_]                 => processBatchedStats(d)
    case m                         => log.warn(s"Received something else: $m")
  }

  private def processBatchedStats(d: Seq[Any]) = {
    log.debug(s"Process batched stas: $d")
    d.filter(_.isInstanceOf[HatDataEvent])
      .map(_.asInstanceOf[HatDataEvent])
      .groupBy(_.hat)
      .map {
        case (hat, stats) =>
          val aggregated = stats.collect {
            case s: DataCreatedEvent       => processor.computeInboundStats(s)
            case s: RichDataRetrievedEvent => processor.computeOutboundStats(s)
            case e: RichDataDebitEvent     => processor.reportDataDebitEvent(e)
            case e: DataDebitEvent         => processor.reportDataDebitEvent(e)
          }
          hat -> aggregated
      }
      .foreach {
        case (hat, hatStats) =>
          if (hatStats.nonEmpty) {
            processor.publishStats(hat, hatStats)
          }
      }
  }

}

class HatDataStatsProcessor @Inject() (
    statsReporter: StatsReporter,
    hatServerProvider: HatServerProvider)(
    implicit
    val ec: ExecutionContext) {

  protected val logger = Logger(this.getClass)

  def computeInboundStats(event: DataCreatedEvent): InboundDataStats = {
    val endpointStats = JsonStatsService.endpointDataCounts(event.data)
    InboundDataStats(event.time.toLocalDateTime, event.user,
      endpointStats.toSeq, event.logEntry)
  }

  def computeOutboundStats(event: RichDataRetrievedEvent): OutboundDataStats = {
    val endpointStats = JsonStatsService.endpointDataCounts(event.data)
    OutboundDataStats(event.time.toLocalDateTime, event.user,
      event.dataDebit.dataDebitKey, endpointStats.toSeq, event.logEntry)
  }

  def reportDataDebitEvent(event: RichDataDebitEvent): DataDebitAction = {
    DataDebitAction(event.dataDebit, event.operation.toString,
      event.time.toLocalDateTime, event.user, event.logEntry)
  }

  def reportDataDebitEvent(event: DataDebitEvent): DataDebitOperation = {
    DataDebitOperation(event.dataDebit, event.operation.toString,
      event.time.toLocalDateTime, event.user, event.logEntry)
  }

  def publishStats(hat: String, stats: Iterable[DataStats]): Future[Done] = {
    logger.debug(s"Publish stats for $hat: $stats")

    hatServerProvider.retrieve(hat) flatMap {
      _ map { implicit hatServer: HatServer =>
        statsReporter.reportStatistics(stats.toSeq)
      } getOrElse {
        logger.error(s"No HAT $hat found to report statistics for")
        Future.failed(new HatServerDiscoveryException(s"HAT $hat discovery failed for stats reporting"))
      }
    }
  }
} 
Example 155
Source File: AccessLoggingFilter.scala    From CM-Well   with Apache License 2.0 5 votes vote down vote up
package filters

import javax.inject._
import akka.stream.Materializer
import play.api.Logger
import play.api.mvc._
import scala.concurrent.{ExecutionContext, Future}

class AccessLoggingFilter @Inject()(implicit val mat: Materializer, ec: ExecutionContext) extends Filter {

  val accessLogger = Logger("access")

  def apply(next: (RequestHeader) => Future[Result])(request: RequestHeader): Future[Result] = {
    val startTime = request.attrs(Attrs.RequestReceivedTimestamp)
    next(request).map { result =>
      val endTime = System.currentTimeMillis
      val reqTime = endTime - startTime
      val ip = request.headers.get("X-Forwarded-For").getOrElse("N/A")
      val msg = s"method=${request.method} uri=${request.uri} remote-address=${request.remoteAddress} " +
        s"status=${result.header.status} process-time=$reqTime x-forwarded-for=${ip}";
      lazy val headers = request.headers.headers.map(h => h._1 + ":" + h._2).mkString(" headers=[", ",", "]")

      if (result.header.status < 400) accessLogger.info(msg)
      else if (result.header.status != 500) accessLogger.warn(msg + headers)
      else accessLogger.error(msg + headers)

      result.withHeaders("X-CMWELL-RT" -> s"${reqTime}ms")
    }
  }
} 
Example 156
Source File: Schema.scala    From play-silhouette-postgres-async-seed   with Apache License 2.0 5 votes vote down vote up
package services.database

import jdub.async.Database
import models.queries.ddl._
import play.api.Logger
import play.api.libs.concurrent.Execution.Implicits.defaultContext

import scala.concurrent.Future

object Schema {
  val tables = Seq(
    "users" -> CreateUsersTable,

    "user_profiles" -> CreateUserProfilesTable,
    "password_info" -> CreatePasswordInfoTable,
    "oauth1_info" -> CreateOAuth1InfoTable,
    "oauth2_info" -> CreateOAuth2InfoTable,
    "openid_info" -> CreateOpenIdInfoTable,
    "session_info" -> CreateSessionInfoTable
  )

  def update() = {
    tables.foldLeft(Future.successful(Unit)) { (f, t) =>
      f.flatMap { u =>
        Database.query(DdlQueries.DoesTableExist(t._1)).flatMap { exists =>
          if (exists) {
            Future.successful(Unit)
          } else {
            Logger.info(s"Creating missing table [${t._1}].")
            val name = s"CreateTable-${t._1}"
            Database.raw(name, t._2.sql).map(x => Unit)
          }
        }
      }
    }
  }
} 
Example 157
Source File: UserSearchService.scala    From play-silhouette-postgres-async-seed   with Apache License 2.0 5 votes vote down vote up
package services.user

import java.util.UUID

import com.mohiva.play.silhouette.api.LoginInfo
import com.mohiva.play.silhouette.api.services.IdentityService
import jdub.async.Database
import models.queries.UserQueries
import models.user.User
import play.api.Logger
import play.api.libs.concurrent.Execution.Implicits.defaultContext

import scala.concurrent.Future

object UserSearchService extends IdentityService[User] {
  def retrieve(id: UUID): Future[Option[User]] = Database.query(UserQueries.getById(Seq(id)))

  def retrieve(username: String): Future[Option[User]] = Database.query(UserQueries.FindUserByUsername(username))

  override def retrieve(loginInfo: LoginInfo) = if (loginInfo.providerID == "anonymous") {
    Database.query(UserQueries.getById(Seq(UUID.fromString(loginInfo.providerKey)))).map {
      case Some(dbUser) =>
        if (dbUser.profiles.nonEmpty) {
          Logger.warn(s"Attempt to authenticate as anonymous for user with profiles [${dbUser.profiles}].")
          None
        } else {
          Some(dbUser)
        }
      case None => None
    }
  } else {
    Database.query(UserQueries.FindUserByProfile(loginInfo))
  }
} 
Example 158
Source File: UserDao.scala    From bay-scalajs.g8   with Apache License 2.0 5 votes vote down vote up
package services.dao

import bay.driver.CustomizedPgDriver
import com.github.t3hnar.bcrypt._
import com.google.inject.{Inject, Singleton}
import models.forms.LoginForm
import java.time._
import play.api.Logger
import play.api.db.slick.{DatabaseConfigProvider, HasDatabaseConfigProvider}
import shared.utils.Implicits
import scala.concurrent.{ExecutionContext, Future}
import shared.models.slick.default._
import models.slick.Default._

@Singleton
class UserDao @Inject()(protected val dbConfigProvider: DatabaseConfigProvider) extends HasDatabaseConfigProvider[CustomizedPgDriver] with Implicits {

  import profile.api._

  def findUserByEmail(email: String): Future[Option[User]] =
    db.run(users.filter(_.email === email.toLowerCase).result.headOption)

  def findUserById(id: Int): Future[Option[User]] =
    db.run(users.filter(_.id === id).result.headOption)

  def resolveUser(id: Int)(implicit ec: ExecutionContext): Future[Option[User]] = {
    db.run(users.filter(_.id === id).result.headOption).map { e =>
      if (e.isDefined) { // don't wait for this update
        db.run(users.filter(_.id === id).map(_.lastAction).update(OffsetDateTime.now.asOption))
      }

      e
    }
  }

  def isInGroup(id: Option[Int], groupName: String): Future[Boolean] =
    db.run(
      userToUserGroups
        .filter(e => e.userId === id && e.groupName === groupName.toLowerCase)
        .exists
        .result)

  def maybeLogin(loginForm: LoginForm)(implicit ec: ExecutionContext): Future[Option[Int]] =
    db.run(users.filter(_.email === loginForm.email).result.headOption).flatMap {
      case Some(user) if loginForm.password.isBcrypted(user.password) =>
        db.run(users.filter(_.id === user.id).map(_.lastLogin).update(OffsetDateTime.now.asOption)) map { n =>
          if (n > 0) {
            Logger.info(s"${user.email} logged in")
            user.id
          } else None
        }
      case _ =>
        None.asFuture
    }
} 
Example 159
Source File: ApplicationTimer.scala    From Full-Stack-Scala-Starter   with Apache License 2.0 5 votes vote down vote up
package services

import java.time.{Clock, Instant}
import javax.inject._
import play.api.Logger
import play.api.inject.ApplicationLifecycle
import scala.concurrent.Future


@Singleton
class ApplicationTimer @Inject() (clock: Clock, appLifecycle: ApplicationLifecycle) {

  // This code is called when the application starts.
  private val start: Instant = clock.instant
  Logger.info(s"ApplicationTimer demo: Starting application at $start.")

  // When the application starts, register a stop hook with the
  // ApplicationLifecycle object. The code inside the stop hook will
  // be run when the application stops.
  appLifecycle.addStopHook { () =>
    val stop: Instant = clock.instant
    val runningTime: Long = stop.getEpochSecond - start.getEpochSecond
    Logger.info(s"ApplicationTimer demo: Stopping application at ${clock.instant} after ${runningTime}s.")
    Future.successful(())
  }
} 
Example 160
Source File: ModelUtils.scala    From DataQuality   with GNU Lesser General Public License v3.0 5 votes vote down vote up
package models

import play.api.Logger

import scala.collection.immutable.Queue


object ModelUtils {

  private lazy val separator: String = ","

  def toSeparatedString(seq: Seq[String]): Option[String] = {
    if (seq.isEmpty) None else Some(seq.mkString(separator))
  }

  def parseSeparatedString(str: Option[String]): Seq[String] = {
    str match {
      case Some(kf) => kf.split(",").toSeq
      case None => Seq.empty
    }
  }

  def findOptimalOrder(graph: Map[String, Seq[String]]): Queue[String] = {

    def loop(current: (String, Seq[String]))(gr: Map[String, Seq[String]], o: Queue[String], v: Set[String]): Queue[String] = {
      Logger.debug(s"Processing tuple: $current")
      Logger.debug(s"Current state: v{${v.mkString(",")}} : o{${o.mkString(",")}}")
      if (v.contains(current._1)) throw new IllegalArgumentException("Graph isn't acyclic.")
      else if (o.contains(current._1)) o
      else {
        val resolved: Queue[String] = current._2.foldLeft(o) {
          case (agg, curr) =>
            curr match {
              case x if x == current._1 => throw new IllegalArgumentException("Graph isn't acyclic.")
              case x if !o.contains(x) =>
                gr.get(x) match {
                  case Some(tail) =>
                    Logger.debug(s"Next: ${current._1} -> $x")
                    loop((x, tail))(gr, agg, v + current._1)
                  case None => Queue.empty[String]
                }
              case _ => Queue.empty[String]
            }
        }
        val order: Queue[String] = if (resolved.nonEmpty) resolved :+ current._1 else o :+ current._1
        Logger.debug(s"Put ${current._1} to o: {${order.mkString(",")}}")
        order
      }
    }

    graph.toSeq.foldLeft(Queue.empty[String]) {
      case (ord: Queue[String], curr: (String, Seq[String])) =>
        val r = loop(curr)(graph, ord, Set.empty)
        Logger.debug(s"${curr._1} :: ${r.mkString(", ")}")
        r
    }
  }

} 
Example 161
Source File: ConfigController.scala    From DataQuality   with GNU Lesser General Public License v3.0 5 votes vote down vote up
package controllers.config

import javax.inject.Inject
import com.typesafe.config.ConfigRenderOptions
import models.AppDB
import models.config.{ConfigReader, ConfigWriter}
import org.squeryl.PrimitiveTypeMode.inTransaction
import play.api.Logger
import play.api.libs.Files.TemporaryFile
import play.api.mvc.{Action, Controller, MultipartFormData}


class ConfigController @Inject()() extends Controller {

  def downloadConfiguration = Action {
//    try{
      val config = inTransaction(ConfigWriter.generateConfig)
      Ok(config.root().render(ConfigRenderOptions.concise().setFormatted(true).setJson(false)))
        .withHeaders("Content-Disposition" -> "attachment; filename=configuration.conf")
//    } catch {
//      case e: Exception => InternalServerError(e.toString)
//    }
  }

  def uploadConfiguration(): Action[MultipartFormData[TemporaryFile]] = Action(parse.multipartFormData) {
    implicit request => request.body.file("configuration")
      .map(file => {
        file.contentType match {
          case Some("application/octet-stream") =>
           try {
             inTransaction(AppDB.resetAll())
             ConfigReader.parseConfiguration(file.ref.file)
             Ok
           } catch {

             case e:  Exception => {
               Logger.error("ERROR reading config: " + e.getMessage)
               InternalServerError(e.toString)

             }
           }
          case _ => BadRequest("No application/octet-stream files were found!")
        }
      })  getOrElse BadRequest("File missing");
  }

  def resetConfiguration() = Action {
    inTransaction(AppDB.resetAll())
    Ok
  }

} 
Example 162
Source File: DAGProcessorSpec.scala    From DataQuality   with GNU Lesser General Public License v3.0 5 votes vote down vote up
package backend

import org.scalatestplus.play._

import scala.collection.immutable.Queue



class DAGProcessorSpec extends PlaySpec {

  import models.ModelUtils._
  import play.api.Logger

  "Graph processor" must {

    val tg1: Map[String, Seq[String]] = Map(
      "1" -> Seq("3"),
      "2" -> Seq("1"),
      "3" -> Seq("4", "5"),
      "4" -> Seq("ext1"),
      "5" -> Seq("ext3"),
      "6" -> Seq("7"),
      "7" -> Seq("3"),
      "8" -> Seq("ext2")
    )

    val tg2: Map[String, Seq[String]] = Map(
      "4" -> Seq("2","3"),
      "1" -> Seq("e1"),
      "2" -> Seq("1"),
      "3" -> Seq("1")
    )
    val tg3: Map[String, Seq[String]] = Map(
      "1" -> Seq("2"),
      "2" -> Seq("3"),
      "3" -> Seq("4"),
      "4" -> Seq("e1")
    )

    val atg1: Map[String, Seq[String]] = Map(
      "2" -> Seq("1"),
      "1" -> Seq("2")
    )

    val atg2: Map[String, Seq[String]] = Map(
      "1" -> Seq("3", "6"),
      "2" -> Seq("1"),
      "3" -> Seq("4", "5","1"),
      "4" -> Seq("ext1"),
      "5" -> Seq("ext3"),
      "6" -> Seq("7"),
      "7" -> Seq("3"),
      "8" -> Seq("ext2")
    )

    val atg3: Map[String, Seq[String]] = Map(
      "1" -> Seq("2"),
      "2" -> Seq("3"),
      "3" -> Seq("4"),
      "4" -> Seq("1")
    )

    "tg1: return same size seq" in {
      val res = findOptimalOrder(tg1)
      Logger.info(res.mkString(" > "))
      assert(res.size == tg1.keys.size)
    }
    "tg2: return same size seq" in {
      val res = findOptimalOrder(tg2)
      Logger.info(res.mkString(" > "))
      assert(res.size == tg2.keys.size)
    }
    "tg3: return correct order" in {
      val res: Queue[String] = findOptimalOrder(tg3)
      Logger.info(res.mkString(" > "))
      assert(res == Queue("4","3","2","1"))
    }
    "atg1: should throw error" in {
      assertThrows[IllegalArgumentException](findOptimalOrder(atg1))
    }
    "atg2: should throw error" in {
      assertThrows[IllegalArgumentException](findOptimalOrder(atg2))
    }
    "atg3: should throw error" in {
      assertThrows[IllegalArgumentException](findOptimalOrder(atg3))
    }

  }
} 
Example 163
Source File: SourcesApiController.scala    From DataQuality   with GNU Lesser General Public License v3.0 5 votes vote down vote up
package api

import com.agilelab.dataquality.api.model._
import javax.inject.{Inject, Singleton}
import play.api.Logger
import play.api.libs.json._
import play.api.mvc._
import utils.MyDBSession

@javax.annotation.Generated(value = Array("org.openapitools.codegen.languages.ScalaPlayFrameworkServerCodegen"), date = "2019-11-20T10:48:16.257+01:00[Europe/Rome]")
@Singleton
class SourcesApiController @Inject()(cc: ControllerComponents, api: SourcesApi,session: MyDBSession) extends AbstractController(cc) {

  val logger: Logger = Logger(this.getClass)

  
  def sourceById(sourceId: String): Action[AnyContent] = Action { request =>
    implicit val requestId: String = request.id.toString

    logger.info(s"API: ${request.id} - ${request.path}")

    def executeApi(): SourceItem = {
      api.sourceById(sourceId)
    }

    val result = executeApi()
    val json = Json.toJson(result)
    Ok(json)
  }

  def getTreeById(sourceId: String): Action[AnyContent] = Action { request =>
    implicit val requestId: String = request.id.toString

    logger.info(s"API: ${request.id} - ${request.path}")

    def executeApi(): (List[SourceItem], List[SourceItem]) = {
      api.getVirtualsourcesBySourceId(sourceId)
    }

    val result = executeApi()
    val json = Json.toJson(result._2.map(s=>s.id))
    Ok(json)
  }

} 
Example 164
Source File: ModelUtils.scala    From DataQuality   with GNU Lesser General Public License v3.0 5 votes vote down vote up
package dbmodel

import play.api.Logger

import scala.collection.immutable.Queue


object ModelUtils {

  private lazy val separator: String = ","

  def toSeparatedString(seq: Seq[String]): Option[String] = {
    if (seq.isEmpty) None else Some(seq.mkString(separator))
  }

  def parseSeparatedString(str: Option[String]): Seq[String] = {
    str match {
      case Some(kf) => kf.split(",").toSeq
      case None => Seq.empty
    }
  }

  def findOptimalOrder(graph: Map[String, Seq[String]]): Queue[String] = {

    def loop(current: (String, Seq[String]))(gr: Map[String, Seq[String]], o: Queue[String], v: Set[String]): Queue[String] = {
      Logger.debug(s"Processing tuple: $current")
      Logger.debug(s"Current state: v{${v.mkString(",")}} : o{${o.mkString(",")}}")
      if (v.contains(current._1)) throw new IllegalArgumentException("Graph isn't acyclic.")
      else if (o.contains(current._1)) o
      else {
        val resolved: Queue[String] = current._2.foldLeft(o) {
          case (agg, curr) =>
            curr match {
              case x if x == current._1 => throw new IllegalArgumentException("Graph isn't acyclic.")
              case x if !o.contains(x) =>
                gr.get(x) match {
                  case Some(tail) =>
                    Logger.debug(s"Next: ${current._1} -> $x")
                    loop((x, tail))(gr, agg, v + current._1)
                  case None => Queue.empty[String]
                }
              case _ => Queue.empty[String]
            }
        }
        val order: Queue[String] = if (resolved.nonEmpty) resolved :+ current._1 else o :+ current._1
        Logger.debug(s"Put ${current._1} to o: {${order.mkString(",")}}")
        order
      }
    }

    graph.toSeq.foldLeft(Queue.empty[String]) {
      case (ord: Queue[String], curr: (String, Seq[String])) =>
        val r = loop(curr)(graph, ord, Set.empty)
        Logger.debug(s"${curr._1} :: ${r.mkString(", ")}")
        r
    }
  }

} 
Example 165
Source File: ApiListingCache.scala    From swagger-play24   with Apache License 2.0 5 votes vote down vote up
package play.modules.swagger

import com.wordnik.swagger.config._
import com.wordnik.swagger.model.ApiListing
import com.wordnik.swagger.reader._
import com.wordnik.swagger.core.util.ReaderUtil
import play.api.Logger

object ApiListingCache extends ReaderUtil {

  var cache: Option[Map[String, ApiListing]] = None

  def listing(docRoot: String): Option[Map[String, com.wordnik.swagger.model.ApiListing]] = {
    cache.orElse {
      Logger("swagger").info("Loading API metadata")
      ClassReaders.reader.map{reader =>
        ScannerFactory.scanner.map(scanner => {
          val classes = scanner match {
            case scanner: Scanner => scanner.classes()
            case _ => List()
          }
          Logger("swagger").debug("Classes count: %s".format(classes.length))
          classes.foreach{ clazz =>
            Logger("swagger").debug("Controller: %s".format(clazz.getName))
          }
          val listings = (for(cls <- classes) yield reader.read(docRoot, cls, ConfigFactory.config)).flatten
          val mergedListings = groupByResourcePath(listings)
          cache = Some(mergedListings.map(m => (m.resourcePath, m)).toMap)
        })
      }
      cache
    }
  }

} 
Example 166
Source File: PlayApiScanner.scala    From swagger-play24   with Apache License 2.0 5 votes vote down vote up
package pl.matisoft.swagger

import com.wordnik.swagger.annotations.Api
import com.wordnik.swagger.core.SwaggerContext
import com.wordnik.swagger.config._

import play.api.Logger
import play.api.routing.Router


class PlayApiScanner(routes: Option[Router]) extends Scanner {

  def classes(): List[Class[_]] = {
    Logger("swagger").warn("ControllerScanner - looking for controllers with API annotation")

    // get controller names from application routes
    val controllers = (routes match {
      case Some(r) => {
        for (doc <- r.documentation) yield {
          Logger("swagger").debug("route: " + doc.toString())
          val m1 = doc._3.lastIndexOf("(") match {
            case i: Int if (i > 0) => doc._3.substring(0, i)
            case _ => doc._3
          }
          Some(m1.substring(0, m1.lastIndexOf(".")).replace("@", ""))
        }
      }
      case None => Seq(None)
    }).flatten.distinct.toList

    controllers.collect {
      case className: String if {
        try {
          SwaggerContext.loadClass(className).getAnnotation(classOf[Api]) != null
        } catch {
          case ex: Exception => {
            Logger("swagger").error("Problem loading class:  %s. %s: %s".format(className, ex.getClass.getName, ex.getMessage))
            false}
        }
      } =>
        Logger("swagger").info("Found API controller:  %s".format(className))
        SwaggerContext.loadClass(className)
    }

  }
} 
Example 167
Source File: SwaggerPluginProvider.scala    From swagger-play24   with Apache License 2.0 5 votes vote down vote up
package pl.matisoft.swagger

import java.net.URL
import javax.inject.{Inject, Provider}

import com.wordnik.swagger.config.{FilterFactory, ScannerFactory, ConfigFactory}
import com.wordnik.swagger.core.SwaggerContext
import com.wordnik.swagger.core.filter.SwaggerSpecFilter
import com.wordnik.swagger.reader.ClassReaders
import play.api.inject.ApplicationLifecycle
import play.api.{Logger, Application}
import play.api.routing.Router
import play.modules.swagger.ApiListingCache
import scala.concurrent.ExecutionContext.Implicits.global

import scala.concurrent.Future

class SwaggerPluginProvider extends Provider[SwaggerPlugin] {

  val logger = Logger("swagger")

  @Inject
  private var router: Router = _

  @Inject
  private var app: Application = _

  @Inject
  private var lifecycle: ApplicationLifecycle = _

  override def get(): SwaggerPlugin = {
    lifecycle.addStopHook(() => Future {
      onStop()
    })

    onStart()
  }

  def onStart(): SwaggerPlugin = {
    val config = app.configuration
    logger.info("Swagger - starting initialisation...")

    val apiVersion = config.getString("api.version") match {
      case None => "beta"
      case Some(value) => value
    }

    val basePath = config.getString("swagger.api.basepath")
        .filter(path => !path.isEmpty)
        .map(getPathUrl(_))
        .getOrElse("http://localhost:9000")

    SwaggerContext.registerClassLoader(app.classloader)
    ConfigFactory.config.setApiVersion(apiVersion)
    ConfigFactory.config.setBasePath(basePath)
    ScannerFactory.setScanner(new PlayApiScanner(Option(router)))
    ClassReaders.reader = Some(new PlayApiReader(Option(router)))

    app.configuration.getString("swagger.filter")
      .filter(p => !p.isEmpty)
      .foreach(loadFilter(_))

    val docRoot = ""
    ApiListingCache.listing(docRoot)

    logger.info("Swagger - initialization done.")
    new SwaggerPlugin()
  }

  def onStop() {
    ApiListingCache.cache = None
    logger.info("Swagger - stopped.")
  }

  def loadFilter(filterClass: String): Unit = {
    try {
      FilterFactory.filter = SwaggerContext.loadClass(filterClass).newInstance.asInstanceOf[SwaggerSpecFilter]
      logger.info(s"Setting swagger.filter to $filterClass")
    } catch {
      case ex: Exception =>logger.error(s"Failed to load filter:$filterClass", ex)
    }
  }

  def getPathUrl(path: String): String = {
    try {
      val basePathUrl = new URL(path)
      logger.info(s"Basepath configured as:$path")
      path
    } catch {
      case ex: Exception =>
        logger.error(s"Misconfiguration - basepath not a valid URL:$path. Swagger abandoning initialisation!")
        throw ex
    }
  }

} 
Example 168
Source File: TEIParserActor.scala    From recogito2   with Apache License 2.0 5 votes vote down vote up
package transform.tei

import akka.actor.Props
import java.io.File
import java.util.UUID
import play.api.Logger
import scala.concurrent.Await
import scala.concurrent.duration._
import services.annotation.AnnotationService
import services.generated.tables.records.{DocumentRecord, DocumentFilepartRecord}
import services.task.TaskService
import transform.{WorkerActor, SpecificJobDefinition}

class TEIParserActor(
  taskService: TaskService,
  annotationService: AnnotationService
) extends WorkerActor(TEIParserService.TASK_TYPE, taskService) {
  
  implicit val ctx = context.dispatcher
  
  override def doWork(
    doc: DocumentRecord, 
    part: DocumentFilepartRecord, 
    dir: File, 
    jobDef: Option[SpecificJobDefinition], 
    taskId: UUID
  ) = {
    val annotations = TEIParserService.extractEntities(part, new File(dir, part.getFile))
    
    val fUpsertAll = annotationService.upsertAnnotations(annotations).map { failed =>
      if (failed.size == 0) {
        taskService.setTaskCompleted(taskId)
      } else {
        val msg = "Failed to store " + failed.size + " annotations"
        Logger.warn(msg)
        failed.foreach(a => Logger.warn(a.toString))
        taskService.setTaskFailed(taskId, Some(msg))
      } 
    } recover { case t: Throwable =>
      t.printStackTrace
      taskService.setTaskFailed(taskId, Some(t.getMessage))
    }

    Await.result(fUpsertAll, 20.minutes)   
  }
  
}

object TEIParserActor {
  
  def props(taskService: TaskService, annotationService: AnnotationService) =
    Props(classOf[TEIParserActor], taskService, annotationService)
  
}