Skip to content

Commit

Permalink
Merge pull request #36 from hmrc/feature/YTA-3163/retrieve-emprefs-fr…
Browse files Browse the repository at this point in the history
…om-epaye-service

Feature/yta 3163/retrieve emprefs from epaye service
  • Loading branch information
cybersaurus authored Jan 31, 2018
2 parents 3179ee5 + 713926b commit e948883
Show file tree
Hide file tree
Showing 20 changed files with 583 additions and 522 deletions.
55 changes: 21 additions & 34 deletions app/uk/gov/hmrc/epayeapi/controllers/ApiController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@
package uk.gov.hmrc.epayeapi.controllers

import akka.stream.Materializer
import play.api.Logger
import play.api.libs.json.Json
import play.api.libs.streams.Accumulator
import play.api.mvc._
import uk.gov.hmrc.auth.core._
import uk.gov.hmrc.auth.core.retrieve.{Retrieval, Retrievals}
import uk.gov.hmrc.auth.core.retrieve.Retrievals
import uk.gov.hmrc.domain.EmpRef
import uk.gov.hmrc.epayeapi.models.Formats._
import uk.gov.hmrc.epayeapi.models.out.ApiErrorJson
Expand All @@ -43,37 +44,22 @@ trait ApiController extends BaseController with AuthorisedFunctions {
Accumulator.done {
authorised(enrolment) {
action(request).run()
} recover recoverAuthFailure
} recover logAuthError(recoverAuthFailure)
}
}

def EnrolmentsAction(enrolment: Enrolment, retrieveEnrolments: Retrieval[Enrolments])(action: Enrolments => EssentialAction): EssentialAction = {
EssentialAction { implicit request =>
Accumulator.done {
authorised(enrolment.withDelegatedAuthRule("epaye-auth"))
.retrieve(retrieveEnrolments) { enrolments =>
action(enrolments)(request).run()
} recover recoverAuthFailure
}
}
}
def EmpRefAction(empRefFromUrl: EmpRef)(action: EssentialAction): EssentialAction = {
val enrolment = epayeEnrolment
.withEmpRef(empRefFromUrl)
.withDelegatedAuth

def EmpRefsAction(action: Set[EmpRef] => EssentialAction): EssentialAction =
EnrolmentsAction(epayeEnrolment, epayeRetrieval) { enrolments =>
EssentialAction { request =>
action(enrolments.enrolments.flatMap(enrolmentToEmpRef))(request)
}
}
AuthorisedAction(enrolment)(action)
}

def EmpRefAction(empRefFromUrl: EmpRef)(action: EssentialAction): EssentialAction = {
EmpRefsAction { empRefsFromAuth =>
EssentialAction { request =>
empRefsFromAuth.find(_ == empRefFromUrl) match {
case Some(empRef) => action(request)
case None => Accumulator.done(invalidEmpRef)
}
}
}
def logAuthError(pf: PartialFunction[Throwable, Result]): PartialFunction[Throwable, Result] = {
case ex: Throwable =>
Logger.info("Recovering from auth error:", ex)
pf(ex)
}

def recoverAuthFailure: PartialFunction[Throwable, Result] = {
Expand All @@ -97,13 +83,14 @@ trait ApiController extends BaseController with AuthorisedFunctions {
def invalidEmpRef: Result =
Forbidden(Json.toJson(InvalidEmpRef))

private def enrolmentToEmpRef(enrolment: Enrolment): Option[EmpRef] = {
for {
"IR-PAYE" <- Option(enrolment.key)
tn <- enrolment.identifiers.find(_.key == "TaxOfficeNumber")
tr <- enrolment.identifiers.find(_.key == "TaxOfficeReference")
if enrolment.isActivated
} yield EmpRef(tn.value, tr.value)
implicit class EnrolmentOps(val enrolment: Enrolment) {
def withDelegatedAuth: Enrolment =
enrolment.withDelegatedAuthRule("epaye-auth")

def withEmpRef(empRef: EmpRef): Enrolment =
enrolment
.withIdentifier("TaxOfficeNumber", empRef.taxOfficeNumber)
.withIdentifier("TaxOfficeReference", empRef.taxOfficeReference)
}
}

Expand Down
43 changes: 43 additions & 0 deletions app/uk/gov/hmrc/epayeapi/controllers/EpayeErrorHandler.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright 2018 HM Revenue & Customs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package uk.gov.hmrc.epayeapi.controllers

import play.api.Logger
import play.api.libs.json.{JsError, Json}
import play.api.mvc.{Controller, Result}
import uk.gov.hmrc.epayeapi.models.Formats._
import uk.gov.hmrc.epayeapi.models.in._
import uk.gov.hmrc.epayeapi.models.out.ApiErrorJson
import uk.gov.hmrc.epayeapi.models.out.ApiErrorJson.EmpRefNotFound

trait EpayeErrorHandler extends Controller {
def errorHandler: PartialFunction[EpayeResponse[_], Result] = {
case EpayeJsonError(err) =>
Logger.error(s"epaye service returned invalid json: ${Json.prettyPrint(JsError.toJson(err))}")
InternalServerError(Json.toJson(ApiErrorJson.InternalServerError))
case EpayeNotFound() =>
Logger.info("epaye service returned a 404")
NotFound(Json.toJson(EmpRefNotFound))
case EpayeError(status, _) =>
Logger.error(s"epaye service returned unexpected response: status=$status")
InternalServerError(Json.toJson(ApiErrorJson.InternalServerError))
case EpayeException(message) =>
Logger.error(s"Caught exception while calling epaye service: message=$message")
InternalServerError(Json.toJson(ApiErrorJson.InternalServerError))
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,15 @@ package uk.gov.hmrc.epayeapi.controllers
import javax.inject.{Inject, Singleton}

import akka.stream.Materializer
import play.api.Logger
import play.api.libs.json.Json
import play.api.mvc.{Action, EssentialAction}
import play.api.mvc.{Action, EssentialAction, Result}
import uk.gov.hmrc.auth.core.AuthConnector
import uk.gov.hmrc.domain.EmpRef
import uk.gov.hmrc.epayeapi.connectors.{EpayeApiConfig, EpayeConnector}
import uk.gov.hmrc.epayeapi.models.Formats._
import uk.gov.hmrc.epayeapi.models.TaxYear
import uk.gov.hmrc.epayeapi.models.in._
import uk.gov.hmrc.epayeapi.models.out.ApiErrorJson.EmpRefNotFound
import uk.gov.hmrc.epayeapi.models.out.{AnnualStatementJson, ApiErrorJson}
import uk.gov.hmrc.epayeapi.models.out.AnnualStatementJson

import scala.concurrent.ExecutionContext

Expand All @@ -41,23 +39,20 @@ case class GetAnnualStatementController @Inject() (
implicit val ec: ExecutionContext,
implicit val mat: Materializer
)
extends ApiController {
extends ApiController
with EpayeErrorHandler {

def getAnnualStatement(empRef: EmpRef, taxYear: TaxYear): EssentialAction =
EmpRefAction(empRef) {
Action.async { request =>
epayeConnector.getAnnualStatement(empRef, taxYear, hc(request)).map {
case EpayeSuccess(epayeAnnualStatement) =>
Ok(Json.toJson(AnnualStatementJson(config.apiBaseUrl, empRef, taxYear, epayeAnnualStatement)))
case EpayeJsonError(err) =>
Logger.error(s"Upstream returned invalid json: $err")
InternalServerError(Json.toJson(ApiErrorJson.InternalServerError))
case EpayeNotFound() =>
NotFound(Json.toJson(EmpRefNotFound))
case error: EpayeResponse[_] =>
Logger.error(s"Error while fetching totals: $error")
InternalServerError(Json.toJson(ApiErrorJson.InternalServerError))
successHandler(empRef, taxYear).orElse(errorHandler)
}
}
}

def successHandler(empRef: EmpRef, taxYear: TaxYear): PartialFunction[EpayeResponse[EpayeAnnualStatement], Result] = {
case EpayeSuccess(epayeAnnualStatement) =>
Ok(Json.toJson(AnnualStatementJson(config.apiBaseUrl, empRef, taxYear, epayeAnnualStatement)))
}
}
15 changes: 3 additions & 12 deletions app/uk/gov/hmrc/epayeapi/controllers/GetEmpRefsController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ case class GetEmpRefsController @Inject() (
implicit val ec: ExecutionContext,
implicit val mat: Materializer
)
extends ApiController {
extends ApiController
with EpayeErrorHandler {

def getEmpRefs(): EssentialAction = AuthorisedAction(epayeEnrolment) {
Action.async { implicit request =>
Expand All @@ -52,18 +53,8 @@ case class GetEmpRefsController @Inject() (

def successHandler: PartialFunction[EpayeResponse[EpayeEmpRefsResponse], Result] = {
case EpayeSuccess(EpayeEmpRefsResponse(empRefs)) =>
Logger.error(s"EmpRefs received: $empRefs")
val empRefsJson = EmpRefsJson.fromSeq(config.apiBaseUrl, empRefs)
Ok(Json.toJson(empRefsJson))
}

def errorHandler: PartialFunction[EpayeResponse[EpayeEmpRefsResponse], Result] = {
case EpayeJsonError(err) =>
Logger.error(s"Upstream returned invalid json: $err")
InternalServerError(Json.toJson(ApiErrorJson.InternalServerError))
case EpayeNotFound() =>
NotFound(Json.toJson(EmpRefNotFound))
case error: EpayeResponse[_] =>
Logger.error(s"Error while fetching totals: $error")
InternalServerError(Json.toJson(ApiErrorJson.InternalServerError))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,14 @@ package uk.gov.hmrc.epayeapi.controllers
import javax.inject.{Inject, Singleton}

import akka.stream.Materializer
import play.api.Logger
import play.api.libs.json.Json
import play.api.mvc.{Action, EssentialAction}
import play.api.mvc.{Action, EssentialAction, Result}
import uk.gov.hmrc.auth.core.AuthConnector
import uk.gov.hmrc.domain.EmpRef
import uk.gov.hmrc.epayeapi.connectors.{EpayeApiConfig, EpayeConnector}
import uk.gov.hmrc.epayeapi.models.Formats._
import uk.gov.hmrc.epayeapi.models.in.{EpayeJsonError, EpayeNotFound, EpayeResponse, EpayeSuccess}
import uk.gov.hmrc.epayeapi.models.out.ApiErrorJson.EmpRefNotFound
import uk.gov.hmrc.epayeapi.models.out.{ApiErrorJson, MonthlyStatementJson}
import uk.gov.hmrc.epayeapi.models.in._
import uk.gov.hmrc.epayeapi.models.out.MonthlyStatementJson
import uk.gov.hmrc.epayeapi.models.{TaxMonth, TaxYear}

import scala.concurrent.ExecutionContext
Expand All @@ -41,7 +39,8 @@ case class GetMonthlyStatementController @Inject() (
implicit val ec: ExecutionContext,
implicit val mat: Materializer
)
extends ApiController {
extends ApiController
with EpayeErrorHandler {

def getStatement(empRef: EmpRef, taxYear: TaxYear, taxMonth: TaxMonth): EssentialAction =
EmpRefAction(empRef) {
Expand All @@ -52,25 +51,13 @@ case class GetMonthlyStatementController @Inject() (
taxYear,
taxMonth
).map {
case EpayeSuccess(json) =>
Ok(Json.toJson(
MonthlyStatementJson(
config.apiBaseUrl,
empRef,
taxYear,
taxMonth,
json
)
))
case EpayeNotFound() =>
NotFound(Json.toJson(EmpRefNotFound))
case EpayeJsonError(error) =>
Logger.error(s"Upstream returned invalid json: $error")
InternalServerError(Json.toJson(ApiErrorJson.InternalServerError))
case error: EpayeResponse[_] =>
Logger.error(s"Error while fetching totals: $error")
InternalServerError(Json.toJson(ApiErrorJson.InternalServerError))
successHandler(empRef, taxYear, taxMonth) orElse errorHandler
}
}
}

def successHandler(empRef: EmpRef, taxYear: TaxYear, taxMonth: TaxMonth): PartialFunction[EpayeResponse[EpayeMonthlyStatement], Result] = {
case EpayeSuccess(json) =>
Ok(Json.toJson(MonthlyStatementJson(config.apiBaseUrl, empRef, taxYear, taxMonth, json)))
}
}
27 changes: 11 additions & 16 deletions app/uk/gov/hmrc/epayeapi/controllers/GetSummaryController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,14 @@ package uk.gov.hmrc.epayeapi.controllers
import javax.inject.{Inject, Singleton}

import akka.stream.Materializer
import play.api.Logger
import play.api.libs.json.Json
import play.api.mvc.{Action, EssentialAction}
import play.api.mvc.{Action, EssentialAction, Result}
import uk.gov.hmrc.auth.core.AuthConnector
import uk.gov.hmrc.domain.EmpRef
import uk.gov.hmrc.epayeapi.connectors.{EpayeApiConfig, EpayeConnector}
import uk.gov.hmrc.epayeapi.models.Formats._
import uk.gov.hmrc.epayeapi.models.in.{EpayeJsonError, EpayeNotFound, EpayeResponse, EpayeSuccess}
import uk.gov.hmrc.epayeapi.models.out.ApiErrorJson.EmpRefNotFound
import uk.gov.hmrc.epayeapi.models.out.{ApiErrorJson, SummaryJson}
import uk.gov.hmrc.epayeapi.models.in._
import uk.gov.hmrc.epayeapi.models.out.SummaryJson

import scala.concurrent.ExecutionContext

Expand All @@ -40,23 +38,20 @@ case class GetSummaryController @Inject() (
implicit val ec: ExecutionContext,
implicit val mat: Materializer
)
extends ApiController {
extends ApiController
with EpayeErrorHandler {

def getSummary(empRef: EmpRef): EssentialAction =
EmpRefAction(empRef) {
Action.async { request =>
epayeConnector.getTotal(empRef, hc(request)).map {
case EpayeSuccess(totals) =>
Ok(Json.toJson(SummaryJson(config.apiBaseUrl, empRef, totals)))
case EpayeJsonError(err) =>
Logger.error(s"Upstream returned invalid json: $err")
InternalServerError(Json.toJson(ApiErrorJson.InternalServerError))
case EpayeNotFound() =>
NotFound(Json.toJson(EmpRefNotFound))
case error: EpayeResponse[_] =>
Logger.error(s"Error while fetching totals: $error")
InternalServerError(Json.toJson(ApiErrorJson.InternalServerError))
successHandler(empRef) orElse errorHandler
}
}
}

def successHandler(empRef: EmpRef): PartialFunction[EpayeResponse[EpayeTotalsResponse], Result] = {
case EpayeSuccess(totals) =>
Ok(Json.toJson(SummaryJson(config.apiBaseUrl, empRef, totals)))
}
}
1 change: 0 additions & 1 deletion app/uk/gov/hmrc/epayeapi/modules/AppModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import uk.gov.hmrc.play.config.ServicesConfig
class AppModule() extends AbstractModule {
def configure(): Unit = {
bind(classOf[PlayAuthConnector]).to(classOf[MicroserviceAuthConnector]).asEagerSingleton()
// bind(classOf[WSHttp]).to(classOf[WSHttp]).asEagerSingleton()
bind(classOf[Startup]).to(classOf[AppStartup]).asEagerSingleton()
}

Expand Down
46 changes: 23 additions & 23 deletions app/uk/gov/hmrc/epayeapi/router/ApiRouter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/

package uk.gov.hmrc.epayeapi.router

import ApiRouter._
import javax.inject.{Inject, Singleton}

import play.api.routing.Router.Routes
Expand All @@ -34,28 +34,6 @@ case class ApiRouter @Inject() (
getMonthlyStatementController: GetMonthlyStatementController
) extends SimpleRouter {

object TaxOfficeNumber {
val regex = "([0-9a-zA-Z]{3})".r
def unapply(string: String): Option[String] = {
string match {
case regex(result) => Some(result)
case _ => None
}
}
}


object TaxOfficeReference {
val regex = "([0-9a-zA-Z]{7,10})".r
def unapply(string: String): Option[String] = {
string match {
case regex(result) => Some(result)
case _ => None
}
}
}


val appRoutes = Router.from {
case GET(p"/") =>
getEmpRefsController.getEmpRefs()
Expand All @@ -73,3 +51,25 @@ case class ApiRouter @Inject() (
val routes: Routes = prodRoutes.routes.orElse(appRoutes.routes)

}

object ApiRouter {
object TaxOfficeNumber {
val regex = "(\\d{3})".r
def unapply(string: String): Option[String] = {
string match {
case regex(result) => Some(result)
case _ => None
}
}
}

object TaxOfficeReference {
val regex = "([0-9A-Z]{1,10})".r
def unapply(string: String): Option[String] = {
string match {
case regex(result) => Some(result)
case _ => None
}
}
}
}
Loading

0 comments on commit e948883

Please sign in to comment.