use std::convert::TryFrom;
use crate::data::party::DamlObjectMeta;
use crate::data::{DamlError, DamlResult};
use crate::grpc_protobuf::com::daml::ledger::api::v2::admin::{Right, User, right};
use crate::util::Required;
#[derive(Debug, Eq, PartialEq, Clone, Default)]
pub struct DamlUser {
pub id: String,
pub primary_party: String,
pub is_deactivated: bool,
pub metadata: Option<DamlObjectMeta>,
pub identity_provider_id: String,
pub primary_party_authentication: bool,
}
impl From<User> for DamlUser {
fn from(u: User) -> Self {
Self {
id: u.id,
primary_party: u.primary_party,
is_deactivated: u.is_deactivated,
metadata: u.metadata.map(DamlObjectMeta::from),
identity_provider_id: u.identity_provider_id,
primary_party_authentication: u.primary_party_authentication,
}
}
}
impl From<DamlUser> for User {
fn from(u: DamlUser) -> Self {
Self {
id: u.id,
primary_party: u.primary_party,
is_deactivated: u.is_deactivated,
metadata: u.metadata.map(Into::into),
identity_provider_id: u.identity_provider_id,
primary_party_authentication: u.primary_party_authentication,
}
}
}
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
pub enum DamlUserRight {
ParticipantAdmin,
CanActAs(String),
CanReadAs(String),
CanExecuteAs(String),
IdentityProviderAdmin,
CanReadAsAnyParty,
CanExecuteAsAnyParty,
}
impl From<DamlUserRight> for Right {
fn from(r: DamlUserRight) -> Self {
let kind = match r {
DamlUserRight::ParticipantAdmin => right::Kind::ParticipantAdmin(right::ParticipantAdmin {}),
DamlUserRight::CanActAs(party) => right::Kind::CanActAs(right::CanActAs {
party,
}),
DamlUserRight::CanReadAs(party) => right::Kind::CanReadAs(right::CanReadAs {
party,
}),
DamlUserRight::CanExecuteAs(party) => right::Kind::CanExecuteAs(right::CanExecuteAs {
party,
}),
DamlUserRight::IdentityProviderAdmin => right::Kind::IdentityProviderAdmin(right::IdentityProviderAdmin {}),
DamlUserRight::CanReadAsAnyParty => right::Kind::CanReadAsAnyParty(right::CanReadAsAnyParty {}),
DamlUserRight::CanExecuteAsAnyParty => right::Kind::CanExecuteAsAnyParty(right::CanExecuteAsAnyParty {}),
};
Self {
kind: Some(kind),
}
}
}
impl TryFrom<Right> for DamlUserRight {
type Error = DamlError;
fn try_from(r: Right) -> DamlResult<Self> {
match r.kind.req()? {
right::Kind::ParticipantAdmin(_) => Ok(Self::ParticipantAdmin),
right::Kind::CanActAs(r) => Ok(Self::CanActAs(r.party)),
right::Kind::CanReadAs(r) => Ok(Self::CanReadAs(r.party)),
right::Kind::CanExecuteAs(r) => Ok(Self::CanExecuteAs(r.party)),
right::Kind::IdentityProviderAdmin(_) => Ok(Self::IdentityProviderAdmin),
right::Kind::CanReadAsAnyParty(_) => Ok(Self::CanReadAsAnyParty),
right::Kind::CanExecuteAsAnyParty(_) => Ok(Self::CanExecuteAsAnyParty),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
fn sample_user() -> DamlUser {
DamlUser {
id: "user-x".to_owned(),
primary_party: "Alice::participant".to_owned(),
is_deactivated: true,
metadata: Some(DamlObjectMeta {
resource_version: "v7".to_owned(),
annotations: std::iter::once(("k".to_owned(), "v".to_owned())).collect(),
}),
identity_provider_id: "idp-1".to_owned(),
primary_party_authentication: true,
}
}
#[test]
fn user_roundtrip() {
let dto = sample_user();
let proto: User = dto.clone().into();
let back: DamlUser = proto.into();
assert_eq!(back, dto);
}
#[test]
fn user_default_roundtrip() {
let dto = DamlUser::default();
let proto: User = dto.clone().into();
let back: DamlUser = proto.into();
assert_eq!(back, dto);
}
#[test]
fn every_right_variant_roundtrips() {
let cases = [
DamlUserRight::ParticipantAdmin,
DamlUserRight::CanActAs("Alice".to_owned()),
DamlUserRight::CanReadAs("Bob".to_owned()),
DamlUserRight::CanExecuteAs("Charlie".to_owned()),
DamlUserRight::IdentityProviderAdmin,
DamlUserRight::CanReadAsAnyParty,
DamlUserRight::CanExecuteAsAnyParty,
];
for original in cases {
let proto: Right = original.clone().into();
let back = DamlUserRight::try_from(proto).expect("known kinds should round-trip");
assert_eq!(back, original, "right variant did not round-trip");
}
}
#[test]
fn right_with_missing_kind_errors() {
let proto = Right {
kind: None,
};
let result = DamlUserRight::try_from(proto);
assert!(matches!(result, Err(DamlError::MissingRequiredField)));
}
}