diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ffc48f3..e4ae399 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,15 +1,15 @@ -name: Build, format & test workflow - -on: [push] -env: - USER: signalconso - USE_TEXT_LOGS: true - -jobs: - # This workflow contains a single job called "greet" - build: - # The type of runner that the job will run on - runs-on: ubuntu-latest +#name: Build, format & test workflow +# +#on: [push] +#env: +# USER: signalconso +# USE_TEXT_LOGS: true +# +#jobs: +# # This workflow contains a single job called "greet" +# build: +# # The type of runner that the job will run on +# runs-on: ubuntu-latest # services: # postgres: # image: postgres:14 @@ -25,21 +25,21 @@ jobs: # --health-interval 10s # --health-timeout 5s # --health-retries 5 - - # Steps represent a sequence of tasks that will be - # executed as part of the job - steps: - - uses: actions/checkout@v3 - - name: Setup JDK - uses: actions/setup-java@v3 - with: - distribution: temurin - java-version: 17 - cache: 'sbt' - - - run: sudo apt-get update +# +# # Steps represent a sequence of tasks that will be +# # executed as part of the job +# steps: +# - uses: actions/checkout@v3 +# - name: Setup JDK +# uses: actions/setup-java@v3 +# with: +# distribution: temurin +# java-version: 17 +# cache: 'sbt' +# +# - run: sudo apt-get update # - run: sudo apt-get install postgresql-client # - run: whoami # - run: psql -d postgresql://signalconso@localhost/test_signalconso -p 5432 -c "CREATE EXTENSION pg_trgm;" - - name: Build and Test - run: sbt scalafmtCheckAll scalafmtSbtCheck -v +test \ No newline at end of file +# - name: Build and Test +# run: sbt scalafmtCheckAll scalafmtSbtCheck -v +test \ No newline at end of file diff --git a/app/controllers/AntivirusController.scala b/app/controllers/AntivirusController.scala index c18b6a6..d64ce17 100644 --- a/app/controllers/AntivirusController.scala +++ b/app/controllers/AntivirusController.scala @@ -9,6 +9,7 @@ import controllers.error.ApiError.FileNameTooLong import controllers.error.ApiError.MalformedFileKey import controllers.error.ApiError.MissingExternalId import controllers.error.AppErrorTransformer.handleError +import models.ScanCommand import play.api.Logger import play.api.libs.Files import play.api.libs.json.JsError @@ -47,12 +48,22 @@ class AntivirusController( .liftTo[Future](MissingExternalId) fileName = filePart.filename file = pathFromFilePart(filePart) - _ <- antivirusService.scanAndSave(externalId, fileName, file) + _ <- antivirusService.scanFromFile(externalId, fileName, file) } yield NoContent app.recover { case err => handleError(request, err) } } + def scan() = + SecuredAction.async(parse.json) { request => + request.body + .validate[ScanCommand] + .fold( + errors => Future.successful(BadRequest(JsError.toJson(errors))), + results => antivirusService.scan(results).map(_ => NoContent) + ) + } + def rescan() = SecuredAction.async(parse.json) { request => request.body diff --git a/app/models/ScanCommand.scala b/app/models/ScanCommand.scala new file mode 100644 index 0000000..98cac62 --- /dev/null +++ b/app/models/ScanCommand.scala @@ -0,0 +1,13 @@ +package models + +import play.api.libs.json._ + +import java.time.OffsetDateTime + +case class ScanCommand( + externalId: String, + filename: String +) +object ScanCommand { + implicit val fileFormat: OFormat[ScanCommand] = Json.format[ScanCommand] +} diff --git a/app/service/AntivirusService.scala b/app/service/AntivirusService.scala index 86f9ee7..379f1a4 100644 --- a/app/service/AntivirusService.scala +++ b/app/service/AntivirusService.scala @@ -4,15 +4,13 @@ import actors.AntivirusScanActor import actors.antivirus.AntivirusScanExitCode import cats.implicits.catsSyntaxOption import controllers.error.ApiError.UnknownExternalId -import models.FileData -import models.FileId +import models.{FileData, FileId, ScanCommand} import org.apache.pekko.actor.typed.ActorRef import play.api.Logger import repositories.FileDataRepositoryInterface import java.time.OffsetDateTime -import scala.concurrent.ExecutionContext -import scala.concurrent.Future +import scala.concurrent.{ExecutionContext, Future} class AntivirusService( antivirusScanActor: ActorRef[AntivirusScanActor.ScanCommand], @@ -20,24 +18,31 @@ class AntivirusService( )(implicit val executionContext: ExecutionContext) { val logger = Logger(this.getClass) - def scanAndSave(externalId: String, filename: String, file: java.io.File): Future[FileData] = + def scanFromFile(externalId: String, filename: String, file: java.io.File): Future[FileData] = for { - fileData <- fileDataRepository.create( - FileData( - FileId.generateId(), - externalId = externalId, - creationDate = OffsetDateTime.now(), - filename = filename, - scanResult = None, - avOutput = None - ) + fileData <- createFileData( + externalId = externalId, + filename = filename ) - _ = logger.debug(s"Uploaded file ${fileData.id} to S3") + _ = logger.debug(s"Scheduling scan for ${fileData.filename}") } yield { antivirusScanActor ! AntivirusScanActor.ScanFromFile(fileData, file) fileData } + def scan(scanCommand: ScanCommand): Future[FileData] = + for { + fileData <- + createFileData( + externalId = scanCommand.externalId, + filename = scanCommand.filename + ) + _ = logger.debug(s"Scheduling scan for ${fileData.filename}") + } yield { + antivirusScanActor ! AntivirusScanActor.ScanFromBucket(fileData) + fileData + } + def reScanFile(fileExternalIds: List[String]) = fileDataRepository .getByExternalId(fileExternalIds) .map { files => @@ -46,6 +51,17 @@ class AntivirusService( .map(file => antivirusScanActor ! AntivirusScanActor.ScanFromBucket(file)) } + private def createFileData(externalId: String, filename: String): Future[FileData] = fileDataRepository.create( + FileData( + FileId.generateId(), + externalId = externalId, + creationDate = OffsetDateTime.now(), + filename = filename, + scanResult = None, + avOutput = None + ) + ) + def fileStatus(externalFileId: String): Future[FileData] = for { fileDataOpt <- fileDataRepository.getByExternalId(List(externalFileId)).map(_.headOption) diff --git a/conf/routes b/conf/routes index 4833793..6af6679 100644 --- a/conf/routes +++ b/conf/routes @@ -1,4 +1,5 @@ -POST /api/file/scan controllers.AntivirusController.scanAndUpload() +POST /api/file/scanFile controllers.AntivirusController.scanAndUpload() +POST /api/file/scan controllers.AntivirusController.scan() POST /api/file/rescan controllers.AntivirusController.rescan() GET /api/file/:externalFileId controllers.AntivirusController.fileStatus(externalFileId :String) \ No newline at end of file