Skip to content

Commit

Permalink
Merge pull request #3 from hmrc/APIS-3471
Browse files Browse the repository at this point in the history
API 3471
  • Loading branch information
FluentSynergyDW authored Oct 26, 2018
2 parents 5c1e387 + b9bac0a commit b7449d5
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 16 deletions.
12 changes: 9 additions & 3 deletions app/uk/gov/hmrc/controllers/GatekeeperController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@
package uk.gov.hmrc.controllers

import java.util.UUID
import javax.inject.Inject

import javax.inject.Inject
import play.api.libs.json.Json
import uk.gov.hmrc.connector.AuthConnector
import uk.gov.hmrc.controllers.ErrorCode._
import uk.gov.hmrc.models.{AuthRole, InvalidStateTransition}
import uk.gov.hmrc.services.{ApplicationService, GatekeeperService}
import uk.gov.hmrc.models.JsonFormatters._
import uk.gov.hmrc.models.{AuthRole, Blocked, InvalidStateTransition}
import uk.gov.hmrc.services.{ApplicationService, GatekeeperService}

import scala.concurrent.ExecutionContext.Implicits.global

Expand Down Expand Up @@ -73,6 +73,12 @@ class GatekeeperController @Inject()(val authConnector: AuthConnector, val appli
} recover recovery
}

def blockApplication(id: UUID) = requiresRole(AuthRole.APIGatekeeper).async { implicit request =>
gatekeeperService.blockApplication(id) map {
case Blocked => Ok
} recover recovery
}

def fetchAppsForGatekeeper = requiresRole(AuthRole.APIGatekeeper).async {
gatekeeperService.fetchNonTestingAppsWithSubmittedDate() map {
apps => Ok(Json.toJson(apps))
Expand Down
17 changes: 8 additions & 9 deletions app/uk/gov/hmrc/models/Application.scala
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ case class ApplicationResponse(id: UUID,
state: ApplicationState = ApplicationState(name = TESTING),
rateLimitTier: RateLimitTier = BRONZE,
trusted: Boolean = false,
checkInformation: Option[CheckInformation] = None)
checkInformation: Option[CheckInformation] = None,
blocked: Boolean = false)

object ApplicationResponse {
private def getEnvironment(data: ApplicationData, clientId: Option[String]): Option[Environment] = {
Expand Down Expand Up @@ -142,7 +143,8 @@ object ApplicationResponse {
data.state,
data.rateLimitTier.getOrElse(BRONZE),
trusted,
data.checkInformation)
data.checkInformation,
data.blocked)
}
}

Expand All @@ -160,7 +162,8 @@ case class ApplicationData(id: UUID,
createdOn: DateTime = DateTimeUtils.now,
rateLimitTier: Option[RateLimitTier] = Some(BRONZE),
environment: String = Environment.PRODUCTION.toString,
checkInformation: Option[CheckInformation] = None) {
checkInformation: Option[CheckInformation] = None,
blocked: Boolean = false) {
lazy val admins = collaborators.filter(_.role == Role.ADMINISTRATOR)
}

Expand Down Expand Up @@ -420,13 +423,9 @@ object RateLimitTier extends Enumeration {
sealed trait ApplicationStateChange

case object UpliftRequested extends ApplicationStateChange

case object UpliftApproved extends ApplicationStateChange

case object UpliftRejected extends ApplicationStateChange

case object UpliftVerified extends ApplicationStateChange

case object VerificationResent extends ApplicationStateChange

case object Deleted extends ApplicationStateChange
case object Deleted extends ApplicationStateChange
case object Blocked extends ApplicationStateChange
54 changes: 52 additions & 2 deletions app/uk/gov/hmrc/models/JsonFormatters.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,15 @@

package uk.gov.hmrc.models

import java.util.UUID

import org.joda.time.DateTime
import play.api.libs.functional.syntax._
import play.api.libs.json._
import uk.gov.hmrc.controllers._
import uk.gov.hmrc.models.AccessType.{PRIVILEGED, ROPC, STANDARD}
import uk.gov.hmrc.models.OverrideType._
import uk.gov.hmrc.models.RateLimitTier.RateLimitTier
import uk.gov.hmrc.mongo.json.ReactiveMongoFormats
import uk.gov.hmrc.play.json.Union
import uk.gov.hmrc.services.WSO2RestoreData
Expand Down Expand Up @@ -105,7 +109,30 @@ object JsonFormatters {
implicit val formatEnvironmentToken = Json.format[EnvironmentToken]
implicit val formatApplicationTokens = Json.format[ApplicationTokens]
implicit val formatSubscriptionData = Json.format[SubscriptionData]
implicit val formatApplicationData = Json.format[ApplicationData]

val applicationDataReads: Reads[ApplicationData] = (
(JsPath \ "id").read[UUID] and
(JsPath \ "name").read[String] and
(JsPath \ "normalisedName").read[String] and
(JsPath \ "collaborators").read[Set[Collaborator]] and
(JsPath \ "description").readNullable[String] and
(JsPath \ "wso2Username").read[String] and
(JsPath \ "wso2Password").read[String] and
(JsPath \ "wso2ApplicationName").read[String] and
(JsPath \ "tokens").read[ApplicationTokens] and
(JsPath \ "state").read[ApplicationState] and
(JsPath \ "access").read[Access] and
(JsPath \ "createdOn").read[DateTime] and
(JsPath \ "rateLimitTier").readNullable[RateLimitTier] and
(JsPath \ "environment").read[String] and
(JsPath \ "checkInformation").readNullable[CheckInformation] and
((JsPath \ "blocked").read[Boolean] or Reads.pure(false))
)(ApplicationData.apply _)

implicit val formatApplicationData = {
Format(applicationDataReads, Json.writes[ApplicationData])
}

implicit val formatCreateApplicationRequest = Json.format[CreateApplicationRequest]
implicit val formatUpdateApplicationRequest = Json.format[UpdateApplicationRequest]
implicit val formatApplicationResponse = Json.format[ApplicationResponse]
Expand Down Expand Up @@ -168,7 +195,30 @@ object MongoFormat {
implicit val formatApplicationTokens = Json.format[ApplicationTokens]
implicit val formatApiIdentifier = Json.format[APIIdentifier]
implicit val formatSubscriptionData = Json.format[SubscriptionData]
implicit val formatApplicationData = Json.format[ApplicationData]

val applicationDataReads: Reads[ApplicationData] = (
(JsPath \ "id").read[UUID] and
(JsPath \ "name").read[String] and
(JsPath \ "normalisedName").read[String] and
(JsPath \ "collaborators").read[Set[Collaborator]] and
(JsPath \ "description").readNullable[String] and
(JsPath \ "wso2Username").read[String] and
(JsPath \ "wso2Password").read[String] and
(JsPath \ "wso2ApplicationName").read[String] and
(JsPath \ "tokens").read[ApplicationTokens] and
(JsPath \ "state").read[ApplicationState] and
(JsPath \ "access").read[Access] and
(JsPath \ "createdOn").read[DateTime] and
(JsPath \ "rateLimitTier").readNullable[RateLimitTier] and
(JsPath \ "environment").read[String] and
(JsPath \ "checkInformation").readNullable[CheckInformation] and
((JsPath \ "blocked").read[Boolean] or Reads.pure(false))
)(ApplicationData.apply _)

implicit val formatApplicationData = {
OFormat(applicationDataReads, Json.writes[ApplicationData])
}

implicit val formatWSO2RestoreData = Json.format[WSO2RestoreData]
}

Expand Down
11 changes: 11 additions & 0 deletions app/uk/gov/hmrc/services/GatekeeperService.scala
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,17 @@ class GatekeeperService @Inject()(applicationRepository: ApplicationRepository,
}
}

def blockApplication(applicationId: UUID)(implicit hc: HeaderCarrier): Future[ApplicationStateChange] = {
def block(application: ApplicationData): ApplicationData = {
application.copy(blocked = true)
}

for {
app <- fetchApp(applicationId)
_ <- applicationRepository.save(block(app))
} yield Blocked
}


private def fetchApp(applicationId: UUID): Future[ApplicationData] = {
lazy val notFoundException = new NotFoundException(s"application not found for id: $applicationId")
Expand Down
1 change: 1 addition & 0 deletions conf/app.routes
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ POST /application/:id/approve-uplift @uk.gov.hmr
POST /application/:id/reject-uplift @uk.gov.hmrc.controllers.GatekeeperController.rejectUplift(id: java.util.UUID)
POST /application/:id/resend-verification @uk.gov.hmrc.controllers.GatekeeperController.resendVerification(id: java.util.UUID)
POST /application/:id/delete @uk.gov.hmrc.controllers.GatekeeperController.deleteApplication(id: java.util.UUID)
POST /application/:id/block @uk.gov.hmrc.controllers.GatekeeperController.blockApplication(id: java.util.UUID)

POST /application/:id/rate-limit-tier @uk.gov.hmrc.controllers.ApplicationController.updateRateLimitTier(id: java.util.UUID)

Expand Down
21 changes: 19 additions & 2 deletions test/unit/controllers/GatekeeperControllerSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import java.util.UUID
import org.apache.http.HttpStatus._
import org.joda.time.DateTime
import org.mockito.ArgumentCaptor
import org.mockito.Matchers.{eq => eqTo, any, anyString}
import org.mockito.Matchers.{any, anyString, eq => eqTo}
import org.mockito.Mockito._
import org.scalatest.concurrent.ScalaFutures
import org.scalatest.mockito.MockitoSugar
Expand All @@ -43,7 +43,9 @@ import common.uk.gov.hmrc.common.LogSuppressing
import common.uk.gov.hmrc.testutils.ApplicationStateUtil

import scala.concurrent.Future.{failed, successful}
import uk.gov.hmrc.http.{ HeaderCarrier, NotFoundException }
import uk.gov.hmrc.http.{HeaderCarrier, NotFoundException}
import uk.gov.hmrc.models.AuthRole.APIGatekeeper
import uk.gov.hmrc.models.RateLimitTier.SILVER

class GatekeeperControllerSpec extends UnitSpec with ScalaFutures with MockitoSugar with WithFakeApplication
with ApplicationStateUtil with LogSuppressing {
Expand Down Expand Up @@ -336,6 +338,21 @@ class GatekeeperControllerSpec extends UnitSpec with ScalaFutures with MockitoSu

}

"blockApplication" should {

val applicationId: UUID = UUID.randomUUID()

"block the application" in new Setup {

when(mockGatekeeperService.blockApplication(any()) (any[HeaderCarrier]())).thenReturn(successful(Blocked))

val result = await(underTest.blockApplication(applicationId)(request))

status(result) shouldBe SC_OK
verify(mockGatekeeperService).blockApplication(applicationId)
}
}

private def aHistory(appId: UUID, state: State = PENDING_GATEKEEPER_APPROVAL) = {
StateHistoryResponse(appId, state, Actor("anEmail", COLLABORATOR), None, DateTimeUtils.now)
}
Expand Down
21 changes: 21 additions & 0 deletions test/unit/services/GatekeeperServiceSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@ import org.joda.time.DateTimeUtils
import org.mockito.ArgumentCaptor
import org.mockito.Matchers.{any, anyString, eq => eqTo}
import org.mockito.Mockito._
import org.apache.http.HttpStatus._
import org.mockito.invocation.InvocationOnMock
import org.mockito.stubbing.Answer
import org.scalatest.BeforeAndAfterAll
import org.scalatest.concurrent.ScalaFutures
import org.scalatest.mockito.MockitoSugar
import play.api.test.FakeRequest
import uk.gov.hmrc.config.AppContext
import uk.gov.hmrc.connector.{ApiSubscriptionFieldsConnector, EmailConnector, ThirdPartyDelegatedAuthorityConnector}
import uk.gov.hmrc.controllers.{DeleteApplicationRequest, RejectUpliftRequest}
Expand Down Expand Up @@ -464,4 +466,23 @@ class GatekeeperServiceSpec extends UnitSpec with ScalaFutures with MockitoSugar
mockSubscriptionRepository, mockAuditService, mockEmailConnector, mockApiSubscriptionFieldsConnector)
}
}

"blockApplication" should {

val applicationId: UUID = UUID.randomUUID()
val applicationData = anApplicationData(applicationId)
val updatedApplication = applicationData.copy(blocked = true)

"set the block flag to true for an application" in new Setup {

when(mockApplicationRepository.fetch(any())).thenReturn(successful(Option(applicationData)))
when(mockApplicationRepository.save(any())).thenReturn(successful(updatedApplication))

val result = await(underTest.blockApplication(applicationId))
result shouldBe Blocked

verify(mockApplicationRepository).fetch(applicationId)
verify(mockApplicationRepository).save(updatedApplication)
}
}
}

0 comments on commit b7449d5

Please sign in to comment.