Skip to content

Commit

Permalink
[JSON-API] User management endpoint adjustments (#12578)
Browse files Browse the repository at this point in the history
* Return an empty object for deleteUser & createUser

* Make the field rights for creating a user optional & fix the tests

changelog_begin

- [HTTP-JSON] Adjusted the response for the createUser & deleteUser endpoint to an empty object instead of "true". This was done to allow possible future extensions to the return type without applying breaking changes.
- [HTTP-JSON] Made the field rights optional for the request body of the createUser endpoint. Now it is possible to create a user with just the userId (i.e. { "userId": "nice.user" }).

changelog_end
  • Loading branch information
realvictorprm authored Jan 31, 2022
1 parent 54c427f commit 8d5d3bd
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -259,14 +259,15 @@ class HttpServiceIntegrationTestUserManagementNoAuth
participantAdminJwt
) { (uri, _, _, _, _) =>
import spray.json._
import spray.json.DefaultJsonProtocol._
val alice = getUniqueParty("Alice")
val createUserRequest = domain.CreateUserRequest(
"nice.user2",
Some(alice.unwrap),
List[domain.UserRight](
domain.CanActAs(alice),
domain.ParticipantAdmin,
Some(
List[domain.UserRight](
domain.CanActAs(alice),
domain.ParticipantAdmin,
)
),
)
for {
Expand All @@ -275,11 +276,39 @@ class HttpServiceIntegrationTestUserManagementNoAuth
createUserRequest.toJson,
headers = authorizationHeader(participantAdminJwt),
)
assertion <- {
status shouldBe StatusCodes.OK
getResult(output).convertTo[Boolean] shouldBe true
}
} yield assertion
} yield {
status shouldBe StatusCodes.OK
getResult(output) shouldBe JsObject()
}
}

"creating a user with default values should be possible via the user/create endpoint" in withHttpServiceAndClient(
participantAdminJwt
) { (uri, _, _, _, _) =>
import spray.json._
val username = getUniqueUserName("nice.user")
for {
(status, output) <- postRequest(
uri.withPath(Uri.Path("/v1/user/create")),
JsObject("userId" -> JsString(username)),
headers = authorizationHeader(participantAdminJwt),
)
_ <- status shouldBe StatusCodes.OK
(status2, output2) <- postRequest(
uri.withPath(Uri.Path("/v1/user")),
domain.GetUserRequest(username).toJson,
headers = authorizationHeader(participantAdminJwt),
)
_ <- status2 shouldBe StatusCodes.OK
_ <- getResult(output2).convertTo[UserDetails] shouldEqual UserDetails(username, None)
(status3, output3) <- postRequest(
uri.withPath(Uri.Path("/v1/user/rights")),
domain.ListUserRightsRequest(username).toJson,
headers = authorizationHeader(participantAdminJwt),
)
_ <- status3 shouldBe StatusCodes.OK
} yield getResult(output3)
.convertTo[List[domain.UserRight]] shouldEqual List.empty
}

"getting all users should be possible via the users endpoint" in withHttpServiceAndClient(
Expand All @@ -295,9 +324,11 @@ class HttpServiceIntegrationTestUserManagementNoAuth
domain.CreateUserRequest(
name,
Some(alice.unwrap),
List[domain.UserRight](
domain.CanActAs(alice),
domain.ParticipantAdmin,
Some(
List[domain.UserRight](
domain.CanActAs(alice),
domain.ParticipantAdmin,
)
),
)
)
Expand Down Expand Up @@ -325,14 +356,15 @@ class HttpServiceIntegrationTestUserManagementNoAuth
participantAdminJwt
) { (uri, _, _, _, _) =>
import spray.json._
import spray.json.DefaultJsonProtocol._
val alice = getUniqueParty("Alice")
val createUserRequest = domain.CreateUserRequest(
getUniqueUserName("nice.user"),
Some(alice.unwrap),
List[domain.UserRight](
domain.CanActAs(alice),
domain.ParticipantAdmin,
Some(
List[domain.UserRight](
domain.CanActAs(alice),
domain.ParticipantAdmin,
)
),
)
for {
Expand All @@ -343,7 +375,7 @@ class HttpServiceIntegrationTestUserManagementNoAuth
)
_ <- {
status1 shouldBe StatusCodes.OK
getResult(output1).convertTo[Boolean] shouldBe true
getResult(output1) shouldBe JsObject()
}
(status2, output2) <- postRequest(
uri.withPath(Uri.Path(s"/v1/user")),
Expand All @@ -363,14 +395,15 @@ class HttpServiceIntegrationTestUserManagementNoAuth
participantAdminJwt
) { (uri, _, _, _, _) =>
import spray.json._
import spray.json.DefaultJsonProtocol._
val alice = getUniqueParty("Alice")
val createUserRequest = domain.CreateUserRequest(
getUniqueUserName("nice.user"),
Some(alice.unwrap),
List[domain.UserRight](
domain.CanActAs(alice),
domain.ParticipantAdmin,
Some(
List[domain.UserRight](
domain.CanActAs(alice),
domain.ParticipantAdmin,
)
),
)
for {
Expand All @@ -381,7 +414,7 @@ class HttpServiceIntegrationTestUserManagementNoAuth
)
_ <- {
status1 shouldBe StatusCodes.OK
getResult(output1).convertTo[Boolean] shouldBe true
getResult(output1) shouldBe JsObject()
}
(status2, output2) <- getRequest(
uri.withPath(Uri.Path(s"/v1/user")),
Expand All @@ -405,9 +438,11 @@ class HttpServiceIntegrationTestUserManagementNoAuth
val createUserRequest = domain.CreateUserRequest(
getUniqueUserName("nice.user"),
Some(alice.unwrap),
List[domain.UserRight](
domain.CanActAs(alice),
domain.ParticipantAdmin,
Some(
List[domain.UserRight](
domain.CanActAs(alice),
domain.ParticipantAdmin,
)
),
)
for {
Expand All @@ -418,7 +453,7 @@ class HttpServiceIntegrationTestUserManagementNoAuth
)
_ <- {
status1 shouldBe StatusCodes.OK
getResult(output1).convertTo[Boolean] shouldBe true
getResult(output1) shouldBe JsObject()
}
(status2, _) <- postRequest(
uri.withPath(Uri.Path(s"/v1/user/delete")),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -484,12 +484,12 @@ class Endpoints(

def deleteUser(req: HttpRequest)(implicit
lc: LoggingContextOf[InstanceUUID with RequestID]
): ET[domain.SyncResponse[Boolean]] =
): ET[domain.SyncResponse[spray.json.JsObject]] =
proxyWithCommandET { (jwt, deleteUserRequest: domain.DeleteUserRequest) =>
for {
userId <- parseUserId(deleteUserRequest.userId)
_ <- EitherT.rightT(userManagementClient.deleteUser(userId, Some(jwt.value)))
} yield domain.OkResponse(true): domain.SyncResponse[Boolean]
} yield emptyObjectResponse
}(req)

def listUsers(req: HttpRequest)(implicit
Expand Down Expand Up @@ -596,7 +596,7 @@ class Endpoints(

def createUser(req: HttpRequest)(implicit
lc: LoggingContextOf[InstanceUUID with RequestID]
): ET[domain.SyncResponse[Boolean]] =
): ET[domain.SyncResponse[spray.json.JsObject]] =
proxyWithCommand { (jwt, createUserRequest: domain.CreateUserRequest) =>
{
import scalaz.std.option._
Expand All @@ -609,7 +609,9 @@ class Endpoints(
primaryParty <- createUserRequest.primaryParty.traverse(it =>
Ref.Party.fromString(it).disjunction
)
rights <- domain.UserRights.toLedgerUserRights(createUserRequest.rights)
rights <- domain.UserRights.toLedgerUserRights(
createUserRequest.rights.getOrElse(List.empty)
)
} yield (username, primaryParty, rights)
for {
info <- EitherT.either(input.leftMap(InvalidUserInput)): ET[
Expand All @@ -623,7 +625,7 @@ class Endpoints(
Some(jwt.value),
)
)
} yield domain.OkResponse(true): domain.SyncResponse[Boolean]
} yield emptyObjectResponse
}.run
}(req)

Expand Down Expand Up @@ -926,6 +928,9 @@ class Endpoints(
UserId.fromString(rawUserId).disjunction.leftMap(InvalidUserInput)
)
}

private val emptyObjectResponse: domain.SyncResponse[spray.json.JsObject] =
domain.OkResponse(spray.json.JsObject())
}

object Endpoints {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ object domain extends com.daml.fetchcontracts.domain.Aliases {
final case class CreateUserRequest(
userId: String,
primaryParty: Option[String],
rights: List[UserRight],
rights: Option[List[UserRight]],
)

final case class ListUserRightsRequest(userId: String)
Expand Down

0 comments on commit 8d5d3bd

Please sign in to comment.