Skip to content

Commit

Permalink
reworking request matching for clarity
Browse files Browse the repository at this point in the history
  • Loading branch information
frj committed Aug 30, 2019
1 parent f891b18 commit 3d278e4
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 31 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package com.gu.holiday_stops

import java.io.{InputStream, OutputStream}
import java.time.LocalDate

import com.amazonaws.services.lambda.runtime.Context
import com.gu.effects.{GetFromS3, RawEffects}
import com.gu.salesforce.SalesforceAuthenticate.SFAuthConfig
import com.gu.salesforce.{RecordsWrapperCaseClass, SalesforceClient}
import com.gu.salesforce.holiday_stops.SalesforceHolidayStopRequestsDetail.{HolidayStopRequestId, ProductName, SubscriptionName}
import com.gu.salesforce.SalesforceClient
import com.gu.salesforce.holiday_stops.SalesforceHolidayStopRequest._
import com.gu.salesforce.holiday_stops.SalesforceHolidayStopRequestsDetail.{HolidayStopRequestId, ProductName, SubscriptionName}
import com.gu.salesforce.holiday_stops.SalesforceSFSubscription.SubscriptionForSubscriptionNameAndContact._
import com.gu.salesforce.holiday_stops.{SalesforceHolidayStopRequest, SalesforceSFSubscription}
import com.gu.util.Logging
Expand All @@ -20,11 +21,10 @@ import com.gu.util.reader.Types.ApiGatewayOp.ContinueProcessing
import com.gu.util.reader.Types._
import com.gu.util.resthttp.JsonHttp.StringHttpRequest
import com.gu.util.resthttp.RestRequestMaker.BodyAsString
import com.gu.util.resthttp.{HttpOp, JsonHttp, Types}
import com.gu.util.resthttp.{HttpOp, JsonHttp}
import okhttp3.{Request, Response}
import java.time.LocalDate

import play.api.libs.json.{Format, Json, Reads}
import scalaz.{-\/, \/, \/-}

object Handler extends Logging {

Expand All @@ -48,26 +48,62 @@ object Handler extends Logging {
val POTENTIAL_PROXY_RESOURCE_PATH = "/potential"
val GET_ALL_AND_CREATE_PROXY_RESOURCE_REGEX = """/hsr.*""".r

def operationForEffects(
response: Request => Response,
stage: Stage,
fetchString: StringFromS3,
): ApiGatewayOp[Operation] = {
def operationForEffects(response: Request => Response, stage: Stage,
fetchString: StringFromS3): ApiGatewayOp[Operation] = {

val loadConfig = LoadConfigModule(stage, fetchString)

for {
sfAuthConfig <- loadConfig[SFAuthConfig].toApiGatewayOp("load sfAuth config")
sfClient <- SalesforceClient(response, sfAuthConfig).value.toDisjunction.toApiGatewayOp("authenticate with SalesForce")
} yield Operation.noHealthcheck( // checking connectivity to SF is sufficient healthcheck so no special steps required
request => ((request.httpMethod,
request.path) match { // TODO will need to match against path params too to support edit endpoint
case (Some("GET"), Some(POTENTIAL_PROXY_RESOURCE_PATH)) => stepsForPotentialHolidayStop _
case (Some("GET"), Some(GET_ALL_AND_CREATE_PROXY_RESOURCE_REGEX())) => stepsToListExisting _
case (Some("POST"), Some(GET_ALL_AND_CREATE_PROXY_RESOURCE_REGEX())) => stepsToCreate _
case (Some("DELETE"), Some(GET_ALL_AND_CREATE_PROXY_RESOURCE_REGEX())) => stepsToDelete _
case _ => unsupported _
})(request, sfClient))
request => validateRequestAndCreateSteps(request)(request, sfClient)
)
}

private def validateRequestAndCreateSteps(request: ApiGatewayRequest) = {
(for {
httpMethod <- validateMethod(request.httpMethod)
path <- validatePath(request.path)
} yield createSteps(httpMethod, path)).fold(
{ errorMessage: String =>
badrequest(errorMessage) _
},
identity
)
}

private def createSteps(httpMethod: String, path: String) = {
path match {
case POTENTIAL_PROXY_RESOURCE_PATH =>
httpMethod match {
case "GET" => stepsForPotentialHolidayStop _
case _ => unsupported _
}
case GET_ALL_AND_CREATE_PROXY_RESOURCE_REGEX() =>
httpMethod match {
case "GET" => stepsToListExisting _
case "POST" => stepsToCreate _
case "DELETE" => stepsToDelete _
case _ => unsupported _
}
case _ =>
notfound _
}
}

private def validateMethod(method: Option[String]): String \/ String = {
method match {
case Some(method) => \/-(method)
case None => -\/("Http method is required")
}
}

private def validatePath(path: Option[String]): String \/ String = {
path match {
case Some(method) => \/-(method)
case None => -\/("Path is required")
}
}

val HEADER_IDENTITY_ID = "x-identity-id"
Expand All @@ -80,6 +116,7 @@ object Handler extends Logging {
}).toApiGatewayOp(s"either '$HEADER_IDENTITY_ID' header OR '$HEADER_SALESFORCE_CONTACT_ID' (one is required)")

case class PotentialHolidayStopParams(startDate: LocalDate, endDate: LocalDate)

def stepsForPotentialHolidayStop(req: ApiGatewayRequest, unused: SfClient): ApiResponse = {
implicit val formatLocalDateAsSalesforceDate: Format[LocalDate] = SalesforceHolidayStopRequest.formatLocalDateAsSalesforceDate
implicit val readsPotentialHolidayStopParams: Reads[PotentialHolidayStopParams] = Json.reads[PotentialHolidayStopParams]
Expand Down Expand Up @@ -131,6 +168,7 @@ object Handler extends Logging {
}

case class DeletePathParams(subscriptionName: SubscriptionName, holidayStopRequestId: HolidayStopRequestId)

def stepsToDelete(req: ApiGatewayRequest, sfClient: SfClient): ApiResponse = {

val lookupOp = SalesforceHolidayStopRequest.LookupByContactAndOptionalSubscriptionName(sfClient.wrapWith(JsonHttp.getWithParams))
Expand All @@ -148,4 +186,9 @@ object Handler extends Logging {
def unsupported(req: ApiGatewayRequest, sfClient: HttpOp[StringHttpRequest, BodyAsString]): ApiResponse =
ApiGatewayResponse.badRequest("UNSUPPORTED HTTP METHOD")

def notfound(req: ApiGatewayRequest, sfClient: HttpOp[StringHttpRequest, BodyAsString]): ApiResponse =
ApiGatewayResponse.notFound("Not Found")

def badrequest(message: String)(req: ApiGatewayRequest, sfClient: HttpOp[StringHttpRequest, BodyAsString]): ApiResponse =
ApiGatewayResponse.badRequest(message)
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,19 @@ class HandlerTest extends FlatSpec with Matchers {
Stage("DEV"),
FakeFetchString.fetchString
).map { operation =>
operation
.steps(potentialIssueDateRequest("Guardian Weekly xxx", "2019-01-01", "2019-02-01"))
}
) {
case ContinueProcessing(response) =>
response.statusCode should equal("200")
inside(Json.fromJson[Array[String]](Json.parse(response.body))) {
case JsSuccess(dates, _) =>
dates should contain inOrderOnly(
"2019-01-04", "2019-01-11", "2019-01-18", "2019-01-25", "2019-02-01"
)
operation
.steps(potentialIssueDateRequest("Guardian Weekly xxx", "2019-01-01", "2019-02-01"))
}
}
) {
case ContinueProcessing(response) =>
response.statusCode should equal("200")
inside(Json.fromJson[Array[String]](Json.parse(response.body))) {
case JsSuccess(dates, _) =>
dates should contain inOrderOnly (
"2019-01-04", "2019-01-11", "2019-01-18", "2019-01-25", "2019-02-01"
)
}
}
}

private def potentialIssueDateRequest(productPrefix: String, startDate: String, endDate: String) = {
Expand All @@ -56,7 +56,8 @@ class HandlerTest extends FlatSpec with Matchers {
None,
Some(Map("x-product-name-prefix" -> productPrefix)),
None,
Some("/potential"))
Some("/potential")
)
}

val testEffects = new TestingRawEffects(
Expand Down

0 comments on commit 3d278e4

Please sign in to comment.