Merge pull request #1987 from hongwei1/develop

docfix/tweaked the document for createUserWithAccountAccess
This commit is contained in:
Simon Redfern 2021-12-05 09:12:00 -06:00 committed by GitHub
commit d7b7712c4f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 59 additions and 79 deletions

View File

@ -4089,9 +4089,9 @@ object SwaggerDefinitionsJSON {
val postAccountAccessJsonV400 = PostAccountAccessJsonV400(userIdExample.value, PostViewJsonV400(ExampleValue.viewIdExample.value, true))
val postCreateUserAccountAccessJsonV400 = PostCreateUserAccountAccessJsonV400(
userIdExample.value,
providerExample.value,
List(PostViewJsonV400(ExampleValue.viewIdExample.value, true))
usernameExample.value,
s"dauth.${providerExample.value}",
List(PostViewJsonV400(viewIdExample.value, isSystemExample.value.toBoolean))
)
val postCreateUserWithRolesJsonV400 = PostCreateUserWithRolesJsonV400(
userIdExample.value,

View File

@ -134,25 +134,12 @@ object DAuth extends RestHelper with MdcLoggable {
}
def getOrCreateResourceUser(jwtPayload: String, callContext: Option[CallContext]) : Box[(User, Option[CallContext])] = {
val username = getFieldFromPayloadJson(jwtPayload, "smart_contract_address")
val provider = getFieldFromPayloadJson(jwtPayload, "network_name")
val providerHardCodePrefixDauth = "dauth."+provider
logger.debug("login_user_name: " + username)
val userName = getFieldFromPayloadJson(jwtPayload, "smart_contract_address")
val provider = "dauth."+getFieldFromPayloadJson(jwtPayload, "network_name")
logger.debug("login_user_name: " + userName)
for {
tuple <-
Users.users.vend.getUserByProviderId(provider = providerHardCodePrefixDauth, idGivenByProvider = username).or { // Find a user
Users.users.vend.createResourceUser( // Otherwise create a new one
provider = providerHardCodePrefixDauth,
providerId = Some(username),
None,
name = Some(username),
email = None,
userId = None,
createdByUserInvitationId = None,
company = None,
lastMarketingAgreementSignedDate = None
)
} match {
tuple <-
UserX.getOrCreateDauthResourceUser(userName, provider) match {
case Full(u) =>
Full((u,callContext)) // Return user
case Empty =>
@ -168,17 +155,16 @@ object DAuth extends RestHelper with MdcLoggable {
}
def getOrCreateResourceUserFuture(jwtPayload: String, callContext: Option[CallContext]) : Future[Box[(User, Option[CallContext])]] = {
val username = getFieldFromPayloadJson(jwtPayload, "smart_contract_address")
val provider = getFieldFromPayloadJson(jwtPayload, "network_name")
val providerHardCodePrefixDauth = "dauth."+provider
val provider = "dauth."+ getFieldFromPayloadJson(jwtPayload, "network_name")
logger.debug("login_user_name: " + username)
for {
tuple <-
Users.users.vend.getOrCreateUserByProviderIdFuture(provider = providerHardCodePrefixDauth, idGivenByProvider = username, consentId = None, name = Some(username), email = None) map {
case (Full(u), _) =>
tuple <- Future { UserX.getOrCreateDauthResourceUser(username, provider)} map {
case (Full(u)) =>
Full(u, callContext) // Return user
case (Empty, _) =>
case (Empty) =>
Failure(ErrorMessages.DAuthCannotGetOrCreateUser)
case (Failure(msg, t, c), _) =>
case (Failure(msg, t, c)) =>
Failure(msg, t, c)
case _ =>
Failure(ErrorMessages.DAuthUnknownError)

View File

@ -1201,8 +1201,8 @@ object ExampleValue {
lazy val productAttributeIdExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
glossaryItems += makeGlossaryItem("product_attribute_id", productAttributeIdExample)
lazy val isSystemExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
glossaryItems += makeGlossaryItem("is_system", isSystemExample)
lazy val isSystemExample = ConnectorField("true", "If the view is the system level, then it is true")
glossaryItems += makeGlossaryItem("view.is_system", isSystemExample)
lazy val detailsExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
glossaryItems += makeGlossaryItem("details", detailsExample)
@ -1309,7 +1309,7 @@ object ExampleValue {
lazy val webUiPropsIdExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
glossaryItems += makeGlossaryItem("web_ui_props_id", webUiPropsIdExample)
lazy val providerExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
lazy val providerExample = ConnectorField("ETHEREUM","the provider name ")
glossaryItems += makeGlossaryItem("provider", providerExample)
lazy val canSeePhysicalLocationExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)

View File

@ -1034,21 +1034,9 @@ object NewStyle {
}
}
def getOrCreateUser(userId: String, provider: String, callContext: Option[CallContext]): OBPReturnType[User] = {
Future { UserX.findByUserId(userId).or( //first try to find the user by userId
Users.users.vend.createResourceUser( // Otherwise create a new user
provider = provider,
providerId = Some(userId),
None,
name = Some(userId),
email = None,
userId = Some(userId),
createdByUserInvitationId = None,
company = None,
lastMarketingAgreementSignedDate = None
)
).map(user =>(user, callContext))} map {
unboxFullOrFail(_, callContext, s"$CannotGetOrCreateUser Current USER_ID($userId) PROVIDER ($provider)", 404)
def getOrCreateResourceUser(username: String, provider: String, callContext: Option[CallContext]): OBPReturnType[User] = {
Future { UserX.getOrCreateDauthResourceUser(username, provider).map(user =>(user, callContext))} map {
unboxFullOrFail(_, callContext, s"$CannotGetOrCreateUser Current USERName($username) PROVIDER ($provider)", 404)
}
}

View File

@ -2747,7 +2747,7 @@ trait APIMethods400 {
s"""
|This endpoint is used as part of the DAuth solution to grant Entitlements for Roles to a smart contract on the blockchain.
|
|Put the smart contract address in user_id
|Put the smart contract address in username
|
|For provider use "dauth"
|
@ -2801,11 +2801,6 @@ trait APIMethods400 {
postedData.provider.startsWith("dauth.")
}
//user_id set the length for the min length of the userId. eg: 36
_ <- Helper.booleanToFuture(s"$InvalidUserId The user.user_id length must be at least 36. ", cc=Some(cc)) {
postedData.user_id.length>=36
}
//check the system role bankId is Empty, but bank level role need bankId
_ <- checkRoleBankIdMappings(callContext, postedData)
@ -2815,7 +2810,7 @@ trait APIMethods400 {
canCreateEntitlementAtAnyBankRole = Entitlement.entitlement.vend.getEntitlement("", loggedInUser.userId, canCreateEntitlementAtAnyBank.toString())
(targetUser, callContext) <- NewStyle.function.getOrCreateUser(postedData.user_id, postedData.provider, callContext)
(targetUser, callContext) <- NewStyle.function.getOrCreateResourceUser(postedData.username, postedData.provider, callContext)
_ <- if (canCreateEntitlementAtAnyBankRole.isDefined) {
//If the loggedIn User has `CanCreateEntitlementAtAnyBankRole` role, then we can grant all the requestRoles to the requestUser.
@ -2827,7 +2822,7 @@ trait APIMethods400 {
assertUserCanGrantRoles(loggedInUser.userId, postedData.roles, callContext)
}
addedEntitlements <- addEntitlementsToUser(postedData, callContext)
addedEntitlements <- addEntitlementsToUser(targetUser.userId, postedData, callContext)
} yield {
(JSONFactory400.createEntitlementJSONs(addedEntitlements), HttpCode.`201`(callContext))
@ -4278,7 +4273,7 @@ trait APIMethods400 {
"Create (DAuth) User with Account Access",
s"""This endpoint is used as part of the DAuth solution to grant access to account and transaction data to a smart contract on the blockchain.
|
|Put the smart contract address in user_id
|Put the smart contract address in username
|
|For provider use "dauth"
|
@ -4291,7 +4286,7 @@ trait APIMethods400 {
|${getGlossaryItem("DAuth")}
|
|""",
postCreateUserWithRolesJsonV400,
postCreateUserAccountAccessJsonV400,
List(viewJsonV300),
List(
$UserNotLoggedIn,
@ -4317,15 +4312,10 @@ trait APIMethods400 {
postJson.provider.startsWith("dauth.")
}
//user_id set the length for the min length of the userId. eg: 36
_ <- Helper.booleanToFuture(s"$InvalidUserId The user.user_id length must be at least 36. ", cc=Some(cc)) {
postJson.user_id.length>=36
}
_ <- NewStyle.function.canGrantAccessToView(bankId, accountId, cc.loggedInUser, cc.callContext)
(user, callContext) <- NewStyle.function.getOrCreateUser(postJson.user_id, postJson.provider, cc.callContext)
(targetUser, callContext) <- NewStyle.function.getOrCreateResourceUser(postJson.username, postJson.provider, cc.callContext)
views <- getViews(bankId, accountId, postJson, callContext)
addedView <- createAccountAccessesToUser(bankId, accountId, user, views, callContext)
addedView <- createAccountAccessesToUser(bankId, accountId, targetUser, views, callContext)
} yield {
val viewsJson = addedView.map(JSONFactory300.createViewJSON(_))
(viewsJson, HttpCode.`201`(callContext))
@ -10963,8 +10953,8 @@ trait APIMethods400 {
Future(Entitlement.entitlement.vend.addEntitlement(entitlement.bank_id, userId, entitlement.role_name)) map { unboxFull(_) }
}
private def addEntitlementsToUser(postedData: PostCreateUserWithRolesJsonV400, callContext: Option[CallContext]) = {
Future.sequence(postedData.roles.distinct.map(addEntitlementToUser(postedData.user_id, _, callContext)))
private def addEntitlementsToUser(userId:String, postedData: PostCreateUserWithRolesJsonV400, callContext: Option[CallContext]) = {
Future.sequence(postedData.roles.distinct.map(addEntitlementToUser(userId, _, callContext)))
}
/**

View File

@ -354,8 +354,8 @@ case class StandingOrderJsonV400(standing_order_id: String,
active: Boolean)
case class PostViewJsonV400(view_id: String, is_system: Boolean)
case class PostAccountAccessJsonV400(user_id: String, view: PostViewJsonV400)
case class PostCreateUserAccountAccessJsonV400(user_id: String, provider:String, views: List[PostViewJsonV400])
case class PostCreateUserWithRolesJsonV400(user_id: String, provider:String, roles: List[CreateEntitlementJSON])
case class PostCreateUserAccountAccessJsonV400(username: String, provider:String, views: List[PostViewJsonV400])
case class PostCreateUserWithRolesJsonV400(username: String, provider:String, roles: List[CreateEntitlementJSON])
case class PostRevokeGrantAccountAccessJsonV400(views: List[String])
case class RevokedJsonV400(revoked: Boolean)

View File

@ -141,6 +141,22 @@ object UserX {
def saveResourceUser(ru: ResourceUser) = {
Users.users.vend.saveResourceUser(ru)
}
def getOrCreateDauthResourceUser(username: String, provider: String) = {
findByUserName(username).or( //first try to find the user by userId
Users.users.vend.createResourceUser( // Otherwise create a new user
provider = provider,
providerId = Some(username),
None,
name = Some(username),
email = None,
userId = None,
createdByUserInvitationId = None,
company = None,
lastMarketingAgreementSignedDate = None
)
)
}
//def bulkDeleteAllResourceUsers(): Box[Boolean] = {
// Users.users.vend.bulkDeleteAllResourceUsers()

View File

@ -39,8 +39,8 @@ class DirectLoginTest extends ServerSetup with BeforeAndAfter {
val EMAIL = randomString(10).toLowerCase + "@example.com"
val USERNAME = "username with spaces"
//these are password, but sonarcloud: "password" detected here, make sure this is not a hard-coded credential.
val NO_EXISTING_PD = "notExistingPassword"
val VALID_PD = """G!y"k9GHD$D"""
val NO_EXISTING_PW = "notExistingPassword"
val VALID_PW = """G!y"k9GHD$D"""
val KEY_DISABLED = randomString(40).toLowerCase
val SECRET_DISABLED = randomString(40).toLowerCase
@ -53,7 +53,7 @@ class DirectLoginTest extends ServerSetup with BeforeAndAfter {
AuthUser.create.
email(EMAIL).
username(USERNAME).
password(VALID_PD).
password(VALID_PW).
validated(true).
firstName(randomString(10)).
lastName(randomString(10)).
@ -80,22 +80,22 @@ class DirectLoginTest extends ServerSetup with BeforeAndAfter {
val accessControlOriginHeader = ("Access-Control-Allow-Origin", "*")
val invalidUsernamePasswordHeader = ("Authorization", ("DirectLogin username=\"notExistingUser\", " +
"password=%s, consumer_key=%s").format(NO_EXISTING_PD, KEY))
"password=%s, consumer_key=%s").format(NO_EXISTING_PW, KEY))
val invalidUsernamePasswordCharaterHeader = ("Authorization", ("DirectLogin username=\" a#s \", " +
"password=%s, consumer_key=%s").format(NO_EXISTING_PD, KEY))
"password=%s, consumer_key=%s").format(NO_EXISTING_PW, KEY))
val validUsernameInvalidPasswordHeader = ("Authorization", ("DirectLogin username=%s," +
"password=%s, consumer_key=%s").format(USERNAME, NO_EXISTING_PD, KEY))
"password=%s, consumer_key=%s").format(USERNAME, NO_EXISTING_PW, KEY))
val invalidConsumerKeyHeader = ("Authorization", ("DirectLogin username=%s, " +
"password=%s, consumer_key=%s").format(USERNAME, VALID_PD, "invalid"))
"password=%s, consumer_key=%s").format(USERNAME, VALID_PW, "invalid"))
val validDeprecatedHeader = ("Authorization", "DirectLogin username=%s, password=%s, consumer_key=%s".
format(USERNAME, VALID_PD, KEY))
format(USERNAME, VALID_PW, KEY))
val validHeader = ("DirectLogin", "username=%s, password=%s, consumer_key=%s".
format(USERNAME, VALID_PD, KEY))
format(USERNAME, VALID_PW, KEY))
val disabledConsumerValidHeader = ("Authorization", "DirectLogin username=%s, password=%s, consumer_key=%s".
format(USERNAME_DISABLED, PASSWORD_DISABLED, KEY_DISABLED))
@ -344,7 +344,7 @@ class DirectLoginTest extends ServerSetup with BeforeAndAfter {
scenario("Login with correct everything but the user is locked", ApiEndpoint1, ApiEndpoint2) {
lazy val username = "firstname.lastname"
lazy val header = ("DirectLogin", "username=%s, password=%s, consumer_key=%s".
format(username, VALID_PD, KEY))
format(username, VALID_PW, KEY))
// Delete the user
AuthUser.findUserByUsernameLocally(username).map(_.delete_!())
@ -352,7 +352,7 @@ class DirectLoginTest extends ServerSetup with BeforeAndAfter {
AuthUser.create.
email(EMAIL).
username(username).
password(VALID_PD).
password(VALID_PW).
validated(true).
firstName(randomString(10)).
lastName(randomString(10)).

View File

@ -143,7 +143,7 @@ class EntitlementTests extends V400ServerSetupAsync with DefaultUsers {
bank_id = testBankId1.value,
role_name = CanUpdateBranch.toString()
))
val postJson = SwaggerDefinitionsJSON.postCreateUserWithRolesJsonV400.copy(user_id ="xx", roles= createEntitlements)
val postJson = SwaggerDefinitionsJSON.postCreateUserWithRolesJsonV400.copy(username ="xx", roles= createEntitlements)
val requestGet = (v4_0_0_Request / "user-entitlements").GET <@ (user1)
val responseGet = makePostRequestAsync(requestGet, write(postJson))
Then("We should get a 200")