javax.inject.Inject Scala Examples

The following examples show how to use javax.inject.Inject. 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: NaptimeModuleTest.scala    From naptime   with Apache License 2.0 8 votes vote down vote up
package org.coursera.naptime

import java.util.Date
import javax.inject.Inject

import akka.stream.Materializer
import com.google.inject.Guice
import com.google.inject.Stage
import com.linkedin.data.schema.DataSchema
import com.linkedin.data.schema.DataSchemaUtil
import com.linkedin.data.schema.PrimitiveDataSchema
import com.linkedin.data.schema.RecordDataSchema
import org.coursera.naptime.model.KeyFormat
import org.coursera.naptime.resources.TopLevelCollectionResource
import org.coursera.naptime.router2.NaptimeRoutes
import org.junit.Test
import org.mockito.Mockito.mock
import org.scalatest.junit.AssertionsForJUnit
import play.api.libs.json.Json
import play.api.libs.json.OFormat

import scala.concurrent.ExecutionContext

object NaptimeModuleTest {
  case class User(name: String, createdAt: Date)
  object User {
    implicit val oFormat: OFormat[User] = Json.format[User]
  }
  class MyResource(implicit val executionContext: ExecutionContext, val materializer: Materializer)
      extends TopLevelCollectionResource[String, User] {
    override implicit def resourceFormat: OFormat[User] = User.oFormat
    override def keyFormat: KeyFormat[KeyType] = KeyFormat.stringKeyFormat
    override def resourceName: String = "myResource"
    implicit val fields = Fields

    def get(id: String) = Nap.get(ctx => ???)
  }
  object MyFakeModule extends NaptimeModule {
    override def configure(): Unit = {
      bindResource[MyResource]
      bind[MyResource].toInstance(mock(classOf[MyResource]))
      bindSchemaType[Date](DataSchemaUtil.dataSchemaTypeToPrimitiveDataSchema(DataSchema.Type.LONG))
    }
  }

  class OverrideTypesHelper @Inject()(val schemaOverrideTypes: NaptimeModule.SchemaTypeOverrides)
}

class NaptimeModuleTest extends AssertionsForJUnit {
  import NaptimeModuleTest._

  
  @Test
  def checkInferredOverrides(): Unit = {
    val injector = Guice.createInjector(Stage.DEVELOPMENT, MyFakeModule, NaptimeModule)
    val overrides = injector.getInstance(classOf[OverrideTypesHelper])
    assert(overrides.schemaOverrideTypes.size === 1)
    assert(overrides.schemaOverrideTypes.contains("java.util.Date"))
  }

  @Test
  def checkComputedOverrides(): Unit = {
    val injector = Guice.createInjector(Stage.DEVELOPMENT, MyFakeModule, NaptimeModule)
    val overrides = injector.getInstance(classOf[OverrideTypesHelper])
    val routes = injector.getInstance(classOf[NaptimeRoutes])
    assert(1 === routes.routerBuilders.size)
    val routerBuilder = routes.routerBuilders.head
    val inferredSchemaKeyed =
      routerBuilder.types.find(_.key == "org.coursera.naptime.NaptimeModuleTest.User").get
    assert(inferredSchemaKeyed.value.isInstanceOf[RecordDataSchema])
    val userSchema = inferredSchemaKeyed.value.asInstanceOf[RecordDataSchema]
    assert(2 === userSchema.getFields.size())
    val initialCreatedAtSchema = userSchema.getField("createdAt").getType.getDereferencedDataSchema
    assert(initialCreatedAtSchema.isInstanceOf[RecordDataSchema])
    assert(
      initialCreatedAtSchema
        .asInstanceOf[RecordDataSchema]
        .getDoc
        .contains("Unable to infer schema"))
    SchemaUtils.fixupInferredSchemas(userSchema, overrides.schemaOverrideTypes)
    val fixedCreatedAtSchema = userSchema.getField("createdAt").getType.getDereferencedDataSchema
    assert(fixedCreatedAtSchema.isInstanceOf[PrimitiveDataSchema])
  }
} 
Example 2
Source File: WithActiveTabAction.scala    From pertax-frontend   with Apache License 2.0 5 votes vote down vote up
package controllers.auth

import controllers.auth.requests.UserRequest
import play.api.mvc.{ActionRefiner, MessagesControllerComponents, Result}
import uk.gov.hmrc.renderer.ActiveTab
import javax.inject.Inject

import scala.concurrent.{ExecutionContext, Future}

class WithActiveTabAction @Inject()(implicit ec: ExecutionContext) {

  def addActiveTab(currentActiveTab: ActiveTab): ActionRefiner[UserRequest, UserRequest] =
    new ActionRefiner[UserRequest, UserRequest] {
      override protected def refine[A](request: UserRequest[A]): Future[Either[Result, UserRequest[A]]] =
        Future.successful(
          Right(
            UserRequest(
              request.nino,
              request.retrievedName,
              request.saUserType,
              request.credentials,
              request.confidenceLevel,
              request.personDetails,
              request.trustedHelper,
              request.profile,
              request.unreadMessageCount,
              Some(currentActiveTab),
              request.breadcrumb,
              request.request
            )
          )
        )

      override protected def executionContext: ExecutionContext = ec
    }
} 
Example 3
Source File: PasswordInfoDAO.scala    From play-silhouette-4.0-slick-postgres-seed   with Apache License 2.0 5 votes vote down vote up
package models.daos

import javax.inject.Inject

import com.mohiva.play.silhouette.api.LoginInfo
import com.mohiva.play.silhouette.api.util.PasswordInfo
import com.mohiva.play.silhouette.persistence.daos.DelegableAuthInfoDAO
import models.daos.PasswordInfoDAO._
import models.tables.{ DbPasswordInfo, PasswordInfoTable }
import play.api.db.slick.DatabaseConfigProvider
import slick.backend.DatabaseConfig
import slick.driver.JdbcProfile
import slick.jdbc.JdbcBackend
import slick.lifted.TableQuery

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

class PasswordInfoDAO @Inject() (
  protected val dbConfigProvider: DatabaseConfigProvider,
  userDAO: UserDAO) extends DelegableAuthInfoDAO[PasswordInfo] {

  val dbConfig: DatabaseConfig[JdbcProfile] = dbConfigProvider.get[JdbcProfile]
  val db: JdbcBackend#DatabaseDef = dbConfig.db

  import dbConfig.driver.api._

  def passwordInfoQuery(loginInfo: LoginInfo): Query[PasswordInfoTable, DbPasswordInfo, Seq] = {
    for {
      dbLoginInfo <- userDAO.loginInfoQuery(loginInfo)
      dbPasswordInfo <- passwordInfos.filter(_.loginInfoId === dbLoginInfo.id)
    } yield dbPasswordInfo
  }

  def find(loginInfo: LoginInfo): Future[Option[PasswordInfo]] = {
    db.run(passwordInfoQuery(loginInfo).result.headOption).map { dbPasswordInfoOption =>
      dbPasswordInfoOption.map {
        dbPasswordInfo => PasswordInfo(dbPasswordInfo.hasher, dbPasswordInfo.password, dbPasswordInfo.salt)
      }
    }
  }

  def add(loginInfo: LoginInfo, authInfo: PasswordInfo): Future[PasswordInfo] = {
    db.run(userDAO.loginInfoQuery(loginInfo).result.headOption.map { dbLoginInfoOption =>
      dbLoginInfoOption.map {
        dbLoginInfo =>
          {
            val dbPasswordInfo = DbPasswordInfo(authInfo.hasher, authInfo.password, authInfo.salt, dbLoginInfo.id.get)
            db.run(passwordInfos += dbPasswordInfo)
          }
      }
    }).map { _ =>
      authInfo
    }
  }

  def update(loginInfo: LoginInfo, authInfo: PasswordInfo): Future[PasswordInfo] = {
    db.run(userDAO.loginInfoQuery(loginInfo).result.headOption.map { dbLoginInfoOption =>
      dbLoginInfoOption.map {
        dbLoginInfo =>
          {
            db.run { 
              passwordInfos.filter(_.loginInfoId === dbLoginInfo.id) 
              .map(p => (p.hasher, p.password, p.salt)) 
              .update((authInfo.hasher, authInfo.password, authInfo.salt)) 
              .transactionally 
            }
          }
      }
    }).map { _ =>
      authInfo
    }
  }

  def save(loginInfo: LoginInfo, authInfo: PasswordInfo): Future[PasswordInfo] = {
    db.run(userDAO.loginInfoQuery(loginInfo).result.headOption.map { dbLoginInfoOption =>
      dbLoginInfoOption.map {
        dbLoginInfo =>
          {
            val dbPasswordInfo = DbPasswordInfo(authInfo.hasher, authInfo.password, authInfo.salt, dbLoginInfo.id.get)
            db.run(passwordInfoQuery(loginInfo).insertOrUpdate(dbPasswordInfo).transactionally)
          }
      }
    }).map { _ =>
      authInfo
    }
  }

  def remove(loginInfo: LoginInfo): Future[Unit] = {
    db.run(passwordInfoQuery(loginInfo).delete).map(_ => Unit)
  }
}

object PasswordInfoDAO {

  private val passwordInfos = TableQuery[PasswordInfoTable]

} 
Example 4
Source File: UserServiceImpl.scala    From play-silhouette-4.0-slick-postgres-seed   with Apache License 2.0 5 votes vote down vote up
package models.services

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

import com.mohiva.play.silhouette.api.LoginInfo
import com.mohiva.play.silhouette.impl.providers.CommonSocialProfile
import models.User
import models.daos.UserDAO
import play.api.libs.concurrent.Execution.Implicits._

import scala.concurrent.Future


  def save(profile: CommonSocialProfile) = {
    userDAO.find(profile.loginInfo).flatMap {
      case Some(user) => // Update user with profile
        userDAO.save(user.copy(
          firstName = profile.firstName,
          lastName = profile.lastName,
          fullName = profile.fullName,
          email = profile.email,
          avatarURL = profile.avatarURL
        ))
      case None => // Insert a new user
        userDAO.save(User(
          userID = UUID.randomUUID(),
          loginInfo = profile.loginInfo,
          firstName = profile.firstName,
          lastName = profile.lastName,
          fullName = profile.fullName,
          email = profile.email,
          avatarURL = profile.avatarURL,
          activated = true
        ))
    }
  }
} 
Example 5
Source File: SocialAuthController.scala    From play-silhouette-4.0-slick-postgres-seed   with Apache License 2.0 5 votes vote down vote up
package controllers.auth

import javax.inject.Inject

import com.mohiva.play.silhouette.api._
import com.mohiva.play.silhouette.api.exceptions.ProviderException
import com.mohiva.play.silhouette.api.repositories.AuthInfoRepository
import com.mohiva.play.silhouette.impl.providers._
import controllers.{ WebJarAssets, auth, pages }
import models.services.UserService
import play.api.i18n.{ I18nSupport, Messages, MessagesApi }
import play.api.libs.concurrent.Execution.Implicits._
import play.api.mvc.{ Action, AnyContent, Controller }
import utils.auth.DefaultEnv

import scala.concurrent.Future


  def authenticate(provider: String): Action[AnyContent] = Action.async { implicit request =>
    (socialProviderRegistry.get[SocialProvider](provider) match {
      case Some(p: SocialProvider with CommonSocialProfileBuilder) =>
        p.authenticate().flatMap {
          case Left(result) => Future.successful(result)
          case Right(authInfo) => for {
            profile <- p.retrieveProfile(authInfo)
            user <- userService.save(profile)
            authInfo <- authInfoRepository.save(profile.loginInfo, authInfo)
            authenticator <- silhouette.env.authenticatorService.create(profile.loginInfo)
            value <- silhouette.env.authenticatorService.init(authenticator)
            result <- silhouette.env.authenticatorService.embed(value, Redirect(pages.routes.ApplicationController.index()))
          } yield {
            silhouette.env.eventBus.publish(LoginEvent(user, request))
            result
          }
        }
      case _ => Future.failed(new ProviderException(s"Cannot authenticate with unexpected social provider $provider"))
    }).recover {
      case e: ProviderException =>
        logger.error("Unexpected provider error", e)
        Redirect(auth.routes.SignInController.view()).flashing("error" -> Messages("could.not.authenticate"))
    }
  }
} 
Example 6
Source File: ChangePasswordController.scala    From play-silhouette-4.0-slick-postgres-seed   with Apache License 2.0 5 votes vote down vote up
package controllers.auth

import javax.inject.Inject

import com.mohiva.play.silhouette.api._
import com.mohiva.play.silhouette.api.exceptions.ProviderException
import com.mohiva.play.silhouette.api.repositories.AuthInfoRepository
import com.mohiva.play.silhouette.api.util.{ Credentials, PasswordHasherRegistry, PasswordInfo }
import com.mohiva.play.silhouette.impl.providers.CredentialsProvider
import controllers.{ WebJarAssets, auth }
import forms.auth.ChangePasswordForm
import models.services.UserService
import play.api.i18n.{ I18nSupport, Messages, MessagesApi }
import play.api.libs.concurrent.Execution.Implicits._
import play.api.mvc.{ Action, AnyContent, Controller }
import utils.auth.{ DefaultEnv, WithProvider }

import scala.concurrent.Future


  def submit: Action[AnyContent] = silhouette.SecuredAction(WithProvider[DefaultEnv#A](CredentialsProvider.ID)).async { implicit request =>
    ChangePasswordForm.form.bindFromRequest.fold(
      form => Future.successful(BadRequest(views.html.auth.changePassword(form, request.identity))),
      password => {
        val (currentPassword, newPassword) = password
        val credentials = Credentials(request.identity.email.getOrElse(""), currentPassword)
        credentialsProvider.authenticate(credentials).flatMap { loginInfo =>
          val passwordInfo = passwordHasherRegistry.current.hash(newPassword)
          authInfoRepository.update[PasswordInfo](loginInfo, passwordInfo).map { _ =>
            Redirect(auth.routes.ChangePasswordController.view()).flashing("success" -> Messages("password.changed"))
          }
        }.recover {
          case e: ProviderException =>
            Redirect(auth.routes.ChangePasswordController.view()).flashing("error" -> Messages("current.password.invalid"))
        }
      }
    )
  }
} 
Example 7
Source File: SignInController.scala    From play-silhouette-4.0-slick-postgres-seed   with Apache License 2.0 5 votes vote down vote up
package controllers.auth

import javax.inject.Inject

import com.mohiva.play.silhouette.api.Authenticator.Implicits._
import com.mohiva.play.silhouette.api._
import com.mohiva.play.silhouette.api.exceptions.ProviderException
import com.mohiva.play.silhouette.api.repositories.AuthInfoRepository
import com.mohiva.play.silhouette.api.util.{ Clock, Credentials }
import com.mohiva.play.silhouette.impl.exceptions.IdentityNotFoundException
import com.mohiva.play.silhouette.impl.providers._
import controllers.{ WebJarAssets, auth, pages }
import forms.auth.SignInForm
import models.services.UserService
import net.ceedubs.ficus.Ficus._
import play.api.Configuration
import play.api.i18n.{ I18nSupport, Messages, MessagesApi }
import play.api.libs.concurrent.Execution.Implicits._
import play.api.mvc.{ Action, AnyContent, Controller }
import utils.auth.DefaultEnv

import scala.concurrent.Future
import scala.concurrent.duration._
import scala.language.postfixOps


  def submit: Action[AnyContent] = silhouette.UnsecuredAction.async { implicit request =>
    SignInForm.form.bindFromRequest.fold(
      form => Future.successful(BadRequest(views.html.auth.signIn(form, socialProviderRegistry))),
      data => {
        val credentials = Credentials(data.email, data.password)
        credentialsProvider.authenticate(credentials).flatMap { loginInfo =>
          val result = Redirect(pages.routes.ApplicationController.index())
          userService.retrieve(loginInfo).flatMap {
            case Some(user) if !user.activated =>
              Future.successful(Ok(views.html.auth.activateAccount(data.email)))
            case Some(user) =>
              val c = configuration.underlying
              silhouette.env.authenticatorService.create(loginInfo).map {
                case authenticator if data.rememberMe =>
                  authenticator.copy(
                    expirationDateTime = clock.now + c.as[FiniteDuration]("silhouette.authenticator.rememberMe.authenticatorExpiry"),
                    idleTimeout = c.getAs[FiniteDuration]("silhouette.authenticator.rememberMe.authenticatorIdleTimeout"),
                    cookieMaxAge = c.getAs[FiniteDuration]("silhouette.authenticator.rememberMe.cookieMaxAge")
                  )
                case authenticator => authenticator
              }.flatMap { authenticator =>
                silhouette.env.eventBus.publish(LoginEvent(user, request))
                silhouette.env.authenticatorService.init(authenticator).flatMap { v =>
                  silhouette.env.authenticatorService.embed(v, result)
                }
              }
            case None => Future.failed(new IdentityNotFoundException("Couldn't find user"))
          }
        }.recover {
          case e: ProviderException =>
            Redirect(auth.routes.SignInController.view()).flashing("error" -> Messages("invalid.credentials"))
        }
      }
    )
  }
} 
Example 8
Source File: ResetPasswordController.scala    From play-silhouette-4.0-slick-postgres-seed   with Apache License 2.0 5 votes vote down vote up
package controllers.auth

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

import com.mohiva.play.silhouette.api._
import com.mohiva.play.silhouette.api.repositories.AuthInfoRepository
import com.mohiva.play.silhouette.api.util.{ PasswordHasherRegistry, PasswordInfo }
import com.mohiva.play.silhouette.impl.providers.CredentialsProvider
import controllers.{ WebJarAssets, auth }
import forms.auth.ResetPasswordForm
import models.services.{ AuthTokenService, UserService }
import play.api.i18n.{ I18nSupport, Messages, MessagesApi }
import play.api.libs.concurrent.Execution.Implicits._
import play.api.mvc.{ Action, AnyContent, Controller }
import utils.auth.DefaultEnv

import scala.concurrent.Future


  def submit(token: UUID): Action[AnyContent] = silhouette.UnsecuredAction.async { implicit request =>
    authTokenService.validate(token).flatMap {
      case Some(authToken) =>
        ResetPasswordForm.form.bindFromRequest.fold(
          form => Future.successful(BadRequest(views.html.auth.resetPassword(form, token))),
          password => userService.retrieve(authToken.userID).flatMap {
            case Some(user) if user.loginInfo.providerID == CredentialsProvider.ID =>
              val passwordInfo = passwordHasherRegistry.current.hash(password)
              authInfoRepository.update[PasswordInfo](user.loginInfo, passwordInfo).map { _ =>
                Redirect(auth.routes.SignInController.view()).flashing("success" -> Messages("password.reset"))
              }
            case _ => Future.successful(Redirect(auth.routes.SignInController.view()).flashing("error" -> Messages("invalid.reset.link")))
          }
        )
      case None => Future.successful(Redirect(auth.routes.SignInController.view()).flashing("error" -> Messages("invalid.reset.link")))
    }
  }
} 
Example 9
Source File: SignUpController.scala    From play-silhouette-4.0-slick-postgres-seed   with Apache License 2.0 5 votes vote down vote up
package controllers.auth

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

import com.mohiva.play.silhouette.api._
import com.mohiva.play.silhouette.api.repositories.AuthInfoRepository
import com.mohiva.play.silhouette.api.services.AvatarService
import com.mohiva.play.silhouette.api.util.PasswordHasherRegistry
import com.mohiva.play.silhouette.impl.providers._
import controllers.{ WebJarAssets, auth }
import forms.auth.SignUpForm
import models.User
import models.services.{ AuthTokenService, UserService }
import play.api.i18n.{ I18nSupport, Messages, MessagesApi }
import play.api.libs.concurrent.Execution.Implicits._
import play.api.libs.mailer.{ Email, MailerClient }
import play.api.mvc.{ Action, AnyContent, Controller }
import utils.auth.DefaultEnv

import scala.concurrent.Future


  def submit: Action[AnyContent] = silhouette.UnsecuredAction.async { implicit request =>
    SignUpForm.form.bindFromRequest.fold(
      form => Future.successful(BadRequest(views.html.auth.signUp(form))),
      data => {
        val result = Redirect(auth.routes.SignUpController.view()).flashing("info" -> Messages("sign.up.email.sent", data.email))
        val loginInfo = LoginInfo(CredentialsProvider.ID, data.email)
        userService.retrieve(loginInfo).flatMap {
          case Some(user) =>
            val url = auth.routes.SignInController.view().absoluteURL()
            mailerClient.send(Email(
              subject = Messages("email.already.signed.up.subject"),
              from = Messages("email.from"),
              to = Seq(data.email),
              bodyText = Some(views.txt.emails.alreadySignedUp(user, url).body),
              bodyHtml = Some(views.html.emails.alreadySignedUp(user, url).body)
            ))

            Future.successful(result)
          case None =>
            val authInfo = passwordHasherRegistry.current.hash(data.password)
            val user = User(
              userID = UUID.randomUUID(),
              loginInfo = loginInfo,
              firstName = Some(data.firstName),
              lastName = Some(data.lastName),
              fullName = Some(data.firstName + " " + data.lastName),
              email = Some(data.email),
              avatarURL = None,
              activated = false
            )
            for {
              avatar <- avatarService.retrieveURL(data.email)
              user <- userService.save(user.copy(avatarURL = avatar))
              authInfo <- authInfoRepository.add(loginInfo, authInfo)
              authToken <- authTokenService.create(user.userID)
            } yield {
              val url = auth.routes.ActivateAccountController.activate(authToken.id).absoluteURL()
              mailerClient.send(Email(
                subject = Messages("email.sign.up.subject"),
                from = Messages("email.from"),
                to = Seq(data.email),
                bodyText = Some(views.txt.emails.signUp(user, url).body),
                bodyHtml = Some(views.html.emails.signUp(user, url).body)
              ))

              silhouette.env.eventBus.publish(SignUpEvent(user, request))
              result
            }
        }
      }
    )
  }
} 
Example 10
Source File: ActivateAccountController.scala    From play-silhouette-4.0-slick-postgres-seed   with Apache License 2.0 5 votes vote down vote up
package controllers.auth

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

import com.mohiva.play.silhouette.api._
import com.mohiva.play.silhouette.impl.providers.CredentialsProvider
import controllers.{ WebJarAssets, auth }
import models.services.{ AuthTokenService, UserService }
import play.api.i18n.{ I18nSupport, Messages, MessagesApi }
import play.api.libs.concurrent.Execution.Implicits._
import play.api.libs.mailer.{ Email, MailerClient }
import play.api.mvc.{ Action, AnyContent, Controller }
import utils.auth.DefaultEnv

import scala.concurrent.Future
import scala.language.postfixOps


  def activate(token: UUID): Action[AnyContent] = silhouette.UnsecuredAction.async { implicit request =>
    authTokenService.validate(token).flatMap {
      case Some(authToken) => userService.retrieve(authToken.userID).flatMap {
        case Some(user) if user.loginInfo.providerID == CredentialsProvider.ID =>
          userService.save(user.copy(activated = true)).map { _ =>
            Redirect(auth.routes.SignInController.view()).flashing("success" -> Messages("account.activated"))
          }
        case _ => Future.successful(Redirect(auth.routes.SignInController.view()).flashing("error" -> Messages("invalid.activation.link")))
      }
      case None => Future.successful(Redirect(auth.routes.SignInController.view()).flashing("error" -> Messages("invalid.activation.link")))
    }
  }
} 
Example 11
Source File: ForgotPasswordController.scala    From play-silhouette-4.0-slick-postgres-seed   with Apache License 2.0 5 votes vote down vote up
package controllers.auth

import javax.inject.Inject

import com.mohiva.play.silhouette.api._
import com.mohiva.play.silhouette.impl.providers.CredentialsProvider
import controllers.{ WebJarAssets, auth }
import forms.auth.ForgotPasswordForm
import models.services.{ AuthTokenService, UserService }
import play.api.i18n.{ I18nSupport, Messages, MessagesApi }
import play.api.libs.concurrent.Execution.Implicits._
import play.api.libs.mailer.{ Email, MailerClient }
import play.api.mvc.{ Action, AnyContent, Controller }
import utils.auth.DefaultEnv

import scala.concurrent.Future


  def submit: Action[AnyContent] = silhouette.UnsecuredAction.async { implicit request =>
    ForgotPasswordForm.form.bindFromRequest.fold(
      form => Future.successful(BadRequest(views.html.auth.forgotPassword(form))),
      email => {
        val loginInfo = LoginInfo(CredentialsProvider.ID, email)
        val result = Redirect(auth.routes.SignInController.view()).flashing("info" -> Messages("reset.email.sent"))
        userService.retrieve(loginInfo).flatMap {
          case Some(user) if user.email.isDefined =>
            authTokenService.create(user.userID).map { authToken =>
              val url = auth.routes.ResetPasswordController.view(authToken.id).absoluteURL()

              mailerClient.send(Email(
                subject = Messages("email.reset.password.subject"),
                from = Messages("email.from"),
                to = Seq(email),
                bodyText = Some(views.txt.emails.resetPassword(user, url).body),
                bodyHtml = Some(views.html.emails.resetPassword(user, url).body)
              ))
              result
            }
          case None => Future.successful(result)
        }
      }
    )
  }
} 
Example 12
Source File: AppDatabase.scala    From phantom-activator-template   with Apache License 2.0 5 votes vote down vote up
package models

import javax.inject.{Inject, Singleton}

import com.outworkers.phantom.builder.query.CreateQuery
import com.outworkers.phantom.dsl._

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

@Singleton
class AppDatabase @Inject()(
  env: play.api.Environment,
  override val connector: CassandraConnection
) extends Database[AppDatabase](connector) {


  object beers extends Beers with Connector {
    override def autocreate(space: KeySpace): CreateQuery.Default[Beers, Beer] = {
      create.ifNotExists()(space)
        .option(default_time_to_live eqs 10)
        .and(gc_grace_seconds eqs 10.seconds)
        .and(read_repair_chance eqs 0.2)
    }
  }

  def initialize(): Future[List[ResultSet]] = {
    val beerList = List(
      Beer(company = "budhizer", style = "white", name = "Summer Bud"),
      Beer(company = "budhizer", style = "dark", name = "Winter Bud"),
      Beer(company = "budhizer", style = "wheat", name = "Spring Bud"),
      Beer(company = "budhizer", style = "pumpkin", name = "Fall Bud")
    )

    for {
      init <- beers.autocreate(space).future()

      // https://github.com/outworkers/phantom/blob/develop/docs/basics/tables.md#automatically-derived-store-method
      records <- beers.storeRecords(beerList)
    } yield records
  }

  // Runs in constructor when the application is started.  Because this is @Singleton,
  // it runs only once, only one instance of this class is created.
  env.mode match {
    case play.api.Mode.Test => initialize()
    case other@_ => Seq.empty
  }
} 
Example 13
Source File: HomeController.scala    From phantom-activator-template   with Apache License 2.0 5 votes vote down vote up
package controllers

import javax.inject.Inject

import models._
import play.api.mvc._

import scala.concurrent.ExecutionContext

class HomeController @Inject()(repo: BeersRepository, cc: ControllerComponents)(implicit ec: ExecutionContext) extends AbstractController(cc) {

  def index(style: Option[String]): Action[AnyContent] = Action.async {
    style match {
      case Some(s) =>
        repo.getByStyle(s).map { beers =>
          Ok(views.html.index(beers))
        }

      case None =>
        repo.all.map { beers =>
          Ok(views.html.index(beers))
        }
    }
  }
} 
Example 14
Source File: Module.scala    From phantom-activator-template   with Apache License 2.0 5 votes vote down vote up
import javax.inject.{Inject, Provider, Singleton}

import com.google.inject.AbstractModule
import com.outworkers.phantom.connectors.{CassandraConnection, ContactPoint}
import models.AppDatabase
import net.codingwell.scalaguice.ScalaModule

class Module extends AbstractModule  with ScalaModule {
  override def configure(): Unit = {
    bind[CassandraConnection].toProvider[ConnectionProvider]
    bind[AppDatabase].asEagerSingleton()
  }
}

@Singleton
class ConnectionProvider @Inject()(env: play.api.Environment) extends Provider[CassandraConnection] {
  lazy val get: CassandraConnection = {
    val builder = env.mode match {
      case play.api.Mode.Test => ContactPoint.embedded
      case _ => ContactPoint.local
    }
    builder.keySpace("outworkers")
  }
} 
Example 15
Source File: ClientsModule.scala    From daf-semantics   with Apache License 2.0 5 votes vote down vote up
package modules

import com.google.inject.ImplementedBy
import play.api.inject.ApplicationLifecycle
import javax.inject.Singleton
import javax.inject.Inject
import play.api.libs.ws.WSClient
import play.api.Application
import play.api.Environment
import play.api.Configuration
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
import play.Logger
import clients.OntonetHubClient
import com.typesafe.config.ConfigFactory
import com.typesafe.config.ConfigRenderOptions

@ImplementedBy(classOf[ClientsModuleBase])
trait ClientsModule

@Singleton
class ClientsModuleBase @Inject() (lifecycle: ApplicationLifecycle,
                                   ws: WSClient,
                                   configuration: Configuration) extends ClientsModule {

  val conf_clients = configuration.underlying
    .getConfig("clients")

  val ontonethub_config = conf_clients.getConfig("ontonethub")

  // TODO: verify if default configurations are needed here
  val ontonethub = new OntonetHubClient(ws, ontonethub_config)

  // TESTING ................................................
  val options = ConfigRenderOptions.concise()
    .setComments(false).setOriginComments(false)
    .setFormatted(true).setJson(true)
  val json = ontonethub_config.root().render(options)
  // TESTING ................................................

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

    Logger.info("ClientsModuleBase START")

    println("\n\n\n\n\n\n")
    println(json)

  }

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

    Future.successful {

      Logger.info("ClientsModuleBase STOP")

    }

  })

} 
Example 16
Source File: Global.scala    From daf-semantics   with Apache License 2.0 5 votes vote down vote up
import play._

import javax.inject.Inject
import com.google.inject.{ AbstractModule, Singleton }
import play.api.inject.ApplicationLifecycle
import scala.concurrent.Future
import modules.ClientsModule
import modules.ClientsModuleBase

@Singleton
class Global @Inject() (lifecycle: ApplicationLifecycle) {

  @Inject
  def onStart() {
    Logger.info("#### Application START")
  }

  // REVIEW here
  lifecycle.addStopHook { () =>
    Future.successful({
      Logger.info("#### Application STOP")
    })
  }

  // TODO: plug a servicefactory for repository

}

@Singleton
class StartModule extends AbstractModule {

  def configure() = {

    bind(classOf[ClientsModule]).to(classOf[ClientsModuleBase]).asEagerSingleton()
  }

} 
Example 17
Source File: Global.scala    From daf-semantics   with Apache License 2.0 5 votes vote down vote up
import play._

import javax.inject.Inject
import com.google.inject.{ AbstractModule, Singleton }
import play.api.inject.ApplicationLifecycle
import scala.concurrent.Future
import modules._

@Singleton
class Global @Inject() (lifecycle: ApplicationLifecycle) {

  @Inject
  def onStart() {
    Logger.info("#### Application START")
  }

  // REVIEW here
  lifecycle.addStopHook { () =>
    Future.successful({
      Logger.info("#### Application STOP")
    })
  }

  // TODO: plug a servicefactory for repository

}

@Singleton
class StartModule extends AbstractModule {

  def configure() = {
    bind(classOf[KBModule]).to(classOf[KBModuleBase]).asEagerSingleton()
  }

} 
Example 18
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 19
Source File: CustomLanguageController.scala    From nisp-frontend   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.nisp.controllers

import javax.inject.Inject
import play.api.{Application, Configuration}
import play.api.i18n.{Lang, MessagesApi}
import play.api.mvc.Call
import uk.gov.hmrc.play.language.{LanguageController, LanguageUtils}

class CustomLanguageController @Inject()(implicit override val messagesApi: MessagesApi,
                                         application: Application,
                                         languageUtils: LanguageUtils,
                                         configuration: Configuration
                                        ) extends LanguageController(configuration, languageUtils) {

  def routeToSwitchLanguage = (lang: String) => routes.CustomLanguageController.switchToLanguage(lang)

  
  override def languageMap: Map[String, Lang] = Map(
    "english" -> Lang("en"),
    "cymraeg" -> Lang("cy")
  )
} 
Example 20
Source File: TimeSpec.scala    From nisp-frontend   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.nisp.views.formatting

import javax.inject.Inject

import org.scalatestplus.play.OneAppPerSuite
import uk.gov.hmrc.play.test.UnitSpec
import play.api.Play.current
import play.api.i18n.Messages.Implicits._
import play.api.i18n.{I18nSupport, Lang, Messages, MessagesApi}

class TimeSpec extends UnitSpec with OneAppPerSuite {
  val messagesApi = app.injector.instanceOf[MessagesApi]
  implicit val messages = new Messages(new Lang("en"), messagesApi)

  "years" should {
    "return 1 year when there is 1 year"  in {
      Time.years(1)(messages) shouldBe "1 year"
    }
    "return 5 years when there is 5 years" in {
      Time.years(5)(messages) shouldBe "5 years"
    }
    "return 0 years when there is 0 years" in {
      Time.years(0)(messages) shouldBe "0 years"
    }
    "return -1 year when there is -1 year" in {
      Time.years(-1)(messages) shouldBe "-1 year"
    }

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


private class AppConfig @Inject()(playConfig: Configuration) {
  val userIdHeader: Option[String] = playConfig.getString("app.userid.header")
  val ckanHost: Option[String] = playConfig.getString("app.ckan.url")
  val dbHost: Option[String] = playConfig.getString("mongo.host")
  val dbPort: Option[Int] = playConfig.getInt("mongo.port")
  val userName :Option[String] = playConfig.getString("mongo.username")
  val password :Option[String] = playConfig.getString("mongo.password")
  val database :Option[String] = playConfig.getString("mongo.database")
  val localUrl :Option[String] = playConfig.getString("app.local.url")
  val securityManHost :Option[String] = playConfig.getString("security.manager.host")
  val cookieExpiration :Option[Long] = playConfig.getLong("cookie.expiration")
  val ingestionUrl :Option[String] = playConfig.getString("ingestion.url")
  val kyloUrl: Option[String] = playConfig.getString("kylo.url")
  val kyloUser: Option[String] = playConfig.getString("kylo.user")
  val kyloPwd: Option[String] = playConfig.getString("kylo.pwd")
  val kafkaProxyUrl: Option[String] = playConfig.getString("kafkaProxy.url")

}



object ConfigReader {

  private val config = new AppConfig(Configuration.load(Environment.simple()))

  require(config.kyloUrl.nonEmpty, "A kylo url must be specified")
  require(config.kyloUser.nonEmpty, "A kylo user must be specified")
  require(config.kyloPwd.nonEmpty, "A kylo password must be specified")

  def userIdHeader: String = config.userIdHeader.getOrElse("userid")
  def getCkanHost: String = config.ckanHost.getOrElse("localhost")
  def getDbHost: String = config.dbHost.getOrElse("localhost")
  def getDbPort: Int = config.dbPort.getOrElse(27017)
  def database :String = config.database.getOrElse("catalog_manager")
  def password :String = config.password.getOrElse("")
  def userName :String = config.userName.getOrElse("")
  def localUrl :String = config.localUrl.getOrElse("http://localhost:9001")
  def securityManHost :String = config.securityManHost.getOrElse("http://localhost:9002/security-manager")
  def cookieExpiration:Long = config.cookieExpiration.getOrElse(30L)// 30 min by default
  def ingestionUrl :String = config.ingestionUrl.getOrElse("http://localhost:9003")
  def kyloUrl: String = config.kyloUrl.get
  def kyloUser: String = config.kyloUser.get
  def kyloPwd: String = config.kyloPwd.get
  def kafkaProxyUrl: String = config.kafkaProxyUrl.getOrElse("")

} 
Example 22
Source File: SecurityFilter.scala    From daf   with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
package it.gov.daf.common.filters.authentication

import javax.inject.{Inject, Singleton}

import akka.stream.Materializer
import org.pac4j.core.config.Config
import org.pac4j.play.store.PlaySessionStore
import play.api.Configuration
import play.api.mvc._
import play.libs.concurrent.HttpExecutionContext

import scala.concurrent.Future

@SuppressWarnings(
  Array(
    "org.wartremover.warts.Overloading"
  )
)
@Singleton
class SecurityFilter @Inject()(mat: Materializer, configuration: Configuration, playSessionStore: PlaySessionStore, config: Config, ec: HttpExecutionContext) extends org.pac4j.play.filters.SecurityFilter(mat, configuration, playSessionStore, config, ec) {

  override def apply(nextFilter: (RequestHeader) => Future[play.api.mvc.Result])
                    (request: RequestHeader): Future[play.api.mvc.Result] = {
    super.apply(nextFilter)(request)
  }
} 
Example 23
Source File: CoreOnlySample.scala    From play-parseq   with Apache License 2.0 5 votes vote down vote up
package controllers.s

import com.linkedin.playparseq.s.PlayParSeq
import javax.inject.Inject
import play.api.mvc._
import scala.concurrent.{ExecutionContext, Future}



  def demo(text: String, start: Int): Action[AnyContent] = Action.async(implicit request => {
    // Run the Task
    playParSeq.runTask(
      // Convert to ParSeq Task
      playParSeq.toTask(
        "substring",
        () => Future(text.substring(start))
          // Recover
          .recover { case _ => DefaultFailure }
          .map(Ok(_))))
  })

} 
Example 24
Source File: SingleTaskSample.scala    From play-parseq   with Apache License 2.0 5 votes vote down vote up
package controllers.s

import com.linkedin.parseq.Task
import com.linkedin.playparseq.s.PlayParSeq
import com.linkedin.playparseq.s.PlayParSeqImplicits._
import com.linkedin.playparseq.trace.s.ParSeqTraceAction
import javax.inject.Inject
import play.api.mvc._
import scala.concurrent.{ExecutionContext, Future}



  def demo: Action[AnyContent] = parSeqTraceAction.async(implicit request => {
    // Run the Task
    playParSeq.runTask(
      // In parallel
      Task.par(
        // Convert to ParSeq Task
        playParSeq.toTask("hello", () => Future("Hello".substring(0))),
        // Simple ParSeq Task
        Task.value("world", "World")
      ).map("concatenate", (h: String, w: String) => Ok(h + " " + w)))
  })

} 
Example 25
Source File: ParSeqTraceRenderer.scala    From play-parseq   with Apache License 2.0 5 votes vote down vote up
package com.linkedin.playparseq.trace.s.renderers

import com.linkedin.parseq.trace.{ShallowTrace, Trace, TraceRelationship}
import com.linkedin.playparseq.s.stores.ParSeqTaskStore
import com.linkedin.playparseq.trace.utils.ParSeqTraceBaseVisualizer
import javax.inject.{Inject, Singleton}
import play.api.Environment
import play.api.http.HttpConfiguration
import play.api.mvc.{RequestHeader, Result, Results}
import scala.collection.JavaConverters._
import scala.concurrent.{ExecutionContext, Future}



  override def render(parSeqTaskStore: ParSeqTaskStore)(implicit requestHeader: RequestHeader): Future[Result] =
    Future {
      val traces: Set[Trace] = parSeqTaskStore.get.map(_.getTrace)
      val traceMap: Map[java.lang.Long, ShallowTrace] = traces.foldLeft(Map[java.lang.Long, ShallowTrace]())(_ ++ _.getTraceMap.asScala)
      val relationships: Set[TraceRelationship] = traces.foldLeft(Set[TraceRelationship]())(_ ++ _.getRelationships.asScala)
      // Generate Result of ParSeq Trace
      Option(showTrace(new Trace(traceMap.asJava, relationships.asJava), environment, httpConfiguration)).map(Results.Ok(_).as("text/html"))
        .getOrElse(Results.InternalServerError("Can't show Trace."))
    }

} 
Example 26
Source File: PlayParSeq.scala    From play-parseq   with Apache License 2.0 5 votes vote down vote up
package com.linkedin.playparseq.s

import com.linkedin.parseq.{Engine, Task}
import com.linkedin.parseq.promise.Promises
import com.linkedin.playparseq.s.PlayParSeqImplicits._
import com.linkedin.playparseq.s.stores.ParSeqTaskStore
import com.linkedin.playparseq.utils.PlayParSeqHelper
import javax.inject.{Inject, Singleton}
import play.api.mvc.RequestHeader
import scala.concurrent.{ExecutionContext, Future}
import scala.util.{Failure, Success}



  override def runTask[T](task: Task[T])(implicit requestHeader: RequestHeader): Future[T] = {
    // Bind a Future to the ParSeq Task
    val future: Future[T] = bindTaskToFuture(task)
    // Put the ParSeq Task into store
    parSeqTaskStore.put(task)
    // Run the ParSeq Task
    engine.run(task)
    // Return the Future
    future
  }

} 
Example 27
Source File: ErrorHandler.scala    From play-table-of-contents   with MIT License 5 votes vote down vote up
import javax.inject.{Inject, Provider, Singleton}

import play.api._
import play.api.http.DefaultHttpErrorHandler
import play.api.mvc.Results._
import play.api.mvc._
import play.api.routing.Router

import scala.concurrent._


@Singleton
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("A server error occurred: " + exception.getMessage)
    )
  }

  override def onForbidden(request: RequestHeader, message: String) = {
    Future.successful(
      Forbidden("You're not allowed to access this resource.")
    )
  }
} 
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: FeatureToggleModel.scala    From smui   with Apache License 2.0 5 votes vote down vote up
package models

import javax.inject.Inject
import play.api.Configuration
import play.twirl.api.utils.StringEscapeUtils

package object FeatureToggleModel {

  trait JsFeatureToggleValue {
    def render(): String
  }

  class JsBoolFeatureToggleValue(bState: Boolean) extends JsFeatureToggleValue {
    override def render(): String = {
      bState.toString
    }
  }

  class JsStringFeatureToggleValue(value: String) extends JsFeatureToggleValue {
    override def render(): String = s""""${StringEscapeUtils.escapeEcmaScript(value)}""""
  }

  case class JsFeatureToggle(toggleName: String, toggleValue: JsFeatureToggleValue)

  @javax.inject.Singleton
  class FeatureToggleService @Inject()(appConfig: Configuration) {

    private val FEATURE_TOGGLE_UI_CONCEPT_UPDOWN_RULES_COMBINED = "toggle.ui-concept.updown-rules.combined"
    private val FEATURE_TOGGLE_UI_CONCEPT_ALL_RULES_WITH_SOLR_FIELDS = "toggle.ui-concept.all-rules.with-solr-fields"
    private val FEATURE_TOGGLE_RULE_DEPLOYMENT_LOG_RULE_ID = "toggle.rule-deployment.log-rule-id"
    private val FEATURE_TOGGLE_RULE_DEPLOYMENT_SPLIT_DECOMPOUND_RULES_TXT = "toggle.rule-deployment.split-decompound-rules-txt"
    private val FEATURE_TOGGLE_RULE_DEPLOYMENT_SPLIT_DECOMPOUND_RULES_TXT_DST_CP_FILE_TO = "toggle.rule-deployment.split-decompound-rules-txt-DST_CP_FILE_TO"
    private val FEATURE_TOGGLE_RULE_DEPLOYMENT_PRE_LIVE_PRESENT = "toggle.rule-deployment.pre-live.present"
    private val FEATURE_TOGGLE_RULE_DEPLOYMENT_CUSTOM_SCRIPT = "toggle.rule-deployment.custom-script"
    private val FEATURE_TOGGLE_RULE_DEPLOYMENT_CUSTOM_SCRIPT_SMUI2SOLR_SH_PATH = "toggle.rule-deployment.custom-script-SMUI2SOLR-SH_PATH"
    private val FEATURE_TOGGLE_HEADLINE = "toggle.headline"
    private val ACTIVATE_RULE_TAGGING = "toggle.rule-tagging"
    private val PREDEFINED_TAGS_FILE = "toggle.predefined-tags-file"
    private val SMUI_AUTH_SIMPLE_LOGOUT = "smui.auth.ui-concept.simple-logout-button-target-url"
    private val SMUI_VERSION = "smui.version"

    def getJsFrontendToogleList: List[JsFeatureToggle] = {
      def jsBoolFeatureToggle(toggleKey: String, bDefault: Boolean): JsFeatureToggle = {
        JsFeatureToggle(
          toggleKey,
          new JsBoolFeatureToggleValue(appConfig.getOptional[Boolean](toggleKey).getOrElse(bDefault))
        )
      }
      List(
        jsBoolFeatureToggle(FEATURE_TOGGLE_UI_CONCEPT_UPDOWN_RULES_COMBINED, true),
        jsBoolFeatureToggle(FEATURE_TOGGLE_UI_CONCEPT_ALL_RULES_WITH_SOLR_FIELDS, true),
        jsBoolFeatureToggle(FEATURE_TOGGLE_RULE_DEPLOYMENT_PRE_LIVE_PRESENT, false),
        jsBoolFeatureToggle(ACTIVATE_RULE_TAGGING, false),
        JsFeatureToggle(FEATURE_TOGGLE_HEADLINE, new JsStringFeatureToggleValue(
          appConfig.getOptional[String](FEATURE_TOGGLE_HEADLINE).getOrElse("Search Management UI"))),
        JsFeatureToggle(SMUI_AUTH_SIMPLE_LOGOUT, new JsStringFeatureToggleValue(
          appConfig.getOptional[String](SMUI_AUTH_SIMPLE_LOGOUT).getOrElse(""))),
        JsFeatureToggle(SMUI_VERSION, new JsStringFeatureToggleValue(models.buildInfo.BuildInfo.version))
      )
    }

    def getToggleRuleDeploymentLogRuleId: Boolean = {
      appConfig.getOptional[Boolean](FEATURE_TOGGLE_RULE_DEPLOYMENT_LOG_RULE_ID).getOrElse(false)
    }

    def getToggleRuleDeploymentSplitDecompoundRulesTxt: Boolean = {
      appConfig.getOptional[Boolean](FEATURE_TOGGLE_RULE_DEPLOYMENT_SPLIT_DECOMPOUND_RULES_TXT).getOrElse(false)
    }

    def getToggleRuleDeploymentSplitDecompoundRulesTxtDstCpFileTo: String = {
      appConfig.getOptional[String](FEATURE_TOGGLE_RULE_DEPLOYMENT_SPLIT_DECOMPOUND_RULES_TXT_DST_CP_FILE_TO).getOrElse("")
    }

    def getToggleRuleDeploymentCustomScript: Boolean = {
      appConfig.getOptional[Boolean](FEATURE_TOGGLE_RULE_DEPLOYMENT_CUSTOM_SCRIPT).getOrElse(false)
    }

    def getToggleRuleDeploymentCustomScriptSmui2solrShPath: String = {
      appConfig.getOptional[String](FEATURE_TOGGLE_RULE_DEPLOYMENT_CUSTOM_SCRIPT_SMUI2SOLR_SH_PATH).getOrElse("")
    }

    def isRuleTaggingActive: Boolean = {
      appConfig.get[Boolean](ACTIVATE_RULE_TAGGING)
    }

    def predefinedTagsFileName: Option[String] = {
      appConfig.getOptional[String](PREDEFINED_TAGS_FILE).filter(_.nonEmpty)
    }
  }

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

import java.io.FileInputStream
import java.time.LocalDateTime
import java.util.UUID
import java.util.Date

import anorm.SqlParser.get
import javax.inject.Inject
import anorm._
import models.FeatureToggleModel.FeatureToggleService
import models.SearchInput.ID
import play.api.db.DBApi

@javax.inject.Singleton
class SearchManagementRepository @Inject()(dbapi: DBApi, toggleService: FeatureToggleService)(implicit ec: DatabaseExecutionContext) {

  private val db = dbapi.database("default")

  // On startup, always sync predefined tags with the DB
  syncPredefinedTagsWithDB()

  private def syncPredefinedTagsWithDB(): Unit = {
    db.withTransaction { implicit connection =>
      if (toggleService.isRuleTaggingActive) {
        for (fileName <- toggleService.predefinedTagsFileName) {
          val tags = PredefinedTag.fromStream(new FileInputStream(fileName))
          PredefinedTag.updateInDB(tags)
        }
      }
    }
  }

  
  def addNewSearchInput(solrIndexId: SolrIndexId, searchInputTerm: String, tags: Seq[InputTagId]): SearchInputId = db.withConnection { implicit connection =>
    val id = SearchInput.insert(solrIndexId, searchInputTerm).id
    if (tags.nonEmpty) {
      TagInputAssociation.updateTagsForSearchInput(id, tags)
    }
    id
  }

  def getDetailedSearchInput(searchInputId: SearchInputId): Option[SearchInputWithRules] = db.withConnection { implicit connection =>
    SearchInputWithRules.loadById(searchInputId)
  }

  def updateSearchInput(searchInput: SearchInputWithRules): Unit = db.withTransaction { implicit connection =>
    SearchInputWithRules.update(searchInput)
  }

  def deleteSearchInput(searchInputId: String): Int = db.withTransaction { implicit connection =>
    SearchInputWithRules.delete(SearchInputId(searchInputId))
  }

  def listAllSuggestedSolrFields(solrIndexId: String): List[SuggestedSolrField] = db.withConnection { implicit connection =>
    SuggestedSolrField.listAll(SolrIndexId(solrIndexId))
  }

  def addNewSuggestedSolrField(solrIndexId: SolrIndexId, suggestedSolrFieldName: String): SuggestedSolrField = db.withConnection { implicit connection =>
    SuggestedSolrField.insert(solrIndexId, suggestedSolrFieldName)
  }

  def addNewDeploymentLogOk(solrIndexId: String, targetPlatform: String): Boolean = db.withConnection { implicit connection =>
    SQL("insert into deployment_log(id, solr_index_id, target_platform, last_update, result) values ({id}, {solr_index_id}, {target_platform}, {last_update}, {result})")
      .on(
        'id -> UUID.randomUUID().toString,
        'solr_index_id -> solrIndexId,
        'target_platform -> targetPlatform,
        'last_update -> new Date(),
        'result -> 0
      )
      .execute()
  }

  case class DeploymentLogDetail(id: String, lastUpdate: LocalDateTime, result: Int)

  val sqlParserDeploymentLogDetail: RowParser[DeploymentLogDetail] = {
    get[String](s"deployment_log.id") ~
      get[LocalDateTime](s"deployment_log.last_update") ~
      get[Int](s"deployment_log.result") map { case id ~ lastUpdate ~ result =>
      DeploymentLogDetail(id, lastUpdate, result)
    }
  }

  def lastDeploymentLogDetail(solrIndexId: String, targetPlatform: String): Option[DeploymentLogDetail] = db.withConnection {
    implicit connection => {
      SQL"select * from deployment_log where solr_index_id = $solrIndexId and target_platform = $targetPlatform order by last_update desc".as(sqlParserDeploymentLogDetail.*).headOption
    }
  }

} 
Example 31
Source File: AuthActionFactory.scala    From smui   with Apache License 2.0 5 votes vote down vote up
package controllers.auth

import javax.inject.Inject
import play.api.{Configuration, Logging}
import play.api.mvc._

import scala.concurrent.ExecutionContext

class AuthActionFactory @Inject()(parser: BodyParsers.Default, appConfig: Configuration)(implicit ec: ExecutionContext) extends Logging {

  private def instantiateAuthAction(strClazz: String, defaultAction: ActionBuilder[Request, AnyContent]): ActionBuilder[Request, AnyContent] = {
    try {

      // TODO if possible instanciate authenticatedAction only once, not with every controller call

      def instantiate(clazz: java.lang.Class[_])(args: AnyRef*): AnyRef = {
        val constructor = clazz.getConstructors()(0)
        constructor.newInstance(args: _*).asInstanceOf[AnyRef]
      }

      val authenticatedAction = instantiate(
        java.lang.Class.forName(strClazz)
      )(parser, appConfig, ec)

      logger.debug(":: having instanciated " + authenticatedAction.toString)

      authenticatedAction.asInstanceOf[ActionBuilder[Request, AnyContent]]

    } catch {
      case e: Throwable =>
        // TODO consider stop serving requests, if an expection during bootstrap of authAction happened. DO NOT return the defaultAction.

        logger.error(":: Exception during instantiation of smui.authAction :: " + e.getMessage)
        logger.error(":: Authentication protection IS NOT ACTIVE!")
        defaultAction
    }
  }

  def getAuthenticatedAction(defaultAction: ActionBuilder[Request, AnyContent]): ActionBuilder[Request, AnyContent] = {
    appConfig.getOptional[String]("smui.authAction") match {
      case Some(strClazz: String) =>
        if (strClazz.trim().equals("scala.None")) defaultAction
        else instantiateAuthAction(strClazz, defaultAction)
      case None =>
        defaultAction
    }
  }

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

import javax.inject.Inject
import controllers.auth.AuthActionFactory
import play.api.{Configuration, Logging}
import play.api.mvc._

import scala.concurrent.{ExecutionContext, Future}
import models.FeatureToggleModel._

class HomeController @Inject()(cc: MessagesControllerComponents,
                               appConfig: Configuration,
                               featureToggleService: FeatureToggleService,
                               authActionFactory: AuthActionFactory)(implicit executionContext: ExecutionContext)
  extends MessagesAbstractController(cc) with Logging {

  def index(urlPath: String) = authActionFactory.getAuthenticatedAction(Action).async {
    Future {
      logger.debug("In HomeController :: index")
      Ok(
        views.html.home(
          featureToggleService.getJsFrontendToogleList
        )
      )
    }(executionContext) // TODO eval withSecurity ... because of play.filters.headers.contentSecurityPolicy (and resolve general setup in application.conf)
  }

  // TODO refactor authorizationTestControllerAction into a proper controller behaviour test
  

} 
Example 33
Source File: CacheManagerTokenStore.scala    From meteorite-core   with Apache License 2.0 5 votes vote down vote up
package bi.meteorite.core.security.tokenprovider

import com.hazelcast.core.HazelcastInstance
import org.ops4j.pax.cdi.api.OsgiService
import org.osgi.framework.BundleContext
import org.osgi.framework.wiring.BundleWiring
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import javax.annotation.PostConstruct
import javax.inject.{Named, Inject, Singleton}


@Singleton
@Named("CManager")
object CacheManagerTokenStore {
  private var logger: Logger = LoggerFactory.getLogger(classOf[CacheManagerTokenStore])
}

@Singleton class CacheManagerTokenStore extends TokenStorageProvider {
  @OsgiService
  @Inject private var cacheManager: HazelcastInstance = null
  @Inject private var bcontext: BundleContext = null

  @PostConstruct def init {
    CacheManagerTokenStore.logger.debug("*** Activating CacheManager")
    val c: CompositeClassLoader = new CompositeClassLoader
    val tccl: ClassLoader = Thread.currentThread.getContextClassLoader
    try {
      cacheManager.getConfig.setClassLoader(c)
    } finally {
      cacheManager.getConfig.setClassLoader(c)
    }
  }

  def addToken(token: Token) {
    addInvokerClassLoader(this.getClass.getClassLoader)
    cacheManager.getMap("tokens").put(token.getToken, token)
  }

  def updateToken(token: Token) {
  }

  def getToken(token: String): Token = {
    addInvokerClassLoader(getInvokerClassLoader)
    cacheManager.getMap("tokens").get(token).asInstanceOf[Token]
  }

  def hasToken(token: String): Boolean = {
    addInvokerClassLoader(getInvokerClassLoader)
    cacheManager.getMap("tokens").get(token) != null
  }

  def removeToken(token: Token) {
  }

  def setCacheManagerService(hazel: HazelcastInstance) {
    this.cacheManager = hazel
  }

  protected def addInvokerClassLoader(cl: ClassLoader) {
    getInstance.getConfig.getClassLoader.asInstanceOf[CompositeClassLoader].add(cl)
  }

  protected def getInvokerClassLoader: ClassLoader = {
    bcontext.getBundle.adapt(classOf[BundleWiring]).getClassLoader
  }

  def setBcontext(bcontext: BundleContext) {
    this.bcontext = bcontext
  }

  def getInstance: HazelcastInstance = {
    cacheManager
  }
} 
Example 34
Source File: SecurityFilter.scala    From meteorite-core   with Apache License 2.0 5 votes vote down vote up
package bi.meteorite.core.security

import javax.inject.{Inject, Named, Singleton}
import javax.servlet.http.{HttpServletRequest, HttpServletResponse}
import javax.servlet.{Filter, FilterChain, FilterConfig, ServletRequest, ServletResponse}

import bi.meteorite.core.api.security.AdminLoginService
import bi.meteorite.core.api.security.exceptions.TokenProviderException
import bi.meteorite.core.api.security.tokenprovider.TokenProvider
import org.ops4j.pax.cdi.api.OsgiService


@Singleton
@Named("securityFilter")
class SecurityFilter extends Filter {

  @Inject
  @OsgiService
  private var tokenProvider: TokenProvider = _

  @Inject
  @OsgiService
  private var adminLoginService: AdminLoginService = _

  override def doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) {
    val servletRequest = request.asInstanceOf[HttpServletRequest]
    val servletResponse = response.asInstanceOf[HttpServletResponse]
    var s = servletRequest.getPathInfo
    val s2 = servletRequest.getServletPath
    if (s != null && s2 != null) {
      s = s2 + s
    } else if (s == null) {
      s = s2
    }
    if (s.startsWith("/admin/ui/") || s == "/rest/core/auth/login") {
      chain.doFilter(request, response)
    } else if (servletRequest.getPathInfo.startsWith("/rest/core/admin")) {
      val token = tokenProvider.getTokenFromRequest(servletRequest)
      var isAdmin = false
      try {
        val userDetails = tokenProvider.verifyToken(token)

        if (adminLoginService.getUsername ==
          userDetails.get(TokenProvider.USERNAME).get) {
          isAdmin = true
        }
      } catch {
        case e: TokenProviderException =>
      }
      if (isAdmin) {
        chain.doFilter(request, response)
      } else {
        servletResponse.sendRedirect("/admin/ui/index.html")
      }
    } else {
      chain.doFilter(request, response)
    }
  }

  override def init(arg0: FilterConfig) {
  }

  override def destroy() {
  }

  def setTokenProvider(tokenProvider: TokenProvider) = this.tokenProvider = tokenProvider

  def setAdminLoginService(adminLoginService: AdminLoginService) = this.adminLoginService = adminLoginService
} 
Example 35
Source File: TokenAuthorizingFilter.scala    From meteorite-core   with Apache License 2.0 5 votes vote down vote up
package bi.meteorite.core.security.authorization

import javax.annotation.Priority
import javax.inject.{Inject, Named, Singleton}
import javax.ws.rs.Priorities
import javax.ws.rs.container.{ContainerRequestContext, ContainerRequestFilter}
import javax.ws.rs.core.Response

import org.apache.cxf.interceptor.security.AccessDeniedException
import org.apache.cxf.jaxrs.utils.JAXRSUtils


@Priority(Priorities.AUTHORIZATION)
@Singleton
@Named("authorizationFilter")
class TokenAuthorizingFilter extends ContainerRequestFilter {

  @Inject
  @Named("authorizationInterceptor")
  private var interceptor: TokenAuthorizingInterceptor = null

  def filter(context: ContainerRequestContext) = {
    try {
      interceptor.handleMessage(JAXRSUtils.getCurrentMessage)
    }
    catch {
      case _: AccessDeniedException => context.abortWith(Response.status(Response.Status.FORBIDDEN).build)
    }

  }

  def setInterceptor(in: TokenAuthorizingInterceptor) = interceptor = in
} 
Example 36
Source File: UserAuthenticationImpl.scala    From meteorite-core   with Apache License 2.0 5 votes vote down vote up
package bi.meteorite.core.security.rest

import javax.inject.{Inject, Singleton}
import javax.ws.rs.core.Response

import bi.meteorite.core.api.security.AdminLoginService
import bi.meteorite.core.api.security.rest.{UserAuthentication, UserService}
import org.ops4j.pax.cdi.api.{OsgiService, OsgiServiceProvider}


@OsgiServiceProvider(classes = Array(classOf[UserAuthentication]))
@Singleton class UserAuthenticationImpl extends UserAuthentication {

  @Inject
  @volatile
  @OsgiService
  private var adminLoginService: AdminLoginService = null

  override def logout(username: String) : Response = {
    if(adminLoginService.logout(username)){
      Response.ok().build()
    }
    else{
      Response.serverError().build()
    }
  }

  def setAdminLoginService(adminLoginService: AdminLoginService) = this.adminLoginService = adminLoginService
} 
Example 37
Source File: WSConfigParser.scala    From play-ws   with Apache License 2.0 5 votes vote down vote up
package play.api.libs.ws

import javax.inject.Inject
import javax.inject.Provider
import javax.inject.Singleton

import com.typesafe.config.Config
import com.typesafe.config.ConfigException
import com.typesafe.sslconfig.ssl.SSLConfigParser
import com.typesafe.sslconfig.util.EnrichedConfig

import scala.concurrent.duration.Duration


@Singleton
class WSConfigParser @Inject() (config: Config, classLoader: ClassLoader) extends Provider[WSClientConfig] {

  def parse(): WSClientConfig = {
    val wsConfig = config.getConfig("play.ws")

    val connectionTimeout = Duration(wsConfig.getString("timeout.connection"))
    val idleTimeout       = Duration(wsConfig.getString("timeout.idle"))
    val requestTimeout    = Duration(wsConfig.getString("timeout.request"))

    val followRedirects    = wsConfig.getBoolean("followRedirects")
    val useProxyProperties = wsConfig.getBoolean("useProxyProperties")

    val userAgent = {
      try {
        Some(wsConfig.getString("useragent"))
      } catch {
        case e: ConfigException.Null =>
          None
      }
    }

    val compressionEnabled = wsConfig.getBoolean("compressionEnabled")

    val sslConfig = new SSLConfigParser(EnrichedConfig(wsConfig.getConfig("ssl")), classLoader).parse()

    WSClientConfig(
      connectionTimeout = connectionTimeout,
      idleTimeout = idleTimeout,
      requestTimeout = requestTimeout,
      followRedirects = followRedirects,
      useProxyProperties = useProxyProperties,
      userAgent = userAgent,
      compressionEnabled = compressionEnabled,
      ssl = sslConfig
    )
  }

  override lazy val get: WSClientConfig = parse()
} 
Example 38
Source File: WebSocket.scala    From trucking-iot   with Apache License 2.0 5 votes vote down vote up
package controllers

import javax.inject.{Inject, Singleton}

import akka.actor.{Actor, ActorRef, ActorSystem, Props}
import akka.kafka.scaladsl.Consumer
import akka.kafka.{ConsumerSettings, Subscriptions}
import akka.stream.scaladsl.Sink
import akka.stream.{Materializer, ThrottleMode}
import com.typesafe.config.ConfigFactory
import org.apache.kafka.clients.consumer.ConsumerConfig
import org.apache.kafka.common.serialization.{ByteArrayDeserializer, StringDeserializer}
import play.api.libs.streams.ActorFlow
import play.api.mvc.{Controller, WebSocket}

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


//@Singleton
class KafkaWebSocket @Inject() (implicit system: ActorSystem, materializer: Materializer) extends Controller {

  def kafkaWS = WebSocket.accept[String, String] { request =>
    ActorFlow.actorRef(out => KafkaWSActor.props(out))
  }

  object KafkaWSActor {
    def props(outRef: ActorRef) = Props(new KafkaWSActor(outRef))
  }

  class KafkaWSActor(outRef: ActorRef) extends Actor {

    val config = ConfigFactory.load()
    val combinedConfig = ConfigFactory.defaultOverrides()
      .withFallback(config)
      .withFallback(ConfigFactory.defaultApplication())
      .getConfig("trucking-web-application.backend")

    val consumerSettings = ConsumerSettings(system, new ByteArrayDeserializer, new StringDeserializer)
      //.withBootstrapServers("sandbox-hdf.hortonworks.com:6667")
      .withBootstrapServers(combinedConfig.getString("kafka.bootstrap-servers"))
      .withGroupId("group1")
      .withProperty(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest")

    Consumer.committableSource(consumerSettings, Subscriptions.topics("trucking_data_joined"))
      .mapAsync(1) { msg => Future(outRef ! msg.record.value).map(_ => msg) }
      //.mapAsync(1) { msg => msg.committableOffset.commitScaladsl() } // TODO: Disabling commits for debug
      .throttle(1, 250.milliseconds, 1, ThrottleMode.Shaping)
      .runWith(Sink.ignore)

    def receive = {
      case msg: String => outRef ! s"Ack: $msg"
    }
  }

} 
Example 39
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 40
Source File: ViewReturnService.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 uk.gov.hmrc.http.HeaderCarrier
import utils.{EndpointLogContext, Logging}
import v1.connectors.ViewReturnConnector
import v1.models.errors._
import v1.models.request.viewReturn.ViewRequest
import v1.models.response.viewReturn.ViewReturnResponse
import v1.support.DesResponseMappingSupport

import scala.concurrent.{ExecutionContext, Future}

@Singleton
class ViewReturnService @Inject()(connector: ViewReturnConnector) extends DesResponseMappingSupport with Logging {

  def viewReturn(request: ViewRequest)(
    implicit hc: HeaderCarrier,
    ec: ExecutionContext,
    logContext: EndpointLogContext): Future[ServiceOutcome[ViewReturnResponse]] = {

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

    result.value
  }

  private def desErrorMap: Map[String, MtdError] =
    Map(
      "INVALID_VRN" -> VrnFormatErrorDes,
      "INVALID_PERIODKEY" -> PeriodKeyFormatErrorDes,
      "INVALID_IDENTIFIER" -> PeriodKeyFormatErrorDesNotFound,
      "NOT_FOUND_VRN" -> DownstreamError,
      "DATE_RANGE_TOO_LARGE" -> RuleDateRangeTooLargeError,
      "INVALID_INPUTDATA" -> InvalidInputDataError,
      "NOT_FOUND" -> EmptyNotFoundError,
      "SERVICE_ERROR" -> DownstreamError,
      "SERVICE_UNAVAILABLE" -> DownstreamError
    )
} 
Example 41
Source File: SubmitReturnService.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 uk.gov.hmrc.http.HeaderCarrier
import utils.{EndpointLogContext, Logging}
import v1.connectors.SubmitReturnConnector
import v1.models.errors._
import v1.models.request.submit.SubmitRequest
import v1.models.response.submit.SubmitResponse
import v1.support.DesResponseMappingSupport

import scala.concurrent.{ExecutionContext, Future}

@Singleton
class SubmitReturnService @Inject()(connector: SubmitReturnConnector) extends DesResponseMappingSupport with Logging {

  def submitReturn(request: SubmitRequest)(
    implicit hc: HeaderCarrier,
    ec: ExecutionContext,
    logContext: EndpointLogContext): Future[ServiceOutcome[SubmitResponse]] = {

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

    result.value
  }

  private def desErrorMap: Map[String, MtdError] =
    Map(
      "INVALID_VRN" -> VrnFormatErrorDes,
      "INVALID_PERIODKEY" -> PeriodKeyFormatErrorDes,
      "INVALID_PAYLOAD" -> BadRequestError,
      "TAX_PERIOD_NOT_ENDED" -> TaxPeriodNotEnded,
      "DUPLICATE_SUBMISSION" -> DuplicateVatSubmission,
      "NOT_FOUND_VRN" -> DownstreamError,
      "INVALID_SUBMISSION" -> DownstreamError,
      "INVALID_ORIGINATOR_ID" -> DownstreamError,
      "SERVICE_ERROR" -> DownstreamError,
      "SERVICE_UNAVAILABLE" -> DownstreamError
    )
} 
Example 42
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 43
Source File: NrsService.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package v1.services

import java.nio.charset.StandardCharsets
import java.util.Base64

import cats.data.EitherT
import cats.implicits._
import javax.inject.Inject
import org.joda.time.DateTime
import play.api.libs.json.Json
import uk.gov.hmrc.http.HeaderCarrier
import v1.connectors.NrsConnector
import v1.controllers.UserRequest
import v1.models.errors.{DownstreamError, ErrorWrapper}
import v1.models.nrs.request.{Metadata, NrsSubmission, SearchKeys}
import v1.models.nrs.response.NrsResponse
import v1.models.request.submit.SubmitRequest

import scala.concurrent.{ExecutionContext, Future}

class NrsService @Inject()(connector: NrsConnector) {

  def submitNrs(vatSubmission: SubmitRequest, submissionTimestamp: DateTime)(
    implicit request: UserRequest[_],
    hc: HeaderCarrier,
    ec: ExecutionContext): Future[Either[ErrorWrapper, NrsResponse]] = {

    val result = for {
      nrsResponse <- EitherT(connector.submitNrs(buildNrsSubmission(vatSubmission, submissionTimestamp, request)))
        .leftMap(_ => ErrorWrapper(None, DownstreamError, None))
    } yield nrsResponse

    result.value
  }

  def buildNrsSubmission(vatSubmission: SubmitRequest, submissionTimestamp: DateTime, request: UserRequest[_]): NrsSubmission = {

    import vatSubmission._

    val payloadString: String =
      Base64.getEncoder.encodeToString(
        Json.toJson(body)
          .toString()
          .getBytes(StandardCharsets.UTF_8)
      )

    NrsSubmission(
      payload = payloadString,
      Metadata(
        businessId = "vat",
        notableEvent = "vat-return",
        payloadContentType = "application/json",
        payloadSha256Checksum = None,
        userSubmissionTimestamp = submissionTimestamp,
        identityData = request.userDetails.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.vrn),
            companyName = None,
            periodKey = body.periodKey,
            taxPeriodEndDate = None
          )
      )
    )
  }
} 
Example 44
Source File: LiabilitiesService.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 uk.gov.hmrc.http.HeaderCarrier
import utils.{EndpointLogContext, Logging}
import v1.connectors.LiabilitiesConnector
import v1.models.errors._
import v1.models.request.liabilities.LiabilitiesRequest
import v1.models.response.liabilities.LiabilitiesResponse
import v1.support.DesResponseMappingSupport

import scala.concurrent.{ExecutionContext, Future}

@Singleton
class LiabilitiesService @Inject()(connector: LiabilitiesConnector) extends DesResponseMappingSupport with Logging {

  def retrieveLiabilities(request: LiabilitiesRequest)(
    implicit hc: HeaderCarrier,
    ec: ExecutionContext,
    logContext: EndpointLogContext): Future[ServiceOutcome[LiabilitiesResponse]] = {

    val result = for {
      desResponseWrapper <- EitherT(connector.retrieveLiabilities(request)).leftMap(mapDesErrors(desErrorMap))
      mtdResponseWrapper <- EitherT.fromEither[Future](validateLiabilitiesSuccessResponse(desResponseWrapper))
    } yield mtdResponseWrapper

    result.value
  }

  private def desErrorMap: Map[String, MtdError] =
    Map(
      "INVALID_IDTYPE" -> DownstreamError,
      "INVALID_IDNUMBER" -> VrnFormatErrorDes,
      "INVALID_REGIMETYPE" -> DownstreamError,
      "INVALID_ONLYOPENITEMS" -> DownstreamError,
      "INVALID_INCLUDELOCKS" -> DownstreamError,
      "INVALID_CALCULATEACCRUEDINTEREST" -> DownstreamError,
      "INVALID_CUSTOMERPAYMENTINFORMATION" -> DownstreamError,
      "INVALID_DATEFROM" -> InvalidDateFromErrorDes,
      "INVALID_DATETO" -> InvalidDateToErrorDes,
      "NOT_FOUND" -> LegacyNotFoundError,
      "INVALID_DATA" -> InvalidDataError,
      "SERVER_ERROR" -> DownstreamError,
      "SERVICE_UNAVAILABLE" -> DownstreamError
    )
} 
Example 45
Source File: PaymentsService.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 uk.gov.hmrc.http.HeaderCarrier
import utils.{EndpointLogContext, Logging}
import v1.connectors.PaymentsConnector
import v1.models.errors._
import v1.models.request.payments.PaymentsRequest
import v1.models.response.payments.PaymentsResponse
import v1.support.DesResponseMappingSupport

import scala.concurrent.{ExecutionContext, Future}

@Singleton
class PaymentsService @Inject()(connector: PaymentsConnector) extends DesResponseMappingSupport with Logging {

  def retrievePayments(request: PaymentsRequest)(
    implicit hc: HeaderCarrier,
    ec: ExecutionContext,
    logContext: EndpointLogContext): Future[ServiceOutcome[PaymentsResponse]] = {

    val result = for {
      desResponseWrapper <- EitherT(connector.retrievePayments(request)).leftMap(mapDesErrors(desErrorMap))
      mtdResponseWrapper <- EitherT.fromEither[Future](validatePaymentsSuccessResponse(desResponseWrapper))
    } yield mtdResponseWrapper

    result.value
  }

  private def desErrorMap: Map[String, MtdError] =
    Map(
      "INVALID_IDTYPE" -> DownstreamError,
      "INVALID_IDNUMBER" -> VrnFormatErrorDes,
      "INVALID_REGIMETYPE" -> DownstreamError,
      "INVALID_ONLYOPENITEMS" -> DownstreamError,
      "INVALID_INCLUDELOCKS" -> DownstreamError,
      "INVALID_CALCULATEACCRUEDINTEREST" -> DownstreamError,
      "INVALID_CUSTOMERPAYMENTINFORMATION" -> DownstreamError,
      "INVALID_DATEFROM" -> InvalidDateFromErrorDes,
      "INVALID_DATETO" -> InvalidDateToErrorDes,
      "INVALID_DATA" -> InvalidDataError,
      "NOT_FOUND" -> LegacyNotFoundError,
      "SERVER_ERROR" -> DownstreamError,
      "SERVICE_UNAVAILABLE" -> DownstreamError
    )
} 
Example 46
Source File: PaymentsController.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package v1.controllers

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

import scala.concurrent.{ExecutionContext, Future}

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

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

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

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

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

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

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

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

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

        result
      }.merge

    }

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

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

import scala.concurrent.{ExecutionContext, Future}

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

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

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

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

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

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

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

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

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

        result
      }.merge

    }

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

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

import scala.concurrent.{ExecutionContext, Future}

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

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

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

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

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

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

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

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

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

        result
      }.merge

    }

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

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

import scala.concurrent.{ExecutionContext, Future}

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

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

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

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

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

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

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

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

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

        result
      }.merge

    }

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

import config.AppConfig
import javax.inject.{Inject, Singleton}
import uk.gov.hmrc.http.HeaderCarrier
import uk.gov.hmrc.play.bootstrap.http.HttpClient
import v1.models.errors.{ConnectorError, ControllerError}
import v1.models.request.liabilities.LiabilitiesRequest
import v1.models.response.liabilities.LiabilitiesResponse

import scala.concurrent.{ExecutionContext, Future}

@Singleton
class LiabilitiesConnector @Inject()(val http: HttpClient,
                                     val appConfig: AppConfig) extends BaseDesConnector {

  def retrieveLiabilities(request: LiabilitiesRequest)(implicit hc: HeaderCarrier,
                                                       ec: ExecutionContext): Future[DesOutcome[LiabilitiesResponse]] = {

    import v1.connectors.httpparsers.StandardDesHttpParser._
    implicit val requestToDate: String = request.to
    implicit val connectorError: ConnectorError =
      ConnectorError(request.vrn.vrn, hc.requestId.fold(""){ requestId => requestId.value})

    val queryParams: Seq[(String, String)] = Seq(
      ("dateFrom", request.from),
      ("dateTo", request.to),
      ("onlyOpenItems", "false"),
      ("includeLocks", "false"),
      ("calculateAccruedInterest", "true"),
      ("customerPaymentInformation", "true")
    )

    get(
      uri = DesUri[LiabilitiesResponse](s"enterprise/financial-data/VRN/${request.vrn.vrn}/VATC"),
      queryParams = queryParams
    )
  }
} 
Example 51
Source File: PaymentsConnector.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package v1.connectors

import config.AppConfig
import javax.inject.{Inject, Singleton}
import uk.gov.hmrc.http.HeaderCarrier
import uk.gov.hmrc.play.bootstrap.http.HttpClient
import v1.models.errors.ConnectorError
import v1.models.request.payments.PaymentsRequest
import v1.models.response.payments.PaymentsResponse

import scala.concurrent.{ExecutionContext, Future}

@Singleton
class PaymentsConnector @Inject()(val http: HttpClient,
                                  val appConfig: AppConfig) extends BaseDesConnector {

  def retrievePayments(request: PaymentsRequest)(implicit hc: HeaderCarrier,
                                                 ec: ExecutionContext): Future[DesOutcome[PaymentsResponse]] = {

    import v1.connectors.httpparsers.StandardDesHttpParser._
    implicit val requestToDate: String = request.to
    implicit val connectorError: ConnectorError =
      ConnectorError(request.vrn.vrn, hc.requestId.fold(""){ requestId => requestId.value})

    val queryParams: Seq[(String, String)] = Seq(
      ("dateFrom", request.from),
      ("dateTo", request.to),
      ("onlyOpenItems", "false"),
      ("includeLocks", "false"),
      ("calculateAccruedInterest", "true"),
      ("customerPaymentInformation", "true")
    )

    get(
      uri = DesUri[PaymentsResponse](s"enterprise/financial-data/VRN/${request.vrn.vrn}/VATC"),
      queryParams = queryParams
    )
  }
} 
Example 52
Source File: SubmitReturnConnector.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package v1.connectors

import config.AppConfig
import javax.inject.{Inject, Singleton}
import uk.gov.hmrc.http.HeaderCarrier
import uk.gov.hmrc.play.bootstrap.http.HttpClient
import v1.models.errors.ConnectorError
import v1.models.request.submit.SubmitRequest
import v1.models.response.submit.SubmitResponse

import scala.concurrent.{ExecutionContext, Future}

@Singleton
class SubmitReturnConnector @Inject()(val http: HttpClient,
                                      val appConfig: AppConfig) extends BaseDesConnector {

  def submitReturn(request: SubmitRequest)(
    implicit hc: HeaderCarrier,
    ec: ExecutionContext): Future[DesOutcome[SubmitResponse]] = {

    import v1.connectors.httpparsers.StandardDesHttpParser._

    val vrn = request.vrn.vrn
    implicit val connectorError: ConnectorError =
      ConnectorError(vrn, hc.requestId.fold(""){ requestId => requestId.value})

    post(
      body = request.body,
      uri = DesUri[SubmitResponse](s"enterprise/return/vat/$vrn")
    )
  }
} 
Example 53
Source File: ViewReturnConnector.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package v1.connectors

import config.AppConfig
import javax.inject.{Inject, Singleton}
import uk.gov.hmrc.http.HeaderCarrier
import uk.gov.hmrc.play.bootstrap.http.HttpClient
import v1.models.errors.ConnectorError
import v1.models.request.viewReturn.ViewRequest
import v1.models.response.viewReturn.ViewReturnResponse

import scala.concurrent.{ExecutionContext, Future}

@Singleton
class ViewReturnConnector @Inject()(val http: HttpClient,
                                    val appConfig: AppConfig) extends BaseDesConnector {

  def viewReturn(request: ViewRequest)(
    implicit hc: HeaderCarrier,
    ec: ExecutionContext): Future[DesOutcome[ViewReturnResponse]] = {

    import v1.connectors.httpparsers.StandardDesHttpParser._

    val vrn = request.vrn.vrn
    implicit val connectorError: ConnectorError =
      ConnectorError(vrn, hc.requestId.fold(""){ requestId => requestId.value})

    val queryParams: Seq[(String, String)] =
      Seq(
        "period-key" -> request.periodKey
      )

    get(
      uri = DesUri[ViewReturnResponse](s"vat/returns/vrn/$vrn"),
      queryParams = queryParams
    )
  }
} 
Example 54
Source File: ObligationsConnector.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package v1.connectors

import config.AppConfig
import javax.inject.{Inject, Singleton}
import uk.gov.hmrc.http.HeaderCarrier
import uk.gov.hmrc.play.bootstrap.http.HttpClient
import v1.models.errors.ConnectorError
import v1.models.request.obligations.ObligationsRequest
import v1.models.response.obligations.ObligationsResponse

import scala.concurrent.{ExecutionContext, Future}

@Singleton
class ObligationsConnector @Inject()(val http: HttpClient,
                                     val appConfig: AppConfig) extends BaseDesConnector {

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

    import v1.connectors.httpparsers.StandardDesHttpParser._

    val vrn = request.vrn.vrn

    implicit val connectorError: ConnectorError =
      ConnectorError(vrn, hc.requestId.fold(""){ requestId => requestId.value})

    val queryParams: Seq[(String, String)] =
      Seq(
        "from" -> request.from,
        "to" -> request.to,
        "status" -> request.status
      ) collect {
        case (key, Some(value)) => key -> value
      }

    get(
      uri = DesUri[ObligationsResponse](s"enterprise/obligation-data/vrn/$vrn/VATC"),
      queryParams = queryParams
    )
  }
} 
Example 55
Source File: NrsConnector.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package v1.connectors

import config.AppConfig
import javax.inject.{Inject, Singleton}
import play.api.libs.ws.WSClient
import uk.gov.hmrc.http.HeaderCarrier
import v1.models.nrs.request.NrsSubmission
import v1.models.nrs.response.NrsResponse

import scala.concurrent.{ExecutionContext, Future}

@Singleton
class NrsConnector @Inject()(val ws: WSClient,
                             val appConfig: AppConfig) extends BaseNrsConnector {

  def submitNrs(body: NrsSubmission)(
    implicit hc: HeaderCarrier,
    ec: ExecutionContext): Future[NrsOutcome[NrsResponse]] = {

    import v1.connectors.httpparsers.StandardNrsWsParser._

    nrsPost[NrsSubmission, NrsResponse](
      uri = NrsUri[NrsResponse](s"submission"),
      body = body,
      defaultResult = Right(NrsResponse.empty)
    )
  }
} 
Example 56
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 57
Source File: VersionRoutingRequestHandler.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package routing

import config.{AppConfig, FeatureSwitch}
import definition.Versions
import javax.inject.{Inject, Singleton}
import play.api.http.{DefaultHttpRequestHandler, HttpConfiguration, HttpErrorHandler, HttpFilters}
import play.api.libs.json.Json
import play.api.mvc.{DefaultActionBuilder, Handler, RequestHeader, Results}
import play.api.routing.Router
import v1.controllers.requestParsers.validators.validations.VrnValidation
import v1.models.errors.{InvalidAcceptHeaderError, UnsupportedVersionError, VrnFormatError}

@Singleton
class VersionRoutingRequestHandler @Inject()(versionRoutingMap: VersionRoutingMap,
                                             errorHandler: HttpErrorHandler,
                                             httpConfiguration: HttpConfiguration,
                                             config: AppConfig,
                                             filters: HttpFilters,
                                             action: DefaultActionBuilder)
  extends DefaultHttpRequestHandler(versionRoutingMap.defaultRouter, errorHandler, httpConfiguration, filters) {

  private val featureSwitch = FeatureSwitch(config.featureSwitch)

  private val unsupportedVersionAction = action(Results.NotFound(Json.toJson(UnsupportedVersionError)))

  private val invalidAcceptHeaderError = action(Results.NotAcceptable(Json.toJson(InvalidAcceptHeaderError)))

  override def routeRequest(request: RequestHeader): Option[Handler] = {

    def documentHandler = routeWith(versionRoutingMap.defaultRouter)(request)

    def apiHandler = Versions.getFromRequest(request) match {
      case Some(version) =>
        versionRoutingMap.versionRouter(version) match {
          case Some(versionRouter) if featureSwitch.isVersionEnabled(version) =>
            routeWith(versionRouter)(request)
          case Some(_) => Some(unsupportedVersionAction)
          case None => Some(unsupportedVersionAction)
        }
      case None => Some(invalidAcceptHeaderError)
    }

    documentHandler orElse apiHandler
  }

  private def routeWith(router: Router)(request: RequestHeader) =
    router
      .handlerFor(request)
      .orElse {
        if (validatePath(request.path)) {
          if (request.path.endsWith("/")) {
            val pathWithoutSlash = request.path.dropRight(1)
            val requestWithModifiedPath = request.withTarget(request.target.withPath(pathWithoutSlash))
            router.handlerFor(requestWithModifiedPath)
          }
          else None
        }
        else {
          Some(action(Results.BadRequest(Json.toJson(VrnFormatError))))
        }
      }

  private def validatePath(path: String) = {
    val vrn = path.split("/")(1)
    if(VrnValidation.validate(vrn) == Nil)
      true
    else false
  }
} 
Example 58
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 59
Source File: DocumentationController.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package config

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

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

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

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

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

import scala.concurrent.ExecutionContext

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

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

    val arn = getArn
    val clientId = getClientId

    implicit val endpoint: Endpoint = Endpoint.RetrieveObligations

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

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

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

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

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

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

  def raml(version: String, file: String): Action[AnyContent] = {
    assets.at(s"/public/api/conf/$version", file)
  }
} 
Example 65
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 66
Source File: AppContext.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.vatapi.config

import com.typesafe.config.ConfigFactory
import javax.inject.{Inject, Singleton}
import play.api.Application
import uk.gov.hmrc.play.bootstrap.config.ServicesConfig
import uk.gov.hmrc.vatapi.auth.VATAuthEnrolments

@Singleton
class AppContext @Inject()(config: ServicesConfig, application: Application) extends FixedConfig {


  //API Platform Config
  lazy val appName: String = config.getString("appName")
  lazy val appUrl: String = config.getString("appUrl")
  lazy val apiGatewayContext: String = config.getString("api.gateway.context")
  lazy val apiGatewayRegistrationContext: String = apiGatewayContext
  lazy val apiGatewayLinkContext: String = apiGatewayContext
  lazy val registrationEnabled: Boolean = application.configuration.getOptional[Boolean](s"microservice.services.service-locator.enabled").getOrElse(true)
  lazy val serviceLocatorUrl: String = config.baseUrl("service-locator")

  //DES Config
  lazy val desEnv: String = config.getString(s"microservice.services.des.env")
  lazy val desToken: String = config.getString(s"microservice.services.des.token")
  lazy val desUrl: String = config.baseUrl("des")
  //NRS Config
  lazy val nrsServiceUrl: String = config.baseUrl("non-repudiation")
  lazy val xApiKey: String = config.getString(s"access-keys.xApiKey")
  lazy val nrsMaxTimeoutMillis: Int = config.getInt(s"microservice.services.non-repudiation.maxTimeout")

  lazy val featureSwitch: String = config.getString(s"feature-switch")

  lazy val vatAuthEnrolments: VATAuthEnrolments = VATAuthEnrolments(config.getString(s"enrolments.key"),
    config.getString(s"enrolments.identifier"),
    config.getConfString(s"enrolments.authRule", "mtd-vat-auth"))

  def apiStatus(version: String): String = config.getString(s"api.$version.status")
}

trait FixedConfig {
  val mtdDate = ConfigFactory.load().getString("mtd-date")
} 
Example 67
Source File: ControllorConfiguration.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.vatapi.config

import com.typesafe.config.Config
import javax.inject.Inject
import net.ceedubs.ficus.Ficus._
import net.ceedubs.ficus.readers.ValueReader
import play.api.Configuration
import uk.gov.hmrc.play.bootstrap.config.ControllerConfig

case class ControllerConfigParams(needsHeaderValidation: Boolean = true,
                                  needsLogging: Boolean = true,
                                  needsAuditing: Boolean = true,
                                  needsTaxYear: Boolean = true)

class ControllerConfiguration @Inject()(configuration: Configuration) extends ControllerConfig {
  private implicit val controllerParamsReader: ValueReader[ControllerConfigParams] =
    ValueReader.relative[ControllerConfigParams] { config =>
      ControllerConfigParams(
        needsHeaderValidation =
          config.getAs[Boolean]("needsHeaderValidation").getOrElse(true),
        needsLogging = config.getAs[Boolean]("needsLogging").getOrElse(true),
        needsAuditing = config.getAs[Boolean]("needsAuditing").getOrElse(true),
        needsTaxYear = config.getAs[Boolean]("needsTaxYear").getOrElse(true)
      )
    }

  lazy val controllerConfigs: Config = configuration.underlying.as[Config]("controllers")

  def controllerParamsConfig(controllerName: String): ControllerConfigParams = {
    controllerConfigs
      .as[Option[ControllerConfigParams]](controllerName)
      .getOrElse(ControllerConfigParams())
  }
} 
Example 68
Source File: VatApiFilters.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.vatapi.filters

import javax.inject.Inject
import play.api.http.DefaultHttpFilters
import uk.gov.hmrc.play.bootstrap.filters._

case class VatApiFilters @Inject()(
                                    agentSimulationFilter: AgentSimulationFilter,
                                    emptyResponseFilter: EmptyResponseFilter,
                                    headerValidatorFilter: HeaderValidatorFilter,
                                    setContentTypeFilter: SetContentTypeFilter,
                                    setXContentTypeOptionsFilter: SetXContentTypeOptionsFilter,
                                    logging: LoggingFilter,
                                    defaultFilters: MicroserviceFilters
                                  ) extends DefaultHttpFilters(
  defaultFilters.filters :+
    agentSimulationFilter :+
    emptyResponseFilter :+
    headerValidatorFilter :+
    setContentTypeFilter :+
    logging :+
    setXContentTypeOptionsFilter: _*) 
Example 69
Source File: EmptyResponseFilter.scala    From vat-api   with Apache License 2.0 5 votes vote down vote up
package uk.gov.hmrc.vatapi.filters

import akka.stream.Materializer
import javax.inject.Inject
import play.api.http.HttpEntity
import play.api.mvc._

import scala.concurrent.{ExecutionContext, Future}

class EmptyResponseFilter @Inject()(implicit val mat: Materializer, ec: ExecutionContext) extends Filter {

  val emptyHeader = "Gov-Empty-Response"

  def apply(f: (RequestHeader) => Future[Result])(rh: RequestHeader): Future[Result] = {
    f(rh) map { res =>
      if ((res.header.status == 201 || res.header.status == 409) && res.body.isKnownEmpty) {
        val headers = res.header.headers
          .updated("Content-Type", "application/json")
          .updated(emptyHeader, "true")
        res.copy(res.header.copy(headers = headers), HttpEntity.NoEntity)
      } else res
    }
  }

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

import akka.stream.Materializer
import javax.inject.Inject
import play.api.libs.json.Json
import play.api.mvc._
import play.api.routing.Router.Attrs
import uk.gov.hmrc.api.controllers.{ErrorAcceptHeaderInvalid, HeaderValidator}
import uk.gov.hmrc.vatapi.config.ControllerConfiguration

import scala.concurrent.Future

class HeaderValidatorFilter @Inject()(implicit val mat: Materializer, controllerConfiguration: ControllerConfiguration,
                                      cc: MessagesControllerComponents
                                     ) extends Filter with HeaderValidator {

  protected def executionContext: scala.concurrent.ExecutionContext = cc.executionContext
  def parser: play.api.mvc.BodyParser[play.api.mvc.AnyContent] = cc.parsers.defaultBodyParser

  def apply(f: (RequestHeader) => Future[Result])(rh: RequestHeader): Future[Result] = {
    val handlerDef = rh.attrs.get(Attrs.HandlerDef)
    val needsHeaderValidation =
      handlerDef.forall(
        hd =>
          controllerConfiguration
            .controllerParamsConfig(hd.controller)
            .needsHeaderValidation)

    if (!needsHeaderValidation || acceptHeaderValidationRules(
      rh.headers.get("Accept"))) {
      f(rh)
    }
    else {
      Future.successful(
        Status(ErrorAcceptHeaderInvalid.httpStatusCode)(
          Json.toJson(ErrorAcceptHeaderInvalid)))
    }
  }

} 
Example 71
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 72
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 73
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 74
Source File: ViewHelpers.scala    From dr-cla   with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
package helpers

import java.net.URL

import javax.inject.Inject
import play.api.{Configuration, Environment}

import scala.io.Source
import scala.util.Try

class ViewHelpers @Inject()
(configuration: Configuration, environment: Environment) {
  val organizationName = configuration.get[String]("app.organization.name")
  val maybeOrganizationLogoUrl = configuration.getOptional[String]("app.organization.logo-url")
  val maybeOrganizationUrl = configuration.getOptional[String]("app.organization.url")
  val maybeOrganizationClaUrl = configuration.getOptional[String]("app.organization.cla-url")

  val claText: String = {
    maybeOrganizationClaUrl
      .flatMap(claUrl => Try(new URL(claUrl)).toOption)
      .orElse(environment.resource("sample-cla.html"))
      .map { claUrl =>
        val text = Source.fromURL(claUrl)
        text.mkString
      } getOrElse {
        throw new Exception("You must set the ORG_CLA environment variable.")
      }
  }
} 
Example 75
Source File: DatabaseModule.scala    From dr-cla   with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
package modules

import com.github.mauricio.async.db.SSLConfiguration
import com.github.mauricio.async.db.pool.{PartitionedConnectionPool, PoolConfiguration}
import com.github.mauricio.async.db.postgresql.pool.PostgreSQLConnectionFactory
import com.github.mauricio.async.db.postgresql.util.URLParser
import io.getquill.{PostgresAsyncContext, SnakeCase}
import javax.inject.{Inject, Singleton}
import org.slf4j.LoggerFactory
import play.api.inject.{ApplicationLifecycle, Binding, Module}
import play.api.{Configuration, Environment}

import scala.concurrent.ExecutionContext

class DatabaseModule extends Module {
  def bindings(environment: Environment, configuration: Configuration): Seq[Binding[_]] = {
    Seq(
      bind[Database].to[DatabaseImpl]
    )
  }
}

trait Database {
  val ctx: PostgresAsyncContext[SnakeCase]
}

@Singleton
class DatabaseImpl @Inject()(lifecycle: ApplicationLifecycle, playConfig: Configuration) (implicit ec: ExecutionContext) extends Database {

  private val log = LoggerFactory.getLogger(this.getClass)

  private val maybeDbUrl = playConfig.getOptional[String]("db.default.url")

  private val config = maybeDbUrl.map(URLParser.parse(_)).getOrElse(URLParser.DEFAULT)

  private val configWithMaybeSsl = playConfig.getOptional[String]("db.default.sslmode").fold(config) { sslmode =>
    val sslConfig = SSLConfiguration(Map("sslmode" -> sslmode))
    config.copy(ssl = sslConfig)
  }

  private val connectionFactory = new PostgreSQLConnectionFactory(configWithMaybeSsl)

  private val defaultPoolConfig = PoolConfiguration.Default

  private val maxObjects = playConfig.getOptional[Int]("db.default.max-objects").getOrElse(defaultPoolConfig.maxObjects)
  private val maxIdleMillis = playConfig.getOptional[Long]("db.default.max-idle-millis").getOrElse(defaultPoolConfig.maxIdle)
  private val maxQueueSize = playConfig.getOptional[Int]("db.default.max-queue-size").getOrElse(defaultPoolConfig.maxQueueSize)
  private val validationInterval = playConfig.getOptional[Long]("db.default.max-queue-size").getOrElse(defaultPoolConfig.validationInterval)

  private val poolConfig = new PoolConfiguration(maxObjects, maxIdleMillis, maxQueueSize, validationInterval)

  private val numberOfPartitions = playConfig.getOptional[Int]("db.default.number-of-partitions").getOrElse(4)

  private val pool = new PartitionedConnectionPool(
    connectionFactory,
    poolConfig,
    numberOfPartitions,
    ec
  )

  lifecycle.addStopHook { () =>
    pool.close
  }

  val ctx = new PostgresAsyncContext(SnakeCase, pool)

} 
Example 76
Source File: DB.scala    From dr-cla   with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
package utils

import javax.inject.Inject
import models.{ClaSignature, Contact}
import modules.Database

import scala.concurrent.{ExecutionContext, Future}

class DB @Inject()(database: Database)(implicit ec: ExecutionContext) {

  import database.ctx._

  private val contacts = quote {
    querySchema[Contact](
      "salesforce.contact",
      _.gitHubId -> "sf_cla__github_id__c",
      _.firstName -> "firstname",
      _.lastName -> "lastname"
    )
  }

  private val claSignatures = quote {
    querySchema[ClaSignature](
      "salesforce.sf_cla__cla_signature__c",
      _.signedOn -> "sf_cla__signed_on__c",
      _.claVersion -> "sf_cla__cla_version__c",
      _.contactGitHubId -> "sf_cla__contact__r__sf_cla__github_id__c"
    )
  }

  def findContactByGitHubId(gitHubId: String): Future[Option[Contact]] = {
    val queryResult = run {
      contacts.filter(_.gitHubId == lift(gitHubId))
    }

    queryResult.map(_.headOption)
  }

  def createContact(contact: Contact): Future[Contact] = {
    val queryResult = run {
      contacts.insert(lift(contact)).returning(_.id)
    }

    queryResult.map(newId => contact.copy(id = newId))
  }

  def createClaSignature(claSignature: ClaSignature): Future[ClaSignature] = {
    val queryResult = run {
      claSignatures.insert(lift(claSignature)).returning(_.id)
    }

    queryResult.map(newId => claSignature.copy(id = newId))
  }

  def findClaSignaturesByGitHubIds(gitHubIds: Set[GitHub.User]): Future[Set[ClaSignature]] = {
    val queryResult = run {
      claSignatures.filter(claSignature => liftQuery(gitHubIds.map(_.username)).contains(claSignature.contactGitHubId))
    }

    queryResult.map(_.toSet)
  }

} 
Example 77
Source File: Filters.scala    From dr-cla   with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
package utils

import akka.stream.Materializer
import javax.inject.Inject
import play.api.http.{HeaderNames, HttpFilters}
import play.api.mvc._
import play.filters.gzip.GzipFilter

import scala.concurrent.{ExecutionContext, Future}

class OnlyHttpsFilter @Inject() (implicit val mat: Materializer, ec: ExecutionContext) extends Filter {
  def apply(nextFilter: (RequestHeader) => Future[Result])(requestHeader: RequestHeader): Future[Result] = {
    nextFilter(requestHeader).map { result =>
      val isWellKnown = requestHeader.path.startsWith(controllers.routes.Application.wellKnown("").url)
      val isForwardedAndInsecure = requestHeader.headers.get(HeaderNames.X_FORWARDED_PROTO).exists(_ != "https")

      if (isWellKnown || !isForwardedAndInsecure) {
        result
      }
      else {
        Results.MovedPermanently("https://" + requestHeader.host + requestHeader.uri)
      }
    }
  }
}

class Filters @Inject() (gzip: GzipFilter, onlyHttpsFilter: OnlyHttpsFilter) extends HttpFilters {
  val filters = Seq(gzip, onlyHttpsFilter)
} 
Example 78
Source File: Crypto.scala    From dr-cla   with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
package utils

import java.util.Base64

import javax.crypto.{Cipher, KeyGenerator}
import javax.inject.Inject
import play.api.Configuration

class Crypto @Inject() (configuration: Configuration) {

  private val secretKey = {
    val cryptoSecret = configuration.get[String]("play.http.secret.key")
    val keyGenerator = KeyGenerator.getInstance("AES")
    keyGenerator.init(128)
    keyGenerator.generateKey()
  }

  def encryptAES(plainText: String): String = {
    val plainTextBytes = plainText.getBytes
    val cipher = Cipher.getInstance("AES")
    cipher.init(Cipher.ENCRYPT_MODE, secretKey)
    val encryptedButes = cipher.doFinal(plainTextBytes)
    Base64.getEncoder.encodeToString(encryptedButes)
  }

  def decryptAES(encryptedText: String): String = {
    val encryptedTextBytes = Base64.getDecoder.decode(encryptedText)
    val cipher = Cipher.getInstance("AES")
    cipher.init(Cipher.DECRYPT_MODE, secretKey)
    val decryptedBytes = cipher.doFinal(encryptedTextBytes)
    new String(decryptedBytes)
  }

} 
Example 79
Source File: RoomDAOImpl.scala    From Aton   with GNU General Public License v3.0 5 votes vote down vote up
package dao.impl

import javax.inject.Inject

import com.google.inject.Singleton
import dao.RoomDAO
import model.Room
import model.table.RoomTable
import org.h2.jdbc.JdbcSQLException
import play.api.db.slick.DatabaseConfigProvider
import play.api.libs.concurrent.Execution.Implicits._
import services.state.ActionState
import services.state
import slick.driver.JdbcProfile

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


  override def listAll: Future[Seq[Room]] = {
    db.run(rooms.result)
  }

  override def getByLaboratory(id: Long): Future[Seq[Room]] = {
    db.run(rooms.filter(_.laboratoryId === id).result)
  }

  override def update(room: Room): Future[ActionState] = {
    db.run {
      val foundLaboratory = search(room.id)
      foundLaboratory.update(room).asTry
    }.map{
      case Success(res) if res == 1 =>
        play.Logger.info(s"updated with result: $res")
        state.ActionCompleted
      case Success(_) =>
        play.Logger.info("Room not found")
        state.NotFound
      case Failure(e: JdbcSQLException) =>
        play.Logger.error("There was an error looking for that room",e)
        state.NotFound
      case _ => state.Failed
    }
  }
} 
Example 80
Source File: ThingsController.scala    From swagger-check   with MIT License 5 votes vote down vote up
package controllers

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

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

import scala.concurrent.ExecutionContext

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

  def createThing = Action {
    Created
  }

  def getThing(id: UUID) = Action.async { implicit request =>
    thingRepository.getById(id).map {
      case Some(thing) =>
        Ok(Json.toJson(thing))
      case None =>
        NotFound
    }
  }
} 
Example 81
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 82
Source File: Worker.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 org.elastic4play.models.JsonFormat.enumFormat
import org.elastic4play.models.{AttributeDef, BaseEntity, ChildModelDef, EntityDef, HiveEnumeration, AttributeFormat ⇒ F, AttributeOption ⇒ O}
import org.elastic4play.utils.Hasher
import org.thp.cortex.models.JsonFormat.workerTypeFormat
import play.api.libs.json.{JsObject, JsString, Json}

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

object RateUnit extends Enumeration with HiveEnumeration {
  type Type = Value
  val Second         = Value(1)
  val Minute         = Value(60)
  val Hour           = Value(60 * 60)
  val Day            = Value(60 * 60 * 24)
  val Month          = Value(60 * 60 * 24 * 30)
  implicit val reads = enumFormat(this)
}

object WorkerType extends Enumeration with HiveEnumeration {
  type Type = Value
  val analyzer, responder = Value
}

trait WorkerAttributes { _: AttributeDef ⇒
  val workerId           = attribute("_id", F.stringFmt, "Worker id", O.model)
  val name               = attribute("name", F.stringFmt, "Worker name")
  val vers               = attribute("version", F.stringFmt, "Worker version", O.readonly)
  val workerDefinitionId = attribute("workerDefinitionId", F.stringFmt, "Worker definition id", O.readonly)
  val description        = attribute("description", F.textFmt, "Worker description", O.readonly)
  val author             = attribute("author", F.textFmt, "Worker author", O.readonly)
  val url                = attribute("url", F.textFmt, "Worker url", O.readonly)
  val license            = attribute("license", F.textFmt, "Worker license", O.readonly)
  val command            = optionalAttribute("command", F.textFmt, "Worker command", O.readonly)
  val dockerImage        = optionalAttribute("dockerImage", F.textFmt, "Worker docker image", O.readonly)
  val dataTypeList       = multiAttribute("dataTypeList", F.stringFmt, "List of data type this worker can manage")
  val configuration      = attribute("configuration", F.rawFmt, "Configuration of the worker", O.sensitive)
  val baseConfig         = attribute("baseConfig", F.stringFmt, "Base configuration key", O.readonly)
  val rate               = optionalAttribute("rate", F.numberFmt, "Number ")
  val rateUnit           = optionalAttribute("rateUnit", F.enumFmt(RateUnit), "")
  val jobCache           = optionalAttribute("jobCache", F.numberFmt, "")
  val jobTimeout         = optionalAttribute("jobTimeout", F.numberFmt, "")
  val tpe                = attribute("type", F.enumFmt(WorkerType), "", O.readonly)
}

@Singleton
class WorkerModel @Inject()(organizationModel: OrganizationModel)
    extends ChildModelDef[WorkerModel, Worker, OrganizationModel, Organization](organizationModel, "worker", "Worker", "/worker")
    with WorkerAttributes
    with AuditedModel {
  override def creationHook(parent: Option[BaseEntity], attrs: JsObject): Future[JsObject] = {
    val hasher = Hasher("md5")
    val id = for {
      organizationId ← parent.map(_.id)
      name           ← (attrs \ "name").asOpt[String]
      tpe            ← (attrs \ "type").asOpt[String]
    } yield hasher.fromString(s"${organizationId}_${name}_$tpe").head.toString
    Future.successful(attrs + ("_id" → JsString(id.getOrElse("<null>"))))
  }
}

class Worker(model: WorkerModel, attributes: JsObject) extends EntityDef[WorkerModel, Worker](model, attributes) with WorkerAttributes {
  def config: JsObject = Try(Json.parse(configuration()).as[JsObject]).getOrElse(JsObject.empty)
  def organization     = parentId.get
} 
Example 83
Source File: Artifact.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 play.api.libs.json.JsObject

import org.elastic4play.models.{AttributeDef, EntityDef, AttributeFormat ⇒ F, AttributeOption ⇒ O, ChildModelDef}

trait ArtifactAttributes { _: AttributeDef ⇒
  val dataType   = attribute("dataType", F.stringFmt, "Type of the artifact", O.readonly)
  val data       = optionalAttribute("data", F.rawFmt, "Content of the artifact", O.readonly)
  val attachment = optionalAttribute("attachment", F.attachmentFmt, "Artifact file content", O.readonly)
  val tlp        = attribute("tlp", TlpAttributeFormat, "TLP level", 2L)
  val tags       = multiAttribute("tags", F.stringFmt, "Artifact tags")
  val message    = optionalAttribute("message", F.textFmt, "Message associated to the analysis")
}

@Singleton
class ArtifactModel @Inject()(reportModel: ReportModel)
    extends ChildModelDef[ArtifactModel, Artifact, ReportModel, Report](reportModel, "artifact", "Artifact", "/artifact")
    with ArtifactAttributes {}

class Artifact(model: ArtifactModel, attributes: JsObject) extends EntityDef[ArtifactModel, Artifact](model, attributes) with ArtifactAttributes 
Example 84
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 85
Source File: WorkerConfig.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 play.api.libs.json.{JsObject, Json}

import org.elastic4play.models.{AttributeDef, ChildModelDef, EntityDef, AttributeFormat ⇒ F, AttributeOption ⇒ O}

import org.thp.cortex.models.JsonFormat.workerTypeFormat

trait WorkerConfigAttributes { _: AttributeDef ⇒
  val name   = attribute("name", F.stringFmt, "Worker name")
  val config = attribute("config", F.rawFmt, "Configuration of worker", O.sensitive)
  val tpe    = attribute("type", F.enumFmt(WorkerType), "", O.readonly)
}

@Singleton
class WorkerConfigModel @Inject()(organizationModel: OrganizationModel)
    extends ChildModelDef[WorkerConfigModel, WorkerConfig, OrganizationModel, Organization](
      organizationModel,
      "workerConfig",
      "WorkerConfig",
      "/worker/config"
    )
    with WorkerConfigAttributes {}

class WorkerConfig(model: WorkerConfigModel, attributes: JsObject)
    extends EntityDef[WorkerConfigModel, WorkerConfig](model, attributes)
    with WorkerConfigAttributes {
  def organization = parentId.get
  def jsonConfig   = Json.parse(config()).as[JsObject]
} 
Example 86
Source File: Job.scala    From Cortex   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.thp.cortex.models

import scala.util.Try

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

import javax.inject.{Inject, Singleton}
import org.thp.cortex.models.JsonFormat.workerTypeFormat

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

object JobStatus extends Enumeration with HiveEnumeration {
  type Type = Value
  val Waiting, InProgress, Success, Failure, Deleted = Value
  implicit val reads                                 = enumFormat(this)
}

trait JobAttributes {
  _: AttributeDef ⇒
  val workerDefinitionId = attribute("workerDefinitionId", F.stringFmt, "Worker definition id", O.readonly)
  val workerId           = attribute("workerId", F.stringFmt, "Worker id", O.readonly)
  val workerName         = attribute("workerName", F.stringFmt, "Worker name", O.readonly)
  val organization       = attribute("organization", F.stringFmt, "Organization ID", O.readonly)
  val status             = attribute("status", F.enumFmt(JobStatus), "Status of the job")
  val startDate          = optionalAttribute("startDate", F.dateFmt, "Analysis start date")
  val endDate            = optionalAttribute("endDate", F.dateFmt, "Analysis end date")
  val dataType           = attribute("dataType", F.stringFmt, "Type of the artifact", O.readonly)
  val data               = optionalAttribute("data", F.rawFmt, "Content of the artifact", O.readonly)
  val attachment         = optionalAttribute("attachment", F.attachmentFmt, "Artifact file content", O.readonly)
  val tlp                = attribute("tlp", TlpAttributeFormat, "TLP level", 2L)
  val pap                = attribute("pap", TlpAttributeFormat, "PAP level", 2L)
  val message            = optionalAttribute("message", F.textFmt, "Message associated to the analysis")
  val errorMessage       = optionalAttribute("errorMessage", F.textFmt, "Message returned by the worker when it fails")
  val parameters         = attribute("parameters", F.rawFmt, "Parameters for this job", "{}")
  val input              = optionalAttribute("input", F.rawFmt, "Data sent to worker")
  val fromCache          = optionalAttribute("fromCache", F.booleanFmt, "Indicates if cache is used", O.form)
  val tpe                = attribute("type", F.enumFmt(WorkerType), "", O.readonly)
  val lbel               = optionalAttribute("label", F.stringFmt, "Label of the job")
  val cacheTag           = optionalAttribute("cacheTag", F.stringFmt, "hash of job discriminant, used for cache", O.readonly)
}

@Singleton
class JobModel @Inject()() extends ModelDef[JobModel, Job]("job", "Job", "/job") with JobAttributes with AuditedModel {

  override val removeAttribute: JsObject = Json.obj("status" → JobStatus.Deleted)

  override def defaultSortBy: Seq[String] = Seq("-createdAt")
}

class Job(model: JobModel, attributes: JsObject) extends EntityDef[JobModel, Job](model, attributes) with JobAttributes {
  val params: JsObject = Try(Json.parse(parameters()).as[JsObject]).getOrElse(JsObject.empty)

  override def toJson: JsObject = {
    val output = input().fold(super.toJson)(
      i ⇒
        super.toJson +
          ("input" → Json.parse(i))
    ) +
      ("parameters"           → params) +
      ("analyzerId"           → JsString(workerId())) +
      ("analyzerName"         → JsString(workerName())) +
      ("analyzerDefinitionId" → JsString(workerDefinitionId())) +
      ("date"                 → Json.toJson(createdAt))
    data() match {
      case Some(d) if tpe() == WorkerType.responder ⇒ output + ("data" → Json.parse(d))
      case _                                        ⇒ output
    }
  }
} 
Example 87
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 88
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 89
Source File: OrganizationSrv.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.Future
import scala.concurrent.duration.Duration

import play.api.Configuration
import play.api.cache.AsyncCacheApi
import play.api.libs.json.JsObject

import akka.NotUsed
import akka.stream.scaladsl.Source
import org.thp.cortex.models.{Organization, OrganizationModel}

import org.elastic4play.controllers.Fields
import org.elastic4play.database.ModifyConfig
import org.elastic4play.services._

@Singleton
class OrganizationSrv(
    cacheExpiration: Duration,
    organizationModel: OrganizationModel,
    getSrv: GetSrv,
    updateSrv: UpdateSrv,
    findSrv: FindSrv,
    deleteSrv: DeleteSrv,
    createSrv: CreateSrv,
    cache: AsyncCacheApi
) {

  @Inject() def this(
      config: Configuration,
      organizationModel: OrganizationModel,
      getSrv: GetSrv,
      updateSrv: UpdateSrv,
      findSrv: FindSrv,
      deleteSrv: DeleteSrv,
      createSrv: CreateSrv,
      cache: AsyncCacheApi
  ) = this(config.get[Duration]("cache.organization"), organizationModel, getSrv, updateSrv, findSrv, deleteSrv, createSrv, cache)

  def create(fields: Fields)(implicit authContext: AuthContext): Future[Organization] =
    createSrv[OrganizationModel, Organization](organizationModel, fields)

  def get(orgId: String): Future[Organization] = cache.getOrElseUpdate(s"org-$orgId", cacheExpiration) {
    getSrv[OrganizationModel, Organization](organizationModel, orgId)
  }

  def update(orgId: String, fields: Fields)(implicit Context: AuthContext): Future[Organization] =
    update(orgId, fields, ModifyConfig.default)

  def update(orgId: String, fields: Fields, modifyConfig: ModifyConfig)(implicit Context: AuthContext): Future[Organization] = {
    cache.remove(s"org-$orgId")
    updateSrv[OrganizationModel, Organization](organizationModel, orgId, fields, modifyConfig)
  }

  def update(organization: Organization, fields: Fields)(implicit Context: AuthContext): Future[Organization] =
    update(organization, fields, ModifyConfig.default)

  def update(organization: Organization, fields: Fields, modifyConfig: ModifyConfig)(implicit Context: AuthContext): Future[Organization] = {
    cache.remove(s"org-${organization.id}")
    updateSrv(organization, fields, modifyConfig)
  }

  def delete(orgId: String)(implicit Context: AuthContext): Future[Organization] = {
    cache.remove(s"org-$orgId")
    deleteSrv[OrganizationModel, Organization](organizationModel, orgId)
  }

  def find(queryDef: QueryDef, range: Option[String], sortBy: Seq[String]): (Source[Organization, NotUsed], Future[Long]) =
    findSrv[OrganizationModel, Organization](organizationModel, queryDef, range, sortBy)

  def stats(queryDef: QueryDef, aggs: Seq[Agg]): Future[JsObject] = findSrv(organizationModel, queryDef, aggs: _*)
} 
Example 90
Source File: AnalyzerConfigSrv.scala    From Cortex   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.thp.cortex.services

import scala.concurrent.{ExecutionContext, Future}

import play.api.Configuration

import akka.stream.Materializer
import javax.inject.{Inject, Singleton}
import org.thp.cortex.models.{BaseConfig, WorkerConfigModel, WorkerType}

import org.elastic4play.services.{CreateSrv, FindSrv, UpdateSrv}

@Singleton
class AnalyzerConfigSrv @Inject()(
    val configuration: Configuration,
    val workerConfigModel: WorkerConfigModel,
    val userSrv: UserSrv,
    val organizationSrv: OrganizationSrv,
    val workerSrv: WorkerSrv,
    val createSrv: CreateSrv,
    val updateSrv: UpdateSrv,
    val findSrv: FindSrv,
    implicit val ec: ExecutionContext,
    implicit val mat: Materializer
) extends WorkerConfigSrv {

  override val workerType: WorkerType.Type = WorkerType.analyzer

  def definitions: Future[Map[String, BaseConfig]] =
    buildDefinitionMap(workerSrv.listAnalyzerDefinitions._1)
} 
Example 91
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 92
Source File: SimpleUserMapper.scala    From Cortex   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.thp.cortex.services.mappers

import scala.concurrent.{ExecutionContext, Future}

import play.api.Configuration
import play.api.libs.json._

import javax.inject.Inject

import org.elastic4play.AuthenticationError
import org.elastic4play.controllers.Fields

class SimpleUserMapper(
    loginAttrName: String,
    nameAttrName: String,
    rolesAttrName: Option[String],
    organizationAttrName: Option[String],
    defaultRoles: Seq[String],
    defaultOrganization: Option[String],
    implicit val ec: ExecutionContext
) extends UserMapper {

  @Inject() def this(configuration: Configuration, ec: ExecutionContext) =
    this(
      configuration.getOptional[String]("auth.sso.attributes.login").getOrElse("name"),
      configuration.getOptional[String]("auth.sso.attributes.name").getOrElse("username"),
      configuration.getOptional[String]("auth.sso.attributes.roles"),
      configuration.getOptional[String]("auth.sso.attributes.organization"),
      configuration.getOptional[Seq[String]]("auth.sso.defaultRoles").getOrElse(Seq()),
      configuration.getOptional[String]("auth.sso.defaultOrganization"),
      ec
    )

  override val name: String = "simple"

  override def getUserFields(jsValue: JsValue, authHeader: Option[(String, String)]): Future[Fields] = {
    val fields = for {
      login ← (jsValue \ loginAttrName).validate[String]
      name  ← (jsValue \ nameAttrName).validate[String]
      roles = rolesAttrName.fold(defaultRoles)(r ⇒ (jsValue \ r).asOpt[Seq[String]].getOrElse(defaultRoles))
      organization ← organizationAttrName
        .flatMap(o ⇒ (jsValue \ o).asOpt[String])
        .orElse(defaultOrganization)
        .fold[JsResult[String]](JsError())(o ⇒ JsSuccess(o))
    } yield Fields(Json.obj("login" → login, "name" → name, "roles" → roles, "organization" → organization))
    fields match {
      case JsSuccess(f, _) ⇒ Future.successful(f)
      case JsError(errors) ⇒ Future.failed(AuthenticationError(s"User info fails: ${errors.map(_._1).mkString}"))
    }
  }
} 
Example 93
Source File: GroupUserMapper.scala    From Cortex   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.thp.cortex.services.mappers

import scala.concurrent.{ExecutionContext, Future}

import play.api.Configuration
import play.api.libs.json._
import play.api.libs.ws.WSClient

import javax.inject.Inject

import org.elastic4play.AuthenticationError
import org.elastic4play.controllers.Fields

class GroupUserMapper(
    loginAttrName: String,
    nameAttrName: String,
    rolesAttrName: Option[String],
    groupAttrName: String,
    organizationAttrName: Option[String],
    defaultRoles: Seq[String],
    defaultOrganization: Option[String],
    groupsUrl: String,
    mappings: Map[String, Seq[String]],
    ws: WSClient,
    implicit val ec: ExecutionContext
) extends UserMapper {

  @Inject() def this(configuration: Configuration, ws: WSClient, ec: ExecutionContext) =
    this(
      configuration.getOptional[String]("auth.sso.attributes.login").getOrElse("name"),
      configuration.getOptional[String]("auth.sso.attributes.name").getOrElse("username"),
      configuration.getOptional[String]("auth.sso.attributes.roles"),
      configuration.getOptional[String]("auth.sso.attributes.groups").getOrElse(""),
      configuration.getOptional[String]("auth.sso.attributes.organization"),
      configuration.getOptional[Seq[String]]("auth.sso.defaultRoles").getOrElse(Seq()),
      configuration.getOptional[String]("auth.sso.defaultOrganization"),
      configuration.getOptional[String]("auth.sso.groups.url").getOrElse(""),
      configuration.getOptional[Map[String, Seq[String]]]("auth.sso.groups.mappings").getOrElse(Map()),
      ws,
      ec
    )

  override val name: String = "group"

  override def getUserFields(jsValue: JsValue, authHeader: Option[(String, String)]): Future[Fields] = {

    val apiCall = authHeader.fold(ws.url(groupsUrl))(headers ⇒ ws.url(groupsUrl).addHttpHeaders(headers))
    apiCall.get.flatMap { r ⇒
      val jsonGroups  = (r.json \ groupAttrName).as[Seq[String]]
      val mappedRoles = jsonGroups.flatMap(mappings.get).maxBy(_.length)
      val roles       = if (mappedRoles.nonEmpty) mappedRoles else defaultRoles

      val fields = for {
        login ← (jsValue \ loginAttrName).validate[String]
        name  ← (jsValue \ nameAttrName).validate[String]
        organization ← organizationAttrName
          .flatMap(o ⇒ (jsValue \ o).asOpt[String])
          .orElse(defaultOrganization)
          .fold[JsResult[String]](JsError())(o ⇒ JsSuccess(o))
      } yield Fields(Json.obj("login" → login, "name" → name, "roles" → roles, "organization" → organization))
      fields match {
        case JsSuccess(f, _) ⇒ Future.successful(f)
        case JsError(errors) ⇒ Future.failed(AuthenticationError(s"User info fails: ${errors.map(_._1).mkString}"))
      }
    }
  }
} 
Example 94
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 95
Source File: LocalAuthSrv.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, Future}
import scala.util.Random

import play.api.mvc.RequestHeader

import akka.stream.Materializer
import org.thp.cortex.models.User

import org.elastic4play.controllers.Fields
import org.elastic4play.services.{AuthCapability, AuthContext, AuthSrv}
import org.elastic4play.utils.Hasher
import org.elastic4play.{AuthenticationError, AuthorizationError}

@Singleton
class LocalAuthSrv @Inject()(userSrv: UserSrv, implicit val ec: ExecutionContext, implicit val mat: Materializer) extends AuthSrv {

  val name                  = "local"
  override val capabilities = Set(AuthCapability.changePassword, AuthCapability.setPassword)

  private[services] def doAuthenticate(user: User, password: String): Boolean =
    user.password().map(_.split(",", 2)).fold(false) {
      case Array(seed, pwd) ⇒
        val hash = Hasher("SHA-256").fromString(seed + password).head.toString
        hash == pwd
      case _ ⇒ false
    }

  override def authenticate(username: String, password: String)(implicit request: RequestHeader): Future[AuthContext] =
    userSrv.get(username).flatMap { user ⇒
      if (doAuthenticate(user, password)) userSrv.getFromUser(request, user, name)
      else Future.failed(AuthenticationError("Authentication failure"))
    }

  override def changePassword(username: String, oldPassword: String, newPassword: String)(implicit authContext: AuthContext): Future[Unit] =
    userSrv.get(username).flatMap { user ⇒
      if (doAuthenticate(user, oldPassword)) setPassword(username, newPassword)
      else Future.failed(AuthorizationError("Authentication failure"))
    }

  override def setPassword(username: String, newPassword: String)(implicit authContext: AuthContext): Future[Unit] = {
    val seed    = Random.nextString(10).replace(',', '!')
    val newHash = seed + "," + Hasher("SHA-256").fromString(seed + newPassword).head.toString
    userSrv.update(username, Fields.empty.set("password", newHash)).map(_ ⇒ ())
  }
} 
Example 96
Source File: KeyAuthSrv.scala    From Cortex   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.thp.cortex.services

import java.util.Base64
import javax.inject.{Inject, Singleton}

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

import play.api.libs.json.JsArray
import play.api.mvc.RequestHeader

import akka.stream.Materializer
import akka.stream.scaladsl.Sink

import org.elastic4play.controllers.Fields
import org.elastic4play.services.{AuthCapability, AuthContext, AuthSrv}
import org.elastic4play.{AuthenticationError, BadRequestError}

@Singleton
class KeyAuthSrv @Inject()(userSrv: UserSrv, implicit val ec: ExecutionContext, implicit val mat: Materializer) extends AuthSrv {
  override val name = "key"

  final protected def generateKey(): String = {
    val bytes = Array.ofDim[Byte](24)
    Random.nextBytes(bytes)
    Base64.getEncoder.encodeToString(bytes)
  }

  override val capabilities = Set(AuthCapability.authByKey)

  override def authenticate(key: String)(implicit request: RequestHeader): Future[AuthContext] = {
    import org.elastic4play.services.QueryDSL._
    // key attribute is sensitive so it is not possible to search on that field
    userSrv
      .find("status" ~= "Ok", Some("all"), Nil)
      ._1
      .filter(_.key().contains(key))
      .runWith(Sink.headOption)
      .flatMap {
        case Some(user) ⇒ userSrv.getFromUser(request, user, name)
        case None       ⇒ Future.failed(AuthenticationError("Authentication failure"))
      }
  }

  override def renewKey(username: String)(implicit authContext: AuthContext): Future[String] = {
    val newKey = generateKey()
    userSrv.update(username, Fields.empty.set("key", newKey)).map(_ ⇒ newKey)
  }

  override def getKey(username: String)(implicit authContext: AuthContext): Future[String] =
    userSrv.get(username).map(_.key().getOrElse(throw BadRequestError(s"User $username hasn't key")))

  override def removeKey(username: String)(implicit authContext: AuthContext): Future[Unit] =
    userSrv.update(username, Fields.empty.set("key", JsArray())).map(_ ⇒ ())
} 
Example 97
Source File: ResponderConfigSrv.scala    From Cortex   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.thp.cortex.services

import scala.concurrent.{ExecutionContext, Future}

import play.api.Configuration

import akka.stream.Materializer
import javax.inject.{Inject, Singleton}
import org.thp.cortex.models.{BaseConfig, WorkerConfigModel, WorkerType}

import org.elastic4play.services.{CreateSrv, FindSrv, UpdateSrv}

@Singleton
class ResponderConfigSrv @Inject()(
    val configuration: Configuration,
    val workerConfigModel: WorkerConfigModel,
    val userSrv: UserSrv,
    val organizationSrv: OrganizationSrv,
    val workerSrv: WorkerSrv,
    val createSrv: CreateSrv,
    val updateSrv: UpdateSrv,
    val findSrv: FindSrv,
    implicit val ec: ExecutionContext,
    implicit val mat: Materializer
) extends WorkerConfigSrv {

  override val workerType: WorkerType.Type         = WorkerType.responder
  def definitions: Future[Map[String, BaseConfig]] = buildDefinitionMap(workerSrv.listResponderDefinitions._1)
} 
Example 98
Source File: StatusCtrl.scala    From Cortex   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.thp.cortex.controllers

import scala.concurrent.ExecutionContext

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

import scala.concurrent.{ExecutionContext, Future}

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

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

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

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

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

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

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

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

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

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

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

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

  def update(analyzerId: String): Action[Fields] = authenticated(Roles.orgAdmin).async(fieldsBodyParser) { implicit request ⇒
    for {
      analyzer        ← workerSrv.getForUser(request.userId, analyzerId)
      updatedAnalyzer ← workerSrv.update(analyzer, request.body)
    } yield renderer.toOutput(OK, analyzerJson(isAdmin = true)(updatedAnalyzer))
  }
} 
Example 101
Source File: AssetCtrl.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 play.api.http.{FileMimeTypes, HttpErrorHandler}
import play.api.mvc.{Action, AnyContent}
import controllers.{Assets, AssetsMetadata, ExternalAssets}
import play.api.Environment

import scala.concurrent.ExecutionContext

trait AssetCtrl {
  def get(file: String): Action[AnyContent]
}

@Singleton
class AssetCtrlProd @Inject()(errorHandler: HttpErrorHandler, meta: AssetsMetadata) extends Assets(errorHandler, meta) with AssetCtrl {
  def get(file: String): Action[AnyContent] = at("/www", file)
}

@Singleton
class AssetCtrlDev @Inject()(environment: Environment)(implicit ec: ExecutionContext, fileMimeTypes: FileMimeTypes)
    extends ExternalAssets(environment)
    with AssetCtrl {
  def get(file: String): Action[AnyContent] = at("www/dist", file)
} 
Example 102
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 103
Source File: DBListCtrl.scala    From Cortex   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.thp.cortex.controllers

import javax.inject.{Inject, Singleton}

import scala.concurrent.{ExecutionContext, Future}

import play.api.libs.json.{JsValue, Json}
import play.api.mvc._

import org.thp.cortex.models.Roles

import org.elastic4play.controllers.{Authenticated, Fields, FieldsBodyParser, Renderer}
import org.elastic4play.services.DBLists
import org.elastic4play.MissingAttributeError

@Singleton
class DBListCtrl @Inject()(
    dblists: DBLists,
    authenticated: Authenticated,
    renderer: Renderer,
    components: ControllerComponents,
    fieldsBodyParser: FieldsBodyParser,
    implicit val ec: ExecutionContext
) extends AbstractController(components) {

  def list: Action[AnyContent] = authenticated(Roles.read).async { _ ⇒
    dblists.listAll.map { listNames ⇒
      renderer.toOutput(OK, listNames)
    }
  }

  def listItems(listName: String): Action[AnyContent] = authenticated(Roles.read) { _ ⇒
    val (src, _) = dblists(listName).getItems[JsValue]
    val items = src
      .map { case (id, value) ⇒ s""""$id":$value""" }
      .intersperse("{", ",", "}")
    Ok.chunked(items).as("application/json")
  }

  def addItem(listName: String): Action[Fields] = authenticated(Roles.superAdmin).async(fieldsBodyParser) { implicit request ⇒
    request.body.getValue("value").fold(Future.successful(NoContent)) { value ⇒
      dblists(listName).addItem(value).map { item ⇒
        renderer.toOutput(OK, item.id)
      }
    }
  }

  def deleteItem(itemId: String): Action[AnyContent] = authenticated(Roles.superAdmin).async { implicit request ⇒
    dblists.deleteItem(itemId).map { _ ⇒
      NoContent
    }
  }

  def updateItem(itemId: String): Action[Fields] = authenticated(Roles.superAdmin).async(fieldsBodyParser) { implicit request ⇒
    request
      .body
      .getValue("value")
      .map { value ⇒
        for {
          item    ← dblists.getItem(itemId)
          _       ← dblists.deleteItem(item)
          newItem ← dblists(item.dblist).addItem(value)
        } yield renderer.toOutput(OK, newItem.id)
      }
      .getOrElse(Future.failed(MissingAttributeError("value")))
  }

  def itemExists(listName: String): Action[Fields] = authenticated(Roles.read).async(fieldsBodyParser) { implicit request ⇒
    val itemKey   = request.body.getString("key").getOrElse(throw MissingAttributeError("Parameter key is missing"))
    val itemValue = request.body.getValue("value").getOrElse(throw MissingAttributeError("Parameter value is missing"))
    dblists(listName).exists(itemKey, itemValue).map(r ⇒ Ok(Json.obj("found" → r)))
  }
} 
Example 104
Source File: AuthenticationCtrl.scala    From Cortex   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.thp.cortex.controllers

import scala.concurrent.{ExecutionContext, Future}

import play.api.mvc._

import javax.inject.{Inject, Singleton}
import org.thp.cortex.models.UserStatus
import org.thp.cortex.services.UserSrv

import org.elastic4play.controllers.{Authenticated, Fields, FieldsBodyParser, Renderer}
import org.elastic4play.database.DBIndex
import org.elastic4play.services.AuthSrv
import org.elastic4play.services.JsonFormat.authContextWrites
import org.elastic4play.{AuthorizationError, MissingAttributeError, OAuth2Redirect, Timed}

@Singleton
class AuthenticationCtrl @Inject()(
    authSrv: AuthSrv,
    userSrv: UserSrv,
    authenticated: Authenticated,
    dbIndex: DBIndex,
    renderer: Renderer,
    components: ControllerComponents,
    fieldsBodyParser: FieldsBodyParser,
    implicit val ec: ExecutionContext
) extends AbstractController(components) {

  @Timed
  def login: Action[Fields] = Action.async(fieldsBodyParser) { implicit request ⇒
    dbIndex.getIndexStatus.flatMap {
      case false ⇒ Future.successful(Results.Status(520))
      case _ ⇒
        for {
          user        ← request.body.getString("user").fold[Future[String]](Future.failed(MissingAttributeError("user")))(Future.successful)
          password    ← request.body.getString("password").fold[Future[String]](Future.failed(MissingAttributeError("password")))(Future.successful)
          authContext ← authSrv.authenticate(user, password)
        } yield authenticated.setSessingUser(renderer.toOutput(OK, authContext), authContext)
    }
  }

  @Timed
  def ssoLogin: Action[AnyContent] = Action.async { implicit request ⇒
    dbIndex.getIndexStatus.flatMap {
      case false ⇒ Future.successful(Results.Status(520))
      case _ ⇒
        (for {
          authContext ← authSrv.authenticate()
          user        ← userSrv.get(authContext.userId)
        } yield {
          if (user.status() == UserStatus.Ok)
            authenticated.setSessingUser(Ok, authContext)
          else
            throw AuthorizationError("Your account is locked")
        }) recover {
          // A bit of a hack with the status code, so that Angular doesn't reject the origin
          case OAuth2Redirect(redirectUrl, qp) ⇒ Redirect(redirectUrl, qp, status = OK)
          case e                               ⇒ throw e
        }
    }
  }

  @Timed
  def logout = Action {
    Ok.withNewSession
  }
} 
Example 105
Source File: AttachmentCtrl.scala    From Cortex   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.thp.cortex.controllers

import java.net.URLEncoder
import java.nio.file.Files
import javax.inject.{Inject, Singleton}

import play.api.http.HttpEntity
import play.api.libs.Files.DefaultTemporaryFileCreator
import play.api.mvc._
import play.api.{mvc, Configuration}

import akka.stream.scaladsl.FileIO
import net.lingala.zip4j.core.ZipFile
import net.lingala.zip4j.model.ZipParameters
import net.lingala.zip4j.util.Zip4jConstants
import org.thp.cortex.models.Roles

import org.elastic4play.Timed
import org.elastic4play.controllers.{Authenticated, Renderer}
import org.elastic4play.models.AttachmentAttributeFormat
import org.elastic4play.services.AttachmentSrv


  @Timed("controllers.AttachmentCtrl.downloadZip")
  def downloadZip(hash: String, name: Option[String]): Action[AnyContent] = authenticated(Roles.read) { _ ⇒
    if (!name.getOrElse("").intersect(AttachmentAttributeFormat.forbiddenChar).isEmpty)
      BadRequest("File name is invalid")
    else {
      val f = tempFileCreator.create("zip", hash).path
      Files.delete(f)
      val zipFile   = new ZipFile(f.toFile)
      val zipParams = new ZipParameters
      zipParams.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_FASTEST)
      zipParams.setEncryptFiles(true)
      zipParams.setEncryptionMethod(Zip4jConstants.ENC_METHOD_STANDARD)
      zipParams.setPassword(password)
      zipParams.setFileNameInZip(name.getOrElse(hash))
      zipParams.setSourceExternalStream(true)
      zipFile.addStream(attachmentSrv.stream(hash), zipParams)

      Result(
        header = ResponseHeader(
          200,
          Map(
            "Content-Disposition"       → s"""attachment; filename="${URLEncoder.encode(name.getOrElse(hash), "utf-8")}.zip"""",
            "Content-Type"              → "application/zip",
            "Content-Transfer-Encoding" → "binary",
            "Content-Length"            → Files.size(f).toString
          )
        ),
        body = HttpEntity.Streamed(FileIO.fromPath(f), Some(Files.size(f)), Some("application/zip"))
      )
    }
  }
} 
Example 106
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 107
Source File: ResponderConfigCtrl.scala    From Cortex   with GNU Affero General Public License v3.0 5 votes vote down vote up
package org.thp.cortex.controllers

import scala.concurrent.{ExecutionContext, Future}

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

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

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

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

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

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

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

import javax.inject.{Inject, Singleton}

import com.google.inject.{Module, Provides}
import com.twitter.finagle.Dtab
import com.twitter.finagle.http.{Request, Response}
import com.twitter.finatra.http.{Controller, HttpServer}
import com.twitter.finatra.http.filters.{CommonFilters, LoggingMDCFilter, TraceIdMDCFilter}
import com.twitter.finatra.http.routing.HttpRouter
import com.twitter.finatra.response.Mustache
import com.twitter.inject.TwitterModule
import com.twitter.inject.annotations.Flag
import net.gutefrage.Dtabs
import net.gutefrage.temperature.thrift.TemperatureService

object FinatraHttpServer extends HttpServer {

  premain {
    Dtabs.init()
  }

  override def modules: Seq[Module] = Seq(TemperatureServiceModule)

  override def defaultFinatraHttpPort = ":9000"

  override protected def configureHttp(router: HttpRouter): Unit =
    router
      .filter[LoggingMDCFilter[Request, Response]]
      .filter[TraceIdMDCFilter[Request, Response]]
      .filter[CommonFilters]
      .add[WeatherController]
}


class WeatherController @Inject()(
  temperatureService: TemperatureService.FutureIface,
  @Flag("local.doc.root") localDocRoot: String,
  @Flag("doc.root") docRoot: String
) extends Controller {

  private val docConfig = DocConfig(localDocRoot, docRoot)

  get("/") { request: Request =>
    temperatureService.mean().map { meanTemperature =>
      DashboardData(meanTemperature, Some("local"), docConfig)
    }
  }

  // Change dtab according to the environment
  get("/:env") { request: Request =>
    val environment = request.params("env")

    Dtab.unwind {
      Dtab.local = Dtab.read(s"/env => /s#/$environment")
      temperatureService.mean().map { meanTemperature =>
        DashboardData(meanTemperature, Some(environment), docConfig)
      }
    }
  }

  // Asset route (for styles.css)
  get("/assets/:*") { request: Request =>
    response.ok.file("/assets/" + request.params("*"))
  }
}

@Mustache("dashboard")
case class DashboardData(
  meanTemperature: Double,
  environment: Option[String],
  docConfig: DocConfig
)
case class DocConfig(localDocRoot: String, docRoot: String) 
Example 109
Source File: UserResource.scala    From naptime   with Apache License 2.0 5 votes vote down vote up
package resources

import java.util.concurrent.atomic.AtomicInteger
import javax.inject.Inject
import javax.inject.Singleton

import org.coursera.naptime.model.KeyFormat
import org.coursera.naptime.model.Keyed
import org.coursera.naptime.NaptimeModule
import org.coursera.naptime.Ok
import org.coursera.example.User
import org.coursera.naptime.courier.CourierFormats
import org.coursera.naptime.resources.TopLevelCollectionResource
import org.coursera.naptime.resources.RestActionHelpers
import play.api.libs.json.OFormat


  def create() = Rest
      .jsonBody[User]
      .create { context =>
        val user = context.body
        val id = userStore.create(user)

        // Could return Ok(Keyed(id, None)) if we want to return 201 Created,
        // with an empty body. Prefer returning the updated body, however.
        Ok(Keyed(id, Some(user)))
      }
}

class ResourceModule extends NaptimeModule {
  override def configure(): Unit = {
    bindResource[UsersResource]
    bind[UserStore].to[UserStoreImpl]
  }
}


trait UserStore {
  def get(id: Int): Option[User]
  def create(user: User): Int
}

class UserStoreImpl extends UserStore {
  @volatile
  var userStore = Map.empty[Int, User]
  val nextId = new AtomicInteger(0)


  def get(id: Int) = userStore.get(id)

  def create(user: User): Int = {
    val id = nextId.incrementAndGet()
    userStore = userStore + (id -> user)
    id
  }


}

class UserBanManager {
  @volatile
  var bannedUsers = Set.empty[Int]
} 
Example 110
Source File: InstructorsResource.scala    From naptime   with Apache License 2.0 5 votes vote down vote up
package resources

import javax.inject.Inject
import javax.inject.Singleton

import akka.stream.Materializer
import org.coursera.example.Instructor
import org.coursera.naptime.Fields
import org.coursera.naptime.FinderGraphQLRelation
import org.coursera.naptime.GetGraphQLRelation
import org.coursera.naptime.Ok
import org.coursera.naptime.ResourceName
import org.coursera.naptime.model.Keyed
import org.coursera.naptime.resources.CourierCollectionResource
import stores.InstructorStore

import scala.concurrent.ExecutionContext

@Singleton
class InstructorsResource @Inject() (
    instructorStore: InstructorStore)(implicit ec: ExecutionContext, mat: Materializer)
  extends CourierCollectionResource[Int, Instructor] {

  override def resourceName = "instructors"
  override def resourceVersion = 1
  override implicit lazy val Fields: Fields[Instructor] = BaseFields
    .withGraphQLRelations(
      "courses" -> FinderGraphQLRelation(
        resourceName = ResourceName("courses", 1),
        finderName = "byInstructor",
        arguments = Map("instructorId" -> "$id")),
      "partner" -> GetGraphQLRelation(
        resourceName = ResourceName("partners", 1),
        id = "$partnerId"))

  def get(id: Int) = Nap.get { context =>
    OkIfPresent(id, instructorStore.get(id))
  }

  def multiGet(ids: Set[Int]) = Nap.multiGet { context =>
    Ok(instructorStore.all()
      .filter(instructor => ids.contains(instructor._1))
      .map { case (id, instructor) => Keyed(id, instructor) }.toList)
  }

  def getAll() = Nap.getAll { context =>
    Ok(instructorStore.all().map { case (id, instructor) => Keyed(id, instructor) }.toList)
  }

} 
Example 111
Source File: UserResource.scala    From naptime   with Apache License 2.0 5 votes vote down vote up
package resources

import java.util.concurrent.atomic.AtomicInteger
import javax.inject.Inject
import javax.inject.Singleton

import akka.stream.Materializer
import org.coursera.naptime.model.KeyFormat
import org.coursera.naptime.model.Keyed
import org.coursera.naptime.Ok
import org.coursera.example.User
import org.coursera.naptime.courier.CourierFormats
import org.coursera.naptime.resources.TopLevelCollectionResource
import play.api.libs.json.OFormat

import scala.concurrent.ExecutionContext


@Singleton
class UsersResource @Inject() (
    userStore: UserStore,
    banManager: UserBanManager)
    (implicit override val executionContext: ExecutionContext,
    override val materializer: Materializer)
  extends TopLevelCollectionResource[Int, User] {

  override def resourceName = "users"
  override def resourceVersion = 1  // optional; defaults to 1
  implicit val fields = Fields.withDefaultFields(  // default field projection
    "id", "name", "email")

  override def keyFormat: KeyFormat[KeyType] = KeyFormat.intKeyFormat
  override implicit def resourceFormat: OFormat[User] = CourierFormats.recordTemplateFormats[User]

  def get(id: Int) = Nap.get { context =>
    OkIfPresent(id, userStore.get(id))
  }

  def multiGet(ids: Set[Int]) = Nap.multiGet { context =>
    Ok(userStore.all()
      .filter(user => ids.contains(user._1))
      .map { case (id, user) => Keyed(id, user) }.toList)
  }

  def getAll() = Nap.getAll { context =>
    Ok(userStore.all().map { case (id, user) => Keyed(id, user) }.toList)
  }

  def create() = Nap
    .jsonBody[User]
    .create { context =>
      val user = context.body
      val id = userStore.create(user)

      // Could return Ok(Keyed(id, None)) if we want to return 201 Created,
      // with an empty body. Prefer returning the updated body, however.
      Ok(Keyed(id, Some(user)))
    }

  def email(email: String) = Nap.finder { context =>
    Ok(userStore.all()
      .filter(_._2.email == email)
      .map { case (id, user) => Keyed(id, user) }.toList)
  }

}


trait UserStore {
  def get(id: Int): Option[User]
  def create(user: User): Int
  def all(): Map[Int, User]
}

@Singleton
class UserStoreImpl extends UserStore {
  @volatile
  var userStore = Map.empty[Int, User]
  val nextId = new AtomicInteger(0)

  def get(id: Int) = userStore.get(id)

  def create(user: User): Int = {
    val id = nextId.incrementAndGet()
    userStore = userStore + (id -> user)
    id
  }

  def all() = userStore

}

class UserBanManager {
  @volatile
  var bannedUsers = Set.empty[Int]
} 
Example 112
Source File: PartnersResource.scala    From naptime   with Apache License 2.0 5 votes vote down vote up
package resources

import javax.inject.Inject
import javax.inject.Singleton

import akka.stream.Materializer
import org.coursera.example.Partner
import org.coursera.naptime.Fields
import org.coursera.naptime.MultiGetGraphQLRelation
import org.coursera.naptime.Ok
import org.coursera.naptime.ResourceName
import org.coursera.naptime.model.Keyed
import org.coursera.naptime.resources.CourierCollectionResource
import stores.PartnerStore

import scala.concurrent.ExecutionContext

@Singleton
class PartnersResource @Inject() (
    partnerStore: PartnerStore)(implicit ec: ExecutionContext, mat: Materializer)
  extends CourierCollectionResource[String, Partner] {

  override def resourceName = "partners"
  override def resourceVersion = 1
  override implicit lazy val Fields: Fields[Partner] = BaseFields
    .withGraphQLRelations(
      "instructors" -> MultiGetGraphQLRelation(
        resourceName = ResourceName("instructors", 1),
        ids = "$instructorIds"),
      "courses" -> MultiGetGraphQLRelation(
        resourceName = ResourceName("courses", 1),
        ids = "$courseIds"))

  def get(id: String) = Nap.get { context =>
    OkIfPresent(id, partnerStore.get(id))
  }

  def multiGet(ids: Set[String]) = Nap.multiGet { context =>
    Ok(partnerStore.all()
      .filter(partner => ids.contains(partner._1))
      .map { case (id, partner) => Keyed(id, partner) }.toList)
  }

  def getAll() = Nap.getAll { context =>
    Ok(partnerStore.all().map { case (id, partner) => Keyed(id, partner) }.toList)
  }

} 
Example 113
Source File: CoursesResource.scala    From naptime   with Apache License 2.0 5 votes vote down vote up
package resources

import javax.inject.Inject
import javax.inject.Singleton

import akka.stream.Materializer
import org.coursera.example.Course
import org.coursera.naptime.Fields
import org.coursera.naptime.GetGraphQLRelation
import org.coursera.naptime.MultiGetGraphQLRelation
import org.coursera.naptime.Ok
import org.coursera.naptime.ResourceName
import org.coursera.naptime.model.Keyed
import org.coursera.naptime.resources.CourierCollectionResource
import stores.CourseStore

import scala.concurrent.ExecutionContext

@Singleton
class CoursesResource @Inject() (
    courseStore: CourseStore)(implicit ec: ExecutionContext, mat: Materializer)
  extends CourierCollectionResource[String, Course] {

  override def resourceName = "courses"
  override def resourceVersion = 1
  override implicit lazy val Fields: Fields[Course] = BaseFields
    .withGraphQLRelations(
      "instructors" -> MultiGetGraphQLRelation(
        resourceName = ResourceName("instructors", 1),
        ids = "$instructorIds"),
      "partner" -> GetGraphQLRelation(
        resourceName = ResourceName("partners", 1),
        id = "$partnerId",
        description = "Partner who produces this course."),
      "courseMetadata/org.coursera.example.CertificateCourseMetadata/certificateInstructors" ->
        MultiGetGraphQLRelation(
          resourceName = ResourceName("instructors", 1),
          ids = "${courseMetadata/certificate/certificateInstructorIds}",
          description = "Instructor whose name and signature appears on the course certificate."),
      "courseMetadata/org.coursera.example.DegreeCourseMetadata/degreeInstructors" ->
        MultiGetGraphQLRelation(
          resourceName = ResourceName("instructors", 1),
          ids = "${courseMetadata/degree/degreeInstructorIds}",
          description = "Instructor whose name and signature appears on the degree certificate."))

  def get(id: String = "v1-123") = Nap.get { context =>
    OkIfPresent(id, courseStore.get(id))
  }

  def multiGet(ids: Set[String], types: Set[String] = Set("course", "specialization")) = Nap.multiGet { context =>
    Ok(courseStore.all()
      .filter(course => ids.contains(course._1))
      .map { case (id, course) => Keyed(id, course) }.toList)
  }

  def getAll() = Nap.getAll { context =>

    val courses = courseStore.all().toList.map { case (id, course) => Keyed(id, course) }
    val coursesAfterNext = context.paging.start
      .map(s => courses.dropWhile(_.key != s))
      .getOrElse(courses)

    val coursesSubset = coursesAfterNext.take(context.paging.limit)

    val next = coursesAfterNext.drop(context.paging.limit).headOption.map(_.key)

    Ok(coursesSubset)
      .withPagination(next, Some(courses.size.toLong))
  }

  def byInstructor(instructorId: String) = Nap.finder { context =>
    val courses = courseStore.all()
      .filter(course => course._2.instructorIds.map(_.toString).contains(instructorId))
    Ok(courses.toList.map { case (id, course) => Keyed(id, course) })
      .withPagination(next = "testNext")
  }

} 
Example 114
Source File: QueryComplexityFilter.scala    From naptime   with Apache License 2.0 5 votes vote down vote up
package org.coursera.naptime.ari.graphql.controllers.filters

import javax.inject.Inject
import javax.inject.Singleton

import com.typesafe.scalalogging.StrictLogging
import org.coursera.naptime.ari.Response
import org.coursera.naptime.ari.graphql.GraphqlSchemaProvider
import org.coursera.naptime.ari.graphql.SangriaGraphQlContext
import org.coursera.naptime.ari.graphql.controllers.GraphQLController
import org.coursera.naptime.ari.graphql.marshaller.NaptimeMarshaller._
import org.coursera.naptime.ari.graphql.resolvers.NaptimeResolver
import org.coursera.naptime.ari.graphql.resolvers.NoopResolver
import play.api.libs.json.JsObject
import play.api.libs.json.Json
import play.api.mvc.Results
import sangria.ast.Document
import sangria.execution.ErrorWithResolver
import sangria.execution.Executor
import sangria.execution.QueryAnalysisError
import sangria.execution.QueryReducer

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

@Singleton
class QueryComplexityFilter @Inject()(
    graphqlSchemaProvider: GraphqlSchemaProvider,
    configuration: ComplexityFilterConfiguration)(implicit executionContext: ExecutionContext)
    extends Filter
    with Results
    with StrictLogging {

  val MAX_COMPLEXITY = configuration.maxComplexity

  def apply(nextFilter: FilterFn): FilterFn = { incoming =>
    computeComplexity(incoming.document, incoming.variables)
      .flatMap { complexity =>
        if (complexity > MAX_COMPLEXITY) {
          Future.successful(
            OutgoingQuery(
              response = Json.obj("error" -> "Query is too complex.", "complexity" -> complexity),
              ariResponse = None))
        } else {
          nextFilter.apply(incoming)
        }
      }
      .recover {
        case error: QueryAnalysisError =>
          OutgoingQuery(error.resolveError.as[JsObject], None)
        case error: ErrorWithResolver =>
          OutgoingQuery(error.resolveError.as[JsObject], None)
        case error: Exception =>
          OutgoingQuery(Json.obj("errors" -> Json.arr(error.getMessage)), None)
      }
  }

  private[graphql] def computeComplexity(queryAst: Document, variables: JsObject)(
      implicit executionContext: ExecutionContext): Future[Double] = {
    // TODO(bryan): is there a way around this var?
    var complexity = 0D
    val complReducer = QueryReducer.measureComplexity[SangriaGraphQlContext] { (c, ctx) =>
      complexity = c
      ctx
    }
    val executorFut = Executor.execute(
      graphqlSchemaProvider.schema,
      queryAst,
      SangriaGraphQlContext(null, null, executionContext, debugMode = false),
      variables = variables,
      exceptionHandler = GraphQLController.exceptionHandler(logger),
      queryReducers = List(complReducer),
      deferredResolver = new NoopResolver())

    executorFut.map { _ =>
      complexity
    }

  }
}

case class ComplexityFilterConfiguration(maxComplexity: Int)

object ComplexityFilterConfiguration {
  val DEFAULT = ComplexityFilterConfiguration(100000)
} 
Example 115
Source File: LocalSchemaProvider.scala    From naptime   with Apache License 2.0 5 votes vote down vote up
package org.coursera.naptime.ari

import javax.inject.Inject

import com.linkedin.data.schema.DataSchema
import com.linkedin.data.schema.RecordDataSchema
import com.typesafe.scalalogging.StrictLogging
import org.coursera.naptime.ResourceName
import org.coursera.naptime.router2.NaptimeRoutes
import org.coursera.naptime.schema.Resource


class LocalSchemaProvider @Inject()(naptimeRoutes: NaptimeRoutes)
    extends SchemaProvider
    with StrictLogging {

  private[this] val resourceSchemaMap: Map[ResourceName, Resource] =
    naptimeRoutes.schemaMap.flatMap {
      // TODO: handle sub resources
      case (_, schema)
          if schema.parentClass.isEmpty ||
            schema.parentClass.contains("org.coursera.naptime.resources.RootResource") =>
        val resourceName = ResourceName(schema.name, version = schema.version.getOrElse(0L).toInt)
        Some(resourceName -> schema)

      case (_, schema) =>
        logger.warn(s"Cannot handle nested resource $schema")
        None
    }

  private[this] val mergedTypes = naptimeRoutes.routerBuilders
    .flatMap(_.types.map(_.tuple))
    .filter(_._2.isInstanceOf[RecordDataSchema])
    .map(tuple => tuple._1 -> tuple._2.asInstanceOf[RecordDataSchema])
    .toMap

  override val fullSchema: FullSchema =
    FullSchema(
      naptimeRoutes.schemaMap.values.toSet,
      naptimeRoutes.routerBuilders.flatMap(_.types.map(_.value)))

  override def mergedType(resourceName: ResourceName): Option[RecordDataSchema] = {
    resourceSchemaMap.get(resourceName).flatMap { schema =>
      mergedTypes.get(schema.mergedType)
    }
  }
} 
Example 116
Source File: Router.scala    From naptime   with Apache License 2.0 5 votes vote down vote up
package org.coursera.naptime.router2

import javax.inject.Inject

import com.google.inject.Injector
import org.coursera.naptime.resources.CollectionResource
import play.api.mvc.RequestHeader

import scala.annotation.tailrec
import scala.collection.immutable
import language.experimental.macros

object Router {
  def build[T <: CollectionResource[_, _, _]]: ResourceRouterBuilder = macro MacroImpls.build[T]

  
      @tailrec
      def routeRequestHelper(
          resourceRouters: Seq[ResourceRouter],
          requestHeader: RequestHeader,
          path: String): Option[RouteAction] = {
        if (resourceRouters.isEmpty) {
          None
        } else {
          val first = resourceRouters.head
          val firstResult = first.routeRequest(path, requestHeader)
          if (firstResult.isDefined) {
            firstResult
          } else {
            routeRequestHelper(resourceRouters.tail, requestHeader, path)
          }
        }
      }

      routeRequestHelper(resourceRouters, requestHeader, path)
    } else {
      None
    }
  }

  // TODO(saeta): add additional functionality (i.e. listing all resources / metadata, etc.)

  // TODO(saeta): performance test the new router implementation & do reasonable optimizations.
} 
Example 117
Source File: OAuth2ProviderActionBuildersSpec.scala    From play2-oauth2-provider   with MIT License 5 votes vote down vote up
package scalaoauth2.provider

import javax.inject.Inject

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

class OAuth2ProviderActionBuildersSpec extends FlatSpec {

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

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

  }

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

} 
Example 118
Source File: Config.scala    From dependency   with MIT License 5 votes vote down vote up
package io.flow.dependency.www.lib

import io.flow.dependency.v0.models.Scms
import io.flow.play.util.{Config => FlowConfig}
import java.net.URLEncoder
import javax.inject.{Inject, Singleton}


@Singleton
class GitHubConfig @Inject()(config: FlowConfig) {
  private val Scopes = Seq("user:email", "repo", "read:repo_hook", "write:repo_hook")
  private val OauthUrl = "https://github.com/login/oauth/authorize"

  private val githubClientId = config.requiredString("github.dependency.client.id")
  private val dependencyWwwHost = config.requiredString("dependency.www.host")
  private val githubBaseUrl = s"$dependencyWwwHost/login/github"

  def githubOauthUrl(returnUrl: Option[String]): String = {
    val returnUrlParam = returnUrl
      .map { encoded =>
        s"$githubBaseUrl?return_url=$encoded"
      }

    val params: Map[String, String] = Seq(
      Some("scope" -> Scopes.mkString(",")),
      Some("client_id" -> githubClientId),
      returnUrlParam.map("redirect_uri" -> _)
    ).flatten.toMap

    val queryParams =
      params
        .view
        .mapValues(URLEncoder.encode(_, "UTF-8"))
        .map {
          case (key, value) => s"$key=$value"
        }

    OauthUrl + "?" + queryParams.mkString("&")
  }

}

object Config {
  val VersionsPerPage = 5

  
  def scmsUrl(scms: Scms, uri: String, path: String): String = {
    val separator = if (path.startsWith("/")) "" else "/"
    val pathSep = separator + path

    scms match {
      case Scms.Github =>
        s"$uri/blob/master$pathSep"

      case Scms.UNDEFINED(_) =>
        uri + pathSep
    }
  }

} 
Example 119
Source File: ResolverActor.scala    From dependency   with MIT License 5 votes vote down vote up
package io.flow.dependency.actors

import javax.inject.Inject
import io.flow.dependency.v0.models.Visibility
import io.flow.postgresql.Pager
import db._
import akka.actor.Actor
import cache.ResolversCache
import io.flow.akka.SafeReceive
import io.flow.log.RollbarLogger

object ResolverActor {

  trait Message

  object Messages {
    case class Created(resolverId: String) extends Message
    case class Sync(resolverId: String) extends Message
    case class Deleted(resolverId: String) extends Message
  }

}

class ResolverActor @Inject()(
  resolversCache: ResolversCache,
  librariesDao: LibrariesDao,
  projectLibrariesDao: InternalProjectLibrariesDao,
  staticUserProvider: StaticUserProvider,
  rollbar: RollbarLogger,
  @javax.inject.Named("project-actor") projectActor: akka.actor.ActorRef,
) extends Actor {

  private[this] implicit val logger: RollbarLogger = rollbar.fingerprint(getClass.getName)
  private[this] lazy val SystemUser = staticUserProvider.systemUser

  def receive: Receive = SafeReceive.withLogUnhandled {

    case ResolverActor.Messages.Created(resolverId) => sync(resolverId)

    case ResolverActor.Messages.Sync(resolverId) => sync(resolverId)

    case ResolverActor.Messages.Deleted(resolverId) =>
      Pager.create { offset =>
        librariesDao.findAll(Authorization.All, resolverId = Some(resolverId), limit = None, offset = offset)
      }.foreach { library =>
        librariesDao.delete(SystemUser, library)
      }
  }

  def sync(resolverId: String): Unit = {
    resolversCache.findByResolverId(resolverId).foreach { resolver =>
      // Trigger resolution for any project libraries that are currently not resolved.
      val auth = (resolver.organization, resolver.visibility) match {
        case (None, _) => Authorization.All
        case (Some(_), Visibility.Public | Visibility.UNDEFINED(_)) => {
          Authorization.All
        }
        case (Some(org), Visibility.Private) => {
          Authorization.Organization(org.id)
        }
      }

      projectLibrariesDao.findAll(auth, hasLibrary = Some(false), limit = None, orderBy = None).foreach { projectLibrary =>
        projectActor ! ProjectActor.Messages.ProjectLibrarySync(projectLibrary.projectId, projectLibrary.id)
      }
    }
  }

} 
Example 120
Source File: PeriodicActor.scala    From dependency   with MIT License 5 votes vote down vote up
package io.flow.dependency.actors

import javax.inject.Inject
import db.{InternalTasksDao, SyncsDao}
import akka.actor.{Actor, ActorLogging, ActorSystem}
import io.flow.akka.SafeReceive
import io.flow.akka.recurring.{ScheduleConfig, Scheduler}
import io.flow.log.RollbarLogger
import io.flow.play.util.ApplicationConfig
import org.joda.time.DateTime

import scala.concurrent.ExecutionContext

object PeriodicActor {

  sealed trait Message

  object Messages {
    case object Purge extends Message
    case object SyncBinaries extends Message
    case object SyncLibraries extends Message
    case object SyncProjects extends Message
  }

}

class PeriodicActor @Inject()(
  config: ApplicationConfig,
  system: ActorSystem,
  syncsDao: SyncsDao,
  internalTasksDao: InternalTasksDao,
  logger: RollbarLogger
) extends Actor with ActorLogging with Scheduler  {

  private[this] implicit val ec: ExecutionContext = system.dispatchers.lookup("periodic-actor-context")
  private[this] implicit val configuredRollbar: RollbarLogger = logger.fingerprint(getClass.getName)

  private[this] case object SyncAll
  private[this] case object Purge

  scheduleRecurring(
    ScheduleConfig.fromConfig(config.underlying.underlying, "io.flow.dependency.api.periodic.sync_all"),
    SyncAll
  )

  scheduleRecurring(
    ScheduleConfig.fromConfig(config.underlying.underlying, "io.flow.dependency.api.periodic.purge"),
    Purge
  )

  def receive: Receive = SafeReceive.withLogUnhandled {
    case Purge => {
      internalTasksDao.deleteAllNonProcessedTasks(DateTime.now.minusHours(12))
      syncsDao.purgeOld()
    }
    case SyncAll => internalTasksDao.queueAll()
  }

} 
Example 121
Source File: UserActor.scala    From dependency   with MIT License 5 votes vote down vote up
package io.flow.dependency.actors

import javax.inject.Inject
import io.flow.dependency.v0.models.{Publication, SubscriptionForm}
import db.{OrganizationsDao, SubscriptionsDao, UserIdentifiersDao, UsersDao}
import akka.actor.Actor
import io.flow.akka.SafeReceive
import io.flow.log.RollbarLogger

object UserActor {

  trait Message

  object Messages {
    case class Created(userId: String) extends Message
  }

}

class UserActor @Inject()(
  organizationsDao: OrganizationsDao,
  userIdentifiersDao: UserIdentifiersDao,
  subscriptionsDao: SubscriptionsDao,
  usersDao: UsersDao,
  rollbar: RollbarLogger
) extends Actor {

  private[this] implicit val logger: RollbarLogger = rollbar.fingerprint(getClass.getName)

  def receive: Receive = SafeReceive.withLogUnhandled {

    case UserActor.Messages.Created(userId) =>
      usersDao.findById(userId).foreach { user =>
        organizationsDao.upsertForUser(user)

        // This method will force create an identifier
        userIdentifiersDao.latestForUser(usersDao.systemUser, user)

        // Subscribe the user automatically to key personalized emails.
        Seq(Publication.DailySummary).foreach { publication =>
          subscriptionsDao.upsertByUserIdAndPublication(
            usersDao.systemUser,
            SubscriptionForm(
              userId = user.id,
              publication = publication
            )
          )
        }
      }
  }

} 
Example 122
Source File: BinaryActor.scala    From dependency   with MIT License 5 votes vote down vote up
package io.flow.dependency.actors

import javax.inject.Inject
import io.flow.postgresql.Pager
import db.{Authorization, InternalItemsDao, ProjectBinariesDao, StaticUserProvider}
import akka.actor.Actor
import io.flow.akka.SafeReceive
import io.flow.log.RollbarLogger

object BinaryActor {

  object Messages {
    case class Delete(binaryId: String)
  }

}

class BinaryActor @Inject() (
  staticUserProvider: StaticUserProvider,
  itemsDao: InternalItemsDao,
  projectBinariesDao: ProjectBinariesDao,
  logger: RollbarLogger,
  @javax.inject.Named("project-actor") projectActor: akka.actor.ActorRef,
) extends Actor {

  private[this] implicit val configuredRollbar: RollbarLogger = logger.fingerprint(getClass.getName)

  def receive: Receive = SafeReceive.withLogUnhandled {

    case BinaryActor.Messages.Delete(binaryId: String) =>
      itemsDao.deleteByObjectId(staticUserProvider.systemUser, binaryId)

      Pager.create { offset =>
        projectBinariesDao.findAll(Authorization.All, binaryId = Some(binaryId), offset = offset)
      }.foreach { projectBinary =>
        projectBinariesDao.removeBinary(staticUserProvider.systemUser, projectBinary)
        projectActor ! ProjectActor.Messages.ProjectBinarySync(projectBinary.project.id, projectBinary.id)
      }
  }

} 
Example 123
Source File: SearchActor.scala    From dependency   with MIT License 5 votes vote down vote up
package io.flow.dependency.actors

import javax.inject.Inject
import db._
import akka.actor.Actor
import io.flow.akka.SafeReceive
import io.flow.common.v0.models.UserReference
import io.flow.log.RollbarLogger

object SearchActor {

  sealed trait Message

  object Messages {
    case class SyncBinary(id: String) extends Message
    case class SyncLibrary(id: String) extends Message
    case class SyncProject(id: String) extends Message
  }

}

class SearchActor @Inject()(
  binariesDao: BinariesDao,
  librariesDao: LibrariesDao,
  projectsDao: ProjectsDao,
  internalItemsDao: InternalItemsDao,
  staticUserProvider: StaticUserProvider,
  logger: RollbarLogger
) extends Actor {

  private[this] implicit val configuredRollbar: RollbarLogger = logger.fingerprint(getClass.getName)

  private[this] lazy val SystemUser: UserReference = staticUserProvider.systemUser

  def receive: Receive = SafeReceive.withLogUnhandled {

    case SearchActor.Messages.SyncBinary(id) =>
      binariesDao.findById(id) match {
        case None => internalItemsDao.deleteByObjectId(SystemUser, id)
        case Some(binary) => internalItemsDao.replaceBinary(SystemUser, binary)
      }
      ()

    case SearchActor.Messages.SyncLibrary(id) =>
      librariesDao.findById(Authorization.All, id) match {
        case None => internalItemsDao.deleteByObjectId(SystemUser, id)
        case Some(library) => internalItemsDao.replaceLibrary(SystemUser, library)
      }
      ()

    case SearchActor.Messages.SyncProject(id) =>
      projectsDao.findById(Authorization.All, id) match {
        case None => internalItemsDao.deleteByObjectId(SystemUser, id)
        case Some(project) => internalItemsDao.replaceProject(SystemUser, project)
      }
      ()
  }

} 
Example 124
Source File: LibraryActor.scala    From dependency   with MIT License 5 votes vote down vote up
package io.flow.dependency.actors

import javax.inject.Inject
import db.{Authorization, InternalItemsDao, InternalProjectLibrariesDao, StaticUserProvider}
import akka.actor.Actor
import io.flow.akka.SafeReceive
import io.flow.log.RollbarLogger

object LibraryActor {

  object Messages {
    case class Delete(id: String)
  }

}

class LibraryActor @Inject()(
  itemsDao: InternalItemsDao,
  projectLibrariesDao: InternalProjectLibrariesDao,
  staticUserProvider: StaticUserProvider,
  logger: RollbarLogger,
  @javax.inject.Named("project-actor") projectActor: akka.actor.ActorRef,
) extends Actor {

  private[this] implicit val configuredRollbar: RollbarLogger = logger.fingerprint(getClass.getName)

  def receive: Receive = SafeReceive.withLogUnhandled {

    case LibraryActor.Messages.Delete(libraryId: String) => {
      itemsDao.deleteByObjectId(staticUserProvider.systemUser, libraryId)

      projectLibrariesDao.findAll(Authorization.All, libraryId = Some(libraryId), limit = None, orderBy = None).foreach { projectLibrary =>
        projectLibrariesDao.removeLibrary(staticUserProvider.systemUser, projectLibrary)
        projectActor ! ProjectActor.Messages.ProjectLibrarySync(projectLibrary.projectId, projectLibrary.id)
      }
    }
  }

} 
Example 125
Source File: LibraryRecommendationsDao.scala    From dependency   with MIT License 5 votes vote down vote up
package db

import javax.inject.{Inject, Singleton}

import io.flow.dependency.api.lib.Recommendations
import io.flow.dependency.v0.models.{Library, LibraryVersion, Project, VersionForm}
import com.google.inject.Provider

case class LibraryRecommendation(
  library: Library,
  from: String,
  to: LibraryVersion,
  latest: LibraryVersion
)

@Singleton
class LibraryRecommendationsDao @Inject()(
  internalProjectLibrariesDao: InternalProjectLibrariesDao,
  libraryVersionsDaoProvider: Provider[LibraryVersionsDao],
  librariesDaoProvider: Provider[LibrariesDao],
){

  def forProject(project: Project): Seq[LibraryRecommendation] = {
    val recommendations = scala.collection.mutable.ListBuffer[LibraryRecommendation]()
    val auth = Authorization.Organization(project.organization.id)

    internalProjectLibrariesDao.findAll(
      Authorization.Organization(project.organization.id),
      projectId = Some(project.id),
      hasLibrary = Some(true),
      limit = None,
      orderBy = None,
    ).foreach { projectLibrary =>
      projectLibrary.db.libraryId.flatMap { libraryId => librariesDaoProvider.get.findById(auth, libraryId) }.map { library =>
        val recentVersions = versionsGreaterThan(auth, library, projectLibrary.db.version)
        recommend(projectLibrary, recentVersions).map { v =>
          recommendations ++= Seq(
            LibraryRecommendation(
              library = library,
              from = projectLibrary.db.version,
              to = v,
              latest = recentVersions.headOption.getOrElse(v)
            )
          )
        }
      }
    }

    recommendations.toSeq
  }

  def recommend(current: InternalProjectLibrary, others: Seq[LibraryVersion]): Option[LibraryVersion] = {
    Recommendations.version(
      VersionForm(current.db.version, current.db.crossBuildVersion),
      others.map(v => VersionForm(v.version, v.crossBuildVersion))
    ).map { version =>
      others.find { _.version == version }.getOrElse {
        sys.error(s"Failed to find recommended library with version[$version]")
      }
    }
  }

  
  private[this] def versionsGreaterThan(
    auth: Authorization,
    library: Library,
    version: String
  ): Seq[LibraryVersion] = {
    libraryVersionsDaoProvider.get.findAll(
      auth,
      libraryId = Some(library.id),
      greaterThanVersion = Some(version),
      limit = None
    )
  }

} 
Example 126
Source File: BinaryRecommendationsDao.scala    From dependency   with MIT License 5 votes vote down vote up
package db

import javax.inject.{Inject, Singleton}

import io.flow.dependency.api.lib.Recommendations
import io.flow.dependency.v0.models.{Binary, BinaryVersion, Project, ProjectBinary, VersionForm}
import io.flow.postgresql.Pager
import com.google.inject.Provider

case class BinaryRecommendation(
  binary: Binary,
  from: String,
  to: BinaryVersion,
  latest: BinaryVersion
)

@Singleton
class BinaryRecommendationsDao @Inject()(
  binaryVersionsDaoProvider: Provider[BinaryVersionsDao],
  projectBinariesDaoProvider: Provider[ProjectBinariesDao],
  binariesDaoProvider: Provider[BinariesDao]
) {

  def forProject(project: Project): Seq[BinaryRecommendation] = {
    val recommendations = scala.collection.mutable.ListBuffer[BinaryRecommendation]()

    Pager.create { offset =>
      projectBinariesDaoProvider.get.findAll(
        Authorization.Organization(project.organization.id),
        projectId = Some(project.id),
        hasBinary = Some(true),
        offset = offset
      )
    }.foreach { projectBinary =>
      projectBinary.binary.flatMap { lib => binariesDaoProvider.get.findById(lib.id) }.map { binary =>
        val recentVersions = versionsGreaterThan(binary, projectBinary.version)
        recommend(projectBinary, recentVersions).map { v =>
          recommendations ++= Seq(
            BinaryRecommendation(
              binary = binary,
              from = projectBinary.version,
              to = v,
              latest = recentVersions.headOption.getOrElse(v)
            )
          )
        }
      }
    }

    recommendations.toSeq
  }

  def recommend(current: ProjectBinary, others: Seq[BinaryVersion]): Option[BinaryVersion] = {
    Recommendations.version(
      VersionForm(current.version),
      others.map(v => VersionForm(v.version))
    ).map { version =>
      others.find {
        _.version == version
      }.getOrElse {
        sys.error(s"Failed to find recommended binary with version[$version]")
      }
    }
  }

  
  private[this] def versionsGreaterThan(binary: Binary, version: String): Seq[BinaryVersion] = {
    val recommendations = scala.collection.mutable.ListBuffer[BinaryVersion]()
    Pager.create { offset =>
      binaryVersionsDaoProvider.get.findAll(
        binaryId = Some(binary.id),
        greaterThanVersion = Some(version),
        offset = offset
      )
    }.foreach { binaryVersion =>
      recommendations ++= Seq(binaryVersion)
    }
    recommendations.toSeq
  }

} 
Example 127
Source File: GithubUsersDao.scala    From dependency   with MIT License 5 votes vote down vote up
package db

import javax.inject.Inject
import io.flow.postgresql.{OrderBy, Query}
import io.flow.dependency.v0.models.{GithubUser, GithubUserForm}
import io.flow.common.v0.models.UserReference
import io.flow.util.IdGenerator
import anorm._
import com.google.inject.Provider
import play.api.db._

class GithubUsersDao @Inject()(
  db: Database,
  usersDaoProvider: Provider[UsersDao]
){

  private[this] val BaseQuery = Query(s"""
    select github_users.id,
           github_users.user_id,
           github_users.github_user_id,
           github_users.login
      from github_users
  """)

  private[this] val InsertQuery = """
    insert into github_users
    (id, user_id, github_user_id, login, updated_by_user_id)
    values
    ({id}, {user_id}, {github_user_id}, {login}, {updated_by_user_id})
  """

  def upsertById(createdBy: Option[UserReference], form: GithubUserForm): GithubUser = {
    db.withConnection { implicit c =>
      upsertByIdWithConnection(createdBy, form)
    }
  }

  def upsertByIdWithConnection(createdBy: Option[UserReference], form: GithubUserForm)(implicit c: java.sql.Connection): GithubUser = {
    findByGithubUserId(form.githubUserId).getOrElse {
      createWithConnection(createdBy, form)
    }
  }

  def create(createdBy: Option[UserReference], form: GithubUserForm): GithubUser = {
    db.withConnection { implicit c =>
      createWithConnection(createdBy, form)
    }
  }

  private[db] def createWithConnection(createdBy: Option[UserReference], form: GithubUserForm)(implicit c: java.sql.Connection): GithubUser = {
    val id = IdGenerator("ghu").randomId()
    SQL(InsertQuery).on(
      Symbol("id") -> id,
      Symbol("user_id") -> form.userId,
      Symbol("github_user_id") -> form.githubUserId,
      Symbol("login") -> form.login.trim,
      Symbol("updated_by_user_id") -> createdBy.getOrElse(usersDaoProvider.get.anonymousUser).id
    ).execute()

    findById(id).getOrElse {
      sys.error("Failed to create github user")
    }
  }

  def findByGithubUserId(githubUserId: Long): Option[GithubUser] = {
    findAll(githubUserId = Some(githubUserId), limit = 1).headOption
  }

  def findById(id: String): Option[GithubUser] = {
    findAll(id = Some(Seq(id)), limit = 1).headOption
  }

  def findAll(
    id: Option[Seq[String]] = None,
    userId: Option[String] = None,
    login: Option[String] = None,
    githubUserId: Option[Long] = None,
    orderBy: OrderBy = OrderBy("github_users.created_at"),
    limit: Long = 25,
    offset: Long = 0
  ): Seq[GithubUser] = {
    db.withConnection { implicit c =>
      BaseQuery.
        optionalIn("github_users.id", id).
        equals("github_users.user_id", userId).
        optionalText("github_users.login", login).
        equals("github_users.github_user_id", githubUserId).
        orderBy(orderBy.sql).
        limit(limit).
        offset(offset).
        as(
          io.flow.dependency.v0.anorm.parsers.GithubUser.parser().*
        )
    }
  }

} 
Example 128
Source File: OrganizationsHelper.scala    From dependency   with MIT License 5 votes vote down vote up
package controllers.helpers

import javax.inject.{Inject, Singleton}

import db.{Authorization, OrganizationsDao}
import io.flow.common.v0.models.UserReference
import io.flow.dependency.v0.models.Organization
import play.api.mvc.{Result, Results}

@Singleton
class OrganizationsHelper @Inject()(
  organizationsDao: OrganizationsDao
) {

  def withOrganization(user: UserReference, id: String)(
    f: Organization => Result
  ) = {
    organizationsDao.findById(Authorization.User(user.id), id) match {
      case None => {
        Results.NotFound
      }
      case Some(organization) => {
        f(organization)
      }
    }
  }

} 
Example 129
Source File: BinaryHelper.scala    From dependency   with MIT License 5 votes vote down vote up
package controllers.helpers

import javax.inject.{Inject, Singleton}

import db.BinariesDao
import io.flow.dependency.v0.models.Binary
import play.api.mvc.{Result, Results}

@Singleton
class BinaryHelper @Inject()(
  binariesDao: BinariesDao
) {

  def withBinary(id: String)(
    f: Binary => Result
  ): Result = {
    binariesDao.findById(id) match {
      case None => {
        Results.NotFound
      }
      case Some(binary) => {
        f(binary)
      }
    }
  }


} 
Example 130
Source File: LibrariesHelper.scala    From dependency   with MIT License 5 votes vote down vote up
package controllers.helpers

import javax.inject.{Inject, Singleton}

import db.{Authorization, LibrariesDao}
import io.flow.common.v0.models.UserReference
import io.flow.dependency.v0.models.Library
import play.api.mvc.{Result, Results}

@Singleton
class LibrariesHelper @Inject()(
  librariesDao: LibrariesDao
) {

  def withLibrary(user: UserReference, id: String)(
    f: Library => Result
  ): Result = {
    librariesDao.findById(Authorization.User(user.id), id) match {
      case None => {
        Results.NotFound
      }
      case Some(library) => {
        f(library)
      }
    }
  }


} 
Example 131
Source File: UsersHelper.scala    From dependency   with MIT License 5 votes vote down vote up
package controllers.helpers

import javax.inject.{Inject, Singleton}

import db.UsersDao
import io.flow.common.v0.models.User
import play.api.mvc.{Result, Results}

@Singleton
class UsersHelper @Inject()(
  usersDao: UsersDao
) {

  def withUser(id: String)(
    f: User => Result
  ) = {
    usersDao.findById(id) match {
      case None => {
        Results.NotFound
      }
      case Some(user) => {
        f(user)
      }
    }
  }

} 
Example 132
Source File: ProjectHelper.scala    From dependency   with MIT License 5 votes vote down vote up
package controllers.helpers

import javax.inject.{Inject, Singleton}

import db.{Authorization, ProjectsDao}
import io.flow.common.v0.models.UserReference
import io.flow.dependency.v0.models.Project
import play.api.mvc.{Result, Results}

@Singleton
class ProjectHelper @Inject()(
  projectsDao: ProjectsDao
) {

  def withProject(user: UserReference, id: String)(
    f: Project => Result
  ): Result = {
    projectsDao.findById(Authorization.User(user.id), id) match {
      case None => {
        Results.NotFound
      }
      case Some(project) => {
        f(project)
      }
    }
  }


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

import javax.inject.Inject
import controllers.util.IdentificationWithFallback
import db.{TokensDao, UsersDao}
import io.flow.log.RollbarLogger
import io.flow.play.controllers.{AuthorizationImpl, FlowController}
import io.flow.play.util.Config
import play.api.mvc.BodyParsers

trait BaseIdentifiedControllerWithFallback extends FlowController {

  def config: Config
  def baseIdentifiedControllerWithFallbackComponents: BaseIdentifiedControllerWithFallbackComponents

  private lazy val identifiedWithFallback: IdentificationWithFallback =
    new IdentificationWithFallback(
      baseIdentifiedControllerWithFallbackComponents.parser,
      config,
      baseIdentifiedControllerWithFallbackComponents.authorization,
      baseIdentifiedControllerWithFallbackComponents.tokensDao,
      baseIdentifiedControllerWithFallbackComponents.usersDao,
    )(
      controllerComponents.executionContext,
      baseIdentifiedControllerWithFallbackComponents.logger
    )

  def IdentifiedWithFallback = identifiedWithFallback

}

case class BaseIdentifiedControllerWithFallbackComponents @Inject() (
  parser: BodyParsers.Default,
  authorization: AuthorizationImpl,
  tokensDao: TokensDao,
  usersDao: UsersDao,
  logger: RollbarLogger
) 
Example 134
Source File: ProjectDependencyResolutions.scala    From dependency   with MIT License 5 votes vote down vote up
package controllers

import cache.ProjectDependencyResolutionServiceCache
import db.{Authorization, MembershipsDao}
import io.flow.common.v0.models.UserReference
import io.flow.dependency.v0.models.json._
import io.flow.play.controllers.FlowControllerComponents
import javax.inject.{Inject, Singleton}
import play.api.mvc._
import io.flow.util.Config
import play.api.libs.json.Json

@Singleton
class ProjectDependencyResolutions @Inject() (
  val config: Config,
  val controllerComponents: ControllerComponents,
  val flowControllerComponents: FlowControllerComponents,
  val baseIdentifiedControllerWithFallbackComponents: BaseIdentifiedControllerWithFallbackComponents,
  membershipsDao: MembershipsDao,
  service: ProjectDependencyResolutionServiceCache,
) extends BaseIdentifiedControllerWithFallback {

  def get(organization: String, groupId: String): Action[AnyContent] = IdentifiedWithFallback { request =>
    withValidatedMember(request.user, organization) {
      Ok(
        Json.toJson(
          service.getByOrganizationKey(organization, groupId = groupId)
        )
      )
    }
  }

  private[this] def withValidatedMember(user: UserReference, organizationKey: String)(f: => Result): Result = {
    membershipsDao.findByOrganizationAndUserId(Authorization.All, organizationKey, user.id) match {
      case None => Unauthorized
      case Some(_) => f
    }
  }
} 
Example 135
Source File: IdentificationWithFallback.scala    From dependency   with MIT License 5 votes vote down vote up
package controllers.util

import java.util.UUID

import javax.inject.{Inject, Singleton}
import db.{TokensDao, UsersDao}
import io.flow.common.v0.models.UserReference
import io.flow.log.RollbarLogger
import io.flow.play.controllers._
import io.flow.play.util.{AuthData, Config}
import play.api.mvc._

import scala.concurrent.{ExecutionContext, Future}

// Custom implementation based on FlowController.Identified but with database fallback for auth
@Singleton
class IdentificationWithFallback @Inject()(
  val parser: BodyParsers.Default,
  val config: Config,
  authorization: AuthorizationImpl,
  tokensDao: TokensDao,
  usersDao: UsersDao
)(implicit val executionContext: ExecutionContext, logger: RollbarLogger)
  extends ActionBuilder[IdentifiedRequest, AnyContent] with FlowActionInvokeBlockHelper {

  def invokeBlock[A](request: Request[A], block: (IdentifiedRequest[A]) => Future[Result]): Future[Result] = {
    auth(request.headers)(AuthData.Identified.fromMap) match {
      case None =>
        legacyUser(request.headers) match {
          case None => Future.successful(unauthorized(request))
          case Some(user) =>
            val ad = AuthData.Identified(user = user, session = None, requestId = "lib-play-" + UUID.randomUUID.toString, customer = None)
            block(new IdentifiedRequest(ad, request))
        }
      case Some(ad) => block(new IdentifiedRequest(ad, request))
    }
  }

  private[this] def legacyUser(headers: Headers): Option[UserReference] = {
    basicAuthorizationToken(headers) match {
      case None => None
      case Some(token) => {
        token match {
          case token: Token => getUser(token.token)
          case token: JwtToken => Some(UserReference(token.userId))
        }
      }
    }
  }

  private def getUser(token: String): Option[UserReference] = {
    tokensDao.findByToken(token) match {
      case Some(t) => Some(UserReference(t.user.id))
      case None => usersDao.findById(token).map(user => UserReference(user.id))
    }
  }

  
  private[this] def basicAuthorizationToken(
    headers: play.api.mvc.Headers
  ): Option[Authorization] = {
    headers.get("Authorization").flatMap { h =>
      authorization.get(h)
    }
  }

} 
Example 136
Source File: Conversions.scala    From dependency   with MIT License 5 votes vote down vote up
package lib

import db.{Authorization, InternalProjectLibrary, ProjectsDao}
import io.flow.dependency.v0.models.{Project, ProjectDetail, ProjectLibrary, Reference}
import javax.inject.Inject

class Conversions @Inject() (
  projectsDao: ProjectsDao,
) {

  def toProjectLibraryModels(libraries: Seq[InternalProjectLibrary]): Seq[ProjectLibrary] = {
    val projectsById = projectsDao.findAll(
      Authorization.All,
      ids = Some(libraries.map(_.projectId).distinct),
      limit = None,
    ).map { p => p.id -> p }.toMap

    libraries.flatMap { pl =>
      projectsById.get(pl.projectId).map { project =>
        ProjectLibrary(
          id = pl.id,
          project = toProjectDetailModel(project),
          groupId = pl.groupId,
          artifactId = pl.artifactId,
          version = pl.db.version,
          crossBuildVersion = pl.db.crossBuildVersion,
          path = pl.db.path,
          library = pl.db.libraryId.map { id => Reference(id) }
        )
      }
    }
  }

  def toProjectLibraryModel(pl: InternalProjectLibrary): Option[ProjectLibrary] = {
    toProjectLibraryModels(Seq(pl)).headOption
  }

  private[this] def toProjectDetailModel(project: Project): ProjectDetail = {
    ProjectDetail(
      id = project.id,
      organization = project.organization,
      name = project.name,
    )
  }
} 
Example 137
Source File: BinarySync.scala    From dependency   with MIT License 5 votes vote down vote up
package sync

import db.{BinariesDao, BinaryVersionsDao, SyncsDao}
import io.flow.common.v0.models.UserReference
import io.flow.dependency.actors.SearchActor
import io.flow.dependency.api.lib.DefaultBinaryVersionProvider
import io.flow.dependency.v0.models.Binary
import io.flow.log.RollbarLogger
import io.flow.postgresql.Pager
import javax.inject.Inject

class BinarySync @Inject() (
  binariesDao: BinariesDao,
  defaultBinaryVersionProvider: DefaultBinaryVersionProvider,
  binaryVersionsDao: BinaryVersionsDao,
  syncsDao: SyncsDao,
  @javax.inject.Named("search-actor") searchActor: akka.actor.ActorRef,
  logger: RollbarLogger,
) {

  def sync(user: UserReference, binaryId: String): Unit = {
    binariesDao.findById(binaryId).foreach { binary =>
      syncsDao.withStartedAndCompleted("binary", binary.id) {
        val versions = defaultBinaryVersionProvider.versions(binary.name)
        logger
          .fingerprint(s"${getClass.getName}:results")
          .withKeyValue("binary", binary.toString)
          .withKeyValue("versions", versions.toString)
          .info("result")

        versions.foreach { version =>
          binaryVersionsDao.upsert(user, binary.id, version.value)
        }
      }
    }
    searchActor ! SearchActor.Messages.SyncBinary(binaryId)
  }
  def iterateAll()(f: Binary => Any): Unit = {
    Pager.create { offset =>
      binariesDao.findAll(offset = offset, limit = 1000)
    }.foreach { rec =>
      f(rec)
    }
  }
} 
Example 138
Source File: LibrarySync.scala    From dependency   with MIT License 5 votes vote down vote up
package sync

import db.{Authorization, InternalTask, InternalTasksDao, LibrariesDao, LibraryVersionsDao, InternalProjectLibrariesDao, ResolversDao, SyncsDao}
import io.flow.common.v0.models.UserReference
import io.flow.dependency.actors.SearchActor
import io.flow.dependency.api.lib.{ArtifactVersion, DefaultLibraryArtifactProvider}
import io.flow.dependency.v0.models.{Library, LibraryVersion, Resolver, VersionForm}
import io.flow.postgresql.Pager
import javax.inject.Inject

class LibrarySync @Inject()(
  librariesDao: LibrariesDao,
  resolversDao: ResolversDao,
  libraryVersionsDao: LibraryVersionsDao,
  projectLibrariesDao: InternalProjectLibrariesDao,
  internalTasksDao: InternalTasksDao,
  artifactProvider: DefaultLibraryArtifactProvider,
  syncsDao: SyncsDao,
  @javax.inject.Named("search-actor") searchActor: akka.actor.ActorRef,
) {

  private[this] def toVersionForm(version: ArtifactVersion): VersionForm = VersionForm(version.tag.value, version.crossBuildVersion.map(_.value))
  private[this] def toVersionForm(lv: LibraryVersion): VersionForm = VersionForm(lv.version, lv.crossBuildVersion)

  
  private[this] def versionsOnResolver(lib: Library, resolver: Resolver): Seq[VersionForm] = {
    artifactProvider.resolve(
      resolver = resolver,
      groupId = lib.groupId,
      artifactId = lib.artifactId
    ) match {
      case None => Nil
      case Some(r) => r.versions.map(toVersionForm)
    }
  }

  def sync(user: UserReference, libraryId: String): Unit = {
    librariesDao.findById(Authorization.All, libraryId).foreach { lib =>
      lazy val existing = existingVersions(lib.id)

      syncsDao.withStartedAndCompleted("library", lib.id) {
        val newVersions: Seq[VersionForm] = resolversDao.findById(Authorization.All, lib.resolver.id).toSeq.flatMap { resolver =>
          versionsOnResolver(lib, resolver).filterNot(existing.contains)
        }
        newVersions.foreach { versionForm =>
          libraryVersionsDao.upsert(
            createdBy = user,
            libraryId = lib.id,
            form = versionForm,
          )
        }
        if (newVersions.nonEmpty) {
          createTaskToSyncProjectsDependentOnLibrary(lib.id)
        }
      }
    }
    searchActor ! SearchActor.Messages.SyncLibrary(libraryId)
  }

  def iterateAll(
    auth: Authorization,
    organizationId: Option[String] = None,
    prefix: Option[String] = None,
  )(f: Library => Any): Unit = {
    Pager.create { offset =>
      librariesDao.findAll(
        auth,
        organizationId = organizationId,
        prefix = prefix,
        offset = offset,
        limit = Some(1000),
      )
    }.foreach { rec =>
      f(rec)
    }
  }

  private[this] def createTaskToSyncProjectsDependentOnLibrary(libraryId: String): Unit = {
    internalTasksDao.queueProjects(
      projectIds = projectLibrariesDao.findAll(
        Authorization.All,
        libraryId = Some(libraryId),
        limit = None,
        orderBy = None,
      ).map(_.projectId),
      priority = InternalTask.MediumPriority
    )
  }
} 
Example 139
Source File: HelloWorldController.scala    From playsonify   with MIT License 5 votes vote down vote up
package controllers

import javax.inject.Inject

import com.alexitc.example.UserError
import controllers.common.{MyJsonController, MyJsonControllerComponents}
import org.scalactic.{Bad, Every, Good}
import play.api.libs.json.{Json, Reads, Writes}

import scala.concurrent.Future

class HelloWorldController @Inject() (components: MyJsonControllerComponents)
    extends MyJsonController(components) {

  import Context._

  def hello = publicInput { context: HasModel[Person] =>
    val msg = s"Hello ${context.model.name}, you are ${context.model.age} years old"
    val helloMessage = HelloMessage(msg)
    val goodResult = Good(helloMessage)

    Future.successful(goodResult)
  }

  def authenticatedHello = authenticated { context: Authenticated =>
    val msg = s"Hello user with id ${context.auth}"
    val helloMessage = HelloMessage(msg)
    val goodResult = Good(helloMessage)

    Future.successful(goodResult)
  }

  def failedHello = public[HelloMessage] { context: Context =>
    val errors = Every(
      UserError.UserEmailIncorrect,
      UserError.UserAlreadyExist,
      UserError.UserNotFound)

    val badResult = Bad(errors)
    Future.successful(badResult)
  }

  def exceptionHello = public[HelloMessage] { context: Context =>
    Future.failed(new RuntimeException("database unavailable"))
  }
}

case class Person(name: String, age: Int)

object Person {
  implicit val reads: Reads[Person] = Json.reads[Person]
}


case class HelloMessage(message: String)

object HelloMessage {
  implicit val writes: Writes[HelloMessage] = Json.writes[HelloMessage]
} 
Example 140
Source File: PublicController.scala    From playsonify   with MIT License 5 votes vote down vote up
package com.alexitc.playsonify.play.controllers

import javax.inject.Inject

import com.alexitc.playsonify.play.common._
import org.scalactic.{Bad, Good, Many}

import scala.concurrent.Future

class PublicController @Inject() (cc: CustomControllerComponents) extends CustomJsonController(cc) {

  def getModel(int: Int, string: String) = public { context =>
    val result = CustomModel(int, string)
    Future.successful(Good(result))
  }

  def getCustomStatus() = public(Created) { context =>
    val result = CustomModel(0, "no")
    Future.successful(Good(result))
  }

  def getErrors() = public[CustomModel] { _: Context =>
    val result = Bad(Many(CustomError.InputError, CustomError.DuplicateError))
    Future.successful(result)
  }

  def getException(exception: Exception) = public[CustomModel] { _: Context =>
    Future.failed(exception)
  }
} 
Example 141
Source File: PersonRepository.scala    From akka-http-test   with Apache License 2.0 5 votes vote down vote up
package com.github.dnvriend.component.repository

import javax.inject.{ Inject, Singleton }

import akka.NotUsed
import akka.stream.scaladsl.Source
import com.github.dnvriend.component.simpleserver.dto.http.Person

import scala.concurrent.{ ExecutionContext, Future }

@Singleton
class PersonRepository @Inject() (implicit ec: ExecutionContext) {
  def people(numberOfPeople: Int): Source[Person, NotUsed] =
    Source.repeat(Person("foo", 1, false)).zipWith(Source.fromIterator(() => Iterator from 0)) {
      case (p, i) => p.copy(
        name = if (i % 10 == 0) "baz-" + i else if (i % 2 == 0) "foo-" + i else "bar-" + i,
        age = i,
        married = i % 2 == 0
      )
    }.take(numberOfPeople)

  def listOfPersons(numberOfPeople: Int): Seq[Person] = (0 to numberOfPeople).map { i =>
    Person(
      name = if (i % 10 == 0) "baz-" + i else if (i % 2 == 0) "foo-" + i else "bar-" + i,
      age = i,
      married = i % 2 == 0
    )
  }

  def personAsync: Future[Person] = Future.successful(personSync)

  def personAsyncFailed: Future[Person] = Future.failed(new RuntimeException("This should fail")).map(_ => personSync)

  def personSync: Person = Person("John Doe", 25, false)
} 
Example 142
Source File: SimpleServer.scala    From akka-http-test   with Apache License 2.0 5 votes vote down vote up
package com.github.dnvriend.component.simpleserver

import javax.inject.Inject

import akka.actor.ActorSystem
import akka.event.{ Logging, LoggingAdapter }
import akka.http.scaladsl._
import akka.pattern.CircuitBreaker
import akka.stream.{ ActorMaterializer, Materializer }
import com.github.dnvriend.component.repository.PersonRepository
import com.github.dnvriend.component.simpleserver.route._
import com.google.inject.Singleton
import play.api.Configuration

import scala.concurrent.ExecutionContext
import scala.concurrent.duration._

@Singleton
class SimpleServer @Inject() (personDao: PersonRepository, cb: CircuitBreaker, interface: String, port: Int)(implicit system: ActorSystem, mat: Materializer, ec: ExecutionContext) {
  Http().bindAndHandle(SimpleServerRestRoutes.routes(personDao, cb), interface, port)
}

object SimpleServerLauncher extends App {
  implicit val system: ActorSystem = ActorSystem()
  implicit val mat: Materializer = ActorMaterializer()
  implicit val ec: ExecutionContext = system.dispatcher
  implicit val log: LoggingAdapter = Logging(system, this.getClass)
  val maxFailures: Int = 3
  val callTimeout: FiniteDuration = 1.seconds
  val resetTimeout: FiniteDuration = 10.seconds
  val cb = new CircuitBreaker(system.scheduler, maxFailures, callTimeout, resetTimeout)
  val config: play.api.Configuration = Configuration(system.settings.config)

  sys.addShutdownHook {
    system.terminate()
  }

  new SimpleServer(new PersonRepository, cb, config.getString("http.interface").getOrElse("0.0.0.0"), config.getInt("http.port").getOrElse(8080))
} 
Example 143
Source File: Module.scala    From akka-http-test   with Apache License 2.0 5 votes vote down vote up
import javax.inject.Inject

import akka.actor.ActorSystem
import akka.pattern.CircuitBreaker
import akka.stream.Materializer
import com.github.dnvriend.component.repository.PersonRepository
import com.github.dnvriend.component.simpleserver.SimpleServer
import com.google.inject.{ AbstractModule, Provider, Provides }
import play.api.Configuration
import play.api.libs.concurrent.AkkaGuiceSupport

import scala.concurrent.ExecutionContext
import scala.concurrent.duration._

class Module extends AbstractModule with AkkaGuiceSupport {
  override def configure(): Unit = {
    bind(classOf[SimpleServer])
      .toProvider(classOf[SimpleServerProvider])
      .asEagerSingleton()
  }

  @Provides
  def circuitBreakerProvider(system: ActorSystem)(implicit ec: ExecutionContext): CircuitBreaker = {
    val maxFailures: Int = 3
    val callTimeout: FiniteDuration = 1.seconds
    val resetTimeout: FiniteDuration = 10.seconds
    new CircuitBreaker(system.scheduler, maxFailures, callTimeout, resetTimeout)
  }
}

// alternative way to provide services
class SimpleServerProvider @Inject() (personRepository: PersonRepository, cb: CircuitBreaker, config: Configuration)(implicit system: ActorSystem, mat: Materializer, ec: ExecutionContext) extends Provider[SimpleServer] {
  override def get(): SimpleServer =
    new SimpleServer(personRepository, cb, config.getString("http.interface").getOrElse("0.0.0.0"), config.getInt("http.port").getOrElse(8080))
} 
Example 144
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 145
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 146
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 147
Source File: SecurityFilterSpec.scala    From play-zhewbacca   with MIT License 5 votes vote down vote up
package org.zalando.zhewbacca

import javax.inject.{Inject, Provider}
import play.api.inject._
import play.api.inject.guice.GuiceApplicationBuilder
import play.api.mvc.Results._
import play.api.mvc._
import play.api.routing.Router
import play.api.test.{FakeRequest, PlaySpecification}
import play.api.{Application, Mode}

class SecurityFilterSpec extends PlaySpecification with BodyParsers {

  val testTokenInfo = TokenInfo("", Scope.Empty, "token type", "user uid", realm = "/employees")

  def appWithRoutes: Application = new GuiceApplicationBuilder()
    .in(Mode.Test)
    .bindings(bind[AuthProvider] to new AlwaysPassAuthProvider(testTokenInfo))
    .overrides(
      bind[Router].toProvider[SecurityFilterTestRouterProvider])
    .configure(
      "play.http.filters" -> "org.zalando.zhewbacca.TestingFilters",
      "authorisation.rules.file" -> "security_filter.conf")
    .build

  "SecurityFilter" should {

    "allow protected inner action to access token info" in {
      val response = route(appWithRoutes, FakeRequest(GET, "/")).get
      status(response) must beEqualTo(OK)
      contentAsString(response) must beEqualTo(testTokenInfo.tokenType)
    }

    "deny an access when there is no security rule for the reguest is given" in {
      val response = route(appWithRoutes, FakeRequest(GET, "/unprotected-by-mistake")).get
      status(response) must beEqualTo(FORBIDDEN)
    }

  }

}

class SecurityFilterTestRouterProvider @Inject() (components: ControllerComponents) extends Provider[Router] {

  import components.{actionBuilder => Action}
  import play.api.routing.sird._

  override def get(): Router = Router.from {
    // test action returning action type. Shows the usage and makes it possible to test basic behaviour
    // security rules described in 'security_filter.conf' file
    case GET(p"/") => Action { request =>
      import TokenInfoConverter._
      Ok(request.tokenInfo.tokenType)
    }

    case GET(p"/unprotected") => Action {
      Ok
    }
  }
} 
Example 148
Source File: PlayTests.scala    From freestyle   with Apache License 2.0 5 votes vote down vote up
package freestyle.free.http

import org.scalatest.{Matchers, WordSpec}
import javax.inject.Inject
import scala.concurrent.ExecutionContext
import cats.Monad
import freestyle.free._
import freestyle.free.implicits._
import freestyle.free.http.play.implicits._
import _root_.play.api.mvc._
import _root_.play.api.http.{ContentTypeOf, Writeable}
import ExecutionContext.Implicits.global

class PlayTests @Inject()(val controllerComponents: ControllerComponents)
    extends WordSpec
    with Matchers
    with BaseController {

  implicit def unitWr(implicit C: Codec): Writeable[Unit] =
    Writeable(data => C.encode(data.toString))

  implicit val unitCT: ContentTypeOf[Unit] = new ContentTypeOf(Option("text/plain"))

  "Play integration" should {
    import cats.instances.future._

    import algebras._
    import handlers._

    def program[F[_]: Noop]: FreeS[F, Result] =
      Noop[F].noop.map(x => Results.Ok(x))

    "FreeS programs can be used as return value in Play actions" in {
      Action.async { _ =>
        program[Noop.Op]
      } shouldBe an[Action[Result]]
    }

    "FreeS.Par programs can interact with a given request and used as returned values in Play actions" in {
      Action.async { request =>
        Noop[Noop.Op].noop.map(_ => Results.Ok(request.method))
      } shouldBe an[Action[Result]]
    }

    "FreeS sequentials programs can interact with a given request and used as returned values in Play actions" in {
      Action.async { request =>
        Noop[Noop.Op].noop.map(_ => Results.Ok(request.method)).freeS
      } shouldBe an[Action[Result]]
    }
  }
}

object algebras {
  @free
  trait Noop {
    def noop: FS[Unit]
  }
}

object handlers {
  import algebras._

  implicit def noopHandler[M[_]](
      implicit MM: Monad[M]
  ): Noop.Handler[M] = new Noop.Handler[M] {
    def noop: M[Unit] = MM.pure(())
  }
} 
Example 149
Source File: AuthenticatedUserAction.scala    From PlayFrameworkLoginAuthenticationExample   with GNU General Public License v3.0 5 votes vote down vote up
package controllers

import javax.inject.Inject
import play.api.mvc.Results._
import play.api.mvc._

import scala.concurrent.{ExecutionContext, Future}


class AuthenticatedUserAction @Inject() (parser: BodyParsers.Default)(implicit ec: ExecutionContext)
    extends ActionBuilderImpl(parser) {

    private val logger = play.api.Logger(this.getClass)

    override def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
        logger.info("ENTERED AuthenticatedUserAction::invokeBlock ...")
        val maybeUsername = request.session.get(models.Global.SESSION_USERNAME_KEY)
        maybeUsername match {
            case None => {
                Future.successful(Forbidden("Dude, you’re not logged in."))
            }
            case Some(u) => {
                val res: Future[Result] = block(request)
                res
            }
        }
    }
} 
Example 150
Source File: UserController.scala    From PlayFrameworkLoginAuthenticationExample   with GNU General Public License v3.0 5 votes vote down vote up
package controllers

import javax.inject.Inject
import models.{Global, User, UserDao}
import play.api.data.Forms._
import play.api.data._
import play.api.mvc._

class UserController @Inject()(
    cc: MessagesControllerComponents,
    userDao: UserDao
) extends MessagesAbstractController(cc) {

    private val logger = play.api.Logger(this.getClass)

    val form: Form[User] = Form (
        mapping(
            "username" -> nonEmptyText
                .verifying("too few chars",  s => lengthIsGreaterThanNCharacters(s, 2))
                .verifying("too many chars", s => lengthIsLessThanNCharacters(s, 20)),
            "password" -> nonEmptyText
                .verifying("too few chars",  s => lengthIsGreaterThanNCharacters(s, 2))
                .verifying("too many chars", s => lengthIsLessThanNCharacters(s, 30)),
        )(User.apply)(User.unapply)
    )

    private val formSubmitUrl = routes.UserController.processLoginAttempt

    def showLoginForm = Action { implicit request: MessagesRequest[AnyContent] =>
        Ok(views.html.userLogin(form, formSubmitUrl))
    }

    def processLoginAttempt = Action { implicit request: MessagesRequest[AnyContent] =>
        val errorFunction = { formWithErrors: Form[User] =>
            // form validation/binding failed...
            BadRequest(views.html.userLogin(formWithErrors, formSubmitUrl))
        }
        val successFunction = { user: User =>
            // form validation/binding succeeded ...
            val foundUser: Boolean = userDao.lookupUser(user)
            if (foundUser) {
                Redirect(routes.LandingPageController.showLandingPage)
                    .flashing("info" -> "You are logged in.")
                    .withSession(Global.SESSION_USERNAME_KEY -> user.username)
            } else {
                Redirect(routes.UserController.showLoginForm)
                    .flashing("error" -> "Invalid username/password.")
            }
        }
        val formValidationResult: Form[User] = form.bindFromRequest
        formValidationResult.fold(
            errorFunction,
            successFunction
        )
    }

    private def lengthIsGreaterThanNCharacters(s: String, n: Int): Boolean = {
        if (s.length > n) true else false
    }

    private def lengthIsLessThanNCharacters(s: String, n: Int): Boolean = {
        if (s.length < n) true else false
    }

} 
Example 151
Source File: UserServiceImpl.scala    From play-silhouette-reactivemongo-seed   with Apache License 2.0 5 votes vote down vote up
package models.services

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

import com.mohiva.play.silhouette.api.LoginInfo
import com.mohiva.play.silhouette.impl.providers.CommonSocialProfile
import models.User
import models.daos.UserDAO
import play.api.libs.concurrent.Execution.Implicits._

import scala.concurrent.Future


  def save(profile: CommonSocialProfile) = {
    userDAO.find(profile.loginInfo).flatMap {
      case Some(user) => // Update user with profile
        userDAO.save(user.copy(
          firstName = profile.firstName,
          lastName = profile.lastName,
          fullName = profile.fullName,
          email = profile.email,
          avatarURL = profile.avatarURL
        ))
      case None => // Insert a new user
        userDAO.save(User(
          userID = UUID.randomUUID(),
          loginInfo = profile.loginInfo,
          firstName = profile.firstName,
          lastName = profile.lastName,
          fullName = profile.fullName,
          email = profile.email,
          avatarURL = profile.avatarURL,
          activated = true
        ))
    }
  }
} 
Example 152
Source File: SocialAuthController.scala    From play-silhouette-reactivemongo-seed   with Apache License 2.0 5 votes vote down vote up
package controllers

import javax.inject.Inject

import com.mohiva.play.silhouette.api._
import com.mohiva.play.silhouette.api.exceptions.ProviderException
import com.mohiva.play.silhouette.api.repositories.AuthInfoRepository
import com.mohiva.play.silhouette.impl.providers._
import models.services.UserService
import play.api.i18n.{ I18nSupport, Messages, MessagesApi }
import play.api.libs.concurrent.Execution.Implicits._
import play.api.mvc.{ Action, Controller }
import utils.auth.DefaultEnv

import scala.concurrent.Future


  def authenticate(provider: String) = Action.async { implicit request =>
    (socialProviderRegistry.get[SocialProvider](provider) match {
      case Some(p: SocialProvider with CommonSocialProfileBuilder) =>
        p.authenticate().flatMap {
          case Left(result) => Future.successful(result)
          case Right(authInfo) => for {
            profile <- p.retrieveProfile(authInfo)
            user <- userService.save(profile)
            authInfo <- authInfoRepository.save(profile.loginInfo, authInfo)
            authenticator <- silhouette.env.authenticatorService.create(profile.loginInfo)
            value <- silhouette.env.authenticatorService.init(authenticator)
            result <- silhouette.env.authenticatorService.embed(value, Redirect(routes.ApplicationController.index()))
          } yield {
            silhouette.env.eventBus.publish(LoginEvent(user, request))
            result
          }
        }
      case _ => Future.failed(new ProviderException(s"Cannot authenticate with unexpected social provider $provider"))
    }).recover {
      case e: ProviderException =>
        logger.error("Unexpected provider error", e)
        Redirect(routes.SignInController.view()).flashing("error" -> Messages("could.not.authenticate"))
    }
  }
} 
Example 153
Source File: ChangePasswordController.scala    From play-silhouette-reactivemongo-seed   with Apache License 2.0 5 votes vote down vote up
package controllers

import javax.inject.Inject

import com.mohiva.play.silhouette.api._
import com.mohiva.play.silhouette.api.exceptions.ProviderException
import com.mohiva.play.silhouette.api.repositories.AuthInfoRepository
import com.mohiva.play.silhouette.api.util.{ Credentials, PasswordHasherRegistry, PasswordInfo }
import com.mohiva.play.silhouette.impl.providers.CredentialsProvider
import forms.ChangePasswordForm
import models.services.UserService
import play.api.i18n.{ I18nSupport, Messages, MessagesApi }
import play.api.libs.concurrent.Execution.Implicits._
import play.api.mvc.Controller
import utils.auth.{ DefaultEnv, WithProvider }

import scala.concurrent.Future


  def submit = silhouette.SecuredAction(WithProvider[DefaultEnv#A](CredentialsProvider.ID)).async { implicit request =>
    ChangePasswordForm.form.bindFromRequest.fold(
      form => Future.successful(BadRequest(views.html.changePassword(form, request.identity))),
      password => {
        val (currentPassword, newPassword) = password
        val credentials = Credentials(request.identity.email.getOrElse(""), currentPassword)
        credentialsProvider.authenticate(credentials).flatMap { loginInfo =>
          val passwordInfo = passwordHasherRegistry.current.hash(newPassword)
          authInfoRepository.update[PasswordInfo](loginInfo, passwordInfo).map { _ =>
            Redirect(routes.ChangePasswordController.view()).flashing("success" -> Messages("password.changed"))
          }
        }.recover {
          case e: ProviderException =>
            Redirect(routes.ChangePasswordController.view()).flashing("error" -> Messages("current.password.invalid"))
        }
      }
    )
  }
} 
Example 154
Source File: SignInController.scala    From play-silhouette-reactivemongo-seed   with Apache License 2.0 5 votes vote down vote up
package controllers

import javax.inject.Inject

import com.mohiva.play.silhouette.api.Authenticator.Implicits._
import com.mohiva.play.silhouette.api._
import com.mohiva.play.silhouette.api.exceptions.ProviderException
import com.mohiva.play.silhouette.api.repositories.AuthInfoRepository
import com.mohiva.play.silhouette.api.util.{ Clock, Credentials }
import com.mohiva.play.silhouette.impl.exceptions.IdentityNotFoundException
import com.mohiva.play.silhouette.impl.providers._
import forms.SignInForm
import models.services.UserService
import net.ceedubs.ficus.Ficus._
import play.api.Configuration
import play.api.i18n.{ I18nSupport, Messages, MessagesApi }
import play.api.libs.concurrent.Execution.Implicits._
import play.api.mvc.Controller
import utils.auth.DefaultEnv

import scala.concurrent.Future
import scala.concurrent.duration._
import scala.language.postfixOps


  def submit = silhouette.UnsecuredAction.async { implicit request =>
    SignInForm.form.bindFromRequest.fold(
      form => Future.successful(BadRequest(views.html.signIn(form, socialProviderRegistry))),
      data => {
        val credentials = Credentials(data.email, data.password)
        credentialsProvider.authenticate(credentials).flatMap { loginInfo =>
          val result = Redirect(routes.ApplicationController.index())
          userService.retrieve(loginInfo).flatMap {
            case Some(user) if !user.activated =>
              Future.successful(Ok(views.html.activateAccount(data.email)))
            case Some(user) =>
              val c = configuration.underlying
              silhouette.env.authenticatorService.create(loginInfo).map {
                case authenticator if data.rememberMe =>
                  authenticator.copy(
                    expirationDateTime = clock.now + c.as[FiniteDuration]("silhouette.authenticator.rememberMe.authenticatorExpiry"),
                    idleTimeout = c.getAs[FiniteDuration]("silhouette.authenticator.rememberMe.authenticatorIdleTimeout"),
                    cookieMaxAge = c.getAs[FiniteDuration]("silhouette.authenticator.rememberMe.cookieMaxAge")
                  )
                case authenticator => authenticator
              }.flatMap { authenticator =>
                silhouette.env.eventBus.publish(LoginEvent(user, request))
                silhouette.env.authenticatorService.init(authenticator).flatMap { v =>
                  silhouette.env.authenticatorService.embed(v, result)
                }
              }
            case None => Future.failed(new IdentityNotFoundException("Couldn't find user"))
          }
        }.recover {
          case e: ProviderException =>
            Redirect(routes.SignInController.view()).flashing("error" -> Messages("invalid.credentials"))
        }
      }
    )
  }
} 
Example 155
Source File: ResetPasswordController.scala    From play-silhouette-reactivemongo-seed   with Apache License 2.0 5 votes vote down vote up
package controllers

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

import com.mohiva.play.silhouette.api._
import com.mohiva.play.silhouette.api.repositories.AuthInfoRepository
import com.mohiva.play.silhouette.api.util.{ PasswordHasherRegistry, PasswordInfo }
import com.mohiva.play.silhouette.impl.providers.CredentialsProvider
import forms.ResetPasswordForm
import models.services.{ AuthTokenService, UserService }
import play.api.i18n.{ I18nSupport, Messages, MessagesApi }
import play.api.libs.concurrent.Execution.Implicits._
import play.api.mvc.Controller
import utils.auth.DefaultEnv

import scala.concurrent.Future


  def submit(token: UUID) = silhouette.UnsecuredAction.async { implicit request =>
    authTokenService.validate(token).flatMap {
      case Some(authToken) =>
        ResetPasswordForm.form.bindFromRequest.fold(
          form => Future.successful(BadRequest(views.html.resetPassword(form, token))),
          password => userService.retrieve(authToken.userID).flatMap {
            case Some(user) if user.loginInfo.providerID == CredentialsProvider.ID =>
              val passwordInfo = passwordHasherRegistry.current.hash(password)
              authInfoRepository.update[PasswordInfo](user.loginInfo, passwordInfo).map { _ =>
                Redirect(routes.SignInController.view()).flashing("success" -> Messages("password.reset"))
              }
            case _ => Future.successful(Redirect(routes.SignInController.view()).flashing("error" -> Messages("invalid.reset.link")))
          }
        )
      case None => Future.successful(Redirect(routes.SignInController.view()).flashing("error" -> Messages("invalid.reset.link")))
    }
  }
} 
Example 156
Source File: ActivateAccountController.scala    From play-silhouette-reactivemongo-seed   with Apache License 2.0 5 votes vote down vote up
package controllers

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

import com.mohiva.play.silhouette.api._
import com.mohiva.play.silhouette.impl.providers.CredentialsProvider
import models.services.{ AuthTokenService, UserService }
import play.api.i18n.{ I18nSupport, Messages, MessagesApi }
import play.api.libs.concurrent.Execution.Implicits._
import play.api.libs.mailer.{ Email, MailerClient }
import play.api.mvc.Controller
import utils.auth.DefaultEnv

import scala.concurrent.Future
import scala.language.postfixOps


  def activate(token: UUID) = silhouette.UnsecuredAction.async { implicit request =>
    authTokenService.validate(token).flatMap {
      case Some(authToken) => userService.retrieve(authToken.userID).flatMap {
        case Some(user) if user.loginInfo.providerID == CredentialsProvider.ID =>
          userService.save(user.copy(activated = true)).map { _ =>
            Redirect(routes.SignInController.view()).flashing("success" -> Messages("account.activated"))
          }
        case _ => Future.successful(Redirect(routes.SignInController.view()).flashing("error" -> Messages("invalid.activation.link")))
      }
      case None => Future.successful(Redirect(routes.SignInController.view()).flashing("error" -> Messages("invalid.activation.link")))
    }
  }
} 
Example 157
Source File: ForgotPasswordController.scala    From play-silhouette-reactivemongo-seed   with Apache License 2.0 5 votes vote down vote up
package controllers

import javax.inject.Inject

import com.mohiva.play.silhouette.api._
import com.mohiva.play.silhouette.impl.providers.CredentialsProvider
import forms.ForgotPasswordForm
import models.services.{ AuthTokenService, UserService }
import play.api.i18n.{ I18nSupport, Messages, MessagesApi }
import play.api.libs.concurrent.Execution.Implicits._
import play.api.libs.mailer.{ Email, MailerClient }
import play.api.mvc.Controller
import utils.auth.DefaultEnv

import scala.concurrent.Future


  def submit = silhouette.UnsecuredAction.async { implicit request =>
    ForgotPasswordForm.form.bindFromRequest.fold(
      form => Future.successful(BadRequest(views.html.forgotPassword(form))),
      email => {
        val loginInfo = LoginInfo(CredentialsProvider.ID, email)
        val result = Redirect(routes.SignInController.view()).flashing("info" -> Messages("reset.email.sent"))
        userService.retrieve(loginInfo).flatMap {
          case Some(user) if user.email.isDefined =>
            authTokenService.create(user.userID).map { authToken =>
              val url = routes.ResetPasswordController.view(authToken.id).absoluteURL()

              mailerClient.send(Email(
                subject = Messages("email.reset.password.subject"),
                from = Messages("email.from"),
                to = Seq(email),
                bodyText = Some(views.txt.emails.resetPassword(user, url).body),
                bodyHtml = Some(views.html.emails.resetPassword(user, url).body)
              ))
              result
            }
          case None => Future.successful(result)
        }
      }
    )
  }
} 
Example 158
Source File: Application.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package controllers

import play.api._
import play.api.mvc._
import scala.collection.JavaConverters._

import javax.inject.Inject

class Application @Inject()(
  env: Environment,
  configuration: Configuration,
  val controllerComponents: ControllerComponents
) extends BaseController {

  def index = Action {
    Ok(views.html.index("Your new application is ready."))
  }

  def config = Action {
    Ok(configuration.underlying.getString("some.config"))
  }

  def count = Action {
    val num = env.resource("application.conf").toSeq.size
    Ok(num.toString)
  }
} 
Example 159
Source File: MavenLoggerProxy.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.maven

import javax.inject.Inject
import javax.inject.Singleton

import com.lightbend.lagom.devmode.MiniLogger
import org.codehaus.plexus.logging.Logger
import play.dev.filewatch.LoggerProxy


@Singleton
class MavenLoggerProxy @Inject() (logger: Logger) extends LoggerProxy with MiniLogger {
  override def debug(message: => String): Unit = {
    if (logger.isDebugEnabled) {
      logger.debug(message)
    }
  }

  override def info(message: => String): Unit = {
    if (logger.isInfoEnabled) {
      logger.info(message)
    }
  }

  override def warn(message: => String): Unit = {
    if (logger.isWarnEnabled) {
      logger.warn(message)
    }
  }

  override def error(message: => String): Unit = {
    if (logger.isErrorEnabled) {
      logger.error(message)
    }
  }

  override def verbose(message: => String): Unit = debug(message)

  override def success(message: => String): Unit = info(message)

  override def trace(t: => Throwable): Unit = {
    if (logger.isDebugEnabled) {
      logger.debug(t.getMessage, t)
    }
  }
} 
Example 160
Source File: ScalaClassLoaderManager.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.maven

import java.net.URLClassLoader
import javax.inject.Inject
import javax.inject.Singleton

import org.eclipse.aether.artifact.Artifact


  def extractScalaClassLoader(artifacts: Seq[Artifact]): ClassLoader = synchronized {
    val scalaArtifacts = artifacts.filter { artifact =>
      ScalaLibs.contains(artifact.getGroupId -> stripScalaVersion(artifact.getArtifactId))
    }

    val cacheKey = createCacheKey(scalaArtifacts)
    cache.get(cacheKey) match {
      case Some(classLoader) =>
        logger.debug(s"ScalaClassLoader cache hit - $cacheKey")
        classLoader
      case None =>
        logger.debug(s"ScalaClassLoader cache miss - $cacheKey")
        // Use System classloader parent as documented here:
        // https://svn.apache.org/repos/infra/websites/production/maven/content/reference/maven-classloading.html#Maven_API_classloader
        // Keep in mind this does not contain any application or javaagent classes, which will
        // be added in the classLoader below.
        //
        // This behaves a little different depending on the Java version used:
        // - For Java 8: the parent is the boostrap class loader (or null), which in the end
        //   means the boostrap class loader is used.
        // - For Java9+: the parent is the platform class loader is a parent or an ancestor
        //   of the system class loader that all platform classes are visible to it.
        val parent      = ClassLoader.getSystemClassLoader().getParent()
        val classLoader = new URLClassLoader(scalaArtifacts.map(_.getFile.toURI.toURL).toArray, parent)
        cache += (cacheKey -> classLoader)
        classLoader
    }
  }
} 
Example 161
Source File: ConfigureMojo.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.maven

import javax.inject.Inject
import org.apache.maven.execution.MavenSession
import org.apache.maven.plugin.AbstractMojo

import scala.beans.BeanProperty


class ConfigureMojo @Inject() (session: MavenSession) extends AbstractMojo {
  @BeanProperty
  var lagomService: Boolean = _

  @BeanProperty
  var playService: Boolean = _

  override def execute(): Unit = {
    LagomKeys.LagomService.put(session.getCurrentProject, lagomService)
    LagomKeys.PlayService.put(session.getCurrentProject, playService)
  }
} 
Example 162
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 163
Source File: JavaServiceRegistryClient.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.internal.javadsl.registry

import java.net.URI
import java.util.Optional

import javax.inject.Inject
import javax.inject.Singleton
import com.lightbend.lagom.devmode.internal.registry.AbstractLoggingServiceRegistryClient
import com.lightbend.lagom.javadsl.api.transport.NotFound

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

@Singleton
private[lagom] class JavaServiceRegistryClient @Inject() (
    registry: ServiceRegistry,
    implicit val ec: ExecutionContext
) extends AbstractLoggingServiceRegistryClient {
  protected override def internalLocateAll(serviceName: String, portName: Option[String]): Future[immutable.Seq[URI]] =
    registry
      .lookup(serviceName, OptionConverters.toJava(portName))
      .invoke()
      .toScala
      .map(immutable.Seq[URI](_))
      .recover {
        case _: NotFound => Nil
      }
} 
Example 164
Source File: ServiceRegistryServiceLocator.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.internal.javadsl.registry

import java.net.URI
import java.util.concurrent.CompletionStage
import java.util.Optional
import java.util.{ List => JList }

import javax.inject.Inject
import javax.inject.Singleton
import com.lightbend.lagom.devmode.internal.registry.ServiceRegistryClient
import com.lightbend.lagom.javadsl.api.Descriptor.Call
import com.lightbend.lagom.javadsl.client.CircuitBreakersPanel
import com.lightbend.lagom.javadsl.client.CircuitBreakingServiceLocator

import scala.collection.JavaConverters._
import scala.compat.java8.FutureConverters._
import scala.compat.java8.OptionConverters._
import scala.concurrent.ExecutionContext

@Singleton
private[lagom] class ServiceRegistryServiceLocator @Inject() (
    circuitBreakers: CircuitBreakersPanel,
    client: ServiceRegistryClient,
    implicit val ec: ExecutionContext
) extends CircuitBreakingServiceLocator(circuitBreakers) {
  override def locateAll(name: String, serviceCall: Call[_, _]): CompletionStage[JList[URI]] =
    // a ServiceLocator doesn't know what a `portName` is so we default to `None` and the
    // implementation will return any registry without a port name. This means that in order
    // for this queries to work any service registered using `http` as portName will also have
    // to be registered without name.
    client.locateAll(name, None).map(_.asJava).toJava

  override def locate(name: String, serviceCall: Call[_, _]): CompletionStage[Optional[URI]] =
    // a ServiceLocator doesn't know what a `portName` is so we default to `None` and the
    // implementation will return any registry without a port name. This means that in order
    // for this queries to work any service registered using `http` as portName will also have
    // to be registered without name.
    client.locateAll(name, None).map(_.headOption.asJava).toJava
} 
Example 165
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 166
Source File: ProjectionRegistryModule.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.javadsl.projection

import java.util.concurrent.CompletionStage

import akka.actor.ActorSystem
import akka.annotation.ApiMayChange
import akka.annotation.InternalApi
import com.lightbend.lagom.internal.projection.ProjectionRegistry
import com.lightbend.lagom.internal.projection.ProjectionRegistryActor.WorkerCoordinates
import com.lightbend.lagom.projection.State
import javax.inject.Inject
import javax.inject.Provider
import javax.inject.Singleton
import play.api.Configuration
import play.api.Environment
import play.api.inject.Binding
import play.api.inject.Module

import scala.compat.java8.FutureConverters
import scala.concurrent.ExecutionContext


private class ProjectionsImpl @Inject() (registry: ProjectionRegistry)(
    implicit executionContext: ExecutionContext
) extends Projections {
  import FutureConverters._

  override def getStatus(): CompletionStage[State] =
    registry.getState().toJava

  override def stopAllWorkers(projectionName: String): Unit =
    registry.stopAllWorkers(projectionName)

  override def stopWorker(projectionName: String, tagName: String): Unit =
    registry.stopWorker(WorkerCoordinates(projectionName, tagName))

  override def startAllWorkers(projectionName: String): Unit =
    registry.startAllWorkers(projectionName)

  override def startWorker(projectionName: String, tagName: String): Unit =
    registry.startWorker(WorkerCoordinates(projectionName, tagName))
} 
Example 167
Source File: PubSubRegistryImpl.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.internal.javadsl.pubsub

import akka.actor.ActorSystem
import akka.cluster.pubsub.DistributedPubSub
import com.typesafe.config.Config
import javax.inject.Inject
import javax.inject.Singleton

import com.lightbend.lagom.javadsl.pubsub.PubSubRef
import com.lightbend.lagom.javadsl.pubsub.PubSubRegistry
import com.lightbend.lagom.javadsl.pubsub.TopicId

@Singleton
private[lagom] class PubSubRegistryImpl(system: ActorSystem, conf: Config) extends PubSubRegistry {
  @Inject
  def this(system: ActorSystem) =
    this(system, system.settings.config.getConfig("lagom.pubsub"))

  private val pubsub          = DistributedPubSub(system)
  private val bufferSize: Int = conf.getInt("subscriber-buffer-size")

  override def refFor[T](topic: TopicId[T]): PubSubRef[T] =
    new PubSubRef(topic, pubsub.mediator, system, bufferSize)
} 
Example 168
Source File: TestRouters.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.it.routers

import javax.inject.Inject
import play.api.mvc
import play.api.mvc._
import play.api.routing.Router.Routes
import play.api.routing.Router
import play.api.routing.SimpleRouterImpl
import play.core.j.JavaRouterAdapter

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


object FixedResponseRouter {
  def apply(msg: String) =
    new SimpleRouterImpl({
      case _ =>
        new Action[Unit] {
          override def parser: BodyParser[Unit] = mvc.BodyParsers.utils.empty

          override def apply(request: Request[Unit]): Future[Result] =
            Future.successful(Results.Ok(msg))

          override def executionContext: ExecutionContext =
            scala.concurrent.ExecutionContext.global
        }
    })

  def newInstanceJava(msg: String) = new JavaRouterAdapter(FixedResponseRouter(msg))
} 
Example 169
Source File: TopicFactory.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.internal.javadsl.api.broker

import javax.inject.Inject
import javax.inject.Singleton

import com.lightbend.lagom.javadsl.api.Descriptor.TopicCall
import com.lightbend.lagom.javadsl.api.broker.Topic
import play.api.inject.Injector

import scala.util.control.NonFatal


trait TopicFactoryProvider {
  def get: Option[TopicFactory]
}

@Singleton
class InjectorTopicFactoryProvider @Inject() (injector: Injector) extends TopicFactoryProvider {
  override lazy val get: Option[TopicFactory] =
    try {
      Some(injector.instanceOf[TopicFactory])
    } catch {
      case NonFatal(e) => None
    }
}

object NoTopicFactoryProvider extends TopicFactoryProvider {
  override val get = None
} 
Example 170
Source File: CircuitBreakerModule.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.internal.javadsl.client

import javax.inject.Inject
import javax.inject.Provider
import javax.inject.Singleton
import akka.actor.ActorSystem
import com.lightbend.lagom.internal.client.CircuitBreakerConfig
import com.lightbend.lagom.internal.client.CircuitBreakerMetricsProviderImpl
import com.lightbend.lagom.internal.client.CircuitBreakerMetricsProviderProvider
import com.lightbend.lagom.internal.spi.CircuitBreakerMetricsProvider
import com.lightbend.lagom.javadsl.client.CircuitBreakersPanel
import play.api.inject.Binding
import play.api.inject.Module
import play.api.Configuration
import play.api.Environment

class CircuitBreakerModule extends Module {
  override def bindings(environment: Environment, configuration: Configuration): Seq[Binding[_]] = {
    Seq(
      bind[CircuitBreakersPanel].to[CircuitBreakersPanelImpl],
      bind[CircuitBreakerMetricsProvider].toProvider[CircuitBreakerMetricsProviderProvider],
      bind[CircuitBreakerConfig].toSelf,
      bind[CircuitBreakerMetricsProviderImpl].toSelf
    )
  }
} 
Example 171
Source File: ServiceClientLoader.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.internal.javadsl.client

import javax.inject.Inject
import javax.inject.Provider
import javax.inject.Singleton
import com.lightbend.lagom.internal.javadsl.api.JacksonPlaceholderExceptionSerializer
import com.lightbend.lagom.internal.javadsl.api.JacksonPlaceholderSerializerFactory
import com.lightbend.lagom.internal.javadsl.api.ServiceReader
import com.lightbend.lagom.javadsl.api.Service
import com.lightbend.lagom.javadsl.jackson.JacksonExceptionSerializer
import com.lightbend.lagom.javadsl.jackson.JacksonSerializerFactory
import play.api.Environment

@Singleton
class ServiceClientLoader @Inject() (
    jacksonSerializerFactory: JacksonSerializerFactory,
    jacksonExceptionSerializer: JacksonExceptionSerializer,
    environment: Environment,
    implementor: JavadslServiceClientImplementor
) {
  def loadServiceClient[T](interface: Class[T]): T = {
    if (classOf[Service].isAssignableFrom(interface)) {
      val descriptor = ServiceReader.readServiceDescriptor(
        environment.classLoader,
        interface.asSubclass(classOf[Service])
      )
      val resolved = ServiceReader.resolveServiceDescriptor(
        descriptor,
        environment.classLoader,
        Map(JacksonPlaceholderSerializerFactory   -> jacksonSerializerFactory),
        Map(JacksonPlaceholderExceptionSerializer -> jacksonExceptionSerializer)
      )
      implementor.implement(interface, resolved)
    } else {
      throw new IllegalArgumentException("Don't know how to load services that don't implement Service")
    }
  }
}

@Singleton
class ServiceClientProvider[T](interface: Class[T]) extends Provider[T] {
  @Inject private var loader: ServiceClientLoader = _
  lazy val get                                    = loader.loadServiceClient(interface)
} 
Example 172
Source File: JavadslWebSocketClient.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.internal.javadsl.client

import javax.inject.Inject
import javax.inject.Singleton

import com.lightbend.lagom.internal.client.WebSocketClient
import com.lightbend.lagom.internal.client.WebSocketClientConfig
import com.typesafe.config.Config
import io.netty.channel.EventLoopGroup
import play.api.Environment
import play.api.inject.ApplicationLifecycle

import scala.concurrent.ExecutionContext

@Singleton
class JavadslWebSocketClient(
    environment: Environment,
    config: WebSocketClientConfig,
    eventLoop: EventLoopGroup,
    lifecycle: ApplicationLifecycle
)(implicit ec: ExecutionContext)
    extends WebSocketClient(environment, config, eventLoop, lifecycle)
    with JavadslServiceApiBridge {
  // Constructor that manages its own event loop
  @Inject
  def this(environment: Environment, config: Config, applicationLifecycle: ApplicationLifecycle)(
      implicit ec: ExecutionContext
  ) = {
    this(
      environment,
      WebSocketClientConfig(config),
      WebSocketClient.createEventLoopGroup(applicationLifecycle),
      applicationLifecycle
    )
  }
} 
Example 173
Source File: CassandraPersistenceModule.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.javadsl.persistence.cassandra

import java.net.URI

import scala.concurrent.Future
import akka.actor.ActorSystem
import com.lightbend.lagom.internal.javadsl.persistence.cassandra._
import com.lightbend.lagom.internal.persistence.cassandra.CassandraOffsetStore
import com.lightbend.lagom.internal.persistence.cassandra.CassandraReadSideSettings
import com.lightbend.lagom.internal.persistence.cassandra.ServiceLocatorAdapter
import com.lightbend.lagom.internal.persistence.cassandra.ServiceLocatorHolder
import com.lightbend.lagom.javadsl.api.ServiceLocator
import com.lightbend.lagom.javadsl.persistence.PersistentEntityRegistry
import com.lightbend.lagom.spi.persistence.OffsetStore
import javax.annotation.PostConstruct
import javax.inject.Inject
import play.api.Configuration
import play.api.Environment
import play.api.inject._

import scala.util.Try


class CassandraPersistenceModule extends Module {
  override def bindings(environment: Environment, configuration: Configuration): Seq[Binding[_]] = Seq(
    bind[CassandraPersistenceModule.InitServiceLocatorHolder].toSelf.eagerly(),
    bind[PersistentEntityRegistry].to[CassandraPersistentEntityRegistry],
    bind[CassandraSession].toSelf,
    bind[CassandraReadSide].to[CassandraReadSideImpl],
    bind[CassandraReadSideSettings].toSelf,
    bind[CassandraOffsetStore].to[JavadslCassandraOffsetStore],
    bind[OffsetStore].to(bind[CassandraOffsetStore])
  )
}

private[lagom] object CassandraPersistenceModule {
  class InitServiceLocatorHolder @Inject() (system: ActorSystem, injector: Injector) {
    // Guice doesn't support this, but other DI frameworks do.
    @PostConstruct
    def init(): Unit = {
      Try(injector.instanceOf[ServiceLocator]).foreach { locator =>
        ServiceLocatorHolder(system).setServiceLocator(new ServiceLocatorAdapter {
          override def locateAll(name: String): Future[List[URI]] = {
            import system.dispatcher
            import scala.compat.java8.FutureConverters._
            import scala.collection.JavaConverters._
            locator.locateAll(name).toScala.map(_.asScala.toList)
          }
        })
      }
    }
  }
} 
Example 174
Source File: CassandraReadSideImpl.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.internal.javadsl.persistence.cassandra

import java.util
import java.util.concurrent.CompletableFuture
import java.util.concurrent.CompletionStage
import java.util.function.BiFunction
import java.util.function.Function
import java.util.function.Supplier

import javax.inject.Inject
import javax.inject.Singleton
import akka.Done
import akka.actor.ActorSystem
import com.datastax.driver.core.BoundStatement
import com.lightbend.lagom.internal.javadsl.persistence.ReadSideImpl
import com.lightbend.lagom.internal.persistence.cassandra.CassandraOffsetStore
import com.lightbend.lagom.javadsl.persistence.ReadSideProcessor.ReadSideHandler
import com.lightbend.lagom.javadsl.persistence._
import com.lightbend.lagom.javadsl.persistence.cassandra.CassandraReadSide.ReadSideHandlerBuilder
import com.lightbend.lagom.javadsl.persistence.cassandra.CassandraReadSide
import com.lightbend.lagom.javadsl.persistence.cassandra.CassandraSession
import play.api.inject.Injector


@Singleton
private[lagom] final class CassandraReadSideImpl @Inject() (
    system: ActorSystem,
    session: CassandraSession,
    offsetStore: CassandraOffsetStore,
    readSide: ReadSideImpl,
    injector: Injector
) extends CassandraReadSide {
  private val dispatcher = system.settings.config.getString("lagom.persistence.read-side.use-dispatcher")
  implicit val ec        = system.dispatchers.lookup(dispatcher)

  override def builder[Event <: AggregateEvent[Event]](eventProcessorId: String): ReadSideHandlerBuilder[Event] = {
    new ReadSideHandlerBuilder[Event] {
      import CassandraAutoReadSideHandler.Handler
      private var prepareCallback: AggregateEventTag[Event] => CompletionStage[Done] =
        tag => CompletableFuture.completedFuture(Done.getInstance())
      private var globalPrepareCallback: () => CompletionStage[Done] =
        () => CompletableFuture.completedFuture(Done.getInstance())
      private var handlers = Map.empty[Class[_ <: Event], Handler[Event]]

      override def setGlobalPrepare(callback: Supplier[CompletionStage[Done]]): ReadSideHandlerBuilder[Event] = {
        globalPrepareCallback = () => callback.get
        this
      }

      override def setPrepare(
          callback: Function[AggregateEventTag[Event], CompletionStage[Done]]
      ): ReadSideHandlerBuilder[Event] = {
        prepareCallback = callback.apply
        this
      }

      override def setEventHandler[E <: Event](
          eventClass: Class[E],
          handler: Function[E, CompletionStage[util.List[BoundStatement]]]
      ): ReadSideHandlerBuilder[Event] = {
        handlers += (eventClass -> ((event: E, offset: Offset) => handler(event)))
        this
      }

      override def setEventHandler[E <: Event](
          eventClass: Class[E],
          handler: BiFunction[E, Offset, CompletionStage[util.List[BoundStatement]]]
      ): ReadSideHandlerBuilder[Event] = {
        handlers += (eventClass -> handler.apply _)
        this
      }

      override def build(): ReadSideHandler[Event] = {
        new CassandraAutoReadSideHandler[Event](
          session,
          offsetStore,
          handlers,
          globalPrepareCallback,
          prepareCallback,
          eventProcessorId,
          dispatcher
        )
      }
    }
  }
} 
Example 175
Source File: JdbcPersistenceModule.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.javadsl.persistence.jdbc

import javax.inject.Inject
import javax.inject.Provider
import javax.inject.Singleton
import akka.actor.ActorSystem
import akka.actor.CoordinatedShutdown
import com.lightbend.lagom.internal.javadsl.persistence.jdbc._
import com.lightbend.lagom.internal.persistence.jdbc.SlickDbProvider
import com.lightbend.lagom.internal.persistence.jdbc.SlickOffsetStore
import com.lightbend.lagom.javadsl.persistence.PersistentEntityRegistry
import com.lightbend.lagom.spi.persistence.OffsetStore
import play.api.Configuration
import play.api.Environment
import play.api.db.DBApi
import play.api.inject.Binding
import play.api.inject.Module

import scala.concurrent.ExecutionContext

class JdbcPersistenceModule extends Module {
  override def bindings(environment: Environment, configuration: Configuration): Seq[Binding[_]] = Seq(
    bind[SlickProvider].toProvider[GuiceSlickProvider],
    bind[JdbcReadSide].to[JdbcReadSideImpl],
    bind[PersistentEntityRegistry].to[JdbcPersistentEntityRegistry],
    bind[JdbcSession].to[JdbcSessionImpl],
    bind[SlickOffsetStore].to[JavadslJdbcOffsetStore],
    bind[OffsetStore].to(bind[SlickOffsetStore])
  )
}

@Singleton
class GuiceSlickProvider @Inject() (
    dbApi: DBApi,
    actorSystem: ActorSystem,
    coordinatedShutdown: CoordinatedShutdown
)(
    implicit ec: ExecutionContext
) extends Provider[SlickProvider] {
  lazy val get = {
    // Ensures JNDI bindings are made before we build the SlickProvider
    SlickDbProvider.buildAndBindSlickDatabases(
      dbApi,
      actorSystem.settings.config,
      coordinatedShutdown
    )
    new SlickProvider(actorSystem, coordinatedShutdown)
  }
} 
Example 176
Source File: JavadslJdbcOffsetStore.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.internal.javadsl.persistence.jdbc

import javax.inject.Inject
import javax.inject.Singleton

import akka.actor.ActorSystem
import com.lightbend.lagom.internal.persistence.ReadSideConfig
import com.lightbend.lagom.internal.persistence.jdbc.AbstractSlickOffsetStoreConfiguration
import com.lightbend.lagom.internal.persistence.jdbc.SlickOffsetStore
import com.typesafe.config.Config

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


@Singleton
private[lagom] class OffsetTableConfiguration @Inject() (config: Config, readSideConfig: ReadSideConfig)
    extends AbstractSlickOffsetStoreConfiguration(config) {
  override def minBackoff: FiniteDuration           = readSideConfig.minBackoff
  override def maxBackoff: FiniteDuration           = readSideConfig.maxBackoff
  override def randomBackoffFactor: Double          = readSideConfig.randomBackoffFactor
  override def globalPrepareTimeout: FiniteDuration = readSideConfig.globalPrepareTimeout
  override def role: Option[String]                 = readSideConfig.role
  override def toString: String                     = s"OffsetTableConfiguration($tableName,$schemaName)"
}

@Singleton
private[lagom] class JavadslJdbcOffsetStore @Inject() (
    slick: SlickProvider,
    system: ActorSystem,
    tableConfig: OffsetTableConfiguration,
    readSideConfig: ReadSideConfig
)(implicit ec: ExecutionContext)
    extends SlickOffsetStore(system, slick, tableConfig) 
Example 177
Source File: JdbcSessionImpl.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.internal.javadsl.persistence.jdbc

import java.util.concurrent.CompletionStage
import javax.inject.Inject
import javax.inject.Singleton

import com.lightbend.lagom.javadsl.persistence.jdbc.JdbcSession
import com.lightbend.lagom.javadsl.persistence.jdbc.JdbcSession.ConnectionFunction

import scala.compat.java8.FutureConverters._


@Singleton
final class JdbcSessionImpl @Inject() (slick: SlickProvider) extends JdbcSession {
  import slick.profile.api._

  override def withConnection[T](block: ConnectionFunction[T]): CompletionStage[T] = {
    slick.db.run {
      SimpleDBIO { ctx =>
        block(ctx.connection)
      }
    }.toJava
  }

  override def withTransaction[T](block: ConnectionFunction[T]): CompletionStage[T] = {
    slick.db.run {
      SimpleDBIO { ctx =>
        block(ctx.connection)
      }.transactionally
    }.toJava
  }
} 
Example 178
Source File: JdbcPersistentEntityRegistry.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.internal.javadsl.persistence.jdbc

import java.util.Optional

import javax.inject.Inject
import javax.inject.Singleton
import akka.actor.ActorSystem
import akka.persistence.jdbc.query.scaladsl.JdbcReadJournal
import com.lightbend.lagom.internal.javadsl.persistence.AbstractPersistentEntityRegistry
import com.lightbend.lagom.javadsl.persistence.PersistentEntity
import play.api.inject.Injector


@Singleton
private[lagom] final class JdbcPersistentEntityRegistry @Inject() (
    system: ActorSystem,
    injector: Injector,
    slickProvider: SlickProvider
) extends AbstractPersistentEntityRegistry(system, injector) {
  private lazy val ensureTablesCreated = slickProvider.ensureTablesCreated()

  override def register[C, E, S](entityClass: Class[_ <: PersistentEntity[C, E, S]]): Unit = {
    ensureTablesCreated
    super.register(entityClass)
  }

  protected override val queryPluginId = Optional.of(JdbcReadJournal.Identifier)
} 
Example 179
Source File: JdbcPersistenceModuleSpec.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.javadsl.persistence.jdbc

import javax.inject.Inject
import org.scalatest._
import play.api.PlayException
import play.api.db.DBApi
import play.api.inject.guice.GuiceApplicationBuilder
import play.api.inject.{ bind => playBind }
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AsyncWordSpec


class JdbcPersistenceModuleSpec extends AsyncWordSpec with Matchers with BeforeAndAfterAll {
  "The JdbcPersistenceModule" should {
    "should start the service when database is not available" in {
      // Should be okay to build an application since Lagom configuration
      // enables it without a database being available.
      val app =
        new GuiceApplicationBuilder()
          .bindings(playBind[DbWrapper].toSelf)
          .configure(
            // Correct configuration, but the database is not available
            "db.default.driver"                             -> "org.h2.Driver",
            "db.default.url"                                -> "jdbc:h2:tcp://localhost/~/notavailable",
            "lagom.cluster.exit-jvm-when-system-terminated" -> "off",
            "lagom.cluster.bootstrap.enabled"               -> "off"
          )
          .build()

      val dbWrapper = app.injector.instanceOf[DbWrapper]
      dbWrapper should not be (null)

      app.stop().map(_ => succeed)
    }

    "should fail to start the service when database is not available and configured to fail fast" in {
      assertThrows[PlayException] {
        new GuiceApplicationBuilder()
          .bindings(playBind[DbWrapper].toSelf)
          .configure(
            // Correct configuration, but the database is not available
            "db.default.driver" -> "org.h2.Driver",
            "db.default.url"    -> "jdbc:h2:tcp://localhost/~/notavailable",
            // And it is configured to fail fast
            "play.db.prototype.hikaricp.initializationFailTimeout" -> "1",
            "lagom.cluster.exit-jvm-when-system-terminated"        -> "off",
            "lagom.cluster.bootstrap.enabled"                      -> "off"
          )
          .build()
      }
    }
  }
}

// So that we can confirm DBApi was created
class DbWrapper @Inject() (val dbApi: DBApi) 
Example 180
Source File: ClusterShardingTypedModule.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.internal.javadsl.cluster.typed

import akka.actor.ActorSystem
import akka.cluster.sharding.typed.javadsl.ClusterSharding
import javax.inject.Inject
import javax.inject.Provider
import play.api.Configuration
import play.api.Environment
import play.api.inject.Binding
import play.api.inject.Module

class ClusterShardingTypedModule extends Module {
  override def bindings(environment: Environment, configuration: Configuration): Seq[Binding[_]] = Seq(
    bind[ClusterSharding].toProvider[ClusterShardingTypedProvider]
  )
}

private[lagom] class ClusterShardingTypedProvider @Inject() (system: ActorSystem) extends Provider[ClusterSharding] {
  private val instance: ClusterSharding = {
    import akka.actor.typed.scaladsl.adapter._
    val actorSystemTyped = system.toTyped
    ClusterSharding.get(actorSystemTyped)
  }

  override def get(): ClusterSharding = instance
} 
Example 181
Source File: JoinCluster.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.internal.javadsl.cluster

import akka.actor.ActorSystem
import com.lightbend.lagom.internal.akka.management.AkkaManagementTrigger
import com.lightbend.lagom.internal.cluster.JoinClusterImpl
import javax.inject.Inject
import play.api.Configuration
import play.api.Environment
import play.api.inject.Binding
import play.api.inject.Module

class JoinClusterModule extends Module {
  override def bindings(environment: Environment, configuration: Configuration): Seq[Binding[_]] = Seq(
    bind[JoinCluster].toSelf.eagerly()
  )
}

private[lagom] class JoinCluster @Inject() (
    system: ActorSystem,
    environment: Environment,
    akkaManagementTrigger: AkkaManagementTrigger
) {
  JoinClusterImpl.join(system, environment, akkaManagementTrigger)
} 
Example 182
Source File: JacksonModule.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.javadsl.jackson

import akka.actor.ActorSystem
import akka.serialization.jackson.JacksonMigration
import play.api.Configuration
import play.api.Environment
import play.api.inject.Binding
import play.api.inject.Module
import javax.inject.Inject


class JacksonModule extends Module {
  override def bindings(environment: Environment, configuration: Configuration): Seq[Binding[_]] = Seq(
    bind[JacksonMigrationCheck].toSelf.eagerly(),
    bind[JacksonSerializerFactory].toSelf,
    bind[JacksonExceptionSerializer].toSelf
  )
}

private[lagom] class JacksonMigrationCheck @Inject() (system: ActorSystem) {
  if (system.settings.config.hasPath("lagom.serialization.json.migrations")) {
    throw new IllegalStateException(
      "JacksonJsonSerializer migrations defined in " +
        s"'lagom.serialization.json.migrations' must be rewritten as [${classOf[JacksonMigration].getName}] " +
        "and defined in config 'akka.serialization.jackson.migrations'."
    )
  }
} 
Example 183
Source File: AkkaManagementModule.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.internal.javadsl.server

import akka.actor.ActorSystem
import akka.actor.CoordinatedShutdown
import com.lightbend.lagom.internal.akka.management.AkkaManagementTrigger
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.Mode

import scala.concurrent.ExecutionContext

private[lagom] class AkkaManagementModule extends Module {
  override def bindings(environment: Environment, configuration: Configuration): Seq[Binding[_]] = {
    // The trigger must be eager because it's often not required by anyone as a dependency to
    // be injected and yet it must be started anyway
    Seq(bind[AkkaManagementTrigger].toProvider[AkkaManagementProvider].eagerly())
  }
}

@Singleton
private[lagom] class AkkaManagementProvider @Inject() (
    config: Config,
    actorSystem: ActorSystem,
    coordinatedShutdown: CoordinatedShutdown,
    environment: Environment,
    executionContext: ExecutionContext
) extends Provider[AkkaManagementTrigger] {
  override def get(): AkkaManagementTrigger = {
    val instance = new AkkaManagementTrigger(config, actorSystem, coordinatedShutdown)(executionContext)
    if (environment.mode == Mode.Prod) {
      instance.start()
    }
    instance
  }
} 
Example 184
Source File: TestServiceLocator.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.internal.testkit

import java.net.URI
import java.util.Optional
import java.util.concurrent.CompletionStage

import scala.compat.java8.FutureConverters._
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
import com.lightbend.lagom.javadsl.api.Descriptor
import javax.inject.Inject
import javax.inject.Singleton

import com.lightbend.lagom.javadsl.client.CircuitBreakersPanel
import com.lightbend.lagom.javadsl.client.CircuitBreakingServiceLocator

@Singleton
private[lagom] class TestServiceLocator @Inject() (
    circuitBreakers: CircuitBreakersPanel,
    port: TestServiceLocatorPort,
    implicit val ec: ExecutionContext
) extends CircuitBreakingServiceLocator(circuitBreakers) {
  private val futureUri = port.port.map(p => URI.create("http://localhost:" + p))

  override def locate(name: String, call: Descriptor.Call[_, _]): CompletionStage[Optional[URI]] =
    futureUri.map(uri => Optional.of(uri)).toJava
}

private[lagom] final case class TestServiceLocatorPort(port: Future[Int]) 
Example 185
Source File: TestTopicFactory.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.internal.testkit

import java.util.concurrent.CompletionStage
import javax.inject.Inject

import akka.Done
import akka.stream.Materializer
import akka.stream.javadsl.Flow
import akka.stream.javadsl.Sink
import akka.stream.javadsl.Source
import com.lightbend.lagom.internal.broker.TaggedOffsetTopicProducer
import com.lightbend.lagom.internal.javadsl.api.MethodTopicHolder
import com.lightbend.lagom.internal.javadsl.api.broker.TopicFactory
import com.lightbend.lagom.internal.javadsl.server.ResolvedServices
import com.lightbend.lagom.javadsl.api.Descriptor.TopicCall
import com.lightbend.lagom.javadsl.api.broker.Topic.TopicId
import com.lightbend.lagom.javadsl.api.broker.Message
import com.lightbend.lagom.javadsl.api.broker.Subscriber
import com.lightbend.lagom.javadsl.api.broker.Topic
import com.lightbend.lagom.javadsl.persistence.AggregateEvent
import com.lightbend.lagom.javadsl.persistence.Offset

import scala.collection.JavaConverters._


class TestTopicFactory @Inject() (resolvedServices: ResolvedServices, materializer: Materializer) extends TopicFactory {
  private val topics: Map[TopicId, Any] = resolvedServices.services.flatMap { service =>
    service.descriptor.topicCalls().asScala.map { topicCall =>
      topicCall.topicId -> service.service
    }
  }.toMap

  override def create[Message](topicCall: TopicCall[Message]): Topic[Message] = {
    topics.get(topicCall.topicId()) match {
      case Some(service) =>
        topicCall.topicHolder() match {
          case method: MethodTopicHolder =>
            method.create(service) match {
              case topicProducer: TaggedOffsetTopicProducer[Message, _] =>
                new TestTopic(topicCall, topicProducer)
              case other =>
                throw new IllegalArgumentException(s"Testkit does not know how to handle topic $other")
            }
        }
      case None => throw new IllegalArgumentException(s"$topicCall hasn't been resolved.")
    }
  }

  private class TestTopic[Payload, Event <: AggregateEvent[Event]](
      topicCall: TopicCall[Payload],
      topicProducer: TaggedOffsetTopicProducer[Payload, Event]
  ) extends Topic[Payload] {
    override def topicId = topicCall.topicId

    override def subscribe(): Subscriber[Payload] = new TestSubscriber[Payload](identity)

    private class TestSubscriber[SubscriberPayload](transform: Payload => SubscriberPayload)
        extends Subscriber[SubscriberPayload] {
      override def withGroupId(groupId: String): Subscriber[SubscriberPayload] = this

      override def withMetadata(): Subscriber[Message[SubscriberPayload]] =
        new TestSubscriber(msg => Message.create(transform(msg)))

      override def atMostOnceSource(): Source[SubscriberPayload, _] = {
        val serializer   = topicCall.messageSerializer().serializerForRequest()
        val deserializer = topicCall.messageSerializer().deserializer(serializer.protocol())

        // Create a source for all the tags, and merge them all together.
        // Then, send the flow through a serializer and deserializer, to simulate sending it over the wire.
        Source
          .from(topicProducer.tags)
          .asScala
          .flatMapMerge(topicProducer.tags.size(), { tag =>
            topicProducer.readSideStream.apply(tag, Offset.NONE).asScala.map(_.first)
          })
          .map { message =>
            serializer.serialize(message)
          }
          .map { bytes =>
            deserializer.deserialize(bytes)
          }
          .map(transform)
          .asJava
      }

      override def atLeastOnce(flow: Flow[SubscriberPayload, Done, _]): CompletionStage[Done] = {
        atMostOnceSource().via(flow).runWith(Sink.ignore[Done], materializer)
      }
    }
  }
} 
Example 186
Source File: ServiceTestSpec.scala    From lagom   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.lagom.javadsl.testkit

import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths

import javax.inject.Inject
import akka.japi.function.Procedure
import com.google.inject.AbstractModule
import com.lightbend.lagom.javadsl.api.Descriptor
import com.lightbend.lagom.javadsl.api.Service
import com.lightbend.lagom.javadsl.persistence.PersistentEntityRegistry
import com.lightbend.lagom.javadsl.server.ServiceGuiceSupport
import com.lightbend.lagom.javadsl.testkit.ServiceTest.Setup
import com.lightbend.lagom.javadsl.testkit.ServiceTest.TestServer
import play.inject.guice.GuiceApplicationBuilder

import scala.collection.JavaConverters._
import scala.compat.java8.FunctionConverters._
import scala.util.Properties
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec

class ServiceTestSpec extends AnyWordSpec with Matchers {
  "ServiceTest" when {
    "started with Cassandra" should {
      "create a temporary directory" in {
        val temporaryFileCountBeforeRun = listTemporaryFiles().size

        withServer(ServiceTest.defaultSetup.withCassandra()) { _ =>
          val temporaryFilesDuringRun = listTemporaryFiles()

          temporaryFilesDuringRun should have size (temporaryFileCountBeforeRun + 1)
        }
      }
    }

    "stopped after starting" should {
      "remove its temporary directory" in {
        val temporaryFileCountBeforeRun = listTemporaryFiles().size

        withServer(ServiceTest.defaultSetup.withCassandra()) { _ =>
          ()
        }

        val temporaryFilesAfterRun = listTemporaryFiles()

        temporaryFilesAfterRun should have size temporaryFileCountBeforeRun
      }
    }

    "started with JDBC" should {
      "start successfully" in {
        withServer(ServiceTest.defaultSetup.withJdbc()) { _ =>
          ()
        }
      }
    }
  }

  def withServer(setup: Setup)(block: TestServer => Unit): Unit = {
    ServiceTest.withServer(setup.configureBuilder((registerService _).asJava), block(_))
  }

  def registerService(builder: GuiceApplicationBuilder): GuiceApplicationBuilder =
    builder.bindings(new TestServiceModule)

  def listTemporaryFiles(): Iterator[Path] = {
    val tmpDir = Paths.get(Properties.tmpDir)
    Files
      .newDirectoryStream(tmpDir, "ServiceTest_*")
      .iterator()
      .asScala
  }
}

trait TestService extends Service {
  import Service._

  final override def descriptor: Descriptor = named("test")
}

class TestServiceImpl @Inject() (persistentEntityRegistry: PersistentEntityRegistry) extends TestService

class TestServiceModule extends AbstractModule with ServiceGuiceSupport {
  override def configure(): Unit = bindService(classOf[TestService], classOf[TestServiceImpl])
} 
Example 187
Source File: AppConfig.scala    From self-assessment-api   with Apache License 2.0 5 votes vote down vote up
package config

import javax.inject.{Inject, Singleton}
import play.api.{Configuration, Environment}
import uk.gov.hmrc.play.bootstrap.config.ServicesConfig

@Singleton
class AppConfig @Inject()(val environment: Environment,
                          val configuration: Configuration,
                          config: ServicesConfig) {

  def appName: String = config.getString("appName")
  def appUrl: String = config.getString("appUrl")
  def registrationEnabled: Boolean = config.getBoolean("microservice.services.service-locator.enabled")

  def featureSwitch: Option[Configuration] = configuration.getOptional[Configuration](s"feature-switch")
  def apiStatus(version: String): String = config.getString(s"api.$version.status")
  def apiGatewayContext: String = config.getString("api.gateway.context")

  //Services
  def saApiUrl: String = config.baseUrl("self-assessment-api")
  def cgApiUrl: String = config.baseUrl("mtd-charitable-giving")
  def taxCalcUrl: String = config.baseUrl("mtd-tax-calculation")
  def propertyUrl: String = config.baseUrl("mtd-property-api")
  def selfEmploymentUrl: String = config.baseUrl("mtd-self-employment")
  def release2Enabled: Boolean = config.getBoolean("release-2.enabled")
  def dividendsApiUrl: String = config.baseUrl("mtd-dividends-income")
  def savingsAccountApiUrl: String = config.baseUrl("mtd-savings-accounts")
  def crystallisationApiUrl: String = config.baseUrl("mtd-crystallisation")

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

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

import scala.concurrent.ExecutionContext

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

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

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

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

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

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

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

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

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

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

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

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

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

import scala.concurrent.ExecutionContext

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

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

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

import scala.concurrent.ExecutionContext

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

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

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

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

import scala.concurrent.ExecutionContext

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


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

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

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

import scala.concurrent.ExecutionContext

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

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

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

import scala.concurrent.ExecutionContext

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


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

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

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

} 
Example 195
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 196
Source File: DividendsResource.scala    From self-assessment-api   with Apache License 2.0 5 votes vote down vote up
package router.resources

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

import scala.concurrent.ExecutionContext

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


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

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

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

import scala.concurrent.ExecutionContext

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

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

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

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

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

import scala.concurrent.ExecutionContext

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

  def get(nino: String, calculationId: String): Action[AnyContent] = AuthAction.async {
    implicit request =>
      service.get().map{
        case Left(error) => buildErrorResponse(error)
        case Right(apiResponse) => buildResponse(apiResponse)
      }
  }
} 
Example 199
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 200
Source File: SelfAssessmentService.scala    From self-assessment-api   with Apache License 2.0 5 votes vote down vote up
package router.services

import javax.inject.Inject
import play.api.libs.json.JsValue
import play.api.mvc.Request
import router.connectors.SelfAssessmentConnector
import router.constants.Versions._
import router.httpParsers.SelfAssessmentHttpParser.SelfAssessmentOutcome
import uk.gov.hmrc.http.HeaderCarrier

import scala.concurrent.Future

class SelfAssessmentService @Inject()(val selfAssessmentConnector: SelfAssessmentConnector) extends Service {

  def get()(implicit hc: HeaderCarrier, req: Request[_]): Future[SelfAssessmentOutcome] = {
    withApiVersion {
      case Some(VERSION_1) => selfAssessmentConnector.get(s"${req.uri}")
      case Some(VERSION_2) => selfAssessmentConnector.get(req.uri)(convertHeaderToVersion1)
    }
  }

  def post(body: JsValue)(implicit hc: HeaderCarrier, req: Request[_]): Future[SelfAssessmentOutcome] = {
    withApiVersion {
      case Some(VERSION_1) => selfAssessmentConnector.post(req.uri, body)
      case Some(VERSION_2) => selfAssessmentConnector.post(req.uri, body)(convertHeaderToVersion1)
    }
  }

  def put(body: JsValue)(implicit hc: HeaderCarrier, req: Request[_]): Future[SelfAssessmentOutcome] = {
    withApiVersion {
      case Some(VERSION_1) => selfAssessmentConnector.put(req.uri, body)
      case Some(VERSION_2) => selfAssessmentConnector.put(req.uri, body)(convertHeaderToVersion1)
    }
  }
}