diff --git a/app/controllers/ElectionsApi.scala b/app/controllers/ElectionsApi.scala index b556200..9d2ce1f 100644 --- a/app/controllers/ElectionsApi.scala +++ b/app/controllers/ElectionsApi.scala @@ -1513,6 +1513,10 @@ object ElectionsApi .flatMap { election => val configJson = Json.parse(election.configuration) val config = configJson.validate[ElectionConfig].get + + // If this is a virtual election, also delete datastores for subelections + val virtualSubelections = config.virtualSubelections.getOrElse(Array[Long]()) + val url = eoUrl(config.director, "public_api/delete") WS.url(url).post( Json.obj( @@ -1524,9 +1528,20 @@ object ElectionsApi } else { BadRequest(error(s"EO returned status ${resp.status} with body ${resp.body}", ErrorCodes.EO_ERROR)) } + }.map { _ => + // Delete the parent election from database + DAL.elections.delete(id) + + // Delete datastore for parent election + Datastore.deleteDatastore(id) + + // Delete datastores for all virtual subelections + virtualSubelections.foreach { subElectionId => + Logger.info(s"Deleting datastore for virtual subelection $subElectionId of parent election $id") + Datastore.deleteDatastore(subElectionId) + } } }.map { _ => - DAL.elections.delete(id) Ok(response("ok")) }.recover { case e: NoSuchElementException => diff --git a/app/utils/Datastore.scala b/app/utils/Datastore.scala index ace1726..6cbad23 100644 --- a/app/utils/Datastore.scala +++ b/app/utils/Datastore.scala @@ -191,6 +191,39 @@ object Datastore { } } + /** Recursively deletes a directory and all its contents */ + private def deleteDirectoryRecursively(directory: File): Unit = { + if (directory.isDirectory) { + val files = directory.listFiles() + if (files != null) { + files.foreach { file => + if (file.isDirectory) { + deleteDirectoryRecursively(file) + } else { + file.delete() + } + } + } + } + directory.delete() + } + + /** deletes all datastore directories for an election (both private and public) */ + def deleteDatastore(electionId: Long) = { + val privatePath = getDirPath(electionId, public = false).toFile + val publicPath = getDirPath(electionId, public = true).toFile + + if (privatePath.exists()) { + Logger.info(s"Deleting private datastore directory for election $electionId: ${privatePath.getAbsolutePath}") + deleteDirectoryRecursively(privatePath) + } + + if (publicPath.exists()) { + Logger.info(s"Deleting public datastore directory for election $electionId: ${publicPath.getAbsolutePath}") + deleteDirectoryRecursively(publicPath) + } + } + // UNUSED remove