Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove user-management error cases from scenario-service proto. #12460

Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -354,11 +354,6 @@ prettyScenarioErrorError (Just err) = do
ScenarioErrorErrorScenarioPartyAlreadyExists name ->
pure $ "Tried to allocate a party that already exists: " <-> ltext name

ScenarioErrorErrorScenarioUserNotFound userId ->
pure $ "User not found: " <-> ltext userId
ScenarioErrorErrorScenarioUserAlreadyExists userId ->
pure $ "User already exists: " <-> ltext userId

ScenarioErrorErrorScenarioContractNotVisible ScenarioError_ContractNotVisible{..} ->
pure $ vcat
[ "Attempt to fetch or exercise a contract not visible to the reading parties."
Expand Down
2 changes: 0 additions & 2 deletions compiler/scenario-service/protos/scenario_service.proto
Original file line number Diff line number Diff line change
Expand Up @@ -279,8 +279,6 @@ message ScenarioError {
Empty ComparableValueError = 29;
ContractIdInContractKey contract_id_in_contract_key = 30;
Empty ValueExceedsMaxNesting = 31;
string scenario_user_not_found = 33;
string scenario_user_already_exists = 34;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,14 +249,6 @@ final class Conversions(

case Error.PartyAlreadyExists(party) =>
builder.setScenarioPartyAlreadyExists(party)

case Error.UserManagement(err) =>
err match {
case Error.UserManagementError.UserNotFound(userId) =>
builder.setScenarioUserNotFound(userId)
case Error.UserManagementError.UserExists(userId) =>
builder.setScenarioUserAlreadyExists(userId)
}
}
builder.build
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
package com.daml.lf
package scenario

import com.daml.lf.data.Ref.{Identifier, Party, UserId}
import com.daml.lf.data.Ref.{Identifier, Party}
import com.daml.lf.data.Time
import com.daml.lf.ledger.EventId
import com.daml.lf.speedy.SError.SError
Expand Down Expand Up @@ -74,13 +74,4 @@ object Error {

/** Tried to allocate a party that already exists. */
final case class PartyAlreadyExists(name: String) extends Error

final case class UserManagement(error: UserManagementError) extends Error

sealed abstract class UserManagementError extends Product with Serializable

object UserManagementError {
final case class UserNotFound(userId: UserId) extends UserManagementError
final case class UserExists(userId: UserId) extends UserManagementError
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,6 @@ private[lf] object Pretty {

case Error.PartyAlreadyExists(party) =>
text(s"Error: Tried to allocate a party that already exists: $party")

case Error.UserManagement(err) => prettyError(err)
}

def prettyError(err: Error.UserManagementError) = err match {
case Error.UserManagementError.UserNotFound(userId) =>
text(s"Error: User with id $userId does not exist")
case Error.UserManagementError.UserExists(userId) =>
text(s"Error: Tried to create a user id $userId but such a user already exists")
}

}
1 change: 0 additions & 1 deletion daml-script/runner/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ da_scala_test(
deps = [
":script-runner-lib",
"//daml-lf/data",
"//daml-lf/scenario-interpreter",
"//language-support/scala/bindings",
"//language-support/scala/bindings-akka",
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,6 @@ class IdeLedgerClient(

private val userManagementStore = new ide.UserManagementStore()

private def handleUserManagement[T](r: ide.UserManagementStore.Result[T]): Future[T] =
r.fold(err => Future.failed(scenario.Error.UserManagement(err)), Future.successful(_))

override def query(parties: OneAnd[Set, Ref.Party], templateId: Identifier)(implicit
ec: ExecutionContext,
mat: Materializer,
Expand Down Expand Up @@ -323,37 +320,28 @@ class IdeLedgerClient(
esf: ExecutionSequencerFactory,
mat: Materializer,
): Future[Option[Unit]] =
userManagementStore.createUser(user, rights.toSet) match {
case Left(scenario.Error.UserManagementError.UserExists(_)) => Future.successful(None)
case a => handleUserManagement(a).map(Some(_))
}
Future.successful(userManagementStore.createUser(user, rights.toSet))

override def getUser(id: UserId)(implicit
ec: ExecutionContext,
esf: ExecutionSequencerFactory,
mat: Materializer,
): Future[Option[User]] =
userManagementStore.getUser(id) match {
case Left(scenario.Error.UserManagementError.UserNotFound(_)) => Future.successful(None)
case a => handleUserManagement(a).map(Some(_))
}
Future.successful(userManagementStore.getUser(id))

override def deleteUser(id: UserId)(implicit
ec: ExecutionContext,
esf: ExecutionSequencerFactory,
mat: Materializer,
): Future[Option[Unit]] =
userManagementStore.deleteUser(id) match {
case Left(scenario.Error.UserManagementError.UserNotFound(_)) => Future.successful(None)
case a => handleUserManagement(a).map(Some(_))
}
Future.successful(userManagementStore.deleteUser(id))

override def listUsers()(implicit
ec: ExecutionContext,
esf: ExecutionSequencerFactory,
mat: Materializer,
): Future[List[User]] =
handleUserManagement(userManagementStore.listUsers())
Future.successful(userManagementStore.listUsers())

override def grantUserRights(
id: UserId,
Expand All @@ -363,10 +351,7 @@ class IdeLedgerClient(
esf: ExecutionSequencerFactory,
mat: Materializer,
): Future[Option[List[UserRight]]] =
userManagementStore.grantRights(id, rights.toSet) match {
case Left(scenario.Error.UserManagementError.UserNotFound(_)) => Future.successful(None)
case a => handleUserManagement(a).map(_.toList).map(Some(_))
}
Future.successful(userManagementStore.grantRights(id, rights.toSet).map(_.toList))

override def revokeUserRights(
id: UserId,
Expand All @@ -376,18 +361,12 @@ class IdeLedgerClient(
esf: ExecutionSequencerFactory,
mat: Materializer,
): Future[Option[List[UserRight]]] =
userManagementStore.revokeRights(id, rights.toSet) match {
case Left(scenario.Error.UserManagementError.UserNotFound(_)) => Future.successful(None)
case a => handleUserManagement(a).map(_.toList).map(Some(_))
}
Future.successful(userManagementStore.revokeRights(id, rights.toSet).map(_.toList))

override def listUserRights(id: UserId)(implicit
ec: ExecutionContext,
esf: ExecutionSequencerFactory,
mat: Materializer,
): Future[Option[List[UserRight]]] =
userManagementStore.listUserRights(id) match {
case Left(scenario.Error.UserManagementError.UserNotFound(_)) => Future.successful(None)
case a => handleUserManagement(a).map(_.toList).map(Some(_))
}
Future.successful(userManagementStore.listUserRights(id).map(_.toList))
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
package com.daml.lf.engine.script.ledgerinteraction.ide

import com.daml.lf.data.Ref.UserId
import com.daml.lf.scenario.Error.UserManagementError
import com.daml.ledger.api.domain.{User, UserRight}

import scala.collection.mutable
Expand All @@ -15,55 +14,54 @@ import scala.collection.mutable
// #11896. While it would be nice to not have to duplicate this for now this seems like the
// simpler option than trying to reuse participant code in the script service.
private[ledgerinteraction] class UserManagementStore {
import UserManagementError._
import UserManagementStore._

def createUser(user: User, rights: Set[UserRight]): Result[Unit] =
def createUser(user: User, rights: Set[UserRight]): Option[Unit] =
putIfAbsent(UserInfo(user, rights)) match {
case Some(_) => Left(UserExists(user.id))
case None => Right(())
case Some(_) => None
case None => Some(())
}

def getUser(id: UserId): Result[User] =
def getUser(id: UserId): Option[User] =
lookup(id) match {
case Some(userInfo) => Right(userInfo.user)
case None => Left(UserNotFound(id))
case Some(userInfo) => Some(userInfo.user)
case None => None
}

def deleteUser(id: UserId): Result[Unit] =
def deleteUser(id: UserId): Option[Unit] =
dropExisting(id) match {
case Some(_) => Right(())
case None => Left(UserNotFound(id))
case Some(_) => Some(())
case None => None
}

def grantRights(id: UserId, granted: Set[UserRight]): Result[Set[UserRight]] =
def grantRights(id: UserId, granted: Set[UserRight]): Option[Set[UserRight]] =
lookup(id) match {
case Some(userInfo) =>
val newlyGranted = granted.diff(userInfo.rights)
replaceInfo(userInfo, userInfo.copy(rights = userInfo.rights ++ newlyGranted))
Right(newlyGranted)
Some(newlyGranted)
case None =>
Left(UserNotFound(id))
None
}

def revokeRights(id: UserId, revoked: Set[UserRight]): Result[Set[UserRight]] =
def revokeRights(id: UserId, revoked: Set[UserRight]): Option[Set[UserRight]] =
lookup(id) match {
case Some(userInfo) =>
val effectivelyRevoked = revoked.intersect(userInfo.rights)
replaceInfo(userInfo, userInfo.copy(rights = userInfo.rights -- effectivelyRevoked))
Right(effectivelyRevoked)
Some(effectivelyRevoked)
case None =>
Left(UserNotFound(id))
None
}

def listUserRights(id: UserId): Result[Set[UserRight]] =
def listUserRights(id: UserId): Option[Set[UserRight]] =
lookup(id) match {
case Some(userInfo) => Right(userInfo.rights)
case None => Left(UserNotFound(id))
case Some(userInfo) => Some(userInfo.rights)
case None => None
}

def listUsers(): Result[List[User]] =
Right(state.values.map(_.user).toList)
def listUsers(): List[User] =
state.values.map(_.user).toList

private val state: mutable.Map[UserId, UserInfo] = mutable.Map()
private def lookup(id: UserId) = state.get(id)
Expand All @@ -89,5 +87,4 @@ object UserManagementStore {
case class UserInfo(user: User, rights: Set[UserRight]) {
def toStateEntry: (UserId, UserInfo) = user.id -> this
}
type Result[T] = Either[UserManagementError, T]
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ package com.daml.lf.engine.script.ledgerinteraction.ide

import com.daml.ledger.api.domain.{User, UserRight}
import com.daml.lf.data.Ref.{Party, UserId}
import com.daml.lf.scenario.Error.UserManagementError._
import org.scalatest.matchers.should.Matchers
import org.scalatest.freespec.AnyFreeSpec
import scala.language.implicitConversions
Expand Down Expand Up @@ -34,7 +33,7 @@ final class InMemoryUserManagementStoreSpec extends AnyFreeSpec with Matchers {
val mgmt = new UserManagementStore()
val user = User("user1", None)
mgmt.createUser(user, Set.empty) shouldBe Right(())
mgmt.createUser(user, Set.empty) shouldBe Left(UserExists("user1"))
mgmt.createUser(user, Set.empty) shouldBe Left(())
}

"find a freshly created user" in {
Expand All @@ -46,15 +45,15 @@ final class InMemoryUserManagementStoreSpec extends AnyFreeSpec with Matchers {

"not find a non-existent user" in {
val mgmt = new UserManagementStore()
mgmt.getUser("user1") shouldBe Left(UserNotFound("user1"))
mgmt.getUser("user1") shouldBe Left(())
}
"not find a deleted user" in {
val mgmt = new UserManagementStore()
val user = User("user1", None)
mgmt.createUser(user, Set.empty) shouldBe Right(())
mgmt.getUser("user1") shouldBe Right(user)
mgmt.deleteUser("user1") shouldBe Right(())
mgmt.getUser("user1") shouldBe Left(UserNotFound("user1"))
mgmt.getUser("user1") shouldBe Left(())
}
"allow recreating a deleted user" in {
val mgmt = new UserManagementStore()
Expand All @@ -65,7 +64,7 @@ final class InMemoryUserManagementStoreSpec extends AnyFreeSpec with Matchers {
}
"fail to delete a non-existent user" in {
val mgmt = new UserManagementStore()
mgmt.deleteUser("user1") shouldBe Left(UserNotFound("user1"))
mgmt.deleteUser("user1") shouldBe Left(())
}
"list created users" in {
val mgmt = new UserManagementStore()
Expand Down Expand Up @@ -103,7 +102,7 @@ final class InMemoryUserManagementStoreSpec extends AnyFreeSpec with Matchers {
}
"listUserRights should fail on non-existent user" in {
val mgmt = new UserManagementStore()
mgmt.listUserRights("user1") shouldBe Left(UserNotFound("user1"))
mgmt.listUserRights("user1") shouldBe Left(())
}
"grantUserRights should add new rights" in {
val mgmt = new UserManagementStore()
Expand All @@ -119,7 +118,7 @@ final class InMemoryUserManagementStoreSpec extends AnyFreeSpec with Matchers {
}
"grantRights should fail on non-existent user" in {
val mgmt = new UserManagementStore()
mgmt.grantRights("user1", Set.empty) shouldBe Left(UserNotFound("user1"))
mgmt.grantRights("user1", Set.empty) shouldBe Left(())
}
"revokeRights should revoke rights" in {
val mgmt = new UserManagementStore()
Expand All @@ -140,7 +139,7 @@ final class InMemoryUserManagementStoreSpec extends AnyFreeSpec with Matchers {
}
"revokeRights should fail on non-existent user" in {
val mgmt = new UserManagementStore()
mgmt.revokeRights("user1", Set.empty) shouldBe Left(UserNotFound("user1"))
mgmt.revokeRights("user1", Set.empty) shouldBe Left(())
}
}
}