Consent endpoints - DONE

This commit is contained in:
Marko Milić 2019-03-26 10:59:36 +01:00
parent 01fdd30bca
commit d3a0217272
7 changed files with 82 additions and 13 deletions

View File

@ -55,6 +55,7 @@ object ApiTag {
val apiTagNewStyle = ResourceDocTag("New-Style")
val apiTagWebhook = ResourceDocTag("Webhook")
val apiTagMockedData = ResourceDocTag("Mocked-Data")
val apiTagConsent = ResourceDocTag("Consent")
//Note: the followings are for the code generator -- UKOpenBankingV3.1.0

View File

@ -163,7 +163,8 @@ object NewStyle {
(nameOf(Implementations3_1_0.createAccountAttribute), ApiVersion.v3_1_0.toString),
(nameOf(Implementations3_1_0.deleteBranch), ApiVersion.v3_1_0.toString),
(nameOf(Implementations3_1_0.getServerJWK), ApiVersion.v3_1_0.toString),
(nameOf(Implementations3_1_0.createConsent), ApiVersion.v3_1_0.toString)
(nameOf(Implementations3_1_0.createConsent), ApiVersion.v3_1_0.toString),
(nameOf(Implementations3_1_0.answerConsentChallenge), ApiVersion.v3_1_0.toString)
)
object HttpCode {

View File

@ -3145,10 +3145,14 @@ trait APIMethods310 {
|Create consent
|""",
PostConsentRequestJsonV310(email = "marko@tesobe.com", `for`="ALL_MY_ACCOUNTS", view="owner"),
ConsentRequestJsonV310(consent_id = "eyJhbGciOiJIUzI1NiJ9.eyJlbnRpdGxlbWVudHMiOltdLCJjcmVhdGVkQnlVc2VySWQiOiJhYjY1MzlhOS1iMTA1LTQ0ODktYTg4My0wYWQ4ZDZjNjE2NTciLCJzdWIiOiIyMWUxYzhjYy1mOTE4LTRlYWMtYjhlMy01ZTVlZWM2YjNiNGIiLCJhdWQiOiJlanpuazUwNWQxMzJyeW9tbmhieDFxbXRvaHVyYnNiYjBraWphanNrIiwibmJmIjoxNTUzNTU0ODk5LCJpc3MiOiJodHRwczpcL1wvd3d3Lm9wZW5iYW5rcHJvamVjdC5jb20iLCJleHAiOjE1NTM1NTg0OTksImlhdCI6MTU1MzU1NDg5OSwianRpIjoiMDlmODhkNWYtZWNlNi00Mzk4LThlOTktNjYxMWZhMWNkYmQ1Iiwidmlld3MiOlt7ImFjY291bnRfaWQiOiJtYXJrb19wcml2aXRlXzAxIiwiYmFua19pZCI6ImdoLjI5LnVrLngiLCJ2aWV3X2lkIjoib3duZXIifSx7ImFjY291bnRfaWQiOiJtYXJrb19wcml2aXRlXzAyIiwiYmFua19pZCI6ImdoLjI5LnVrLngiLCJ2aWV3X2lkIjoib3duZXIifV19.8cc7cBEf2NyQvJoukBCmDLT7LXYcuzTcSYLqSpbxLp4"),
ConsentRequestJsonV310(
consent_id = "9d429899-24f5-42c8-8565-943ffa6a7945",
jwt = "eyJhbGciOiJIUzI1NiJ9.eyJlbnRpdGxlbWVudHMiOltdLCJjcmVhdGVkQnlVc2VySWQiOiJhYjY1MzlhOS1iMTA1LTQ0ODktYTg4My0wYWQ4ZDZjNjE2NTciLCJzdWIiOiIyMWUxYzhjYy1mOTE4LTRlYWMtYjhlMy01ZTVlZWM2YjNiNGIiLCJhdWQiOiJlanpuazUwNWQxMzJyeW9tbmhieDFxbXRvaHVyYnNiYjBraWphanNrIiwibmJmIjoxNTUzNTU0ODk5LCJpc3MiOiJodHRwczpcL1wvd3d3Lm9wZW5iYW5rcHJvamVjdC5jb20iLCJleHAiOjE1NTM1NTg0OTksImlhdCI6MTU1MzU1NDg5OSwianRpIjoiMDlmODhkNWYtZWNlNi00Mzk4LThlOTktNjYxMWZhMWNkYmQ1Iiwidmlld3MiOlt7ImFjY291bnRfaWQiOiJtYXJrb19wcml2aXRlXzAxIiwiYmFua19pZCI6ImdoLjI5LnVrLngiLCJ2aWV3X2lkIjoib3duZXIifSx7ImFjY291bnRfaWQiOiJtYXJrb19wcml2aXRlXzAyIiwiYmFua19pZCI6ImdoLjI5LnVrLngiLCJ2aWV3X2lkIjoib3duZXIifV19.8cc7cBEf2NyQvJoukBCmDLT7LXYcuzTcSYLqSpbxLp4",
status = "INITIATED"
),
List(UnknownError),
Catalogs(Core, notPSD2, OBWG),
apiTagCustomer :: apiTagNewStyle :: Nil)
apiTagConsent :: apiTagNewStyle :: Nil)
lazy val createConsent : OBPEndpoint = {
case "banks" :: BankId(bankId) :: "my" :: "consent" :: sca_method :: Nil JsonPost json -> _ => {
@ -3163,26 +3167,67 @@ trait APIMethods310 {
consentJson <- NewStyle.function.tryons(failMsg, 400, callContext) {
json.extract[PostConsentRequestJsonV310]
}
consent <- Future(Consents.consentProvider.vend.createConsent()) map {
createdConsent <- Future(Consents.consentProvider.vend.createConsent()) map {
i => connectorEmptyResponse(i, callContext)
}
consentJWT = Consent.createConsentJWT(user, consentJson.view, consent.secret, consent.consentId)
_ <- Future(Consents.consentProvider.vend.updateConsent(consent.consentId, consentJWT)) map {
consentJWT = Consent.createConsentJWT(user, consentJson.view, createdConsent.secret, createdConsent.consentId)
_ <- Future(Consents.consentProvider.vend.setJsonWebToken(createdConsent.consentId, consentJWT)) map {
i => connectorEmptyResponse(i, callContext)
}
} yield {
sca_method match {
case "email" => // Send the email
val params = PlainMailBodyType(consent.challenge) :: List(To(consentJson.email))
val params = PlainMailBodyType(createdConsent.challenge) :: List(To(consentJson.email))
Mailer.sendMail(
From("challenge@tesobe.com"),
//From("challenge@tesobe.com"),
From("marko.milic@yahoo.com"),
Subject("Challenge request"),
params :_*
)
case "sms" =>
case _ =>
}
(ConsentRequestJsonV310(consentJWT), HttpCode.`201`(callContext))
(ConsentRequestJsonV310(createdConsent.consentId, consentJWT, createdConsent.status), HttpCode.`201`(callContext))
}
}
}
resourceDocs += ResourceDoc(
answerConsentChallenge,
implementedInApiVersion,
nameOf(answerConsentChallenge),
"POST",
"/banks/BANK_ID/consent/CONSENT_ID/challenge",
"Answer Consent Challenge",
s"""
|Answer consent challenge
|""",
PostConsentChallengeJsonV310(answer = "12345678"),
ConsentChallengeJsonV310(
consent_id = "9d429899-24f5-42c8-8565-943ffa6a7945",
jwt = "eyJhbGciOiJIUzI1NiJ9.eyJlbnRpdGxlbWVudHMiOltdLCJjcmVhdGVkQnlVc2VySWQiOiJhYjY1MzlhOS1iMTA1LTQ0ODktYTg4My0wYWQ4ZDZjNjE2NTciLCJzdWIiOiIyMWUxYzhjYy1mOTE4LTRlYWMtYjhlMy01ZTVlZWM2YjNiNGIiLCJhdWQiOiJlanpuazUwNWQxMzJyeW9tbmhieDFxbXRvaHVyYnNiYjBraWphanNrIiwibmJmIjoxNTUzNTU0ODk5LCJpc3MiOiJodHRwczpcL1wvd3d3Lm9wZW5iYW5rcHJvamVjdC5jb20iLCJleHAiOjE1NTM1NTg0OTksImlhdCI6MTU1MzU1NDg5OSwianRpIjoiMDlmODhkNWYtZWNlNi00Mzk4LThlOTktNjYxMWZhMWNkYmQ1Iiwidmlld3MiOlt7ImFjY291bnRfaWQiOiJtYXJrb19wcml2aXRlXzAxIiwiYmFua19pZCI6ImdoLjI5LnVrLngiLCJ2aWV3X2lkIjoib3duZXIifSx7ImFjY291bnRfaWQiOiJtYXJrb19wcml2aXRlXzAyIiwiYmFua19pZCI6ImdoLjI5LnVrLngiLCJ2aWV3X2lkIjoib3duZXIifV19.8cc7cBEf2NyQvJoukBCmDLT7LXYcuzTcSYLqSpbxLp4",
status = "INITIATED"
),
List(UnknownError),
Catalogs(Core, notPSD2, OBWG),
apiTagConsent :: apiTagNewStyle :: Nil)
lazy val answerConsentChallenge : OBPEndpoint = {
case "banks" :: BankId(bankId) :: "consent" :: consentId :: "challenge" :: Nil JsonPost json -> _ => {
cc =>
for {
(_, callContext) <- authorizedAccess(cc)
(_, callContext) <- NewStyle.function.getBank(bankId, callContext)
failMsg = s"$InvalidJsonFormat The Json body should be the $PostConsentChallengeJsonV310 "
consentJson <- NewStyle.function.tryons(failMsg, 400, callContext) {
json.extract[PostConsentChallengeJsonV310]
}
consent <- Future(Consents.consentProvider.vend.checkAnswer(consentId, consentJson.answer)) map {
i => connectorEmptyResponse(i, callContext)
}
} yield {
(ConsentRequestJsonV310(consent.consentId, consent.jsonWebToken, consent.status), HttpCode.`201`(callContext))
}
}
}

View File

@ -472,7 +472,10 @@ case class MeetingsJsonV310(
)
case class PostConsentRequestJsonV310(email: String, `for`: String, view: String)
case class ConsentRequestJsonV310(consent_id: String)
case class ConsentRequestJsonV310(consent_id: String, jwt: String, status: String)
case class PostConsentChallengeJsonV310(answer: String)
case class ConsentChallengeJsonV310(consent_id: String, jwt: String, status: String)
object JSONFactory310{
def createCheckbookOrdersJson(checkbookOrders: CheckbookOrdersJson): CheckbookOrdersJson =

View File

@ -337,6 +337,7 @@ object OBPAPI3_1_0 extends OBPRestHelper with APIMethods130 with APIMethods140 w
Implementations3_1_0.getMeeting ::
Implementations3_1_0.getServerJWK ::
Implementations3_1_0.createConsent ::
Implementations3_1_0.answerConsentChallenge ::
Nil
val allResourceDocs = Implementations3_1_0.resourceDocs ++

View File

@ -11,7 +11,8 @@ object Consents extends SimpleInjector {
trait ConsentProvider {
def getConsentByConsentId(consentId: String): Box[MappedConsent]
def createConsent(): Box[MappedConsent]
def updateConsent(consentId: String, jwt: String): Box[MappedConsent]
def setJsonWebToken(consentId: String, jwt: String): Box[MappedConsent]
def checkAnswer(consentId: String, challenge: String): Box[MappedConsent]
}
trait Consent {

View File

@ -22,12 +22,11 @@ object MappedConsentProvider extends ConsentProvider {
.saveMe()
}
}
override def updateConsent(consentId: String, jwt: String): Box[MappedConsent] = {
override def setJsonWebToken(consentId: String, jwt: String): Box[MappedConsent] = {
MappedConsent.find(By(MappedConsent.mConsentId, consentId)) match {
case Full(consent) =>
tryo(consent
.mJsonWebToken(jwt)
.mConsentId(consentId)
.saveMe())
case Empty =>
Empty ?~! ErrorMessages.ConsentNotFound
@ -35,6 +34,24 @@ object MappedConsentProvider extends ConsentProvider {
Failure(msg)
case _ =>
Failure(ErrorMessages.UnknownError)
}
}
override def checkAnswer(consentId: String, challenge: String): Box[MappedConsent] = {
MappedConsent.find(By(MappedConsent.mConsentId, consentId)) match {
case Full(consent) =>
consent.status match {
case value if value == ConsentStatus.INITIATED.toString =>
val status = if (consent.challenge == challenge) ConsentStatus.ACCEPTED.toString else ConsentStatus.REJECTED.toString
tryo(consent.mStatus(status).saveMe())
case _ =>
Full(consent)
}
case Empty =>
Empty ?~! ErrorMessages.ConsentNotFound
case Failure(msg, _, _) =>
Failure(msg)
case _ =>
Failure(ErrorMessages.UnknownError)
}
}