Skip to content

Commit

Permalink
TRELLO-2692 : save consumer ip (#1810)
Browse files Browse the repository at this point in the history
  • Loading branch information
ssedoudbgouv authored Dec 21, 2024
1 parent 28ecfbb commit 7964b85
Show file tree
Hide file tree
Showing 11 changed files with 71 additions and 19 deletions.
4 changes: 3 additions & 1 deletion app/controllers/ReportController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,11 @@ class ReportController(

def createReport: Action[JsValue] = IpRateLimitedAction2.async(parse.json) { implicit request =>
implicit val userRole: Option[UserRole] = None

for {
draftReport <- request.parseBody[ReportDraft]()
createdReport <- reportOrchestrator.validateAndCreateReport(draftReport).recover {
consumerIp = ConsumerIp(request.remoteAddress)
createdReport <- reportOrchestrator.validateAndCreateReport(draftReport, consumerIp).recover {
case err: SpammerEmailBlocked =>
logger.warn(err.details)
reportOrchestrator.createFakeReportForBlacklistedUser(draftReport)
Expand Down
21 changes: 21 additions & 0 deletions app/models/report/ConsumerIp.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package models.report

import play.api.libs.json.Format
import play.api.libs.json.Json
import repositories.PostgresProfile.api._
import slick.ast.BaseTypedType
import slick.jdbc.H2Profile.MappedColumnType
import slick.jdbc.JdbcType

case class ConsumerIp(value: String) extends AnyVal

object ConsumerIp {
implicit val ConsumerIpFormat: Format[ConsumerIp] = Json.valueFormat[ConsumerIp]

implicit val ConsumerIpColumnType: JdbcType[ConsumerIp] with BaseTypedType[ConsumerIp] =
MappedColumnType.base[ConsumerIp, String](
_.value,
ConsumerIp(_)
)

}
4 changes: 3 additions & 1 deletion app/models/report/reportmetadata/ReportMetadata.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package models.report.reportmetadata

import models.company.Address
import models.company.Company
import models.report.ConsumerIp
import models.report.Report
import play.api.libs.json.Json
import play.api.libs.json.Writes
Expand All @@ -15,7 +16,8 @@ case class ReportMetadata(
reportId: UUID,
isMobileApp: Boolean,
os: Option[Os],
assignedUserId: Option[UUID]
assignedUserId: Option[UUID],
consumerIp: Option[ConsumerIp]
)

object ReportMetadata {
Expand Down
7 changes: 5 additions & 2 deletions app/models/report/reportmetadata/ReportMetadataDraft.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package models.report.reportmetadata

import ai.x.play.json.Encoders.encoder
import ai.x.play.json.Jsonx
import cats.implicits.catsSyntaxOptionId
import models.report.ConsumerIp

import java.util.UUID
import scala.annotation.nowarn
Expand All @@ -11,12 +13,13 @@ case class ReportMetadataDraft(
isMobileApp: Boolean,
os: Option[Os]
) {
def toReportMetadata(reportId: UUID) =
def toReportMetadata(reportId: UUID, consumerIp: ConsumerIp) =
ReportMetadata(
reportId = reportId,
isMobileApp = isMobileApp,
os = os,
assignedUserId = None
assignedUserId = None,
consumerIp.some
)
}

Expand Down
7 changes: 5 additions & 2 deletions app/models/report/sampledata/SampleDataService.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import models.UserRole.Professionnel
import models.company.AccessLevel
import models.company.Company
import models.report.ExistingResponseDetails.REMBOURSEMENT_OU_AVOIR
import models.report.ConsumerIp
import models.report.IncomingReportResponse
import models.report.ReportResponseType.ACCEPTED
import models.report.ReportResponseType.NOT_CONCERNED
Expand Down Expand Up @@ -159,7 +160,7 @@ class SampleDataService(
s"--- Company access given to user"
)
reports = ReportGenerator.visibleReports(c)
createdReports <- reports.traverse(reportOrchestrator.createReport)
createdReports <- reports.traverse(reportOrchestrator.createReport(_, ConsumerIp("1.1.1.1")))
_ = logger.info(
s"--- Pending reports created"
)
Expand Down Expand Up @@ -219,7 +220,9 @@ class SampleDataService(
)

private def processedReports(c: Company, response: IncomingReportResponse, proUser: User) = for {
createdReports <- ReportGenerator.visibleReports(c).traverse(reportOrchestrator.createReport)
createdReports <- ReportGenerator
.visibleReports(c)
.traverse(reportOrchestrator.createReport(_, ConsumerIp("1.1.1.1")))
_ = logger.info(
s"--- Closed reports created"
)
Expand Down
16 changes: 10 additions & 6 deletions app/orchestrators/ReportOrchestrator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -184,14 +184,14 @@ class ReportOrchestrator(
}.sequence
}

def validateAndCreateReport(draftReport: ReportDraft): Future[Report] =
def validateAndCreateReport(draftReport: ReportDraft, consumerIp: ConsumerIp): Future[Report] =
for {
_ <- validateCompany(draftReport)
_ <- validateSpamSimilarReport(draftReport)
_ <- validateReportIdentification(draftReport)
_ <- validateConsumerEmail(draftReport)
_ <- validateNumberOfAttachments(draftReport)
createdReport <- createReport(draftReport)
createdReport <- createReport(draftReport, consumerIp)
} yield createdReport

private def validateReportIdentification(draftReport: ReportDraft) =
Expand Down Expand Up @@ -317,7 +317,7 @@ class ReportOrchestrator(
} yield Done
}

def createReport(draftReport: ReportDraft): Future[Report] =
def createReport(draftReport: ReportDraft, consumerIp: ConsumerIp): Future[Report] =
for {
maybeCompany <- extractOptionalCompany(draftReport)
maybeCountry = extractOptionalCountry(draftReport)
Expand All @@ -338,18 +338,22 @@ class ReportOrchestrator(
)
report <- reportRepository.create(reportToCreate)
_ = logger.debug(s"Created report with id ${report.id}")
_ <- createReportMetadata(draftReport, report)
_ <- createReportMetadata(draftReport, report, consumerIp)
files <- reportFileOrchestrator.attachFilesToReport(draftReport.fileIds, report.id)
updatedReport <- notifyProfessionalIfNeeded(maybeCompany, report)
_ <- emailNotificationOrchestrator.notifyDgccrfIfNeeded(updatedReport)
_ <- notifyConsumer(updatedReport, maybeCompany, files)
_ = logger.debug(s"Report ${updatedReport.id} created")
} yield updatedReport

def createReportMetadata(draftReport: ReportDraft, createdReport: Report): Future[Any] =
private def createReportMetadata(
draftReport: ReportDraft,
createdReport: Report,
consumerIp: ConsumerIp
): Future[Any] =
draftReport.metadata
.map { metadataDraft =>
val metadata = metadataDraft.toReportMetadata(reportId = createdReport.id)
val metadata = metadataDraft.toReportMetadata(reportId = createdReport.id, consumerIp)
reportMetadataRepository.create(metadata)
}
.getOrElse(Future.unit)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ class ReportMetadataRepository(override val dbConfig: DatabaseConfig[JdbcProfile
existingMetadata <- table.filter(_.reportId === reportId).result.headOption
newOrUpdatedMetadata = existingMetadata
.map(_.copy(assignedUserId = Some(userId)))
.getOrElse(ReportMetadata(reportId = reportId, isMobileApp = false, os = None, assignedUserId = Some(userId)))
.getOrElse(
ReportMetadata(reportId = reportId, isMobileApp = false, os = None, assignedUserId = Some(userId), None)
)
_ <-
table.insertOrUpdate(newOrUpdatedMetadata)
} yield newOrUpdatedMetadata).transactionally
Expand Down
10 changes: 9 additions & 1 deletion app/repositories/reportmetadata/ReportMetadataTable.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package repositories.reportmetadata

import models.report.ConsumerIp
import models.report.reportmetadata.Os
import models.report.reportmetadata.ReportMetadata
import repositories.DatabaseTable
Expand All @@ -8,6 +9,7 @@ import repositories.report.ReportTable
import repositories.reportmetadata.ReportMetadataColumnType._
import slick.ast.ColumnOption.PrimaryKey
import slick.collection.heterogeneous.HNil
import slick.collection.heterogeneous.syntax.::
import slick.collection.heterogeneous.syntax._

import java.util.UUID
Expand All @@ -18,6 +20,7 @@ class ReportMetadataTable(tag: Tag) extends DatabaseTable[ReportMetadata](tag, "
def isMobileApp = column[Boolean]("is_mobile_app")
def os = column[Option[Os]]("os")
def assignedUserId = column[Option[UUID]]("assigned_user_id")
def consumerIp = column[Option[ConsumerIp]]("consumer_ip")

def report = foreignKey("fk_reports", reportId, ReportTable.table)(
_.id,
Expand All @@ -30,12 +33,14 @@ class ReportMetadataTable(tag: Tag) extends DatabaseTable[ReportMetadata](tag, "
isMobileApp ::
os ::
assignedUserId ::
consumerIp ::
HNil =>
ReportMetadata(
reportId = reportId,
isMobileApp = isMobileApp,
os = os,
assignedUserId = assignedUserId
assignedUserId = assignedUserId,
consumerIp = consumerIp
)
}

Expand All @@ -44,6 +49,7 @@ class ReportMetadataTable(tag: Tag) extends DatabaseTable[ReportMetadata](tag, "
rm.isMobileApp ::
rm.os ::
rm.assignedUserId ::
rm.consumerIp ::
HNil
)

Expand All @@ -52,13 +58,15 @@ class ReportMetadataTable(tag: Tag) extends DatabaseTable[ReportMetadata](tag, "
Boolean ::
Option[Os] ::
Option[UUID] ::
Option[ConsumerIp] ::
HNil

def * = (
reportId ::
isMobileApp ::
os ::
assignedUserId ::
consumerIp ::
HNil
) <> (construct, extract)
}
Expand Down
2 changes: 2 additions & 0 deletions conf/db/migration/default/V49__consumerip.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE reports_metadata
ADD COLUMN consumer_ip VARCHAR;
9 changes: 5 additions & 4 deletions test/orchestrators/ReportOrchestratorTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import org.apache.pekko.Done
import controllers.error.AppError.CannotReportPublicAdministration
import controllers.error.AppError.DuplicateReportCreation
import io.scalaland.chimney.dsl._
import models.report.ConsumerIp
import models.report.DetailInputValue
import models.report.Report
import models.report.ReportDraft
Expand Down Expand Up @@ -67,7 +68,7 @@ class ReportOrchestratorTest(implicit ee: ExecutionEnv) extends Specification wi
.withFieldConst(_.ccrfCode, None)
.withFieldConst(_.metadata, None)
.transform
_ <- components.reportOrchestrator.validateAndCreateReport(reportDraft)
_ <- components.reportOrchestrator.validateAndCreateReport(reportDraft, ConsumerIp("0.0.0.0"))
} yield ()

res must throwA[DuplicateReportCreation].await
Expand Down Expand Up @@ -104,7 +105,7 @@ class ReportOrchestratorTest(implicit ee: ExecutionEnv) extends Specification wi
.withFieldConst(_.ccrfCode, None)
.withFieldConst(_.metadata, None)
.transform
_ <- components.reportOrchestrator.validateAndCreateReport(reportDraft)
_ <- components.reportOrchestrator.validateAndCreateReport(reportDraft, ConsumerIp("0.0.0.0"))
} yield ()

res must throwA[DuplicateReportCreation].await
Expand Down Expand Up @@ -183,7 +184,7 @@ class ReportOrchestratorTest(implicit ee: ExecutionEnv) extends Specification wi
.withFieldConst(_.ccrfCode, None)
.withFieldConst(_.metadata, None)
.transform
_ <- components.reportOrchestrator.validateAndCreateReport(reportDraft)
_ <- components.reportOrchestrator.validateAndCreateReport(reportDraft, ConsumerIp("0.0.0.0"))
} yield ()

res must throwA[DuplicateReportCreation].await
Expand Down Expand Up @@ -237,7 +238,7 @@ class ReportOrchestratorTest(implicit ee: ExecutionEnv) extends Specification wi
companyActivityCode = Some("84.10")
)
val res =
components.reportOrchestrator.validateAndCreateReport(draftReportOnPublicCompany)
components.reportOrchestrator.validateAndCreateReport(draftReportOnPublicCompany, ConsumerIp("0.0.0.0"))
res must throwA[CannotReportPublicAdministration.type].await
}

Expand Down
6 changes: 5 additions & 1 deletion test/repositories/ReportRepositorySpec.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package repositories

import cats.implicits.catsSyntaxOptionId
import models.report.ConsumerIp
import models.report.ReportFilter
import models.report.ReportStatus
import models.report.ReportTag
Expand Down Expand Up @@ -149,7 +151,9 @@ class ReportRepositorySpec(implicit ee: ExecutionEnv)
Await.result(components.reportRepository.create(report7), Duration.Inf)
Await.result(components.reportRepository.create(englishReport), Duration.Inf)
Await.result(
components.reportMetadataRepository.create(ReportMetadata(report2.id, false, Some(Os.Ios), None)),
components.reportMetadataRepository.create(
ReportMetadata(report2.id, false, Some(Os.Ios), None, ConsumerIp("0.0.0.0").some)
),
Duration.Inf
)

Expand Down

0 comments on commit 7964b85

Please sign in to comment.