diff --git a/app/controllers/SessionDataController.scala b/app/controllers/SessionDataController.scala index e8e5e6e..1941b5f 100644 --- a/app/controllers/SessionDataController.scala +++ b/app/controllers/SessionDataController.scala @@ -67,4 +67,10 @@ class SessionDataController @Inject()(authService: AuthService, ).map(_ => Ok) } } + + def deleteAllSessionData(): Action[AnyContent] = Action.async { implicit request => + authService.authorised() { + sessionDataService.deleteAllSessionData.map(_ => Ok) + } + } } diff --git a/app/repositories/SessionDataRepository.scala b/app/repositories/SessionDataRepository.scala index 81edc97..8b0fe98 100644 --- a/app/repositories/SessionDataRepository.scala +++ b/app/repositories/SessionDataRepository.scala @@ -101,7 +101,6 @@ class SessionDataRepository @Inject()(config: SessionDataRepositoryConfig)(impli findAndUpdate(selector, update) } - private def findAndUpdate(selector: JsObject, update: JsObject, fetchNewObject: Boolean = false, upsert: Boolean = false) = { collection .findOneAndUpdate(selector, update, findOneAndUpdateOptions(upsert)) @@ -109,6 +108,15 @@ class SessionDataRepository @Inject()(config: SessionDataRepositoryConfig)(impli .map(asOption) } + def deleteDataBySessionId(sessionId: String): Future[Option[JsValue]] = { + val selector: JsObject = Json.obj("session-id" -> sessionId) + findAndDelete(selector) + } + private def findAndDelete(selector: JsObject): Future[Option[JsValue]] = { + collection.findOneAndDelete(selector) + .toFutureOption() + } + def insert(document: JsObject): Future[InsertOneResult] = { collection .insertOne(document) diff --git a/app/services/SessionDataService.scala b/app/services/SessionDataService.scala index 88e7db6..44ae424 100644 --- a/app/services/SessionDataService.scala +++ b/app/services/SessionDataService.scala @@ -48,6 +48,10 @@ class SessionDataService @Inject()(sessionDataRepository: SessionDataRepository, dataId = dataId ) + def deleteAllSessionData(implicit hc: HeaderCarrier): Future[Option[JsValue]] = + sessionDataRepository.deleteDataBySessionId(sessionId = sessionIdFromHC) + + private[services] def sessionIdFromHC(implicit hc: HeaderCarrier): String = { hc.sessionId.fold( throw new InternalServerException("[SessionDataService][sessionIdFromHC] - No session id in header carrier") diff --git a/conf/subscription.routes b/conf/subscription.routes index f299a99..40a3f95 100644 --- a/conf/subscription.routes +++ b/conf/subscription.routes @@ -18,6 +18,7 @@ GET /session-data/all controllers.SessionDataCont GET /session-data/id/:id controllers.SessionDataController.retrieveSessionData(id: String) POST /session-data/id/:id controllers.SessionDataController.insertSessionData(id: String) DELETE /session-data/id/:id controllers.SessionDataController.deleteSessionData(id: String) +DELETE /session-data/id controllers.SessionDataController.deleteAllSessionData POST /mis/sign-up/:nino/:taxYear controllers.SignUpController.signUp(nino: String, taxYear: String) diff --git a/it/test/controllers/SessionDataControllerISpec.scala b/it/test/controllers/SessionDataControllerISpec.scala index dd6af0c..166f629 100644 --- a/it/test/controllers/SessionDataControllerISpec.scala +++ b/it/test/controllers/SessionDataControllerISpec.scala @@ -177,4 +177,14 @@ class SessionDataControllerISpec extends ComponentSpecBase with FeatureSwitching } } } + + s"DELETE ${controllers.routes.SessionDataController.deleteAllSessionData.url}" should { + "return OK and remove the entire document related to the user in mongo" when { + "the sessionId exists in mongo for the user" in { + AuthStub.stubAuthSuccess() + await(repository.insert(testDocumentAll)) + IncomeTaxSubscription.deleteAllSessionData should have(httpStatus(OK)) + } + } + } } diff --git a/it/test/helpers/ComponentSpecBase.scala b/it/test/helpers/ComponentSpecBase.scala index a71bc82..61dee5d 100644 --- a/it/test/helpers/ComponentSpecBase.scala +++ b/it/test/helpers/ComponentSpecBase.scala @@ -159,6 +159,9 @@ trait ComponentSpecBase extends AnyWordSpecLike def deleteSessionData(id:String): WSResponse = authorisedClient(s"/session-data/id/$id").delete().futureValue + def deleteAllSessionData(): WSResponse = + authorisedClient(s"/session-data/id").delete().futureValue + def insertSessionData(id:String, body: JsObject): WSResponse = authorisedClient(s"/session-data/id/$id", "Content-Type" -> "application/json").post(body.toString()).futureValue diff --git a/it/test/repositories/SessionDataRepositorySpec.scala b/it/test/repositories/SessionDataRepositorySpec.scala index 1210e76..aa4a8cd 100644 --- a/it/test/repositories/SessionDataRepositorySpec.scala +++ b/it/test/repositories/SessionDataRepositorySpec.scala @@ -18,6 +18,7 @@ package repositories import helpers.IntegrationTestConstants.testArn import org.scalatest.concurrent.ScalaFutures.convertScalaFuture +import org.scalatest.matchers.must.Matchers.convertToAnyMustWrapper import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpecLike import org.scalatest.{BeforeAndAfterEach, OptionValues} @@ -154,6 +155,26 @@ class SessionDataRepositorySpec extends AnyWordSpecLike with Matchers with Optio } } + "deleteDataBySessionId" when { + "the document was found" should { + "delete the entire document" in new Setup(testDocument()) { + testSessionDataRepository.deleteDataBySessionId(testSessionId).futureValue.map(_ \ "session-id").flatMap(_.asOpt[String]) shouldBe Some(testSessionId) + + val optionalData: Option[JsValue] = testSessionDataRepository.getSessionData(testSessionId).futureValue + optionalData shouldBe None + } + } + + "the document is not found" should { + "return no document" in new Setup(testDocument("testSessionIdTwo")) { + testSessionDataRepository.deleteDataBySessionId(testSessionId).futureValue shouldBe None + + val optionalData: Option[JsValue] = testSessionDataRepository.getSessionData("testSessionIdTwo").futureValue + optionalData.isDefined shouldBe true + } + } + } + "the document is not found" should { "return no document" in new Setup(testDocument()) { testSessionDataRepository.deleteDataWithSession(testSessionId + "-2", "testDataIdOne").futureValue shouldBe None diff --git a/test/services/SessionDataServiceSpec.scala b/test/services/SessionDataServiceSpec.scala index 7e9d76a..7e2bebc 100644 --- a/test/services/SessionDataServiceSpec.scala +++ b/test/services/SessionDataServiceSpec.scala @@ -110,4 +110,19 @@ class SessionDataServiceSpec extends CommonSpec with MockitoSugar with FeatureSw } } + "deleteAllSessionData" should { + "delete session using sessionId" in new Setup { + + when(mockSessionDataRepository.deleteDataBySessionId(ArgumentMatchers.eq(testSessionId))) + .thenReturn(Future.successful(Some(testJson))) + + await(service.deleteAllSessionData(headerCarrier)) shouldBe Some(testJson) + } + "throw an internal server exception when no session id exists" in new Setup { + intercept[InternalServerException]( + await(service.deleteAllSessionData(headerCarrierWithOutSessionId)) + ).message shouldBe errorMessage + } + } + }