From 1f344bc3cd8e055035756415a8e5ba9e5fc1a9fd Mon Sep 17 00:00:00 2001 From: Quentin Aubert Date: Wed, 8 Nov 2023 17:10:19 +0100 Subject: [PATCH] wip - migrate to play 2.9 --- daikoku/app/audit/audit.scala | 26 +- daikoku/app/audit/config.scala | 4 +- .../app/controllers/AdminApiController.scala | 23 +- daikoku/app/controllers/ApiController.scala | 12 +- .../controllers/AuditTrailController.scala | 6 +- .../app/controllers/EntitiesController.scala | 6 +- .../app/controllers/GraphQLController.scala | 8 +- daikoku/app/controllers/HomeController.scala | 12 +- .../IntegrationApiController.scala | 15 +- daikoku/app/controllers/JobsController.scala | 6 +- daikoku/app/controllers/LoginController.scala | 4 +- .../app/controllers/MessageController.scala | 7 +- daikoku/app/controllers/MockController.scala | 6 +- .../controllers/NotificationController.scala | 2 +- .../OtoroshiSettingsController.scala | 39 +-- daikoku/app/controllers/PaymentClient.scala | 10 +- .../app/controllers/SessionController.scala | 6 +- daikoku/app/controllers/TeamController.scala | 2 +- .../app/controllers/TenantController.scala | 8 +- .../controllers/TranslationController.scala | 12 +- daikoku/app/controllers/UsersController.scala | 9 +- daikoku/app/daikoku.scala | 2 +- daikoku/app/domain/SchemaDefinition.scala | 6 +- daikoku/app/jobs/OtoroshiVerifierJob.scala | 4 +- daikoku/app/jobs/QueueJob.scala | 6 +- daikoku/app/login/api.scala | 321 +++++++++++------- daikoku/app/login/oauth.scala | 2 +- daikoku/app/login/otoroshi.scala | 2 +- .../drivers/postgres/PostgresDataStore.scala | 5 +- .../storage/drivers/postgres/ReactivePg.scala | 6 +- daikoku/app/utils/ApiService.scala | 10 +- daikoku/app/utils/DeletionService.scala | 6 +- daikoku/app/utils/admin.scala | 22 +- daikoku/app/utils/otoroshi.scala | 2 +- daikoku/app/utils/s3.scala | 2 +- 35 files changed, 340 insertions(+), 279 deletions(-) diff --git a/daikoku/app/audit/audit.scala b/daikoku/app/audit/audit.scala index ca8dba7b1..48e73c728 100644 --- a/daikoku/app/audit/audit.scala +++ b/daikoku/app/audit/audit.scala @@ -6,7 +6,7 @@ import akka.http.scaladsl.util.FastFuture import akka.http.scaladsl.util.FastFuture._ import akka.kafka.ProducerSettings import akka.stream.scaladsl.{Keep, Sink, Source} -import akka.stream.{OverflowStrategy, QueueOfferResult} +import akka.stream.{Materializer, OverflowStrategy, QueueOfferResult} import cats.data.EitherT import controllers.AppError import fr.maif.otoroshi.daikoku.audit.config.{ElasticAnalyticsConfig, Webhook} @@ -231,10 +231,10 @@ object AuditActor { class AuditActor(implicit env: Env, messagesApi: MessagesApi, translator: Translator) extends Actor { - implicit lazy val ec = env.defaultExecutionContext + implicit lazy val ec: ExecutionContext = env.defaultExecutionContext - lazy val logger = Logger("audit-actor") - lazy val console = Logger("audit-console") + lazy val logger: Logger = Logger("audit-actor") + lazy val console: Logger = Logger("audit-console") lazy val kafkaWrapperAudit = new KafkaWrapper(env.defaultActorSystem, env, _.auditTopic) @@ -434,7 +434,7 @@ case class KafkaConfig(servers: Seq[String], ) object KafkaConfig { - implicit val format = Json.format[KafkaConfig] + implicit val format: OFormat[KafkaConfig] = Json.format[KafkaConfig] } object KafkaSettings { @@ -497,12 +497,12 @@ class KafkaWrapper(actorSystem: ActorSystem, class KafkaWrapperActor(env: Env, topicFunction: KafkaConfig => String) extends Actor { - implicit val ec = env.defaultExecutionContext + implicit val ec: ExecutionContext = env.defaultExecutionContext var config: Option[KafkaConfig] = None var eventProducer: Option[KafkaEventProducer] = None - lazy val logger = play.api.Logger("kafka-wrapper") + lazy val logger: Logger = play.api.Logger("kafka-wrapper") override def receive: Receive = { case event: KafkaWrapperEvent @@ -546,9 +546,9 @@ class KafkaEventProducer(_env: Env, config: KafkaConfig, topicFunction: KafkaConfig => String) { - implicit val ec = _env.defaultExecutionContext + implicit val ec: ExecutionContext = _env.defaultExecutionContext - lazy val logger = play.api.Logger("kafka-connector") + lazy val logger: Logger = play.api.Logger("kafka-connector") lazy val topic = topicFunction(config) @@ -557,10 +557,10 @@ class KafkaEventProducer(_env: Env, private lazy val producerSettings = KafkaSettings.producerSettings(_env, config) private lazy val producer: Producer[Array[Byte], String] = - producerSettings.createKafkaProducer + producerSettings.createKafkaProducer() def publish(event: JsValue): Future[Done] = { - val promise = Promise[RecordMetadata] + val promise = Promise[RecordMetadata]() try { val message = Json.stringify(event) producer.send(new ProducerRecord[Array[Byte], String](topic, message), @@ -664,7 +664,7 @@ class ElasticWritesAnalytics(config: ElasticAnalyticsConfig, env: Env) { private val index: String = config.index.getOrElse("otoroshi-events") private val `type`: String = config.`type`.getOrElse("event") private val searchUri = urlFromPath(s"/$index*/_search") - private implicit val mat = env.defaultMaterializer + private implicit val mat: Materializer = env.defaultMaterializer private def url(url: String): WSRequest = { val builder = env.wsClient.url(url) @@ -815,7 +815,7 @@ class ElasticReadsAnalytics(config: ElasticAnalyticsConfig, env: Env) { private val index: String = config.index.getOrElse("otoroshi-events") private val `type`: String = config.`type`.getOrElse("event") private val searchUri = urlFromPath(s"/$index*/_search") - private implicit val mat = env.defaultMaterializer + private implicit val mat: Materializer = env.defaultMaterializer private def url(url: String): WSRequest = { val builder = env.wsClient.url(url) diff --git a/daikoku/app/audit/config.scala b/daikoku/app/audit/config.scala index 3b5c7fbbb..c24e173ac 100644 --- a/daikoku/app/audit/config.scala +++ b/daikoku/app/audit/config.scala @@ -17,7 +17,7 @@ case class ElasticAnalyticsConfig( } object ElasticAnalyticsConfig { - val format = new Format[ElasticAnalyticsConfig] { + val format: Format[ElasticAnalyticsConfig] = new Format[ElasticAnalyticsConfig] { override def writes(o: ElasticAnalyticsConfig) = { Json.obj( "clusterUri" -> o.clusterUri, @@ -57,5 +57,5 @@ case class Webhook(url: String, } object Webhook { - implicit val format = Json.format[Webhook] + implicit val format: OFormat[Webhook] = Json.format[Webhook] } diff --git a/daikoku/app/controllers/AdminApiController.scala b/daikoku/app/controllers/AdminApiController.scala index 11d63eed2..422b8361f 100644 --- a/daikoku/app/controllers/AdminApiController.scala +++ b/daikoku/app/controllers/AdminApiController.scala @@ -1,6 +1,8 @@ package fr.maif.otoroshi.daikoku.ctrls import akka.http.scaladsl.util.FastFuture +import akka.stream.Materializer +import akka.stream.scaladsl.Source import akka.util.ByteString import cats.implicits._ import fr.maif.otoroshi.daikoku.actions.{DaikokuAction, DaikokuActionContext} @@ -20,6 +22,7 @@ import play.api.mvc._ import storage.drivers.postgres.PostgresDataStore import storage.{DataStore, Repo} +import scala.concurrent.ExecutionContext import scala.util.{Failure, Success, Using} class StateController(DaikokuAction: DaikokuAction, @@ -29,11 +32,11 @@ class StateController(DaikokuAction: DaikokuAction, pgPool: PgPool) extends AbstractController(cc) { - implicit val ec = env.defaultExecutionContext - implicit val mat = env.defaultMaterializer - implicit val ev = env + implicit val ec: ExecutionContext = env.defaultExecutionContext + implicit val mat: Materializer = env.defaultMaterializer + implicit val ev: Env = env - val bodyParser = BodyParser("Import parser") { _ => + val bodyParser: BodyParser[Source[ByteString, _]] = BodyParser("Import parser") { _ => Accumulator.source[ByteString].map(Right.apply) } @@ -184,11 +187,11 @@ class StateAdminApiController( cc: ControllerComponents) extends AbstractController(cc) { - implicit val ec = env.defaultExecutionContext - implicit val mat = env.defaultMaterializer - implicit val ev = env + implicit val ec: ExecutionContext = env.defaultExecutionContext + implicit val mat: Materializer = env.defaultMaterializer + implicit val ev: Env = env - val bodyParser = BodyParser("Import parser") { _ => + val bodyParser: BodyParser[Source[ByteString, _]] = BodyParser("Import parser") { _ => Accumulator.source[ByteString].map(Right.apply) } @@ -405,8 +408,8 @@ class CredentialsAdminApiController(DaikokuApiAction: DaikokuApiAction, env: Env, cc: ControllerComponents) extends AbstractController(cc) { - implicit val ec = env.defaultExecutionContext - implicit val ev = env + implicit val ec: ExecutionContext = env.defaultExecutionContext + implicit val ev: Env = env def getCredentials(token: String) = DaikokuApiAction.async { ctx => env.dataStore.apiSubscriptionRepo diff --git a/daikoku/app/controllers/ApiController.scala b/daikoku/app/controllers/ApiController.scala index 5a0a7ab07..f2fa4d381 100644 --- a/daikoku/app/controllers/ApiController.scala +++ b/daikoku/app/controllers/ApiController.scala @@ -33,7 +33,7 @@ import play.api.libs.json._ import play.api.libs.streams.Accumulator import play.api.mvc._ -import scala.concurrent.Future +import scala.concurrent.{ExecutionContext, Future} import scala.util.{Failure, Success, Try} class ApiController( @@ -51,11 +51,11 @@ class ApiController( ) extends AbstractController(cc) with I18nSupport { - implicit val ec = env.defaultExecutionContext - implicit val ev = env - implicit val tr = translator + implicit val ec: ExecutionContext = env.defaultExecutionContext + implicit val ev: Env = env + implicit val tr: Translator = translator - val logger = Logger("ApiController") + val logger: Logger = Logger("ApiController") def me() = DaikokuAction.async { ctx => @@ -210,7 +210,7 @@ class ApiController( ctx.setCtxValue("team.name", team.name) ctx.setCtxValue("team.id", team.id) - FastFuture.successful(Right(Ok(team.toUiPayload))) + FastFuture.successful(Right(Ok(team.toUiPayload()))) } } diff --git a/daikoku/app/controllers/AuditTrailController.scala b/daikoku/app/controllers/AuditTrailController.scala index 8e45c1848..9cd72f1c3 100644 --- a/daikoku/app/controllers/AuditTrailController.scala +++ b/daikoku/app/controllers/AuditTrailController.scala @@ -9,14 +9,16 @@ import org.joda.time.DateTime import play.api.libs.json.{JsArray, Json} import play.api.mvc.{AbstractController, ControllerComponents} +import scala.concurrent.ExecutionContext + class AuditTrailController(DaikokuAction: DaikokuAction, env: Env, otoroshiClient: OtoroshiClient, cc: ControllerComponents) extends AbstractController(cc) { - implicit val ec = env.defaultExecutionContext - implicit val ev = env + implicit val ec: ExecutionContext = env.defaultExecutionContext + implicit val ev: Env = env def auditTrail() = DaikokuAction.async { ctx => val from = ctx.request diff --git a/daikoku/app/controllers/EntitiesController.scala b/daikoku/app/controllers/EntitiesController.scala index 389054561..959c3eabd 100644 --- a/daikoku/app/controllers/EntitiesController.scala +++ b/daikoku/app/controllers/EntitiesController.scala @@ -15,13 +15,15 @@ import org.mindrot.jbcrypt.BCrypt import play.api.libs.json.Json import play.api.mvc._ +import scala.concurrent.ExecutionContext + class EntitiesController(DaikokuAction: DaikokuAction, env: Env, cc: ControllerComponents) extends AbstractController(cc) { - implicit val ec = env.defaultExecutionContext - implicit val ev = env + implicit val ec: ExecutionContext = env.defaultExecutionContext + implicit val ev: Env = env def newTenant() = DaikokuAction.async { ctx => PublicUserAccess( diff --git a/daikoku/app/controllers/GraphQLController.scala b/daikoku/app/controllers/GraphQLController.scala index 960353738..52cbcca41 100644 --- a/daikoku/app/controllers/GraphQLController.scala +++ b/daikoku/app/controllers/GraphQLController.scala @@ -18,7 +18,7 @@ import sangria.renderer.SchemaRenderer import storage.DataStore import java.util.concurrent.TimeUnit -import scala.concurrent.Future +import scala.concurrent.{ExecutionContext, Future} import scala.concurrent.duration.FiniteDuration import scala.util.{Failure, Success} @@ -31,12 +31,12 @@ class GraphQLController( extends AbstractController(cc) with I18nSupport { - implicit val ec = env.defaultExecutionContext - implicit val ev = env + implicit val ec: ExecutionContext = env.defaultExecutionContext + implicit val ev: Env = env lazy val (schema, resolver) = SchemaDefinition.getSchema(env) - val logger = Logger("GraphQLController") + val logger: Logger = Logger("GraphQLController") def adminApiSearch() = DaikokuApiAction.async(parse.json) { ctx => val query = (ctx.request.body \ "query").as[String] diff --git a/daikoku/app/controllers/HomeController.scala b/daikoku/app/controllers/HomeController.scala index 53519acd6..f08c7456c 100644 --- a/daikoku/app/controllers/HomeController.scala +++ b/daikoku/app/controllers/HomeController.scala @@ -12,7 +12,7 @@ import fr.maif.otoroshi.daikoku.domain.json.CmsPageFormat import fr.maif.otoroshi.daikoku.env.Env import fr.maif.otoroshi.daikoku.utils.{Errors, IdGenerator, diff_match_patch} import org.joda.time.DateTime -import play.api.i18n.I18nSupport +import play.api.i18n.{I18nSupport, MessagesApi} import play.api.libs.json._ import play.api.mvc._ @@ -20,7 +20,7 @@ import java.io.{ByteArrayOutputStream, File, FileInputStream, FileOutputStream} import java.util import java.util.concurrent.TimeUnit import java.util.zip.{ZipEntry, ZipInputStream, ZipOutputStream} -import scala.concurrent.Future +import scala.concurrent.{ExecutionContext, Future} import scala.concurrent.duration.DurationInt class HomeController( @@ -32,9 +32,9 @@ class HomeController( extends AbstractController(cc) with I18nSupport { - implicit val ec = env.defaultExecutionContext - implicit val e = env - implicit val m = messagesApi + implicit val ec: ExecutionContext = env.defaultExecutionContext + implicit val e: Env = env + implicit val m: MessagesApi = messagesApi case class CmsPageCache(contentType: String, content: String) @@ -288,7 +288,7 @@ class HomeController( val cacheId = s"${ctx.user.map(_.id.value).getOrElse("")}-${r.path.getOrElse("")}" - cache.policy + cache.policy() .expireAfterWrite() .ifPresent(eviction => { val ttl: Long = ctx.tenant.style diff --git a/daikoku/app/controllers/IntegrationApiController.scala b/daikoku/app/controllers/IntegrationApiController.scala index d610d10b1..1f19587a9 100644 --- a/daikoku/app/controllers/IntegrationApiController.scala +++ b/daikoku/app/controllers/IntegrationApiController.scala @@ -5,29 +5,22 @@ import controllers.AppError import fr.maif.otoroshi.daikoku.actions._ import fr.maif.otoroshi.daikoku.audit.AuditTrailEvent import fr.maif.otoroshi.daikoku.ctrls.authorizations.async.TenantAdminAccessTenant -import fr.maif.otoroshi.daikoku.domain.{ - Api, - ApiState, - ApiVisibility, - Team, - UsagePlan, - json -} +import fr.maif.otoroshi.daikoku.domain.{Api, ApiState, ApiVisibility, Team, UsagePlan, json} import fr.maif.otoroshi.daikoku.env.Env import fr.maif.otoroshi.daikoku.utils.StringImplicits._ import fr.maif.otoroshi.daikoku.utils.future._ import play.api.libs.json.{JsArray, JsObject, Json} import play.api.mvc.{AbstractController, ControllerComponents, Result} -import scala.concurrent.Future +import scala.concurrent.{ExecutionContext, Future} class IntegrationApiController(DaikokuAction: DaikokuAction, env: Env, cc: ControllerComponents) extends AbstractController(cc) { - implicit val ec = env.defaultExecutionContext - implicit val ev = env + implicit val ec: ExecutionContext = env.defaultExecutionContext + implicit val ev: Env = env def findById(ctx: DaikokuActionContext[_], teamId: String, diff --git a/daikoku/app/controllers/JobsController.scala b/daikoku/app/controllers/JobsController.scala index ada508802..dcb94f470 100644 --- a/daikoku/app/controllers/JobsController.scala +++ b/daikoku/app/controllers/JobsController.scala @@ -7,6 +7,8 @@ import jobs.{ApiKeyStatsJob, AuditTrailPurgeJob, OtoroshiVerifierJob} import play.api.libs.json.Json import play.api.mvc.{AbstractController, ControllerComponents} +import scala.concurrent.ExecutionContext + class JobsController(otoroshiVerifierJob: OtoroshiVerifierJob, apiKeyStatsJob: ApiKeyStatsJob, auditTrailPurgeJob: AuditTrailPurgeJob, @@ -15,8 +17,8 @@ class JobsController(otoroshiVerifierJob: OtoroshiVerifierJob, otoroshiClient: OtoroshiClient) extends AbstractController(cc) { - implicit val ec = env.defaultExecutionContext - implicit val ev = env + implicit val ec: ExecutionContext = env.defaultExecutionContext + implicit val ev: Env = env def otoroshiSyncJob() = Action.async { req => if (env.config.otoroshiSyncByCron) { diff --git a/daikoku/app/controllers/LoginController.scala b/daikoku/app/controllers/LoginController.scala index b1693ad18..ee1eb19d6 100644 --- a/daikoku/app/controllers/LoginController.scala +++ b/daikoku/app/controllers/LoginController.scala @@ -37,7 +37,7 @@ class LoginController(DaikokuAction: DaikokuAction, extends AbstractController(cc) { implicit val ec: ExecutionContext = env.defaultExecutionContext implicit val ev: Env = env - implicit val tr = translator + implicit val tr: Translator = translator def loginPage(provider: String) = DaikokuTenantAction.async { ctx => AuthProvider(provider) match { @@ -706,7 +706,7 @@ class LoginController(DaikokuAction: DaikokuAction, else FastFuture.successful( BadRequest(Json.obj("error" -> "Invalid code"))) - case None => + case _ => FastFuture.successful( BadRequest(Json.obj("error" -> "Invalid token"))) } diff --git a/daikoku/app/controllers/MessageController.scala b/daikoku/app/controllers/MessageController.scala index 3c937a1a2..056cd0789 100644 --- a/daikoku/app/controllers/MessageController.scala +++ b/daikoku/app/controllers/MessageController.scala @@ -23,6 +23,7 @@ import play.api.libs.json._ import play.api.mvc.{AbstractController, ControllerComponents} import java.util.UUID.randomUUID +import scala.concurrent.ExecutionContext import scala.concurrent.duration._ class MessageController(DaikokuAction: DaikokuAction, @@ -32,10 +33,10 @@ class MessageController(DaikokuAction: DaikokuAction, extends AbstractController(cc) with I18nSupport { - implicit val ec = env.defaultExecutionContext - implicit val ev = env + implicit val ec: ExecutionContext = env.defaultExecutionContext + implicit val ev: Env = env implicit val timeout: Timeout = Timeout(5.seconds) - implicit val tr = translator + implicit val tr: Translator = translator val messageActor: ActorRef = env.defaultActorSystem.actorOf(Props(new MessageActor()), "messages") diff --git a/daikoku/app/controllers/MockController.scala b/daikoku/app/controllers/MockController.scala index 311f1b498..3bf5e0f7a 100644 --- a/daikoku/app/controllers/MockController.scala +++ b/daikoku/app/controllers/MockController.scala @@ -16,16 +16,16 @@ import org.mindrot.jbcrypt.BCrypt import play.api.libs.json._ import play.api.mvc._ -import scala.concurrent.Future +import scala.concurrent.{ExecutionContext, Future} class MockController(DaikokuAction: DaikokuAction, env: Env, cc: ControllerComponents) extends AbstractController(cc) { - implicit val ec = env.defaultExecutionContext + implicit val ec: ExecutionContext = env.defaultExecutionContext - val scalaCode = + val scalaCode: String = """```scala |import zio.App |import zio.console._ diff --git a/daikoku/app/controllers/NotificationController.scala b/daikoku/app/controllers/NotificationController.scala index 763b078da..f3976031f 100644 --- a/daikoku/app/controllers/NotificationController.scala +++ b/daikoku/app/controllers/NotificationController.scala @@ -30,7 +30,7 @@ class NotificationController( implicit val ec: ExecutionContext = env.defaultExecutionContext implicit val ev: Env = env - implicit val tr = translator + implicit val tr: Translator = translator def unreadNotificationsCountOfTeam(teamId: String) = DaikokuAction.async { ctx => diff --git a/daikoku/app/controllers/OtoroshiSettingsController.scala b/daikoku/app/controllers/OtoroshiSettingsController.scala index aba3b7507..3c2a7f110 100644 --- a/daikoku/app/controllers/OtoroshiSettingsController.scala +++ b/daikoku/app/controllers/OtoroshiSettingsController.scala @@ -11,22 +11,8 @@ import controllers.AppError import fr.maif.otoroshi.daikoku.actions.DaikokuAction import fr.maif.otoroshi.daikoku.audit.AuditTrailEvent import fr.maif.otoroshi.daikoku.ctrls.authorizations.async._ -import fr.maif.otoroshi.daikoku.domain.json.{ - AuthorizedEntitiesFormat, - OtoroshiSettingsFormat, - OtoroshiSettingsIdFormat, - TestingConfigFormat -} -import fr.maif.otoroshi.daikoku.domain.{ - ActualOtoroshiApiKey, - Api, - ApiKeyRestrictions, - AuthorizedEntities, - OtoroshiSettings, - Testing, - TestingAuth, - UsagePlan -} +import fr.maif.otoroshi.daikoku.domain.json.{AuthorizedEntitiesFormat, OtoroshiSettingsFormat, OtoroshiSettingsIdFormat, TestingConfigFormat} +import fr.maif.otoroshi.daikoku.domain.{ActualOtoroshiApiKey, Api, ApiKeyRestrictions, AuthorizedEntities, OtoroshiSettings, Testing, TestingAuth, UsagePlan} import fr.maif.otoroshi.daikoku.env.Env import fr.maif.otoroshi.daikoku.logger.AppLogger import fr.maif.otoroshi.daikoku.utils.{IdGenerator, OtoroshiClient} @@ -35,15 +21,9 @@ import org.joda.time.DateTime import play.api.http.HttpEntity import play.api.libs.json._ import play.api.libs.streams.Accumulator -import play.api.mvc.{ - AbstractController, - BodyParser, - ControllerComponents, - Request, - Result -} +import play.api.mvc.{AbstractController, BodyParser, ControllerComponents, Request, Result} -import scala.concurrent.Future +import scala.concurrent.{ExecutionContext, Future} class OtoroshiSettingsController(DaikokuAction: DaikokuAction, env: Env, @@ -51,8 +31,8 @@ class OtoroshiSettingsController(DaikokuAction: DaikokuAction, cc: ControllerComponents) extends AbstractController(cc) { - implicit val ec = env.defaultExecutionContext - implicit val ev = env + implicit val ec: ExecutionContext = env.defaultExecutionContext + implicit val ev: Env = env def otoroshisSettings(tenantId: String) = DaikokuAction.async { ctx => TenantAdminOnly( @@ -576,9 +556,6 @@ class OtoroshiSettingsController(DaikokuAction: DaikokuAction, .forTenant(ctx.tenant) .findByIdOrHrId(apiId) .flatMap { - case None => - FastFuture.successful( - NotFound(Json.obj("error" -> "Api not found"))) case Some(api) if !api.testing.enabled => ??? case Some(api) if api.testing.enabled => { val url = (ctx.request.body \ "url").as[String] @@ -664,6 +641,10 @@ class OtoroshiSettingsController(DaikokuAction: DaikokuAction, InternalServerError(Json.obj("error" -> e.getMessage)) } } + case _ => + FastFuture.successful( + NotFound(Json.obj("error" -> "Api not found"))) + } } } diff --git a/daikoku/app/controllers/PaymentClient.scala b/daikoku/app/controllers/PaymentClient.scala index e0eb2a04b..4a6a1319a 100644 --- a/daikoku/app/controllers/PaymentClient.scala +++ b/daikoku/app/controllers/PaymentClient.scala @@ -12,11 +12,11 @@ import fr.maif.otoroshi.daikoku.logger.AppLogger import fr.maif.otoroshi.daikoku.utils.Cypher.encrypt import fr.maif.otoroshi.daikoku.utils.IdGenerator import play.api.libs.json.{JsArray, JsObject, JsValue, Json} -import play.api.libs.ws.{WSAuthScheme, WSRequest} +import play.api.libs.ws.{WSAuthScheme, WSClient, WSRequest} import play.api.mvc.Result import play.api.mvc.Results.Ok -import scala.concurrent.Future +import scala.concurrent.{ExecutionContext, Future} class PaymentClient( env: Env @@ -26,10 +26,10 @@ class PaymentClient( type PriceId = String type CustomerId = String - implicit val ec = env.defaultExecutionContext - implicit val ev = env + implicit val ec: ExecutionContext = env.defaultExecutionContext + implicit val ev: Env = env val STRIPE_URL = "https://api.stripe.com"; - val ws = env.wsClient + val ws: WSClient = env.wsClient def getStripeProductName(api: Api, plan: UsagePlan) = s"${api.name}::${api.currentVersion.value}/${plan.customName.getOrElse(plan.typeName)}" diff --git a/daikoku/app/controllers/SessionController.scala b/daikoku/app/controllers/SessionController.scala index 994de368f..2a1d83745 100644 --- a/daikoku/app/controllers/SessionController.scala +++ b/daikoku/app/controllers/SessionController.scala @@ -8,13 +8,15 @@ import org.joda.time.DateTime import play.api.libs.json.{JsArray, Json} import play.api.mvc._ +import scala.concurrent.ExecutionContext + class SessionController(DaikokuAction: DaikokuAction, env: Env, cc: ControllerComponents) extends AbstractController(cc) { - implicit val ec = env.defaultExecutionContext - implicit val ev = env + implicit val ec: ExecutionContext = env.defaultExecutionContext + implicit val ev: Env = env def allSessions() = DaikokuAction.async { ctx => DaikokuAdminOnly(AuditTrailEvent("@{user.name} has accessed all sessions"))( diff --git a/daikoku/app/controllers/TeamController.scala b/daikoku/app/controllers/TeamController.scala index 4dc4b3a1d..34fe1b1ef 100644 --- a/daikoku/app/controllers/TeamController.scala +++ b/daikoku/app/controllers/TeamController.scala @@ -35,7 +35,7 @@ class TeamController(DaikokuAction: DaikokuAction, implicit val ec: ExecutionContext = env.defaultExecutionContext implicit val ev: Env = env implicit val mat: Materializer = env.defaultMaterializer - implicit val tr = translator + implicit val tr: Translator = translator def team(teamId: String) = DaikokuActionMaybeWithGuest.async { ctx => diff --git a/daikoku/app/controllers/TenantController.scala b/daikoku/app/controllers/TenantController.scala index a0c475bb0..31783d52b 100644 --- a/daikoku/app/controllers/TenantController.scala +++ b/daikoku/app/controllers/TenantController.scala @@ -23,7 +23,7 @@ import play.api.libs.json._ import play.api.mvc.{AbstractController, ControllerComponents, Result, Results} import java.util.concurrent.TimeUnit -import scala.concurrent.Future +import scala.concurrent.{ExecutionContext, Future} import scala.util.Try class TenantController(DaikokuAction: DaikokuAction, @@ -35,9 +35,9 @@ class TenantController(DaikokuAction: DaikokuAction, extends AbstractController(cc) with I18nSupport { - implicit val ec = env.defaultExecutionContext - implicit val ev = env - implicit val tr = translator + implicit val ec: ExecutionContext = env.defaultExecutionContext + implicit val ev: Env = env + implicit val tr: Translator = translator def namesOfTenants() = DaikokuAction.async(parse.json) { ctx => val tenantIdsJs: JsArray = ctx.request.body.as[JsArray] diff --git a/daikoku/app/controllers/TranslationController.scala b/daikoku/app/controllers/TranslationController.scala index 28ae132bc..8e374ad77 100644 --- a/daikoku/app/controllers/TranslationController.scala +++ b/daikoku/app/controllers/TranslationController.scala @@ -1,6 +1,7 @@ package fr.maif.otoroshi.daikoku.ctrls import akka.http.scaladsl.util.FastFuture +import akka.stream.Materializer import controllers.AppError import controllers.AppError.TranslationNotFound import fr.maif.otoroshi.daikoku.actions.{DaikokuAction, DaikokuActionMaybeWithGuest, DaikokuActionMaybeWithoutUser} @@ -15,9 +16,10 @@ import play.api.i18n.I18nSupport import play.api.libs.json._ import play.api.mvc.{AbstractController, ControllerComponents} +import scala.concurrent.ExecutionContext + class TranslationController( DaikokuAction: DaikokuAction, - DaikokuActionMaybeWithGuest: DaikokuActionMaybeWithGuest, DaikokuActionMaybeWithoutUser: DaikokuActionMaybeWithoutUser, env: Env, cc: ControllerComponents, @@ -25,11 +27,11 @@ class TranslationController( extends AbstractController(cc) with I18nSupport { - implicit val ec = env.defaultExecutionContext - implicit val ev = env - implicit val mat = env.defaultMaterializer + implicit val ec: ExecutionContext = env.defaultExecutionContext + implicit val ev: Env = env + implicit val mat: Materializer = env.defaultMaterializer - val languages = supportedLangs.availables.map(_.language) + val languages: Seq[String] = supportedLangs.availables.map(_.language) def getLanguages() = DaikokuAction.async { ctx => TenantAdminOnly( diff --git a/daikoku/app/controllers/UsersController.scala b/daikoku/app/controllers/UsersController.scala index de1a3f1d2..714714658 100644 --- a/daikoku/app/controllers/UsersController.scala +++ b/daikoku/app/controllers/UsersController.scala @@ -21,6 +21,7 @@ import java.util.Base64 import java.util.concurrent.TimeUnit import javax.crypto.KeyGenerator import javax.crypto.spec.SecretKeySpec +import scala.concurrent.ExecutionContext import scala.concurrent.duration.FiniteDuration class UsersController(DaikokuAction: DaikokuAction, @@ -30,8 +31,8 @@ class UsersController(DaikokuAction: DaikokuAction, deletionService: DeletionService) extends AbstractController(cc) { - implicit val ec = env.defaultExecutionContext - implicit val ev = env + implicit val ec: ExecutionContext = env.defaultExecutionContext + implicit val ev: Env = env def allTenantUsers() = DaikokuAction.async { ctx => TenantAdminOnly( @@ -325,7 +326,7 @@ class UsersController(DaikokuAction: DaikokuAction, FastFuture.successful( BadRequest(Json.obj("error" -> "Can't updated user"))) } - case Some(_) => + case _ => FastFuture.successful(BadRequest(Json.obj( "error" -> "Unable to retrieve generated qrcode when 2fa enabled"))) } @@ -427,7 +428,7 @@ class UsersController(DaikokuAction: DaikokuAction, BadRequest( Json.obj("error" -> "Missing invitation information")) ) - case None => + case _ => BadRequest(Json.obj( "error" -> "You're token is invalid, expired or you are already in the team")) } diff --git a/daikoku/app/daikoku.scala b/daikoku/app/daikoku.scala index 843339a53..1cf18e376 100644 --- a/daikoku/app/daikoku.scala +++ b/daikoku/app/daikoku.scala @@ -248,7 +248,7 @@ package object modules { private class ErrorHandler(env: Env) extends HttpErrorHandler { - implicit val ec = env.defaultExecutionContext + implicit val ec: ExecutionContext = env.defaultExecutionContext lazy val logger = Logger("daikoku-error-handler") diff --git a/daikoku/app/domain/SchemaDefinition.scala b/daikoku/app/domain/SchemaDefinition.scala index dd3c7e1c5..8bf00fa2d 100644 --- a/daikoku/app/domain/SchemaDefinition.scala +++ b/daikoku/app/domain/SchemaDefinition.scala @@ -32,7 +32,7 @@ object SchemaDefinition { case object DateCoercionViolation extends ValueCoercionViolation("Date value expected") case object MapCoercionViolation extends ValueCoercionViolation("Map value can't be parsed") - implicit val TimeUnitType = ScalarType[TimeUnit]("TimeUnit", + implicit val TimeUnitType: ScalarType[TimeUnit] = ScalarType[TimeUnit]("TimeUnit", description = Some("TimeUnit type"), coerceOutput = (value, _) => value, coerceUserInput = { @@ -44,7 +44,7 @@ object SchemaDefinition { case _ => Left(JsArrayCoercionViolation) }) - implicit val JsArrayType = ScalarType[JsArray]("JsArray", + implicit val JsArrayType: ScalarType[JsArray] = ScalarType[JsArray]("JsArray", description = Some("JsArray type"), coerceOutput = (value, _) => value, coerceUserInput = { @@ -56,7 +56,7 @@ object SchemaDefinition { case _ => Left(JsArrayCoercionViolation) }) - implicit val JsonType = ScalarType[JsValue]("Json", + implicit val JsonType: ScalarType[JsValue] = ScalarType[JsValue]("Json", description = Some("Raw JSON value"), coerceOutput = (value, _) => value, coerceUserInput = { diff --git a/daikoku/app/jobs/OtoroshiVerifierJob.scala b/daikoku/app/jobs/OtoroshiVerifierJob.scala index 10f858f55..54ae18da7 100644 --- a/daikoku/app/jobs/OtoroshiVerifierJob.scala +++ b/daikoku/app/jobs/OtoroshiVerifierJob.scala @@ -68,8 +68,8 @@ class OtoroshiVerifierJob(client: OtoroshiClient, implicit val ec: ExecutionContext = env.defaultExecutionContext implicit val ev: Env = env - implicit val me = messagesApi - implicit val tr = translator + implicit val me: MessagesApi = messagesApi + implicit val tr: Translator = translator private val jobUser = User( id = UserId("otoroshi-verifier-job"), diff --git a/daikoku/app/jobs/QueueJob.scala b/daikoku/app/jobs/QueueJob.scala index c403cb17a..ead881d4a 100644 --- a/daikoku/app/jobs/QueueJob.scala +++ b/daikoku/app/jobs/QueueJob.scala @@ -159,7 +159,7 @@ class QueueJob( ), Json.obj("closed" -> JsNumber(DateTime.now().toDate.getTime)) ) - case None => FastFuture.successful(0L) + case _ => FastFuture.successful(0L) } } @@ -342,7 +342,7 @@ class QueueJob( paymentClient.syncWithThirdParty(consumption, settings, informations) - }.toIterable) + }.toList) .map(_.headOption)) _ <- OptionT.liftF( env.dataStore.operationRepo.forTenant(o.tenant).deleteById(o.id)) @@ -449,7 +449,7 @@ class QueueJob( private def awaitF(duration: FiniteDuration)( implicit actorSystem: ActorSystem, ec: ExecutionContext): Future[Unit] = { - val p = Promise[Unit] + val p = Promise[Unit]() actorSystem.scheduler.scheduleOnce(duration) { p.trySuccess(()) } diff --git a/daikoku/app/login/api.scala b/daikoku/app/login/api.scala index 7e925283e..b08b12a18 100644 --- a/daikoku/app/login/api.scala +++ b/daikoku/app/login/api.scala @@ -40,19 +40,20 @@ object AuthProvider { } val values: Seq[AuthProvider] = Seq(Local, Otoroshi, LDAP, OAuth2) - def apply(name: String): Option[AuthProvider] = name.toLowerCase() match { - case "Local" => Local.some - case "local" => Local.some - // case "LocalWithFIDOU2F" => LocalWithFIDOU2F.some - // case "localwithfidou2f" => LocalWithFIDOU2F.some - case "Otoroshi" => Otoroshi.some - case "otoroshi" => Otoroshi.some - case "LDAP" => LDAP.some - case "ldap" => LDAP.some - case "OAuth2" => OAuth2.some - case "oauth2" => OAuth2.some - case _ => None - } + def apply(name: String): Option[AuthProvider] = + name.toLowerCase() match { + case "Local" => Local.some + case "local" => Local.some + // case "LocalWithFIDOU2F" => LocalWithFIDOU2F.some + // case "localwithfidou2f" => LocalWithFIDOU2F.some + case "Otoroshi" => Otoroshi.some + case "otoroshi" => Otoroshi.some + case "LDAP" => LDAP.some + case "ldap" => LDAP.some + case "OAuth2" => OAuth2.some + case "oauth2" => OAuth2.some + case _ => None + } } object IdentityAttrs { @@ -73,31 +74,38 @@ object TenantHelper { .get("Daikoku-Tenant") .flatMap(t => Option( - env.config.tenantJwtVerifier.verify(t).getClaim("value").asString())) + env.config.tenantJwtVerifier.verify(t).getClaim("value").asString() + ) + ) .map(TenantId.apply) .getOrElse(Tenant.Default) } - def withTenant(request: RequestHeader, env: Env)(f: Tenant => Future[Result])( - implicit ec: ExecutionContext): Future[Result] = { + def withTenant(request: RequestHeader, env: Env)( + f: Tenant => Future[Result] + )(implicit ec: ExecutionContext): Future[Result] = { env.config.tenantProvider match { case TenantProvider.Header => { val tenantId = TenantHelper.extractTenantId(request)(env) env.dataStore.tenantRepo.findByIdNotDeleted(tenantId).flatMap { case None => - Errors.craftResponseResult("Tenant does not exists (1)", - Results.NotFound, - request, - None, - env) + Errors.craftResponseResult( + "Tenant does not exists (1)", + Results.NotFound, + request, + None, + env + ) case Some(tenant) if !tenant.enabled => - Errors.craftResponseResult("Tenant does not exists (2)", - Results.NotFound, - request, - None, - env, - tenant) + Errors.craftResponseResult( + "Tenant does not exists (2)", + Results.NotFound, + request, + None, + env, + tenant + ) case Some(tenant) => f(tenant) } } @@ -112,25 +120,32 @@ object TenantHelper { Json.obj( "_deleted" -> false, "domain" -> domain - )) + ) + ) .flatMap { case None => AppLogger.info( - s"Tenant does not exists - host $host - domain $domain - None") - Errors.craftResponseResult(s"Tenant does not exists (3)", - Results.NotFound, - request, - None, - env) + s"Tenant does not exists - host $host - domain $domain - None" + ) + Errors.craftResponseResult( + s"Tenant does not exists (3)", + Results.NotFound, + request, + None, + env + ) case Some(tenant) if !tenant.enabled => AppLogger.info( - s"Tenant does not exists - host $host - domain $domain - tenant disabled") - Errors.craftResponseResult("Tenant does not exists (4)", - Results.NotFound, - request, - None, - env, - tenant) + s"Tenant does not exists - host $host - domain $domain - tenant disabled" + ) + Errors.craftResponseResult( + "Tenant does not exists (4)", + Results.NotFound, + request, + None, + env, + tenant + ) case Some(tenant) => f(tenant) } case TenantProvider.Local => @@ -143,8 +158,6 @@ object TenantHelper { env.dataStore.userSessionRepo .findOne(Json.obj("sessionId" -> sessionId)) .flatMap { - case None => - FastFuture.successful(Tenant.Default) case Some(session) if !session.expires.isAfterNow => FastFuture.successful(Tenant.Default) case Some(session) if session.expires.isAfterNow => @@ -161,24 +174,31 @@ object TenantHelper { FastFuture.successful(tenantId) } } + case _ => + FastFuture.successful(Tenant.Default) + } } tenantIdF .flatMap(env.dataStore.tenantRepo.findByIdNotDeleted(_)) .flatMap { case None => - Errors.craftResponseResult("Tenant does not exists (5)", - Results.NotFound, - request, - None, - env) + Errors.craftResponseResult( + "Tenant does not exists (5)", + Results.NotFound, + request, + None, + env + ) case Some(tenant) if !tenant.enabled => - Errors.craftResponseResult("Tenant does not exists (6)", - Results.NotFound, - request, - None, - env, - tenant) + Errors.craftResponseResult( + "Tenant does not exists (6)", + Results.NotFound, + request, + None, + env, + tenant + ) case Some(tenant) => f(tenant) } .recoverWith { @@ -189,15 +209,17 @@ object TenantHelper { Results.NotFound, request, None, - env) + env + ) } } } } -class LoginFilter(env: Env)(implicit val mat: Materializer, - ec: ExecutionContext) - extends Filter { +class LoginFilter(env: Env)(implicit + val mat: Materializer, + ec: ExecutionContext +) extends Filter { import fr.maif.otoroshi.daikoku.utils.RequestImplicits._ implicit class RegexOps(sc: StringContext) { @@ -216,9 +238,12 @@ class LoginFilter(env: Env)(implicit val mat: Materializer, for { teamRepo <- env.dataStore.teamRepo.forTenantF(tenantId) maybePersonnalTeam: Option[Team] <- teamRepo.findOne( - Json.obj("type" -> TeamType.Personal.name, - "users.userId" -> user.id.value, - "_deleted" -> false)) + Json.obj( + "type" -> TeamType.Personal.name, + "users.userId" -> user.id.value, + "_deleted" -> false + ) + ) backupTeam = Team( id = TeamId(IdGenerator.token(32)), tenant = tenantId, @@ -230,9 +255,10 @@ class LoginFilter(env: Env)(implicit val mat: Materializer, contact = user.email, avatar = Some(user.picture) ) - theMaybeTeam: Option[Team] <- if (maybePersonnalTeam.isDefined) - FastFuture.successful(maybePersonnalTeam) - else teamRepo.save(backupTeam).map(_ => Some(backupTeam)) + theMaybeTeam: Option[Team] <- + if (maybePersonnalTeam.isDefined) + FastFuture.successful(maybePersonnalTeam) + else teamRepo.save(backupTeam).map(_ => Some(backupTeam)) // maybePersonnalTeamId = maybePersonnalTeam.map(_.id).getOrElse(Team.Default) // maybeLastTeam <- teamRepo.findByIdNotDeleted(user.lastTeams.getOrElse(tenantId, maybePersonnalTeamId)) } yield { @@ -258,11 +284,13 @@ class LoginFilter(env: Env)(implicit val mat: Materializer, } } - def apply(nextFilter: RequestHeader => Future[Result])( - request: RequestHeader): Future[Result] = { + def apply( + nextFilter: RequestHeader => Future[Result] + )(request: RequestHeader): Future[Result] = { AppLogger.debug( - s"Filtering on ${request.method.toLowerCase()} => ${request.relativeUri}") + s"Filtering on ${request.method.toLowerCase()} => ${request.relativeUri}" + ) (request.method.toLowerCase(), request.relativeUri) match { case (_, r"/fakeotoroshi/.*") => nextFilter(request) @@ -326,7 +354,8 @@ class LoginFilter(env: Env)(implicit val mat: Materializer, AppLogger.info("No personal token found") FastFuture.successful( Results.Unauthorized( - Json.obj("error" -> "not authorized")) + Json.obj("error" -> "not authorized") + ) ) case Some(token) => env.dataStore.userRepo @@ -336,14 +365,14 @@ class LoginFilter(env: Env)(implicit val mat: Materializer, AppLogger.info("No user found") FastFuture.successful( Results.Unauthorized( - Json.obj("error" -> "not authorized")) + Json.obj("error" -> "not authorized") + ) ) case Some(_user) => val user = _user.copy(tenants = _user.tenants + tenant.id) val session = UserSession( - id = DatastoreId( - IdGenerator.token(32)), + id = DatastoreId(IdGenerator.token(32)), userId = user.id, userName = user.name, userEmail = user.email, @@ -363,11 +392,13 @@ class LoginFilter(env: Env)(implicit val mat: Materializer, Results .Redirect( fr.maif.otoroshi.daikoku.ctrls.routes.LoginController - .loginPage(provider.name)) + .loginPage(provider.name) + ) .removingFromSession("sessionId")(request) .withSession( "redirect" -> cleanupRedirect( - request.relativeUri) + request.relativeUri + ) ) ) case Some(team) => @@ -375,26 +406,39 @@ class LoginFilter(env: Env)(implicit val mat: Materializer, _ => env.dataStore.teamRepo .forTenant(tenant) - .exists(Json.obj( - "type" -> "Admin", - "users.userId" -> user.id.asJson)) + .exists( + Json.obj( + "type" -> "Admin", + "users.userId" -> user.id.asJson + ) + ) .flatMap(isTenantAdmin => { nextFilter( request - .addAttr(IdentityAttrs.TeamKey, - team) - .addAttr(IdentityAttrs.UserKey, - user) + .addAttr( + IdentityAttrs.TeamKey, + team + ) + .addAttr( + IdentityAttrs.UserKey, + user + ) .addAttr( IdentityAttrs.TenantAdminKey, - isTenantAdmin) + isTenantAdmin + ) .addAttr( IdentityAttrs.ImpersonatorKey, - None) - .addAttr(IdentityAttrs.TenantKey, - tenant) - .addAttr(IdentityAttrs.SessionKey, - session) + None + ) + .addAttr( + IdentityAttrs.TenantKey, + tenant + ) + .addAttr( + IdentityAttrs.SessionKey, + session + ) ) }) } @@ -406,7 +450,8 @@ class LoginFilter(env: Env)(implicit val mat: Materializer, Results .Redirect( fr.maif.otoroshi.daikoku.ctrls.routes.LoginController - .loginPage(provider.name)) + .loginPage(provider.name) + ) .removingFromSession("sessionId")(request) .withSession( "redirect" -> cleanupRedirect(request.relativeUri) @@ -425,7 +470,8 @@ class LoginFilter(env: Env)(implicit val mat: Materializer, Results .Redirect( fr.maif.otoroshi.daikoku.ctrls.routes.LoginController - .loginPage(provider.name)) + .loginPage(provider.name) + ) .removingFromSession("sessionId")(request) .withSession( "redirect" -> cleanupRedirect(request.relativeUri) @@ -433,14 +479,16 @@ class LoginFilter(env: Env)(implicit val mat: Materializer, ) case None => nextFilter( - request.addAttr(IdentityAttrs.TenantKey, tenant)) + request.addAttr(IdentityAttrs.TenantKey, tenant) + ) case Some(session) if session.expires.isBeforeNow => AppLogger.info("Session expired") FastFuture.successful( Results .Redirect( fr.maif.otoroshi.daikoku.ctrls.routes.LoginController - .loginPage(provider.name)) + .loginPage(provider.name) + ) .removingFromSession("sessionId")(request) .withSession( "redirect" -> cleanupRedirect(request.relativeUri) @@ -451,16 +499,21 @@ class LoginFilter(env: Env)(implicit val mat: Materializer, .findByIdNotDeleted(session.userId) .flatMap { case None => - AppLogger.info("" + - "No user found") + AppLogger.info( + "" + + "No user found" + ) FastFuture.successful( Results - .Redirect(fr.maif.otoroshi.daikoku.ctrls.routes.LoginController - .loginPage(provider.name)) + .Redirect( + fr.maif.otoroshi.daikoku.ctrls.routes.LoginController + .loginPage(provider.name) + ) .removingFromSession("sessionId")(request) .withSession( "redirect" -> cleanupRedirect( - request.relativeUri) + request.relativeUri + ) ) ) case Some(_user) => @@ -473,42 +526,63 @@ class LoginFilter(env: Env)(implicit val mat: Materializer, Results .Redirect( fr.maif.otoroshi.daikoku.ctrls.routes.LoginController - .loginPage(provider.name)) + .loginPage(provider.name) + ) .removingFromSession("sessionId")(request) .withSession( "redirect" -> cleanupRedirect( - request.relativeUri) + request.relativeUri + ) ) ) case Some(team) => for { _ <- env.dataStore.userRepo.save(user) - isTenantAdmin <- env.dataStore.teamRepo - .forTenant(tenant) - .exists(Json.obj( - "type" -> "Admin", - "users.userId" -> user.id.asJson)) - result <- session.impersonatorId - .map(id => - env.dataStore.userRepo.findByIdNotDeleted( - id)) - .getOrElse(FastFuture.successful(None)) - .flatMap { maybeImpersonator => - nextFilter( - request - .addAttr(IdentityAttrs.TeamKey, team) - .addAttr(IdentityAttrs.UserKey, user) - .addAttr(IdentityAttrs.TenantAdminKey, - isTenantAdmin) - .addAttr( - IdentityAttrs.ImpersonatorKey, - maybeImpersonator) - .addAttr(IdentityAttrs.TenantKey, - tenant) - .addAttr(IdentityAttrs.SessionKey, - session) + isTenantAdmin <- + env.dataStore.teamRepo + .forTenant(tenant) + .exists( + Json.obj( + "type" -> "Admin", + "users.userId" -> user.id.asJson + ) ) - } + result <- + session.impersonatorId + .map(id => + env.dataStore.userRepo + .findByIdNotDeleted(id) + ) + .getOrElse(FastFuture.successful(None)) + .flatMap { maybeImpersonator => + nextFilter( + request + .addAttr( + IdentityAttrs.TeamKey, + team + ) + .addAttr( + IdentityAttrs.UserKey, + user + ) + .addAttr( + IdentityAttrs.TenantAdminKey, + isTenantAdmin + ) + .addAttr( + IdentityAttrs.ImpersonatorKey, + maybeImpersonator + ) + .addAttr( + IdentityAttrs.TenantKey, + tenant + ) + .addAttr( + IdentityAttrs.SessionKey, + session + ) + ) + } } yield { result } @@ -519,7 +593,8 @@ class LoginFilter(env: Env)(implicit val mat: Materializer, Results .Redirect( fr.maif.otoroshi.daikoku.ctrls.routes.LoginController - .loginPage(provider.name)) + .loginPage(provider.name) + ) .removingFromSession("sessionId")(request) .withSession( "redirect" -> cleanupRedirect(request.relativeUri) diff --git a/daikoku/app/login/oauth.scala b/daikoku/app/login/oauth.scala index 94a073e3e..298698edd 100644 --- a/daikoku/app/login/oauth.scala +++ b/daikoku/app/login/oauth.scala @@ -285,7 +285,7 @@ object OAuth2Support { if picture.isDefined && u.pictureFromProvider => picture.get case true if picture.isEmpty => User.DEFAULT_IMAGE - case false => u.picture + case _ => u.picture }, isDaikokuAdmin = if (u.isDaikokuAdmin) true else isDaikokuAdmin diff --git a/daikoku/app/login/otoroshi.scala b/daikoku/app/login/otoroshi.scala index b35e1478d..d2ada3f0c 100644 --- a/daikoku/app/login/otoroshi.scala +++ b/daikoku/app/login/otoroshi.scala @@ -324,7 +324,6 @@ object OtoroshiIdentityFilter { } maybeSession.flatMap { - case None => createSessionFromOtoroshi() case Some(session) if session.expires.isBefore(DateTime.now()) => for { @@ -345,6 +344,7 @@ object OtoroshiIdentityFilter { maybeUser = Some(user), maybeSession = Some(session)) } + case _ => createSessionFromOtoroshi() } } } diff --git a/daikoku/app/storage/drivers/postgres/PostgresDataStore.scala b/daikoku/app/storage/drivers/postgres/PostgresDataStore.scala index b6a5fa294..b9d6bfc9f 100644 --- a/daikoku/app/storage/drivers/postgres/PostgresDataStore.scala +++ b/daikoku/app/storage/drivers/postgres/PostgresDataStore.scala @@ -253,9 +253,6 @@ case class PostgresTenantCapableConsumptionRepo( ) extends PostgresTenantCapableRepo[ApiKeyConsumption, DatastoreId] with ConsumptionRepo { - private implicit val logger = Logger( - "daikoku-reactive-pg-PostgresTenantCapableConsumptionRepo") - implicit val jsObjectFormat: OFormat[JsObject] = new OFormat[JsObject] { override def reads(json: JsValue): JsResult[JsObject] = json.validate[JsObject](Reads.JsObjectReads) @@ -1630,7 +1627,7 @@ abstract class PostgresTenantAwareRepo[Of, Id <: ValueType]( abstract class CommonRepo[Of, Id <: ValueType](env: Env, reactivePg: ReactivePg) extends Repo[Of, Id] { - private implicit val logger = Logger("CommonPostgresRepo") + private implicit val logger: Logger = Logger("CommonPostgresRepo") val jsObjectWrites: OWrites[JsObject] = (o: JsObject) => o diff --git a/daikoku/app/storage/drivers/postgres/ReactivePg.scala b/daikoku/app/storage/drivers/postgres/ReactivePg.scala index dba98496f..dda075e2d 100644 --- a/daikoku/app/storage/drivers/postgres/ReactivePg.scala +++ b/daikoku/app/storage/drivers/postgres/ReactivePg.scala @@ -12,7 +12,7 @@ object pgimplicits { implicit class VertxFutureEnhancer[A](val future: io.vertx.core.Future[A]) extends AnyVal { def scala: Future[A] = { - val promise = Promise.apply[A] + val promise = Promise.apply[A]() future.onSuccess(a => promise.trySuccess(a)) future.onFailure(e => promise.tryFailure(e)) promise.future @@ -55,7 +55,7 @@ object pgimplicits { implicit class VertxQueryEnhancer[A](val query: io.vertx.sqlclient.Query[A]) extends AnyVal { def executeAsync(): Future[A] = { - val promise = Promise.apply[A] + val promise = Promise.apply[A]() val future = query.execute() future.onSuccess(a => promise.trySuccess(a)) future.onFailure(e => promise.tryFailure(e)) @@ -71,7 +71,7 @@ class ReactivePg(pool: Pool, configuration: Configuration)( import scala.jdk.CollectionConverters._ - private implicit val logger = Logger("otoroshi-reactive-pg-kv") + private implicit val logger: Logger = Logger("otoroshi-reactive-pg-kv") private val debugQueries = configuration .getOptional[Boolean]("daikoku.postgres.logQueries") diff --git a/daikoku/app/utils/ApiService.scala b/daikoku/app/utils/ApiService.scala index 97c09cb14..868f3a554 100644 --- a/daikoku/app/utils/ApiService.scala +++ b/daikoku/app/utils/ApiService.scala @@ -25,7 +25,7 @@ import play.api.libs.json._ import play.api.mvc.Result import play.api.mvc.Results.Ok -import scala.concurrent.Future +import scala.concurrent.{ExecutionContext, Future} import scala.util.Try class ApiService(env: Env, @@ -36,10 +36,10 @@ class ApiService(env: Env, otoroshiSynchronisator: OtoroshiVerifierJob, paymentClient: PaymentClient) { - implicit val ec = env.defaultExecutionContext - implicit val ev = env - implicit val me = messagesApi - implicit val tr = translator + implicit val ec: ExecutionContext = env.defaultExecutionContext + implicit val ev: Env = env + implicit val me: MessagesApi = messagesApi + implicit val tr: Translator = translator def getListFromStringMap(key: String, metadata: Map[String, String]): Set[String] = { diff --git a/daikoku/app/utils/DeletionService.scala b/daikoku/app/utils/DeletionService.scala index bc52df7bb..3a6b9b22c 100644 --- a/daikoku/app/utils/DeletionService.scala +++ b/daikoku/app/utils/DeletionService.scala @@ -12,12 +12,12 @@ import fr.maif.otoroshi.daikoku.logger.AppLogger import jobs.ApiKeyStatsJob import play.api.libs.json.{JsArray, JsNull, JsValue, Json} -import scala.concurrent.Future +import scala.concurrent.{ExecutionContext, Future} class DeletionService(env: Env, apiService: ApiService, apiKeyStatsJob: ApiKeyStatsJob, otoroshiClient: OtoroshiClient) { - implicit val ec = env.defaultExecutionContext - implicit val ev = env + implicit val ec: ExecutionContext = env.defaultExecutionContext + implicit val ev: Env = env /** * Delete logically a team diff --git a/daikoku/app/utils/admin.scala b/daikoku/app/utils/admin.scala index 169554a45..5a8830620 100644 --- a/daikoku/app/utils/admin.scala +++ b/daikoku/app/utils/admin.scala @@ -32,7 +32,7 @@ class DaikokuApiAction(val parser: BodyParser[AnyContent], env: Env) extends ActionBuilder[DaikokuApiActionContext, AnyContent] with ActionFunction[Request, DaikokuApiActionContext] { - implicit lazy val ec = env.defaultExecutionContext + implicit lazy val ec: ExecutionContext = env.defaultExecutionContext def decodeBase64(encoded: String): String = new String(Base64.getUrlDecoder.decode(encoded), Charsets.UTF_8) @@ -74,12 +74,6 @@ class DaikokuApiAction(val parser: BodyParser[AnyContent], env: Env) } case LocalAdminApiConfig(_) => request.headers.get("Authorization") match { - case None => - Errors.craftResponseResult("No api key provided", - Results.Unauthorized, - request, - None, - env) case Some(auth) if auth.startsWith("Basic ") => extractUsernamePassword(auth) match { case None => @@ -106,6 +100,12 @@ class DaikokuApiAction(val parser: BodyParser[AnyContent], env: Env) env) }) } + case _ => + Errors.craftResponseResult("No api key provided", + Results.Unauthorized, + request, + None, + env) } } } @@ -119,7 +119,7 @@ class DaikokuApiActionWithoutTenant(val parser: BodyParser[AnyContent], extends ActionBuilder[Request, AnyContent] with ActionFunction[Request, Request] { - implicit lazy val ec = env.defaultExecutionContext + implicit lazy val ec: ExecutionContext = env.defaultExecutionContext override def invokeBlock[A]( request: Request[A], @@ -171,10 +171,10 @@ abstract class AdminApiController[Of, Id <: ValueType]( cc: ControllerComponents) extends AbstractController(cc) { - implicit val ec = env.defaultExecutionContext - implicit val ev = env + implicit val ec: ExecutionContext = env.defaultExecutionContext + implicit val ev: Env = env - val logger = Logger(s"admin-controller-$entityName") + val logger: Logger = Logger(s"admin-controller-$entityName") def description: String = entityClass.getName def pathRoot: String diff --git a/daikoku/app/utils/otoroshi.scala b/daikoku/app/utils/otoroshi.scala index a1de670bb..9ef29b811 100644 --- a/daikoku/app/utils/otoroshi.scala +++ b/daikoku/app/utils/otoroshi.scala @@ -47,7 +47,7 @@ class OtoroshiExpositionFilter(stateHeaderName: String, class OtoroshiClient(env: Env) { - implicit val ec = env.defaultExecutionContext + implicit val ec: ExecutionContext = env.defaultExecutionContext val ws = env.wsClient def client(path: String)( diff --git a/daikoku/app/utils/s3.scala b/daikoku/app/utils/s3.scala index cbd2fc130..54155486b 100644 --- a/daikoku/app/utils/s3.scala +++ b/daikoku/app/utils/s3.scala @@ -163,7 +163,7 @@ class AssetsDataStore(actorSystem: ActorSystem)(implicit ec: ExecutionContext, byteString case Some(v) if !v => throw new BadFileContentFromContentType() - case None => + case _ => validated.set(true) byteString }