use polyc_proto::proto::polychrome::state::v1 as pb;
use polyc_state::{
administration::{
AdminRoster, AdministrationCommand, AdministrationOperation, DeploymentSettings,
administration_scope,
},
command::{CommandEnvelope, CommandMetadata, ResourceBounds},
digest::ContentDigest,
error::StateError,
id::{Audience, CommandId, NamespaceId, Purpose},
versioned::{
MAX_MUTATIONS_PER_TRANSACTION, MAX_TRANSACTION_PAYLOAD_BYTES,
authority::{AdminStatus, PersonaId},
},
};
use crate::{
persona::wire::{expected_from_wire, expected_to_wire},
wire::{fixed_bytes, malformed, required},
};
pub(crate) fn status_to_wire(value: &AdminStatus) -> pb::AdministrationStatus {
pb::AdministrationStatus {
administrator: value.is_administrator(),
operator: value.is_operator(),
admin_removed_by: value.admin_removed_by().to_owned(),
admin_removed_at_ms: value.admin_removed_at_ms(),
__buffa_unknown_fields: buffa::UnknownFields::default(),
}
}
pub(crate) fn status_from_wire(
value: &pb::AdministrationStatus,
) -> Result<AdminStatus, StateError> {
if value.admin_removed_by.is_empty() != (value.admin_removed_at_ms == 0) {
return Err(malformed(
"status",
"administrator-removal actor and time are present together",
));
}
Ok(AdminStatus::new(value.administrator, value.operator)
.with_admin_removal(value.admin_removed_by.clone(), value.admin_removed_at_ms))
}
pub(crate) fn roster_to_wire(value: &AdminRoster) -> pb::AdministrationRoster {
pb::AdministrationRoster {
administrators: value
.administrators()
.iter()
.map(|persona| persona.as_str().to_owned())
.collect(),
rebuilt_at_ms: value.rebuilt_at_ms(),
updated_at_ms: value.updated_at_ms(),
__buffa_unknown_fields: buffa::UnknownFields::default(),
}
}
pub(crate) fn roster_from_wire(value: pb::AdministrationRoster) -> AdminRoster {
AdminRoster::new(
value
.administrators
.into_iter()
.map(PersonaId::new)
.collect(),
value.rebuilt_at_ms,
value.updated_at_ms,
)
}
pub(crate) fn settings_to_wire(value: &DeploymentSettings) -> pb::AdministrationSettings {
pb::AdministrationSettings {
require_linked: value.require_linked(),
updated_at_ms: value.updated_at_ms(),
blocked_identifiers: value.blocked_identifiers().to_vec(),
max_identities_per_provider: value.max_identities_per_provider(),
__buffa_unknown_fields: buffa::UnknownFields::default(),
}
}
pub(crate) fn settings_from_wire(value: pb::AdministrationSettings) -> DeploymentSettings {
DeploymentSettings::new(
value.require_linked,
value.updated_at_ms,
value.blocked_identifiers,
value.max_identities_per_provider,
)
}
pub(crate) fn operation_to_wire(value: &AdministrationOperation) -> pb::AdministrationOperation {
use pb::__buffa::oneof::administration_operation::Operation;
let operation = match value {
AdministrationOperation::BootstrapAdministrator {
target,
target_profile_expected,
target_expected,
roster_expected,
roster,
} => Operation::from(pb::BootstrapAdministrator {
target: target.as_str().to_owned(),
target_profile_expected: buffa::MessageField::some(expected_to_wire(
*target_profile_expected,
)),
target_expected: buffa::MessageField::some(expected_to_wire(*target_expected)),
roster_expected: buffa::MessageField::some(expected_to_wire(*roster_expected)),
roster: buffa::MessageField::some(roster_to_wire(roster)),
__buffa_unknown_fields: buffa::UnknownFields::default(),
}),
AdministrationOperation::SetRoles {
actor,
actor_profile_expected,
target,
target_profile_expected,
status,
actor_expected,
target_expected,
roster,
roster_expected,
} => Operation::from(pb::SetAdministrationRoles {
actor: actor.as_str().to_owned(),
actor_profile_expected: buffa::MessageField::some(expected_to_wire(
*actor_profile_expected,
)),
target: target.as_str().to_owned(),
target_profile_expected: buffa::MessageField::some(expected_to_wire(
*target_profile_expected,
)),
status: buffa::MessageField::some(status_to_wire(status)),
actor_expected: buffa::MessageField::some(expected_to_wire(*actor_expected)),
target_expected: buffa::MessageField::some(expected_to_wire(*target_expected)),
roster: buffa::MessageField::some(roster_to_wire(roster)),
roster_expected: buffa::MessageField::some(expected_to_wire(*roster_expected)),
__buffa_unknown_fields: buffa::UnknownFields::default(),
}),
AdministrationOperation::PutSettings {
actor,
actor_profile_expected,
settings,
actor_expected,
settings_expected,
} => Operation::from(pb::PutAdministrationSettings {
actor: actor.as_str().to_owned(),
actor_profile_expected: buffa::MessageField::some(expected_to_wire(
*actor_profile_expected,
)),
settings: buffa::MessageField::some(settings_to_wire(settings)),
actor_expected: buffa::MessageField::some(expected_to_wire(*actor_expected)),
settings_expected: buffa::MessageField::some(expected_to_wire(*settings_expected)),
__buffa_unknown_fields: buffa::UnknownFields::default(),
}),
};
pb::AdministrationOperation {
operation: Some(operation),
__buffa_unknown_fields: buffa::UnknownFields::default(),
}
}
pub(crate) fn operation_from_wire(
value: pb::AdministrationOperation,
) -> Result<AdministrationOperation, StateError> {
use pb::__buffa::oneof::administration_operation::Operation;
Ok(match value.operation {
Some(Operation::Bootstrap(value)) => AdministrationOperation::BootstrapAdministrator {
target: PersonaId::new(value.target),
target_profile_expected: expected_from_wire(required(
"target_profile_expected",
"bootstrap carries the target profile premise",
value.target_profile_expected,
)?)?,
target_expected: expected_from_wire(required(
"target_expected",
"bootstrap carries the target premise",
value.target_expected,
)?)?,
roster_expected: expected_from_wire(required(
"roster_expected",
"bootstrap carries the roster premise",
value.roster_expected,
)?)?,
roster: roster_from_wire(required(
"roster",
"bootstrap carries the resulting roster",
value.roster,
)?),
},
Some(Operation::SetRoles(value)) => AdministrationOperation::SetRoles {
actor: PersonaId::new(value.actor),
actor_profile_expected: expected_from_wire(required(
"actor_profile_expected",
"a role change carries the actor profile premise",
value.actor_profile_expected,
)?)?,
target: PersonaId::new(value.target),
target_profile_expected: expected_from_wire(required(
"target_profile_expected",
"a role change carries the target profile premise",
value.target_profile_expected,
)?)?,
status: status_from_wire(&required(
"status",
"a role change carries the complete role state",
value.status,
)?)?,
actor_expected: expected_from_wire(required(
"actor_expected",
"a role change carries the actor premise",
value.actor_expected,
)?)?,
target_expected: expected_from_wire(required(
"target_expected",
"a role change carries the target premise",
value.target_expected,
)?)?,
roster: roster_from_wire(required(
"roster",
"a role change carries the resulting roster",
value.roster,
)?),
roster_expected: expected_from_wire(required(
"roster_expected",
"a role change carries the roster premise",
value.roster_expected,
)?)?,
},
Some(Operation::PutSettings(value)) => AdministrationOperation::PutSettings {
actor: PersonaId::new(value.actor),
actor_profile_expected: expected_from_wire(required(
"actor_profile_expected",
"a settings write carries the actor profile premise",
value.actor_profile_expected,
)?)?,
settings: settings_from_wire(required(
"settings",
"a settings write carries its complete value",
value.settings,
)?),
actor_expected: expected_from_wire(required(
"actor_expected",
"a settings write carries the actor premise",
value.actor_expected,
)?)?,
settings_expected: expected_from_wire(required(
"settings_expected",
"a settings write carries the row premise",
value.settings_expected,
)?)?,
},
None => {
return Err(malformed(
"operation",
"an administration command names one operation",
));
}
})
}
pub(crate) fn metadata_to_wire(
command: &AdministrationCommand,
) -> pb::AdministrationCommandMetadata {
let value = command.metadata();
pb::AdministrationCommandMetadata {
command_id: value.command_id().as_str().to_owned(),
namespace: value.scope().namespace().as_str().to_owned(),
purpose: value.envelope().purpose().as_str().to_owned(),
command_audience: value.envelope().audience().as_str().to_owned(),
digest: value.digest().as_bytes().to_vec(),
__buffa_unknown_fields: buffa::UnknownFields::default(),
}
}
pub(crate) fn command_from_wire(
metadata: pb::AdministrationCommandMetadata,
operation: pb::AdministrationOperation,
) -> Result<AdministrationCommand, StateError> {
let namespace = NamespaceId::new(metadata.namespace);
let digest = ContentDigest::from_bytes(fixed_bytes::<{ ContentDigest::LEN }>(
"digest",
&metadata.digest,
)?);
Ok(AdministrationCommand::new(
CommandMetadata::new(
CommandId::new(metadata.command_id),
polyc_state::versioned::family(),
digest,
administration_scope(&namespace),
CommandEnvelope::new(
Purpose::new(metadata.purpose),
Audience::new(metadata.command_audience),
ResourceBounds::new(MAX_TRANSACTION_PAYLOAD_BYTES, MAX_MUTATIONS_PER_TRANSACTION),
),
),
operation_from_wire(operation)?,
))
}
#[cfg(test)]
mod tests {
use super::*;
use polyc_state::versioned::EntryExpectation;
#[test]
fn every_operation_round_trips_and_missing_oneof_fails_closed() {
let values = vec![
AdministrationOperation::BootstrapAdministrator {
target: PersonaId::new("admin"),
target_profile_expected: EntryExpectation::Revision(
polyc_state::revision::Revision::new(1),
),
target_expected: EntryExpectation::Absent,
roster_expected: EntryExpectation::Absent,
roster: AdminRoster::new(vec![PersonaId::new("admin")], 0, 1),
},
AdministrationOperation::SetRoles {
actor: PersonaId::new("admin"),
actor_profile_expected: EntryExpectation::Revision(
polyc_state::revision::Revision::new(1),
),
target: PersonaId::new("operator"),
target_profile_expected: EntryExpectation::Revision(
polyc_state::revision::Revision::new(2),
),
status: AdminStatus::new(false, true),
actor_expected: EntryExpectation::Revision(polyc_state::revision::Revision::new(1)),
target_expected: EntryExpectation::Absent,
roster: AdminRoster::new(vec![PersonaId::new("admin")], 0, 2),
roster_expected: EntryExpectation::Revision(polyc_state::revision::Revision::new(
1,
)),
},
AdministrationOperation::PutSettings {
actor: PersonaId::new("admin"),
actor_profile_expected: EntryExpectation::Revision(
polyc_state::revision::Revision::new(1),
),
settings: DeploymentSettings::new(true, 3, vec!["blocked".into()], 4),
actor_expected: EntryExpectation::Revision(polyc_state::revision::Revision::new(1)),
settings_expected: EntryExpectation::Absent,
},
];
for value in values {
assert_eq!(
operation_from_wire(operation_to_wire(&value)).unwrap(),
value
);
}
let audit =
AdminStatus::new(false, true).with_admin_removal("administrator".to_owned(), 44);
assert_eq!(status_from_wire(&status_to_wire(&audit)).unwrap(), audit);
assert!(
status_from_wire(&pb::AdministrationStatus {
admin_removed_at_ms: 44,
..Default::default()
})
.is_err()
);
assert!(
operation_from_wire(pb::AdministrationOperation {
operation: None,
__buffa_unknown_fields: buffa::UnknownFields::default(),
})
.is_err()
);
}
}