Skip to content

Commit

Permalink
Merge pull request #129 from hmrc/add-non-nrs-auth-check
Browse files Browse the repository at this point in the history
Removed ITMP retrivals for endpoints that do not use the NPS service
  • Loading branch information
MarkAKelly authored Apr 24, 2018
2 parents 5ad4f48 + ac852cc commit 45ec6d9
Show file tree
Hide file tree
Showing 10 changed files with 281 additions and 115 deletions.
4 changes: 2 additions & 2 deletions app/uk/gov/hmrc/vatapi/models/NRSSubmission.scala
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ case class IdentityData(internalId: Option[String] = None,
groupIdentifier: Option[String] = None,
credentialRole: Option[CredentialRole],
mdtpInformation: Option[MdtpInformation] = None,
itmpName: ItmpName,
itmpName: Option[ItmpName],
itmpDateOfBirth: Option[LocalDate] = None,
itmpAddress: ItmpAddress,
itmpAddress: Option[ItmpAddress],
affinityGroup: Option[AffinityGroup],
credentialStrength: Option[String] = None,
loginTimes: LoginTimes)
Expand Down
27 changes: 24 additions & 3 deletions app/uk/gov/hmrc/vatapi/resources/BaseResource.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ trait BaseResource extends BaseController {
private val authService = AuthorisationService
private lazy val featureSwitch = FeatureSwitch(AppContext.featureSwitch)

def AuthAction(vrn: Vrn) = new ActionRefiner[Request, AuthRequest] {
def AuthAction(vrn: Vrn): ActionRefiner[Request, AuthRequest] = new ActionRefiner[Request, AuthRequest] {
logger.debug(s"[BaseResource][AuthAction] Check MTD VAT authorisation for the VRN : $vrn")
override protected def refine[A](request: Request[A]): Future[Either[Result, AuthRequest[A]]] =
if (featureSwitch.isAuthEnabled){
Expand All @@ -48,16 +48,37 @@ trait BaseResource extends BaseController {
Future.successful(Right(new AuthRequest(Organisation(), request)))
}

def APIAction(vrn: Vrn, summary: Option[String] = None): ActionBuilder[AuthRequest] =
def AuthActionWithNrsRequirement(vrn: Vrn): ActionRefiner[Request, AuthRequest] = new ActionRefiner[Request, AuthRequest] {
logger.debug(s"[BaseResource][AuthAction] Check MTD VAT authorisation for the VRN : $vrn and retrieve NRS data")
override protected def refine[A](request: Request[A]): Future[Either[Result, AuthRequest[A]]] =
if (featureSwitch.isAuthEnabled){
implicit val ev: Request[A] = request
authService.authCheckWithNrsRequirement(vrn) map {
case Right(authContext) => Right(new AuthRequest(authContext, request))
case Left(authError) => Left(authError)
}
} else
Future.successful(Right(new AuthRequest(Organisation(), request)))
}

def APIAction(vrn: Vrn, nrsRequired: Boolean = false): ActionBuilder[AuthRequest] = if (nrsRequired) {
new ActionBuilder[Request] with ActionFilter[Request] {
override protected def filter[A](request: Request[A]): Future[Option[Result]] =
Future {
None
}
} andThen AuthActionWithNrsRequirement(vrn)
} else {
new ActionBuilder[Request] with ActionFilter[Request] {
override protected def filter[A](request: Request[A]): Future[Option[Result]] =
Future {
None
}
} andThen AuthAction(vrn)
}


def getRequestDateTimestamp(implicit request: AuthRequest[_]) = {
def getRequestDateTimestamp(implicit request: AuthRequest[_]): String = {
val requestTimestampHeader = "X-Request-Timestamp"
val requestTimestamp = request.headers.get(requestTimestampHeader) match {
case Some(timestamp) if timestamp.trim.length > 0 => timestamp.trim
Expand Down
54 changes: 41 additions & 13 deletions app/uk/gov/hmrc/vatapi/services/AuthorisationService.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import play.api.libs.json.{JsArray, JsResultException, Json}
import play.api.mvc.Results._
import play.api.mvc.{RequestHeader, Result}
import uk.gov.hmrc.auth.core.authorise.RawJsonPredicate
import uk.gov.hmrc.auth.core.retrieve.{Retrievals, ~}
import uk.gov.hmrc.auth.core.retrieve.{OptionalRetrieval, Retrievals, ~}
import uk.gov.hmrc.auth.core.{Enrolment, Enrolments, _}
import uk.gov.hmrc.domain.Vrn
import uk.gov.hmrc.http.HeaderCarrier
Expand All @@ -35,7 +35,7 @@ import uk.gov.hmrc.vatapi.models.Errors.ClientOrAgentNotAuthorized

import scala.concurrent.{ExecutionContext, Future}

object AuthorisationService extends AuthorisationService{
object AuthorisationService extends AuthorisationService {
override val apiAuthorisedFunctions: APIAuthorisedFunctions.type = APIAuthorisedFunctions
}

Expand All @@ -50,6 +50,9 @@ trait AuthorisationService {
def authCheck(vrn: Vrn)(implicit hc: HeaderCarrier, reqHeader: RequestHeader, ec: ExecutionContext): Future[AuthResult] =
authoriseAsClient(vrn)

def authCheckWithNrsRequirement(vrn: Vrn)(implicit hc: HeaderCarrier, reqHeader: RequestHeader, ec: ExecutionContext): Future[AuthResult] =
authoriseAsClientWithNrsRequirement(vrn)

def getClientReference(enrolments: Enrolments): Option[String] =
enrolments.enrolments
.flatMap(_.identifiers)
Expand All @@ -63,22 +66,47 @@ trait AuthorisationService {

logger.debug(s"[AuthorisationService] [authoriseAsClient] Check user authorisation for MTD VAT based on VRN $vrn.")
apiAuthorisedFunctions.authorised(
RawJsonPredicate(JsArray.apply(Seq(Json.toJson(Enrolment(vatAuthEnrolments.enrolmentToken).withIdentifier(vatAuthEnrolments.identifier, vrn.vrn)
RawJsonPredicate(JsArray(Seq(Json.toJson(Enrolment(vatAuthEnrolments.enrolmentToken).withIdentifier(vatAuthEnrolments.identifier, vrn.vrn)
.withDelegatedAuthRule(vatAuthEnrolments.authRule.getOrElse("mtd-vat-auth")))))))
.retrieve(
affinityGroup and authorisedEnrolments and agentInformation
) {
case Some(userType) ~ enrolments ~ agentInfo
if userType == AffinityGroup.Organisation || userType == AffinityGroup.Individual || userType == AffinityGroup.Agent =>
logger.debug(s"[AuthorisationService] [authoriseAsClient] Authorisation succeeded as fully-authorised organisation " +
s"for VRN ${getClientReference(enrolments).getOrElse("")}.")
Future.successful(Right(authContext(userType, None, Some(agentInfo))))
case _ => logger.error(s"[AuthorisationService] [authoriseAsClient] Authorisation failed due to unsupported affinity group.")
Future.successful(Left(Forbidden(toJson(ClientOrAgentNotAuthorized))))
} recoverWith unauthorisedError
}

private def authoriseAsClientWithNrsRequirement(vrn: Vrn)(implicit hc: HeaderCarrier,
requestHeader: RequestHeader,
ec: ExecutionContext): Future[AuthResult] = {
import Retrievals._

val individualName = OptionalRetrieval(itmpName.propertyNames.head, itmpName.reads)
val individualAddress = OptionalRetrieval(itmpAddress.propertyNames.head, itmpAddress.reads)

logger.debug(s"[AuthorisationService] [authoriseAsClientWithNrsRequirement] Check user authorisation for MTD VAT based on VRN $vrn.")
apiAuthorisedFunctions.authorised(
RawJsonPredicate(JsArray(Seq(Json.toJson(Enrolment(vatAuthEnrolments.enrolmentToken).withIdentifier(vatAuthEnrolments.identifier, vrn.vrn)
.withDelegatedAuthRule(vatAuthEnrolments.authRule.getOrElse("mtd-vat-auth")))))))
.retrieve(
affinityGroup and authorisedEnrolments
and internalId and externalId and agentCode and credentials
and confidenceLevel and nino and saUtr and name and dateOfBirth
and email and agentInformation and groupIdentifier and credentialRole
and mdtpInformation and itmpName and itmpDateOfBirth and itmpAddress
and credentialStrength and loginTimes
){
and internalId and externalId and agentCode and credentials
and confidenceLevel and nino and saUtr and name and dateOfBirth
and email and agentInformation and groupIdentifier and credentialRole
and mdtpInformation and individualName and itmpDateOfBirth and individualAddress
and credentialStrength and loginTimes
) {
case affGroup ~ enrolments ~ inId ~ exId ~ agCode ~ creds
~ confLevel ~ ni ~ saRef ~ nme ~ dob
~ eml ~ agInfo ~ groupId ~ credRole
~ mdtpInfo ~ iname ~ idob ~ iaddress
~ credStrength ~ logins
if affGroup.contains(AffinityGroup.Organisation) || affGroup.contains(AffinityGroup.Individual) || affGroup.contains(AffinityGroup.Agent) =>
if affGroup.contains(AffinityGroup.Organisation) || affGroup.contains(AffinityGroup.Individual) || affGroup.contains(AffinityGroup.Agent) =>

val identityData =
IdentityData(
Expand All @@ -88,10 +116,10 @@ trait AuthorisationService {
credRole, mdtpInfo, iname, idob,
iaddress, affGroup, credStrength, logins)
val afGroup = affGroup.get
logger.debug(s"[AuthorisationService] [authoriseAsClient] Authorisation succeeded as fully-authorised organisation " +
logger.debug(s"[AuthorisationService] [authoriseAsClientWithNrsRequirement] Authorisation succeeded as fully-authorised organisation " +
s"for VRN ${getClientReference(enrolments).getOrElse("")}.")
Future.successful(Right(authContext(afGroup,Some(identityData), Some(agInfo))))
case _ => logger.error(s"[AuthorisationService] [authoriseAsClient] Authorisation failed due to unsupported affinity group.")
Future.successful(Right(authContext(afGroup, Some(identityData), Some(agInfo))))
case _ => logger.error(s"[AuthorisationService] [authoriseAsClientWithNrsRequirement] Authorisation failed due to unsupported affinity group.")
Future.successful(Left(Forbidden(toJson(ClientOrAgentNotAuthorized))))
} recoverWith unauthorisedError
}
Expand Down
31 changes: 31 additions & 0 deletions func/uk/gov/hmrc/support/BaseFunctionalSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,37 @@ trait BaseFunctionalSpec extends TestApplication {
}

def userIsFullyAuthorisedForTheResource: Givens = {
stubFor(
post(urlPathEqualTo(s"/auth/authorise"))
.willReturn(
aResponse()
.withStatus(200)
.withBody("""
|{
| "agentInformation": {
| "agentCode" : "TZRXXV",
| "agentFriendlyName" : "Bodgitt & Legget LLP",
| "agentId": "BDGL"
| },
| "affinityGroup": "Organisation",
| "authorisedEnrolments": [
| {
| "key":"HMRC-MTD-VAT",
| "identifiers":[
| {
| "key":"VRN",
| "value":"1000051409"
| }
| ],
| "state":"Activated"
| }
| ]
|}
""".stripMargin)))
this
}

def userIsFullyAuthorisedForTheNrsDependantResource: Givens = {
stubFor(
post(urlPathEqualTo(s"/auth/authorise"))
.willReturn(
Expand Down
18 changes: 9 additions & 9 deletions func/uk/gov/hmrc/vatapi/resources/ValueAddedTaxReturnsSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class ValueAddedTaxReturnsSpec extends BaseFunctionalSpec {

"allow users to submit VAT returns" in {
given()
.userIsFullyAuthorisedForTheResource
.userIsFullyAuthorisedForTheNrsDependantResource
.nrs().nrsVatReturnSuccessFor(vrn)
.des().vatReturns.expectVatReturnSubmissionFor(vrn)
.when()
Expand All @@ -55,7 +55,7 @@ class ValueAddedTaxReturnsSpec extends BaseFunctionalSpec {

"allow users to submit VAT returns even with negative amounts" in {
given()
.userIsFullyAuthorisedForTheResource
.userIsFullyAuthorisedForTheNrsDependantResource
.nrs().nrsVatReturnSuccessFor(vrn)
.des().vatReturns.expectVatReturnSubmissionFor(vrn)
.when()
Expand Down Expand Up @@ -83,7 +83,7 @@ class ValueAddedTaxReturnsSpec extends BaseFunctionalSpec {

"not allow users to submit undeclared VAT returns" in {
given()
.userIsFullyAuthorisedForTheResource
.userIsFullyAuthorisedForTheNrsDependantResource
.nrs().nrsVatReturnSuccessFor(vrn)
.des().vatReturns.expectVatReturnSubmissionFor(vrn)
.when()
Expand All @@ -96,7 +96,7 @@ class ValueAddedTaxReturnsSpec extends BaseFunctionalSpec {

"reject submission with invalid period key" in {
given()
.userIsFullyAuthorisedForTheResource
.userIsFullyAuthorisedForTheNrsDependantResource
.nrs().nrsVatReturnSuccessFor(vrn)
.des().vatReturns.expectVatReturnToFail(vrn, "INVALID_PERIODKEY")
.when()
Expand All @@ -109,7 +109,7 @@ class ValueAddedTaxReturnsSpec extends BaseFunctionalSpec {

"reject submission with invalid ARN" in {
given()
.userIsFullyAuthorisedForTheResource
.userIsFullyAuthorisedForTheNrsDependantResource
.nrs().nrsVatReturnSuccessFor(vrn)
.des().vatReturns.expectVatReturnToFail(vrn, "INVALID_ARN")
.when()
Expand All @@ -122,7 +122,7 @@ class ValueAddedTaxReturnsSpec extends BaseFunctionalSpec {

"reject submission with invalid VRN" in {
given()
.userIsFullyAuthorisedForTheResource
.userIsFullyAuthorisedForTheNrsDependantResource
.nrs().nrsVatReturnSuccessFor(vrn)
.des().vatReturns.expectVatReturnToFail(vrn, "INVALID_VRN")
.when()
Expand All @@ -135,7 +135,7 @@ class ValueAddedTaxReturnsSpec extends BaseFunctionalSpec {

"reject submission with invalid payload" in {
given()
.userIsFullyAuthorisedForTheResource
.userIsFullyAuthorisedForTheNrsDependantResource
.nrs().nrsVatReturnSuccessFor(vrn)
.des().vatReturns.expectVatReturnToFail(vrn, "INVALID_PAYLOAD")
.when()
Expand All @@ -148,7 +148,7 @@ class ValueAddedTaxReturnsSpec extends BaseFunctionalSpec {

"reject duplicate submission" in {
given()
.userIsFullyAuthorisedForTheResource
.userIsFullyAuthorisedForTheNrsDependantResource
.nrs().nrsVatReturnSuccessFor(vrn)
.des().vatReturns.expectVatReturnToFail(vrn, "DUPLICATE_SUBMISSION")
.when()
Expand All @@ -161,7 +161,7 @@ class ValueAddedTaxReturnsSpec extends BaseFunctionalSpec {

"fail if submission to Non-Repudiation service failed" in {
given()
.userIsFullyAuthorisedForTheResource
.userIsFullyAuthorisedForTheNrsDependantResource
.nrs().nrsFailurefor(vrn)
.when()
.post(s"/$vrn/returns", Some(Json.parse(body())))
Expand Down
18 changes: 11 additions & 7 deletions test/uk/gov/hmrc/vatapi/assets/TestConstants.scala
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@ object TestConstants {
),
groupIdentifier = Some("testGroupId-840cf4e3-c8ad-48f4-80fd-ea267f916be5"),
credentialRole = Some(User),
itmpName = ItmpName(
itmpName = Some(ItmpName(
givenName = Some("a"),
middleName = Some("b"),
familyName = Some("c")
),
itmpAddress = ItmpAddress(
)),
itmpAddress = Some(ItmpAddress(
line1 = Some("1"),
line2 = Some("2"),
line3 = Some("3"),
Expand All @@ -66,7 +66,7 @@ object TestConstants {
postCode = Some("cw93nm"),
countryName = Some("uk"),
countryCode = Some("uk")
),
)),
affinityGroup = Some(AffinityGroup.Organisation),
credentialStrength = Some("strong"),
loginTimes = LoginTimes(
Expand All @@ -83,9 +83,13 @@ object TestConstants {
agentId = Some("JB007")
))

val orgAuthContext: AuthContext = Organisation(Some(orgIdentityData))
val indAuthContext: AuthContext = Individual(Some(indIdentityData))
val agentAuthContext: AuthContext = Agent(Some("AGENT007"), Some("JB007"), Some(agentIdentityData))
val orgAuthContextWithNrsData: AuthContext = Organisation(Some(orgIdentityData))
val indAuthContextWithNrsData: AuthContext = Individual(Some(indIdentityData))
val agentAuthContextWithNrsData: AuthContext = Agent(Some("AGENT007"), Some("JB007"), Some(agentIdentityData))

val orgAuthContext: AuthContext = Organisation(None)
val indAuthContext: AuthContext = Individual(None)
val agentAuthContext: AuthContext = Agent(Some("AGENT007"), Some("JB007"), None)
}

object VatReturn {
Expand Down
Loading

0 comments on commit 45ec6d9

Please sign in to comment.