Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 29 additions & 6 deletions app/v1/controllers/AuthorisedController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,29 @@
package v1.controllers

import play.api.libs.json.Json
import play.api.libs.typedmap.TypedKey
import play.api.mvc._
import uk.gov.hmrc.auth.core.Enrolment
import uk.gov.hmrc.auth.core.authorise.Predicate
import uk.gov.hmrc.http.HeaderCarrier
import uk.gov.hmrc.play.bootstrap.backend.controller.BackendController
import utils.IdGenerator
import v1.controllers.requestParsers.validators.validations.VrnValidation
import v1.models.auth.UserDetails
import v1.models.errors.{DownstreamError, ForbiddenDownstreamError, LegacyUnauthorisedError, VrnFormatError}
import v1.services.EnrolmentsAuthService
import v1.services.{AuditService, EnrolmentsAuthService}

import scala.concurrent.{ExecutionContext, Future}

case class UserRequest[A](userDetails: UserDetails, request: Request[A]) extends WrappedRequest[A](request)

abstract class AuthorisedController(cc: ControllerComponents)(implicit ec: ExecutionContext) extends BackendController(cc) {
object AuditFailureHandler { val AttrKey: TypedKey[(String, RequestHeader, Result) => Unit] = TypedKey("auditFailureHandler")}

val authService: EnrolmentsAuthService
val idGenerator: IdGenerator

def authorisedAction(vrn: String, nrsRequired: Boolean = false): ActionBuilder[UserRequest, AnyContent] = new ActionBuilder[UserRequest, AnyContent] {
def authorisedAction(vrn: String, nrsRequired: Boolean = false, auditOnFailure: Boolean = false): ActionBuilder[UserRequest, AnyContent] = new ActionBuilder[UserRequest, AnyContent] {

override def parser: BodyParser[AnyContent] = cc.parsers.defaultBodyParser

Expand All @@ -51,16 +55,35 @@ abstract class AuthorisedController(cc: ControllerComponents)(implicit ec: Execu
implicit val headerCarrier: HeaderCarrier = hc(request)

val clientId = request.headers.get("X-Client-Id").getOrElse("N/A")
val correlationId: String = idGenerator.getUid

def auditFailure(result: Result): Unit =
if (auditOnFailure) {
println("checking for audit failure")
request.attrs
.get(AuditFailureHandler.AttrKey)
.foreach{handler =>
println(s"checking for handler failure")
handler(correlationId, request, result)}
}

if (VrnValidation.validate(vrn) == Nil) {
authService.authorised(predicate(vrn), nrsRequired)(headerCarrier,executionContext, request).flatMap[Result] {
case Right(userDetails) => block(UserRequest(userDetails.copy(clientId = clientId), request))
case Left(LegacyUnauthorisedError) => Future.successful(Forbidden(Json.toJson(LegacyUnauthorisedError)))
case Left(ForbiddenDownstreamError) => Future.successful(Forbidden(Json.toJson(DownstreamError)))
case Left(_) => Future.successful(InternalServerError(Json.toJson(DownstreamError)))
case Left(LegacyUnauthorisedError) => val result = Forbidden(Json.toJson(LegacyUnauthorisedError))
auditFailure(result)
Future.successful(result)
case Left(ForbiddenDownstreamError) => val result = Forbidden(Json.toJson(DownstreamError))
auditFailure(result)
Future.successful(result)
case Left(_) => val result = InternalServerError(Json.toJson(DownstreamError))
auditFailure(result)
Future.successful(result)
}
} else {
Future.successful(BadRequest(Json.toJson(VrnFormatError)))
val result = BadRequest(Json.toJson(VrnFormatError))
auditFailure(result)
Future.successful(result)
}
}
}
Expand Down
25 changes: 21 additions & 4 deletions app/v1/controllers/CustomerInfoController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,14 @@ package v1.controllers
import cats.data.EitherT
import cats.implicits._
import play.api.libs.json.Json
import play.api.mvc.{Action, AnyContent, ControllerComponents, Result}
import play.api.mvc.{Action, AnyContent, ControllerComponents, Request, RequestHeader, Result}
import uk.gov.hmrc.http.HeaderCarrier
import uk.gov.hmrc.play.http.HeaderCarrierConverter
import utils.{EndpointLogContext, IdGenerator, Logging}
import v1.audit.AuditEvents
import v1.controllers.requestParsers.CustomerInfoRequestParser
import v1.models.audit.AuditResponse
import v1.models.audit.{AuditError, AuditResponse}
import v1.models.auth.UserDetails
import v1.models.errors._
import v1.models.request.information.CustomerRawData
import v1.models.response.information.{CustomerDetails, CustomerInfoResponse, FlatRateScheme}
Expand All @@ -48,9 +51,22 @@ extends AuthorisedController(cc) with BaseController with Logging {
endpointName = "retrieveCustomerInfo"
)

def retrieveCustomerInfo(vrn: String): Action[AnyContent] =
authorisedAction(vrn).async { implicit request =>
def retrieveCustomerInfo(vrn: String): Action[AnyContent] = {
val handler: (String, RequestHeader, Result) => Unit = {(correlationId, request, result) =>
implicit val hc: HeaderCarrier = HeaderCarrierConverter.fromRequestAndSession(request, request.session)
println(s"[Audit DEBUG] inside custom audit = $correlationId, status=$result.header.status}")
auditService.auditEvent(AuditEvents.auditCustomerInfo(
correlationId,
UserDetails("unknown", None, "unknown", None), // or better if accessible
AuditResponse(result.header.status, Left(Seq(AuditError("UNAUTHORISED_OR_INVALID"))))
))
}

authorisedAction(vrn,
auditOnFailure = true
).async { implicit request =>
val updatedRequest = request.addAttr(AuditFailureHandler.AttrKey, handler)
implicit val reqWithAttr: Request[AnyContent] = updatedRequest
implicit val correlationId: String = idGenerator.getUid
infoLog(s"[${endpointLogContext.controllerName}][${endpointLogContext.endpointName}] " +
s"Retrieve Customer Info for VRN : $vrn with correlationId : $correlationId")
Expand Down Expand Up @@ -91,6 +107,7 @@ extends AuthorisedController(cc) with BaseController with Logging {
leftResult
}.merge
}
}

private def errorResult(errorWrapper: ErrorWrapper): Result = {
(errorWrapper.error: @unchecked) match {
Expand Down
2 changes: 1 addition & 1 deletion app/v1/controllers/SubmitReturnController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class SubmitReturnController @Inject()(val authService: EnrolmentsAuthService,
auditService: AuditService,
cc: ControllerComponents,
dateTime: CurrentDateTime,
idGenerator: IdGenerator,
val idGenerator: IdGenerator,
override val metrics: MetricRegistry)
(implicit ec: ExecutionContext)
extends AuthorisedController(cc) with BaseController with Timer with Logging {
Expand Down
2 changes: 1 addition & 1 deletion app/v1/services/AuditService.scala
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class AuditService @Inject()(auditConnector: AuditConnector,
detail = Json.toJson(event.detail),
tags = eventTags
)

logger.info(s"[Audit DEBUG] Sending event: type = ${event.auditType}, detail = ${Json.prettyPrint(Json.toJson(event.detail))}")
auditConnector.sendExtendedEvent(dataEvent)
}
}
6 changes: 6 additions & 0 deletions test/v1/controllers/AuthorisedControllerSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import play.api.libs.json.{JsValue, Json}
import play.api.mvc._
import uk.gov.hmrc.auth.core.Enrolment
import uk.gov.hmrc.http.HeaderCarrier
import utils.IdGenerator
import v1.mocks.services.MockEnrolmentsAuthService
import v1.models.errors.{DownstreamError, ForbiddenDownstreamError, LegacyUnauthorisedError, MtdError}
import v1.services.EnrolmentsAuthService
Expand All @@ -34,8 +35,13 @@ class AuthorisedControllerSpec extends ControllerBaseSpec {
val hc: HeaderCarrier = HeaderCarrier()
val authorisedController: TestController = new TestController()

val mockIdGenerator: IdGenerator = new IdGenerator {
override def getUid: String = "test-correlation-id"
}

class TestController extends AuthorisedController(cc) {
override val authService: EnrolmentsAuthService = mockEnrolmentsAuthService
override val idGenerator: IdGenerator = mockIdGenerator

def action(vrn: String): Action[AnyContent] = authorisedAction(vrn).async {
Future.successful(Ok(Json.obj()))
Expand Down