bugfix/use the MappedExpectedChallengeAnswer to save all challenges for V400

This commit is contained in:
hongwei 2022-06-02 14:54:18 +02:00
parent 435de19d4a
commit 0d470a0fc6
19 changed files with 82 additions and 78 deletions

View File

@ -25,12 +25,11 @@ import code.connectormethod.{JsonConnectorMethod, JsonConnectorMethodMethodBody}
import code.dynamicMessageDoc.JsonDynamicMessageDoc
import code.dynamicResourceDoc.JsonDynamicResourceDoc
import code.sandbox.SandboxData
import code.transactionrequests.TransactionRequests.TransactionChallengeTypes
import code.transactionrequests.TransactionRequests.TransactionRequestTypes._
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.model
import com.openbankproject.commons.model.PinResetReason.{FORGOT, GOOD_SECURITY_PRACTICE}
import com.openbankproject.commons.model.enums.{AttributeCategory, CardAttributeType}
import com.openbankproject.commons.model.enums.{AttributeCategory, CardAttributeType, ChallengeType}
import com.openbankproject.commons.model.{UserAuthContextUpdateStatus, ViewBasic, _}
import com.openbankproject.commons.util.{ApiVersion, FieldNameApiVersions, ReflectUtils, RequiredArgs, RequiredInfo}
import net.liftweb.json
@ -4309,7 +4308,7 @@ object SwaggerDefinitionsJSON {
id = transactionIdExample.value,
user_id = userIdExample.value,
allowed_attempts =3,
challenge_type = TransactionChallengeTypes.OTP_VIA_API.toString,
challenge_type = ChallengeType.OBP_TRANSACTION_REQUEST_CHALLENGE.toString,
link = "/obp/v4.0.0/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/transaction-request-types/TRANSACTION_REQUEST_TYPE/transaction-requests/TRANSACTION_REQUEST_ID/challenge"
)
val transactionRequestWithChargeJSON400 = TransactionRequestWithChargeJSON400(

View File

@ -1078,7 +1078,7 @@ The ASPSP might make the usage of this access method unnecessary, since the rela
}
(challenges, callContext) <- NewStyle.function.createChallengesC2(
List(u.userId),
ChallengeType.BERLINGROUP_CONSENT,
ChallengeType.BERLINGROUP_CONSENT_CHALLENGE,
None,
getSuggestedDefaultScaMethod(),
Some(StrongCustomerAuthenticationStatus.received),
@ -1154,7 +1154,7 @@ Maybe in a later version the access path will change.
challenges.filter(_.challengeId == authorisationId).size == 1
}
(challenge, callContext) <- NewStyle.function.validateChallengeAnswerC2(
ChallengeType.BERLINGROUP_CONSENT,
ChallengeType.BERLINGROUP_CONSENT_CHALLENGE,
None,
Some(consentId),
challenges.filter(_.challengeId == authorisationId).head.challengeId,

View File

@ -675,7 +675,7 @@ This applies in the following scenarios:
(challenges, callContext) <- NewStyle.function.createChallengesC2(
List(u.userId),
ChallengeType.BERLINGROUP_PAYMENT,
ChallengeType.BERLINGROUP_PAYMENT_CHALLENGE,
Some(paymentId),
getScaMethodAtInstance(SEPA_CREDIT_TRANSFERS.toString).toOption,
Some(StrongCustomerAuthenticationStatus.received),
@ -765,7 +765,7 @@ This applies in the following scenarios:
}
(challenges, callContext) <- NewStyle.function.createChallengesC2(
List(u.userId),
ChallengeType.BERLINGROUP_PAYMENT,
ChallengeType.BERLINGROUP_PAYMENT_CHALLENGE,
Some(paymentId),
getScaMethodAtInstance(SEPA_CREDIT_TRANSFERS.toString).toOption,
Some(StrongCustomerAuthenticationStatus.received),
@ -877,7 +877,7 @@ There are the following request types on this access path:
}
(_, callContext) <- NewStyle.function.getTransactionRequestImpl(TransactionRequestId(paymentId), callContext)
(challenge, callContext) <- NewStyle.function.validateChallengeAnswerC2(
ChallengeType.BERLINGROUP_PAYMENT,
ChallengeType.BERLINGROUP_PAYMENT_CHALLENGE,
Some(paymentId),
None,
cancellationId,
@ -997,7 +997,7 @@ There are the following request types on this access path:
existingTransactionRequest.status == TransactionRequestStatus.INITIATED.toString
}
(challenge, callContext) <- NewStyle.function.validateChallengeAnswerC2(
ChallengeType.BERLINGROUP_PAYMENT,
ChallengeType.BERLINGROUP_PAYMENT_CHALLENGE,
Some(paymentId),
None,
authorisationid,

View File

@ -72,7 +72,6 @@ import code.dynamicMessageDoc.{DynamicMessageDocProvider, JsonDynamicMessageDoc}
import code.dynamicResourceDoc.{DynamicResourceDocProvider, JsonDynamicResourceDoc}
import code.endpointMapping.{EndpointMappingProvider, EndpointMappingT}
import code.endpointTag.EndpointTagT
import code.transactionrequests.TransactionRequests.TransactionChallengeTypes
import code.util.Helper.MdcLoggable
import code.views.system.AccountAccess
import net.liftweb.mapper.By
@ -1155,7 +1154,7 @@ object NewStyle extends MdcLoggable{
transactionRequestCommonBody: TransactionRequestCommonBodyJSON,
detailsPlain: String,
chargePolicy: String,
challengeType: Option[TransactionChallengeTypes.Value],
challengeType: Option[ChallengeType.Value],
scaMethod: Option[SCA],
reasons: Option[List[TransactionRequestReason]],
berlinGroupPayments: Option[SepaCreditTransfersBerlinGroupV13],
@ -1340,14 +1339,12 @@ object NewStyle extends MdcLoggable{
bankId: BankId,
accountId: AccountId,
transReqId: TransactionRequestId,
challenges: List[ChallengeTrait],
callContext: Option[CallContext]
): OBPReturnType[Boolean] =
Connector.connector.vend.allChallengesSuccessfullyAnswered(
bankId: BankId,
accountId: AccountId,
transReqId: TransactionRequestId,
challenges: List[ChallengeTrait],
callContext: Option[CallContext]
) map { i =>
(unboxFullOrFail(i._1, callContext, s"$InvalidConnectorResponse"), i._2)
@ -1366,10 +1363,10 @@ object NewStyle extends MdcLoggable{
hashOfSuppliedAnswer: String,
callContext: Option[CallContext]
): OBPReturnType[ChallengeTrait] = {
if(challengeType == ChallengeType.BERLINGROUP_PAYMENT && transactionRequestId.isEmpty ){
Future{ throw new Exception(s"$UnknownError The following parameters can not be empty for BERLINGROUP_PAYMENT challengeType: paymentId($transactionRequestId) ")}
}else if(challengeType == ChallengeType.BERLINGROUP_CONSENT && consentId.isEmpty ){
Future{ throw new Exception(s"$UnknownError The following parameters can not be empty for BERLINGROUP_CONSENT challengeType: consentId($consentId) ")}
if(challengeType == ChallengeType.BERLINGROUP_PAYMENT_CHALLENGE && transactionRequestId.isEmpty ){
Future{ throw new Exception(s"$UnknownError The following parameters can not be empty for BERLINGROUP_PAYMENT_CHALLENGE challengeType: paymentId($transactionRequestId) ")}
}else if(challengeType == ChallengeType.BERLINGROUP_CONSENT_CHALLENGE && consentId.isEmpty ){
Future{ throw new Exception(s"$UnknownError The following parameters can not be empty for BERLINGROUP_CONSENT_CHALLENGE challengeType: consentId($consentId) ")}
}else{
Connector.connector.vend.validateChallengeAnswerC2(
transactionRequestId: Option[String],
@ -1405,9 +1402,9 @@ object NewStyle extends MdcLoggable{
authenticationMethodId: Option[String],
callContext: Option[CallContext]
) : OBPReturnType[List[ChallengeTrait]] = {
if(challengeType == ChallengeType.BERLINGROUP_PAYMENT && (transactionRequestId.isEmpty || scaStatus.isEmpty || scaMethod.isEmpty)){
if(challengeType == ChallengeType.BERLINGROUP_PAYMENT_CHALLENGE && (transactionRequestId.isEmpty || scaStatus.isEmpty || scaMethod.isEmpty)){
Future{ throw new Exception(s"$UnknownError The following parameters can not be empty for BERLINGROUP_PAYMENT challengeType: paymentId($transactionRequestId), scaStatus($scaStatus), scaMethod($scaMethod) ")}
}else if(challengeType == ChallengeType.BERLINGROUP_CONSENT && (consentId.isEmpty || scaStatus.isEmpty || scaMethod.isEmpty)){
}else if(challengeType == ChallengeType.BERLINGROUP_CONSENT_CHALLENGE && (consentId.isEmpty || scaStatus.isEmpty || scaMethod.isEmpty)){
Future{ throw new Exception(s"$UnknownError The following parameters can not be empty for BERLINGROUP_CONSENT challengeType: consentId($consentId), scaStatus($scaStatus), scaMethod($scaMethod) ")}
}else{
Connector.connector.vend.createChallengesC2(

View File

@ -1,7 +1,6 @@
package code.api.v2_1_0
import java.util.Date
import code.TransactionTypes.TransactionType
import code.api.util
import code.api.util.ApiTag._
@ -23,12 +22,13 @@ import code.fx.fx
import code.metrics.APIMetrics
import code.model.{BankAccountX, BankX, Consumer, UserX, toUserExtended}
import code.sandbox.SandboxData
import code.transactionrequests.TransactionRequests.{TransactionChallengeTypes, TransactionRequestTypes}
import code.transactionrequests.TransactionRequests.TransactionRequestTypes
import code.usercustomerlinks.UserCustomerLink
import code.users.Users
import code.util.Helper.booleanToBox
import code.views.Views
import com.openbankproject.commons.model._
import com.openbankproject.commons.model.enums.ChallengeType
import com.openbankproject.commons.util.ApiVersion
import net.liftweb.json.Extraction
import net.liftweb.util.Helpers.tryo
@ -639,7 +639,7 @@ trait APIMethods210 {
//Check the challenge type, Note: not support yet, the default value is SANDBOX_TAN
_ <- Helper.booleanToFuture(s"${InvalidChallengeType} ", cc=callContext) {
existingTransactionRequest.challenge.challenge_type == TransactionChallengeTypes.OTP_VIA_API.toString
existingTransactionRequest.challenge.challenge_type == ChallengeType.OBP_TRANSACTION_REQUEST_CHALLENGE.toString
}
(isChallengeAnswerValidated, callContext) <- NewStyle.function.validateChallengeAnswer(challengeAnswerJson.id, challengeAnswerJson.answer, callContext)

View File

@ -58,7 +58,6 @@ import code.scope.Scope
import code.snippet.{WebUIPlaceholder, WebUITemplate}
import code.transactionChallenge.MappedExpectedChallengeAnswer
import code.transactionrequests.MappedTransactionRequestProvider
import code.transactionrequests.TransactionRequests.TransactionChallengeTypes._
import code.transactionrequests.TransactionRequests.TransactionRequestTypes
import code.transactionrequests.TransactionRequests.TransactionRequestTypes.{apply => _, _}
import code.usercustomerlinks.UserCustomerLink
@ -73,6 +72,7 @@ import code.webuiprops.MappedWebUiPropsProvider.getWebUiPropsValue
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.ExecutionContext.Implicits.global
import com.openbankproject.commons.dto.GetProductsParam
import com.openbankproject.commons.model.enums.ChallengeType.OBP_TRANSACTION_REQUEST_CHALLENGE
import com.openbankproject.commons.model.enums.DynamicEntityOperation._
import com.openbankproject.commons.model.enums.{TransactionRequestStatus, _}
import com.openbankproject.commons.model.{ListResult, _}
@ -1035,7 +1035,7 @@ trait APIMethods400 {
transactionRequestBodyRefundJson.copy(description = newDescription),
transDetailsSerialized,
sharedChargePolicy.toString,
Some(OTP_VIA_API),
Some(OBP_TRANSACTION_REQUEST_CHALLENGE),
getScaMethodAtInstance(transactionRequestType.value).toOption,
None,
None,
@ -1091,7 +1091,7 @@ trait APIMethods400 {
transactionRequestBodySandboxTan,
transDetailsSerialized,
sharedChargePolicy.toString,
Some(OTP_VIA_API),
Some(OBP_TRANSACTION_REQUEST_CHALLENGE),
getScaMethodAtInstance(transactionRequestType.value).toOption,
None,
None,
@ -1120,7 +1120,7 @@ trait APIMethods400 {
transactionRequestBodySandboxTan,
transDetailsSerialized,
sharedChargePolicy.toString,
Some(OTP_VIA_WEB_FORM),
Some(OBP_TRANSACTION_REQUEST_CHALLENGE),
getScaMethodAtInstance(transactionRequestType.value).toOption,
None,
None,
@ -1155,7 +1155,7 @@ trait APIMethods400 {
transactionRequestBodyCounterparty,
transDetailsSerialized,
chargePolicy,
Some(OTP_VIA_API),
Some(OBP_TRANSACTION_REQUEST_CHALLENGE),
getScaMethodAtInstance(transactionRequestType.value).toOption,
None,
None,
@ -1207,7 +1207,7 @@ trait APIMethods400 {
transactionRequestBodySimple,
transDetailsSerialized,
chargePolicy,
Some(OTP_VIA_API),
Some(OBP_TRANSACTION_REQUEST_CHALLENGE),
getScaMethodAtInstance(transactionRequestType.value).toOption,
None,
None,
@ -1242,7 +1242,7 @@ trait APIMethods400 {
transDetailsSEPAJson,
transDetailsSerialized,
chargePolicy,
Some(OTP_VIA_API),
Some(OBP_TRANSACTION_REQUEST_CHALLENGE),
getScaMethodAtInstance(transactionRequestType.value).toOption,
transDetailsSEPAJson.reasons.map(_.map(_.transform)),
None,
@ -1267,7 +1267,7 @@ trait APIMethods400 {
transactionRequestBodyFreeForm,
transDetailsSerialized,
sharedChargePolicy.toString,
Some(OTP_VIA_API),
Some(OBP_TRANSACTION_REQUEST_CHALLENGE),
getScaMethodAtInstance(transactionRequestType.value).toOption,
None,
None,
@ -1384,17 +1384,16 @@ trait APIMethods400 {
_ <- Helper.booleanToFuture(s"${TransactionRequestTypeHasChanged} It should be :'$existingTransactionRequestType', but current value (${transactionRequestType.value}) ", cc=callContext) {
existingTransactionRequestType.equals(transactionRequestType.value)
}
(challenges, callContext) <- NewStyle.function.getChallengesByTransactionRequestId(transReqId.value, callContext)
//Check the challenge type, Note: not supported yet, the default value is SANDBOX_TAN
_ <- Helper.booleanToFuture(s"${InvalidChallengeType} ", cc=callContext) {
List(
OTP_VIA_API.toString,
OTP_VIA_WEB_FORM.toString
).exists(_ == existingTransactionRequest.challenge.challenge_type)
_ <- Helper.booleanToFuture(s"$InvalidChallengeType Current Type is ${challenges.map(_.challengeType)}" , cc=callContext) {
challenges.map(_.challengeType)
.filterNot(challengeType => challengeType.equals(ChallengeType.OBP_TRANSACTION_REQUEST_CHALLENGE.toString))
.isEmpty
}
(challenges, callContext) <- NewStyle.function.getChallengesByTransactionRequestId(transReqId.value, callContext)
(transactionRequest, callContext) <- challengeAnswerJson.answer match {
// If the challenge answer is `REJECT` - Currently only to Reject a SEPA transaction request REFUND
case "REJECT" =>
@ -1453,7 +1452,7 @@ trait APIMethods400 {
challengeAnswerIsValidated
}
(challengeAnswerIsValidated, callContext) <- NewStyle.function.allChallengesSuccessfullyAnswered(bankId, accountId, transReqId, challenges, callContext)
(challengeAnswerIsValidated, callContext) <- NewStyle.function.allChallengesSuccessfullyAnswered(bankId, accountId, transReqId, callContext)
_ <- Helper.booleanToFuture(s"$NextChallengePending", cc=callContext) {
challengeAnswerIsValidated
}

View File

@ -54,11 +54,12 @@ import code.model.dataAccess.ResourceUser
import code.model.{Consumer, ModeratedBankAccount, ModeratedBankAccountCore}
import code.ratelimiting.RateLimiting
import code.standingorders.StandingOrderTrait
import code.transactionrequests.TransactionRequests.TransactionChallengeTypes
import code.userlocks.UserLocks
import code.users.{UserAgreement, UserAttribute, UserInvitation}
import code.views.system.AccountAccess
import code.webhook.{AccountWebhook, BankAccountNotificationWebhookTrait, SystemAccountNotificationWebhookTrait}
import com.openbankproject.commons.model.enums.ChallengeType
import com.openbankproject.commons.model.{DirectDebitTrait, ProductFeeTrait, _}
import net.liftweb.common.{Box, Full}
import net.liftweb.json.JValue
@ -1229,8 +1230,8 @@ object JSONFactory400 {
stringOrNull(tr.id.value),
"/challenge").mkString("")
val link = challenge.challengeType match {
case challengeType if challengeType == TransactionChallengeTypes.OTP_VIA_WEB_FORM.toString => otpViaWebFormPath
case challengeType if challengeType == TransactionChallengeTypes.OTP_VIA_API.toString => otpViaApiPath
case challengeType if challengeType == ChallengeType.OBP_TRANSACTION_REQUEST_CHALLENGE.toString => otpViaWebFormPath
case challengeType if challengeType == ChallengeType.OBP_TRANSACTION_REQUEST_CHALLENGE.toString => otpViaApiPath
case _ => ""
}
ChallengeJsonV400(

View File

@ -404,7 +404,6 @@ trait Connector extends MdcLoggable {
bankId: BankId,
accountId: AccountId,
transReqId: TransactionRequestId,
challenges: List[ChallengeTrait],
callContext: Option[CallContext]
): OBPReturnType[Box[Boolean]]= Future{(Full(true), callContext)}
@ -845,7 +844,7 @@ trait Connector extends MdcLoggable {
}
} else {
//if challenge necessary, create a new one
val challenge = TransactionRequestChallenge(id = generateUUID(), allowed_attempts = 3, challenge_type = TransactionChallengeTypes.OTP_VIA_API.toString)
val challenge = TransactionRequestChallenge(id = generateUUID(), allowed_attempts = 3, challenge_type = ChallengeType.OBP_TRANSACTION_REQUEST_CHALLENGE.toString)
saveTransactionRequestChallenge(result.id, challenge)
result = result.copy(challenge = challenge)
}
@ -913,7 +912,7 @@ trait Connector extends MdcLoggable {
}
} else {
//if challenge necessary, create a new one
val challenge = TransactionRequestChallenge(id = generateUUID(), allowed_attempts = 3, challenge_type = TransactionChallengeTypes.OTP_VIA_API.toString)
val challenge = TransactionRequestChallenge(id = generateUUID(), allowed_attempts = 3, challenge_type = ChallengeType.OBP_TRANSACTION_REQUEST_CHALLENGE.toString)
saveTransactionRequestChallenge(result.id, challenge)
result = result.copy(challenge = challenge)
}
@ -1043,7 +1042,7 @@ trait Connector extends MdcLoggable {
(unboxFullOrFail(i._1, callContext, s"$InvalidConnectorResponseForCreateChallenge ", 400), i._2)
}
newChallenge = TransactionRequestChallenge(challengeId, allowed_attempts = 3, challenge_type = challengeType.getOrElse(TransactionChallengeTypes.OTP_VIA_API.toString))
newChallenge = TransactionRequestChallenge(challengeId, allowed_attempts = 3, challenge_type = challengeType.getOrElse(ChallengeType.OBP_TRANSACTION_REQUEST_CHALLENGE.toString))
_ <- Future (saveTransactionRequestChallenge(transactionRequest.id, newChallenge))
transactionRequest <- Future(transactionRequest.copy(challenge = newChallenge))
} yield {
@ -1223,7 +1222,7 @@ trait Connector extends MdcLoggable {
tr.map(_._1) match {
case Full(tr: TransactionRequest) =>
if (tr.challenge.allowed_attempts > 0) {
if (tr.challenge.challenge_type == TransactionChallengeTypes.OTP_VIA_API.toString) {
if (tr.challenge.challenge_type == ChallengeType.OBP_TRANSACTION_REQUEST_CHALLENGE.toString) {
//check if answer supplied is correct (i.e. for now, TAN -> some number and not empty)
for {
nonEmpty <- booleanToBox(answer.nonEmpty) ?~ "Need a non-empty answer"

View File

@ -65,7 +65,7 @@ import code.transactionChallenge.{Challenges, MappedExpectedChallengeAnswer}
import code.transactionRequestAttribute.TransactionRequestAttributeX
import code.transactionattribute.TransactionAttributeX
import code.transactionrequests.TransactionRequests.TransactionRequestTypes._
import code.transactionrequests.TransactionRequests.{TransactionChallengeTypes, TransactionRequestTypes}
import code.transactionrequests.TransactionRequests.TransactionRequestTypes
import code.transactionrequests._
import code.users.{UserAttribute, UserAttributeProvider, Users}
import code.util.Helper
@ -76,6 +76,7 @@ import com.nexmo.client.NexmoClient
import com.nexmo.client.sms.messages.TextMessage
import com.openbankproject.commons.ExecutionContext.Implicits.global
import com.openbankproject.commons.dto.{CustomerAndAttribute, GetProductsParam, ProductCollectionItemsTree}
import com.openbankproject.commons.model.enums.ChallengeType.OBP_TRANSACTION_REQUEST_CHALLENGE
import com.openbankproject.commons.model.enums.DynamicEntityOperation._
import com.openbankproject.commons.model.enums.StrongCustomerAuthentication.SCA
import com.openbankproject.commons.model.enums.StrongCustomerAuthenticationStatus.SCAStatus
@ -211,6 +212,7 @@ object LocalMappedConnector extends Connector with MdcLoggable {
None, //there are only for new version, set the empty here.
None,//there are only for new version, set the empty here.
None,//there are only for new version, set the empty here.
challengeType = OBP_TRANSACTION_REQUEST_CHALLENGE.toString,
callContext: Option[CallContext])
(challenge._1.map(_.challengeId),challenge._2)
}
@ -240,6 +242,7 @@ object LocalMappedConnector extends Connector with MdcLoggable {
None, //there are only for new version, set the empty here.
None,//there are only for new version, set the empty here.
None,//there are only for new version, set the empty here.
challengeType = OBP_TRANSACTION_REQUEST_CHALLENGE.toString,
callContext
)
challenge.map(_.challengeId).toList
@ -267,6 +270,7 @@ object LocalMappedConnector extends Connector with MdcLoggable {
scaStatus,
consentId,
authenticationMethodId,
challengeType = OBP_TRANSACTION_REQUEST_CHALLENGE.toString,
callContext
)
challengeId.toList
@ -290,7 +294,8 @@ object LocalMappedConnector extends Connector with MdcLoggable {
scaMethod: Option[SCA],
scaStatus: Option[SCAStatus], //Only use for BerlinGroup Now
consentId: Option[String], // Note: consentId and transactionRequestId are exclusive here.
authenticationMethodId: Option[String],
authenticationMethodId: Option[String],
challengeType: String,
callContext: Option[CallContext]
) = {
def createHashedPassword(challengeAnswer: String) = {
@ -306,7 +311,8 @@ object LocalMappedConnector extends Connector with MdcLoggable {
scaMethod,
scaStatus,
consentId,
authenticationMethodId), callContext)
authenticationMethodId,
challengeType), callContext)
}
scaMethod match {
@ -389,11 +395,11 @@ object LocalMappedConnector extends Connector with MdcLoggable {
bankId: BankId,
accountId: AccountId,
transReqId: TransactionRequestId,
challenges: List[ChallengeTrait],
callContext: Option[CallContext]
): OBPReturnType[Box[Boolean]] = {
for {
(accountAttributes, callContext) <- Connector.connector.vend.getAccountAttributesByAccount(bankId, accountId, callContext)
(challenges, callContext) <- NewStyle.function.getChallengesByTransactionRequestId(transReqId.value, callContext)
quorum = accountAttributes.toList.flatten.find(_.name == "REQUIRED_CHALLENGE_ANSWERS").map(_.value).getOrElse("1").toInt
challengeSuccess = challenges.count(_.successful == true) match {
case number if number >= quorum => true
@ -4559,7 +4565,7 @@ object LocalMappedConnector extends Connector with MdcLoggable {
}
} else {
//if challenge necessary, create a new one
val challenge = TransactionRequestChallenge(id = generateUUID(), allowed_attempts = 3, challenge_type = TransactionChallengeTypes.OTP_VIA_API.toString)
val challenge = TransactionRequestChallenge(id = generateUUID(), allowed_attempts = 3, challenge_type = ChallengeType.OBP_TRANSACTION_REQUEST_CHALLENGE.toString)
saveTransactionRequestChallenge(result.id, challenge)
result = result.copy(challenge = challenge)
}
@ -4630,7 +4636,7 @@ object LocalMappedConnector extends Connector with MdcLoggable {
}
} else {
//if challenge necessary, create a new one
val challenge = TransactionRequestChallenge(id = generateUUID(), allowed_attempts = 3, challenge_type = TransactionChallengeTypes.OTP_VIA_API.toString)
val challenge = TransactionRequestChallenge(id = generateUUID(), allowed_attempts = 3, challenge_type = ChallengeType.OBP_TRANSACTION_REQUEST_CHALLENGE.toString)
saveTransactionRequestChallenge(result.id, challenge)
result = result.copy(challenge = challenge)
}
@ -4767,7 +4773,7 @@ object LocalMappedConnector extends Connector with MdcLoggable {
(unboxFullOrFail(i._1, callContext, s"$InvalidConnectorResponseForCreateChallenge ", 400), i._2)
}
newChallenge = TransactionRequestChallenge(challengeId, allowed_attempts = 3, challenge_type = challengeType.getOrElse(TransactionChallengeTypes.OTP_VIA_API.toString))
newChallenge = TransactionRequestChallenge(challengeId, allowed_attempts = 3, challenge_type = challengeType.getOrElse(ChallengeType.OBP_TRANSACTION_REQUEST_CHALLENGE.toString))
_ <- Future(saveTransactionRequestChallenge(transactionRequest.id, newChallenge))
transactionRequest <- Future(transactionRequest.copy(challenge = newChallenge))
} yield {
@ -4841,6 +4847,9 @@ object LocalMappedConnector extends Connector with MdcLoggable {
chargeLevelAmount <- NewStyle.function.tryons(s"$InvalidNumber chargeLevel.amount: ${chargeLevel.amount} can not be transferred to decimal !", 400, callContext) {
BigDecimal(chargeLevel.amount)
}
challengeTypeValue <- NewStyle.function.tryons(s"$InvalidChallengeType Current Type is $challengeType", 400, callContext) {
challengeType.map(ChallengeType.withName(_)).head
}
chargeValue <- getChargeValue(chargeLevelAmount, transactionRequestCommonBodyAmount)
charge = TransactionRequestCharge("Total charges for completed transaction", AmountOfMoney(transactionRequestCommonBody.value.currency, chargeValue))
// Always create a new Transaction Request
@ -4921,7 +4930,7 @@ object LocalMappedConnector extends Connector with MdcLoggable {
//So here we return the challengeIds.
(challenges, callContext) <- Connector.connector.vend.createChallengesC2(
userIds = users.toList.flatten.map(_.userId),
challengeType = ChallengeType.OBP_PAYMENT,//TODO, here just hard code, it is TransactionChallengeTypes.Value in createTransactionRequestv400 method
challengeType = challengeTypeValue,
transactionRequestId = Some(transactionRequest.id.value),
scaMethod = scaMethod,
scaStatus = None, //Only use for BerlinGroup Now
@ -4934,7 +4943,7 @@ object LocalMappedConnector extends Connector with MdcLoggable {
//NOTE:this is only for Backward compatibility, now we use the MappedExpectedChallengeAnswer tables instead of the single field in TransactionRequest.
//Here only put the dummy date.
newChallenge = TransactionRequestChallenge(s"challenges number:${challenges.length}", allowed_attempts = 3, challenge_type = TransactionChallengeTypes.OTP_VIA_API.toString)
newChallenge = TransactionRequestChallenge(s"challenges number:${challenges.length}", allowed_attempts = 3, challenge_type = ChallengeType.OBP_TRANSACTION_REQUEST_CHALLENGE.toString)
_ <- Future(saveTransactionRequestChallenge(transactionRequest.id, newChallenge))
transactionRequest <- Future(transactionRequest.copy(challenge = newChallenge))
} yield {
@ -5052,7 +5061,7 @@ object LocalMappedConnector extends Connector with MdcLoggable {
tr.map(_._1) match {
case Full(tr: TransactionRequest) =>
if (tr.challenge.allowed_attempts > 0) {
if (tr.challenge.challenge_type == TransactionChallengeTypes.OTP_VIA_API.toString) {
if (tr.challenge.challenge_type == ChallengeType.OBP_TRANSACTION_REQUEST_CHALLENGE.toString) {
//check if answer supplied is correct (i.e. for now, TAN -> some number and not empty)
for {
nonEmpty <- booleanToBox(answer.nonEmpty) ?~ "Need a non-empty answer"

View File

@ -11,7 +11,7 @@ import code.api.util.ExampleValue._
import code.api.util._
import code.bankconnectors._
import code.bankconnectors.akka.actor.{AkkaConnectorActorInit, AkkaConnectorHelperActor}
import code.transactionrequests.TransactionRequests.TransactionChallengeTypes
import com.openbankproject.commons.ExecutionContext.Implicits.global
import com.openbankproject.commons.dto._
import com.openbankproject.commons.model._

View File

@ -21,10 +21,11 @@ object RemotedataChallenges extends ObpActorInit with ChallengeProvider {
scaMethod: Option[SCA],
scaStatus: Option[SCAStatus],
consentId: Option[String], // Note: consentId and transactionRequestId are exclusive here.
authenticationMethodId: Option[String]
authenticationMethodId: Option[String],
challengeType: String,
): Box[ChallengeTrait] =
getValueFromFuture(
(actor ? cc.saveChallenge(challengeId, transactionRequestId, salt, expectedAnswer, expectedUserId, scaMethod, scaStatus, consentId, authenticationMethodId))
(actor ? cc.saveChallenge(challengeId, transactionRequestId, salt, expectedAnswer, expectedUserId, scaMethod, scaStatus, consentId, authenticationMethodId, challengeType))
.mapTo[Box[ChallengeTrait]]
)

View File

@ -18,10 +18,11 @@ class RemotedataChallengesActor extends Actor with ObpActorHelper with MdcLoggab
scaMethod: Option[SCA],
scaStatus: Option[SCAStatus],
consentId: Option[String], // Note: consentId and transactionRequestId are exclusive here.
authenticationMethodId: Option[String]
authenticationMethodId: Option[String],
challengeType: String,
) =>
logger.debug(s"saveChallenge($challengeId, $transactionRequestId, $salt, $expectedAnswer, $expectedUserId)")
sender ! (mapper.saveChallenge(challengeId, transactionRequestId, salt, expectedAnswer, expectedUserId, scaMethod, scaStatus, consentId, authenticationMethodId))
sender ! (mapper.saveChallenge(challengeId, transactionRequestId, salt, expectedAnswer, expectedUserId, scaMethod, scaStatus, consentId, authenticationMethodId, challengeType: String))
case cc.getChallenge(challengeId: String) =>
logger.debug(s"getChallenge($challengeId)")

View File

@ -17,7 +17,8 @@ trait ChallengeProvider {
scaMethod: Option[SCA],
scaStatus: Option[SCAStatus],
consentId: Option[String], // Note: consentId and transactionRequestId are exclusive here.
authenticationMethodId: Option[String],
authenticationMethodId: Option[String],
challengeType: String,
): Box[ChallengeTrait]
def getChallenge(challengeId: String): Box[ChallengeTrait]
@ -45,7 +46,8 @@ class RemotedataChallengeProviderCaseClasses {
scaMethod: Option[SCA],
scaStatus: Option[SCAStatus],
consentId: Option[String], // Note: consentId and transactionRequestId are exclusive here.
authenticationMethodId: Option[String]
authenticationMethodId: Option[String],
challengeType: String,
)
case class getChallenge(challengeId: String)
case class getChallengesByTransactionRequestId(transactionRequestId: String)

View File

@ -25,12 +25,14 @@ object MappedChallengeProvider extends ChallengeProvider {
scaMethod: Option[SCA],
scaStatus: Option[SCAStatus],
consentId: Option[String], // Note: consentId and transactionRequestId are exclusive here.
authenticationMethodId: Option[String],
authenticationMethodId: Option[String],
challengeType: String,
): Box[ChallengeTrait] =
tryo (
MappedExpectedChallengeAnswer
.create
.mChallengeId(challengeId)
.mChallengeType(challengeType)
.mTransactionRequestId(transactionRequestId)
.mSalt(salt)
.mExpectedAnswer(expectedAnswer)

View File

@ -13,7 +13,7 @@ class MappedExpectedChallengeAnswer extends ChallengeTrait with LongKeyedMapper[
// Unique
object mChallengeId extends MappedUUID(this)
object mChallengeType extends MappedUUID(this)
object mChallengeType extends MappedString(this, 100)
object mTransactionRequestId extends MappedUUID(this)
object mExpectedAnswer extends MappedString(this,50)
object mExpectedUserId extends MappedUUID(this)

View File

@ -200,7 +200,7 @@ class MappedTransactionRequest extends LongKeyedMapper[MappedTransactionRequest]
object mEndDate extends MappedDate(this)
object mChallenge_Id extends MappedString(this, 64)
object mChallenge_AllowedAttempts extends MappedInt(this)
object mChallenge_ChallengeType extends MappedString(this, 32)
object mChallenge_ChallengeType extends MappedString(this, 100)
object mCharge_Summary extends MappedString(this, 64)
object mCharge_Amount extends MappedString(this, 32)
object mCharge_Currency extends MappedString(this, 3)

View File

@ -15,11 +15,6 @@ object TransactionRequests extends SimpleInjector {
val payments, bulk_payments, periodic_payments = Value
}
object TransactionChallengeTypes extends Enumeration {
type TransactionChallengeTypes = Value
val OTP_VIA_API, OTP_VIA_WEB_FORM = Value
}
object TransactionRequestTypes extends Enumeration {
type TransactionRequestTypes = Value
val SANDBOX_TAN, ACCOUNT, ACCOUNT_OTP, COUNTERPARTY, SEPA, FREE_FORM, SIMPLE,

View File

@ -8,8 +8,7 @@ import code.api.v1_4_0.JSONFactory1_4_0._
import code.bankconnectors.Connector
import code.setup.DefaultUsers
import code.transactionrequests.TransactionRequests.TransactionRequestTypes._
import code.transactionrequests.TransactionRequests.TransactionChallengeTypes
import com.openbankproject.commons.model.enums.TransactionRequestStatus
import com.openbankproject.commons.model.enums.{ChallengeType, TransactionRequestStatus}
import net.liftweb.json.JsonAST.JString
import net.liftweb.json.Serialization.write
import org.scalatest.Tag
@ -202,7 +201,7 @@ class TransactionRequestsTest extends V140ServerSetup with DefaultUsers {
//amount over 100 , so should trigger challenge request
val amt = BigDecimal("1250.00")
val bodyValue = AmountOfMoneyJsonV121("EUR", amt.toString())
val transactionRequestBody = TransactionRequestBodyJsonV140(toAccountJson, bodyValue, "Test Transaction Request description", TransactionChallengeTypes.OTP_VIA_API.toString)
val transactionRequestBody = TransactionRequestBodyJsonV140(toAccountJson, bodyValue, "Test Transaction Request description", ChallengeType.OBP_TRANSACTION_REQUEST_CHALLENGE.toString)
//call createTransactionRequest API method
var request = (v1_4Request / "banks" / testBank.bankId.value / "accounts" / fromAccount.accountId.value /

View File

@ -116,10 +116,10 @@ object StrongCustomerAuthenticationStatus extends OBPEnumeration[StrongCustomerA
sealed trait ChallengeType extends EnumValue
object ChallengeType extends OBPEnumeration[ChallengeType] {
object OBP_PAYMENT extends Value
object OBP_CONSENT extends Value
object BERLINGROUP_PAYMENT extends Value
object BERLINGROUP_CONSENT extends Value
object OBP_TRANSACTION_REQUEST_CHALLENGE extends Value
object OBP_CONSENT_CHALLENGE extends Value
object BERLINGROUP_PAYMENT_CHALLENGE extends Value
object BERLINGROUP_CONSENT_CHALLENGE extends Value
}
sealed trait PemCertificateRole extends EnumValue