From 6d21212d5f74be631a6f07fe73dd6341b4d9804f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Fri, 6 Sep 2019 15:42:28 +0200 Subject: [PATCH] Added endpoint resetPasswordUrl v4.0.0 --- .../main/scala/code/api/util/ApiRole.scala | 4 ++ .../scala/code/api/v4_0_0/APIMethods400.scala | 47 ++++++++++++++++++- .../code/api/v4_0_0/JSONFactory4.0.0.scala | 2 + .../scala/code/api/v4_0_0/OBPAPI4_0_0.scala | 1 + .../code/model/dataAccess/AuthUser.scala | 15 ++++++ 5 files changed, 68 insertions(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/util/ApiRole.scala b/obp-api/src/main/scala/code/api/util/ApiRole.scala index ce82e2061..07789f1d3 100644 --- a/obp-api/src/main/scala/code/api/util/ApiRole.scala +++ b/obp-api/src/main/scala/code/api/util/ApiRole.scala @@ -362,6 +362,9 @@ object ApiRole { case class CanDeleteDynamicEntity(requiresBankId: Boolean = false) extends ApiRole lazy val canDeleteDynamicEntity = CanDeleteDynamicEntity() + + case class CanCreateResetPasswordUrl(requiresBankId: Boolean = false) extends ApiRole + lazy val canCreateResetPasswordUrl = CanCreateResetPasswordUrl() private val roles = canSearchAllTransactions :: @@ -476,6 +479,7 @@ object ApiRole { canCreateDynamicEntity :: canUpdateDynamicEntity :: canDeleteDynamicEntity :: + canCreateResetPasswordUrl :: Nil lazy val rolesMappedToClasses = roles.map(_.getClass) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 761fd00c0..2319e6edc 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -5,13 +5,14 @@ import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._ import code.api.util.APIUtil._ import code.api.util.ApiRole._ import code.api.util.ApiTag._ -import code.api.util.ErrorMessages.{AccountNotFound, AllowedAttemptsUsedUp, BankNotFound, CounterpartyBeneficiaryPermit, InsufficientAuthorisationToCreateTransactionRequest, InvalidAccountIdFormat, InvalidBankIdFormat, InvalidChallengeAnswer, InvalidChallengeType, InvalidChargePolicy, InvalidISOCurrencyCode, InvalidJsonFormat, InvalidNumber, InvalidTransactionRequesChallengeId, InvalidTransactionRequestCurrency, InvalidTransactionRequestType, NotPositiveAmount, TransactionDisabled, TransactionRequestStatusNotInitiated, TransactionRequestTypeHasChanged, UnknownError, UserHasMissingRoles, UserNoPermissionAccessView, UserNotLoggedIn, ViewNotFound} +import code.api.util.ErrorMessages.{AccountNotFound, AllowedAttemptsUsedUp, BankNotFound, CounterpartyBeneficiaryPermit, InsufficientAuthorisationToCreateTransactionRequest, InvalidAccountIdFormat, InvalidBankIdFormat, InvalidChallengeAnswer, InvalidChallengeType, InvalidChargePolicy, InvalidISOCurrencyCode, InvalidJsonFormat, InvalidNumber, InvalidTransactionRequesChallengeId, InvalidTransactionRequestCurrency, InvalidTransactionRequestType, InvalidWebUiProps, NotPositiveAmount, TransactionDisabled, TransactionRequestStatusNotInitiated, TransactionRequestTypeHasChanged, UnknownError, UserHasMissingRoles, UserNoPermissionAccessView, UserNotLoggedIn, ViewNotFound} import code.api.util.NewStyle.HttpCode import code.api.util._ import code.api.v1_4_0.JSONFactory1_4_0.{ChallengeAnswerJSON, TransactionRequestAccountJsonV140} import code.api.v2_1_0._ import code.api.v3_1_0.ListResult import code.dynamicEntity.DynamicEntityCommons +import code.model.dataAccess.AuthUser import code.model.toUserExtended import code.transactionrequests.TransactionRequests.TransactionChallengeTypes._ import code.transactionrequests.TransactionRequests.TransactionRequestTypes @@ -1026,6 +1027,50 @@ trait APIMethods400 { } } + + + resourceDocs += ResourceDoc( + resetPasswordUrl, + implementedInApiVersion, + nameOf(resetPasswordUrl), + "POST", + "/management/user/reset-password-url", + "Request password reset url", + s"""Request password reset url. + | + |${authenticationRequiredMessage(true)} + | + |""", + PostResetPasswordUrlJsonV400("jobloggs", "jo@gmail.com", "74a8ebcc-10e4-4036-bef3-9835922246bf"), + ResetPasswordUrlJsonV400( "https://apisandbox.openbankproject.com/user_mgt/reset_password/QOL1CPNJPCZ4BRMPX3Z01DPOX1HMGU3L"), + List( + UserNotLoggedIn, + UserHasMissingRoles, + InvalidJsonFormat, + UnknownError + ), + Catalogs(notCore, notPSD2, notOBWG), + List(apiTagUser, apiTagApi, apiTagNewStyle), + Some(List(canCreateResetPasswordUrl))) + + lazy val resetPasswordUrl : OBPEndpoint = { + case "management" :: "user" :: "reset-password-url" :: Nil JsonPost json -> _ => { + cc => + for { + (Full(u), callContext) <- authorizedAccess(cc) + // _ <- NewStyle.function.hasEntitlement("", u.userId, canCreateResetPasswordUrl, callContext) + failMsg = s"$InvalidJsonFormat The Json body should be the ${classOf[PostResetPasswordUrlJsonV400]} " + postedData <- NewStyle.function.tryons(failMsg, 400, callContext) { + json.extract[PostResetPasswordUrlJsonV400] + } + } yield { + val resetLink = AuthUser.passwordResetUrl(postedData.username, postedData.email, postedData.user_id) + (ResetPasswordUrlJsonV400(resetLink), HttpCode.`201`(callContext)) + } + } + } + + } } diff --git a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala index e01b6361f..b79f6a3ce 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/JSONFactory4.0.0.scala @@ -70,6 +70,8 @@ case class TransactionRequestWithChargeJSON400( challenge: ChallengeJsonV400, charge : TransactionRequestChargeJsonV200 ) +case class PostResetPasswordUrlJsonV400(username: String, email: String, user_id: String) +case class ResetPasswordUrlJsonV400(reset_password_url: String) object JSONFactory400 { def createBankJSON400(bank: Bank): BankJson400 = { diff --git a/obp-api/src/main/scala/code/api/v4_0_0/OBPAPI4_0_0.scala b/obp-api/src/main/scala/code/api/v4_0_0/OBPAPI4_0_0.scala index 1aab7c1ca..4b037cdb2 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/OBPAPI4_0_0.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/OBPAPI4_0_0.scala @@ -391,6 +391,7 @@ object OBPAPI4_0_0 extends OBPRestHelper with APIMethods130 with APIMethods140 w Implementations4_0_0.updateDynamicEntity :: Implementations4_0_0.deleteDynamicEntity :: Implementations4_0_0.genericEndpoint :: + Implementations4_0_0.resetPasswordUrl :: Nil def allResourceDocs = MockerConnector.doc ++ diff --git a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala index 15c9f297d..ee1db9ebb 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala @@ -873,6 +873,21 @@ def restoreSomeSessions(): Unit = { protected def findUserByUsernameLocally(name: String): Box[TheUserType] = { find(By(this.username, name)) } + + def passwordResetUrl(name: String, email: String, userId: String): String = { + find(By(this.username, name)) match { + case Full(authUser) if authUser.validated_? && authUser.email == email => + Users.users.vend.getUserByUserId(userId) match { + case Full(u) if u.name == name && u.emailAddress == email => + authUser.resetUniqueId().save + val resetLink = APIUtil.getPropsValue("hostname", "ERROR")+ + passwordResetPath.mkString("/", "/", "/")+urlEncode(authUser.getUniqueId()) + resetLink + case _ => "" + } + case _ => "" + } + } /** * Find the authUsers by author email(authUser and resourceUser are the same). * Only search for the local database.