Skip to content

Commit

Permalink
Merge MTDSA-1505 changes into master
Browse files Browse the repository at this point in the history
  • Loading branch information
scott committed Apr 17, 2018
2 parents da62e2e + 1a47ca7 commit 7acd619
Show file tree
Hide file tree
Showing 17 changed files with 316 additions and 206 deletions.
19 changes: 13 additions & 6 deletions app/uk/gov/hmrc/vatapi/auth/AuthContext.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,39 +18,46 @@ package uk.gov.hmrc.vatapi.auth
import uk.gov.hmrc.auth.core.AffinityGroup
import AuthConstants._

import nrs.models.IdentityData

sealed trait AuthContext {
val affinityGroup: String
val agentCode: Option[String]
val agentReference: Option[String]
val userType: String

val identityData: Option[IdentityData]
}

case object Organisation extends AuthContext {
case class Organisation(override val identityData: Option[IdentityData] = None) extends AuthContext {
override val affinityGroup: String = ORGANISATION
override val agentCode: Option[String] = None
override val agentReference: Option[String] = None
override val userType = "OrgVatPayer"
}

case object Individual extends AuthContext {
case class Individual(override val identityData: Option[IdentityData]) extends AuthContext {
override val affinityGroup: String = INDIVIDUAL
override val agentCode: Option[String] = None
override val agentReference: Option[String] = None
override val userType = "IndVatPayer"
}

case class Agent(override val agentCode: Option[String], override val agentReference: Option[String]) extends AuthContext {
case class Agent(override val agentCode: Option[String],
override val agentReference: Option[String],
override val identityData: Option[IdentityData] = None
) extends AuthContext {
override val affinityGroup: String = "agent"
override val userType = "Agent"
}

case class VATAuthEnrolments(enrolmentToken: String, identifier: String, authRule: Option[String] = None)

object AffinityGroupToAuthContext {
def authContext(affinityGroup: AffinityGroup) = {
def authContext(affinityGroup: AffinityGroup, identityData: Option[IdentityData]) = {
affinityGroup.getClass.getSimpleName.dropRight(1) match {
case ORGANISATION => Organisation
case INDIVIDUAL => Individual
case ORGANISATION => Organisation(identityData)
case INDIVIDUAL => Individual(identityData)
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion app/uk/gov/hmrc/vatapi/connectors/NRSConnector.scala
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ trait NRSConnector extends BaseConnector {

private val xApiKeyHeader = "X-API-Key"

val nrsSubmissionUrl: String => String = vrn => s"${AppContext.nrsServiceUrl}/submission/$vrn"
val nrsSubmissionUrl: String => String = vrn => s"${AppContext.nrsServiceUrl}/submission"

def submit(vrn: Vrn, nrsSubmission: NRSSubmission)(implicit hc: HeaderCarrier, ec: ExecutionContext): Future[NrsSubmissionOutcome] = {

Expand Down
157 changes: 35 additions & 122 deletions app/uk/gov/hmrc/vatapi/models/NRSSubmission.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,165 +17,78 @@
package nrs.models

import org.joda.time.{DateTime, LocalDate}
import play.api.libs.functional.syntax._
import play.api.libs.json.{Writes, __, _}
import uk.gov.hmrc.auth.core.ConfidenceLevel
import uk.gov.hmrc.domain.{Nino, SaUtr, Vrn}
import play.api.libs.json._
import uk.gov.hmrc.auth.core.retrieve._
import uk.gov.hmrc.auth.core.{AffinityGroup, ConfidenceLevel, CredentialRole}
import uk.gov.hmrc.domain.Vrn
import uk.gov.hmrc.http.controllers.RestFormats
import uk.gov.hmrc.vatapi.models.isoInstantDateFormat

case class NRSSubmission(payload: String,
metadata: Metadata)
case class NRSSubmission( payload: String,
metadata: Metadata )

object NRSSubmission{
implicit val mdFormat: OFormat[Metadata] = Metadata.format
implicit val format: OFormat[NRSSubmission] = Json.format[NRSSubmission]
}

//Identity Data should always be populated, but allow it to be optional for when the authEnabled flag is disabled
case class Metadata(businessId: String,
notableEvent: String,
payloadContentType: String,
payloadSha256Checksum: Option[String],
userSubmissionTimestamp: DateTime,
identityData: IdentityData,
identityData: Option[IdentityData],
userAuthToken: String,
headerData: HeaderData,
headerData: JsValue,
searchKeys: SearchKeys)

object Metadata{
implicit val dateTimeFormat: Format[DateTime] = RestFormats.dateTimeFormats
implicit val idformat: OFormat[IdentityData] = IdentityData.format
implicit val hdWrts: Writes[HeaderData] = HeaderData.writes
implicit val hdRds: Reads[HeaderData] = HeaderData.reads
implicit val format: OFormat[Metadata] = Json.format[Metadata]
}

//Todo: match against NRS mandatory fields with what may not be returned from auth. Appropriate error handling
case class IdentityData(internalId: Option[String] = None,
externalId: Option[String] = None,
agentCode: Option[String] = None,
credentials: Option[Credentials] = None,
confidenceLevel: Option[ConfidenceLevel] = None,
nino: Option[Nino] = None,
saUtr: Option[SaUtr] = None,
name: Option[Name] = None,
credentials: Credentials,
confidenceLevel: ConfidenceLevel,
nino: Option[String] = None,
saUtr: Option[String] = None,
name: Name,
dateOfBirth: Option[LocalDate] = None,
email: Option[String] = None,
agentInformation: Option[AgentInformation] = None,
agentInformation: AgentInformation,
groupIdentifier: Option[String] = None,
credentialRole: Option[String] = None,
credentialRole: Option[CredentialRole],
mdtpInformation: Option[MdtpInformation] = None,
itmpName: Option[ItmpName] = None,
itmpName: ItmpName,
itmpDateOfBirth: Option[LocalDate] = None,
itmpAddress: Option[ItmpAddress] = None,
affinityGroup: Option[String] = None,
itmpAddress: ItmpAddress,
affinityGroup: Option[AffinityGroup],
credentialStrength: Option[String] = None,
loginTimes: Option[LoginTimes] = None)
loginTimes: LoginTimes)

object IdentityData {
implicit val localDateFormat: Format[LocalDate] = RestFormats.localDateFormats
implicit val dateTimeReads: Format[DateTime] = RestFormats.dateTimeFormats
implicit val credFormat: OFormat[Credentials] = Json.format[Credentials]
implicit val nameFormat: OFormat[Name] = Json.format[Name]
implicit val agentInfoFormat: OFormat[AgentInformation] = Json.format[AgentInformation]
implicit val mdtpInfoFormat: OFormat[MdtpInformation] = Json.format[MdtpInformation]
implicit val itmpNameFormat: OFormat[ItmpName] = Json.format[ItmpName]
implicit val itmpAddressFormat: OFormat[ItmpAddress] = Json.format[ItmpAddress]
implicit val loginTimesFormat: OFormat[LoginTimes] = Json.format[LoginTimes]
implicit val format: OFormat[IdentityData] = Json.format[IdentityData]
}

case class HeaderData(publicIp: Option[String] = None,
port: Option[String] = None,
deviceId: Option[String] = None,
userId: Option[String] = None,
timeZone: Option[String] = None,
localIp: Option[String] = None,
screenResolution: Option[String] = None,
windowSize: Option[String] = None,
colourDepth: Option[String] = None)

object HeaderData {
implicit val writes: Writes[HeaderData] = (
(__ \ "Gov-Client-Public-IP").writeNullable[String] and
(__ \ "Gov-Client-Public-Port").writeNullable[String] and
(__ \ "Gov-Client-Device-ID").writeNullable[String] and
(__ \ "Gov-Client-User-ID").writeNullable[String] and
(__ \ "Gov-Client-Timezone").writeNullable[String] and
(__ \ "Gov-Client-Local-IP").writeNullable[String] and
(__ \ "Gov-Client-Screen-Resolution").writeNullable[String] and
(__ \ "Gov-Client-Window-Size").writeNullable[String] and
(__ \ "Gov-Client-Colour-Depth").writeNullable[String]
)(unlift(HeaderData.unapply))

implicit val reads: Reads[HeaderData] = (
(__ \ "Gov-Client-Public-IP").readNullable[String] and
(__ \ "Gov-Client-Public-Port").readNullable[String] and
(__ \ "Gov-Client-Device-ID").readNullable[String] and
(__ \ "Gov-Client-User-ID").readNullable[String] and
(__ \ "Gov-Client-Timezone").readNullable[String] and
(__ \ "Gov-Client-Local-IP").readNullable[String] and
(__ \ "Gov-Client-Screen-Resolution").readNullable[String] and
(__ \ "Gov-Client-Window-Size").readNullable[String] and
(__ \ "Gov-Client-Colour-Depth").readNullable[String]
)(HeaderData.apply _)
}

case class SearchKeys(vrn: Vrn,
companyName: String,
taxPeriodEndDate: LocalDate)
case class SearchKeys(vrn: Option[Vrn] = None,
companyName: Option[String] = None,
taxPeriodEndDate: Option[LocalDate] = None,
periodKey: Option[String] = None
)

object SearchKeys{
implicit val localDateFormat: Format[LocalDate] = RestFormats.localDateFormats
implicit val format: OFormat[SearchKeys] = Json.format[SearchKeys]
}

case class Credentials(providerId: String, providerType: String)

object Credentials {
implicit val format: Format[Credentials] = Json.format[Credentials]
}

case class Name(name: Option[String], lastName: Option[String])

object Name {
implicit val format: Format[Name] = Json.format[Name]
}

case class PostCode(value: String)

object PostCode {
implicit val format: Format[PostCode] = Json.format[PostCode]
}

case class ItmpName(givenName: Option[String],
middleName: Option[String],
familyName: Option[String])

object ItmpName {
implicit val format: Format[ItmpName] = Json.format[ItmpName]
}

case class ItmpAddress(line1: Option[String],
line2: Option[String],
line3: Option[String],
line4: Option[String],
line5: Option[String],
postCode: Option[String],
countryName: Option[String],
countryCode: Option[String])

object ItmpAddress {
implicit val format: Format[ItmpAddress] = Json.format[ItmpAddress]
}

case class MdtpInformation(deviceId: String, sessionId: String)
object MdtpInformation {
implicit val format: Format[MdtpInformation] = Json.format[MdtpInformation]
}

case class AgentInformation(agentId: Option[String],
agentCode: Option[String],
agentFriendlyName: Option[String])

object AgentInformation {
implicit val format: Format[AgentInformation] = Json.format[AgentInformation]
}

case class LoginTimes(currentLogin: DateTime, previousLogin: Option[DateTime])

object LoginTimes {
implicit val dateTimeReads: Format[DateTime] = RestFormats.dateTimeFormats
implicit val format: Format[LoginTimes] = Json.format[LoginTimes]
}
}
7 changes: 7 additions & 0 deletions app/uk/gov/hmrc/vatapi/models/models.scala
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,13 @@ package object models {
def trimNullable: Reads[Option[String]] = reads.map(_.map(_.trim))
}

val isoInstantDatePattern = "yyyy-MM-dd'T'HH:mm:ss'Z'"

implicit val isoInstantDateFormat: Format[DateTime] = Format[DateTime](
JodaReads.jodaDateReads(isoInstantDatePattern),
JodaWrites.jodaDateWrites(isoInstantDatePattern)
)

val dateTimePattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"

implicit val dateTimeFormat: Format[DateTime] = Format[DateTime](
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import uk.gov.hmrc.domain.Vrn
import uk.gov.hmrc.http.HeaderCarrier
import uk.gov.hmrc.vatapi.httpparsers.NRSData
import uk.gov.hmrc.vatapi.models.{ErrorResult, Errors, InternalServerErrorResult, VatReturnDeclaration}
import uk.gov.hmrc.vatapi.resources.AuthRequest
import uk.gov.hmrc.vatapi.resources.wrappers.VatReturnResponse
import uk.gov.hmrc.vatapi.services.{NRSService, VatReturnsService}

Expand All @@ -42,7 +43,7 @@ trait VatReturnsOrchestrator {

def submitVatReturn(vrn: Vrn,
vatReturn: VatReturnDeclaration
)(implicit hc: HeaderCarrier): Future[Either[ErrorResult, VatReturnResponse]] = {
)(implicit hc: HeaderCarrier, request: AuthRequest[_]): Future[Either[ErrorResult, VatReturnResponse]] = {

logger.debug(s"[VatReturnsOrchestrator][submitVatReturn] - Orchestrating calls to NRS and Vat Returns")
nrsService.submit(vrn, vatReturn) map {
Expand Down
2 changes: 1 addition & 1 deletion app/uk/gov/hmrc/vatapi/resources/BaseResource.scala
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ trait BaseResource extends BaseController {
case Left(authError) => Left(authError)
}
} else
Future.successful(Right(new AuthRequest(Organisation, request)))
Future.successful(Right(new AuthRequest(Organisation(), request)))
}

def APIAction(vrn: Vrn, summary: Option[String] = None): ActionBuilder[AuthRequest] =
Expand Down
4 changes: 0 additions & 4 deletions app/uk/gov/hmrc/vatapi/resources/VatReturnsResource.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,9 @@
package uk.gov.hmrc.vatapi.resources

import cats.implicits._
import play.api.Logger

import play.api.libs.json.{JsNull, JsValue, Json, OFormat}
import play.api.mvc.{Action, AnyContent, Request}
import uk.gov.hmrc.domain.Vrn
import uk.gov.hmrc.play.microservice.controller.BaseController
import uk.gov.hmrc.vatapi.audit.AuditEvent
import uk.gov.hmrc.vatapi.audit.AuditService.audit
import uk.gov.hmrc.vatapi.connectors.VatReturnsConnector
Expand All @@ -38,7 +35,6 @@ object VatReturnsResource extends BaseResource {
private val orchestrator = VatReturnsOrchestrator

def submitVatReturn(vrn: Vrn): Action[JsValue] = APIAction(vrn).async(parse.json) { implicit request =>

val receiptId = "Receipt-ID"
val receiptTimestamp = "Receipt-Timestamp"
val receiptSignature = "Receipt-Signature"
Expand Down
Loading

0 comments on commit 7acd619

Please sign in to comment.