use crate::keys::{KeyRecord, KeyStatus, KeyType};
use crate::protocols::key_management::sign::SignAlgorithm;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize)]
#[allow(dead_code)]
pub struct HealthResponse {
pub status: String,
#[serde(default)]
pub version: Option<String>,
#[serde(default)]
pub mediator_url: Option<String>,
#[serde(default)]
pub mediator_did: Option<String>,
}
#[derive(Debug, Deserialize)]
pub struct ConfigResponse {
#[serde(flatten)]
pub config: crate::protocols::vta_management::get_config::GetConfigResultBody,
}
impl ConfigResponse {
pub fn vta_did(&self) -> Option<&str> {
self.config.vta_did()
}
pub fn public_url(&self) -> Option<&str> {
self.config.get("public_url").and_then(|v| v.as_str())
}
pub fn vta_name(&self) -> Option<&str> {
self.config.get("vta_name").and_then(|v| v.as_str())
}
}
#[derive(Debug, Serialize)]
pub struct UpdateConfigRequest {
#[serde(flatten)]
pub patch: crate::protocols::vta_management::update_config::UpdateConfigBody,
}
#[derive(Debug, Serialize)]
#[must_use]
pub struct CreateKeyRequest {
pub key_type: KeyType,
#[serde(skip_serializing_if = "Option::is_none")]
pub derivation_path: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub key_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub mnemonic: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub label: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub context_id: Option<String>,
}
impl CreateKeyRequest {
pub fn new(key_type: KeyType) -> Self {
Self {
key_type,
derivation_path: None,
key_id: None,
mnemonic: None,
label: None,
context_id: None,
}
}
pub fn derivation_path(mut self, path: impl Into<String>) -> Self {
self.derivation_path = Some(path.into());
self
}
pub fn key_id(mut self, id: impl Into<String>) -> Self {
self.key_id = Some(id.into());
self
}
pub fn mnemonic(mut self, m: impl Into<String>) -> Self {
self.mnemonic = Some(m.into());
self
}
pub fn label(mut self, label: impl Into<String>) -> Self {
self.label = Some(label.into());
self
}
pub fn context(mut self, ctx: impl Into<String>) -> Self {
self.context_id = Some(ctx.into());
self
}
}
#[derive(Debug, Serialize)]
pub struct ImportKeyRequest {
pub key_type: KeyType,
#[serde(skip_serializing_if = "Option::is_none")]
pub private_key_sealed: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub private_key_jwe: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub private_key_multibase: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub label: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub context_id: Option<String>,
}
#[derive(Debug, Deserialize)]
pub struct ImportKeyResponse {
pub key_id: String,
pub key_type: KeyType,
pub public_key: String,
pub status: KeyStatus,
pub label: Option<String>,
pub origin: crate::keys::KeyOrigin,
pub created_at: chrono::DateTime<chrono::Utc>,
}
#[derive(Debug, Deserialize)]
pub struct WrappingKeyResponse {
pub kid: String,
pub kty: String,
pub crv: String,
pub x: String,
}
#[derive(Debug, Serialize)]
#[must_use]
pub struct CreateContextRequest {
pub id: String,
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub parent: Option<String>,
}
impl CreateContextRequest {
pub fn new(id: impl Into<String>, name: impl Into<String>) -> Self {
Self {
id: id.into(),
name: name.into(),
description: None,
parent: None,
}
}
pub fn description(mut self, desc: impl Into<String>) -> Self {
self.description = Some(desc.into());
self
}
pub fn parent(mut self, parent: impl Into<String>) -> Self {
self.parent = Some(parent.into());
self
}
}
#[derive(Debug, Default, Serialize)]
pub struct UpdateContextRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub did: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub context_policy: Option<crate::context_policy::ContextPolicy>,
}
#[derive(Debug, Serialize)]
pub struct UpdateContextDidRequest {
pub did: String,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct ContextResponse {
pub id: String,
pub name: String,
pub did: Option<String>,
pub description: Option<String>,
pub base_path: String,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
#[derive(Debug, Deserialize)]
pub struct ContextListResponse {
pub contexts: Vec<ContextResponse>,
}
#[derive(Debug, Deserialize)]
pub struct CreateKeyResponse {
pub key_id: String,
pub key_type: KeyType,
pub derivation_path: String,
pub public_key: String,
pub status: KeyStatus,
pub label: Option<String>,
pub created_at: DateTime<Utc>,
}
#[derive(Debug, Deserialize)]
pub struct InvalidateKeyResponse {
pub key_id: String,
pub status: KeyStatus,
pub updated_at: DateTime<Utc>,
}
#[derive(Debug, Serialize)]
pub struct RenameKeyRequest {
pub key_id: String,
}
#[derive(Debug, Deserialize)]
pub struct RenameKeyResponse {
pub key_id: String,
pub updated_at: DateTime<Utc>,
}
#[derive(Debug, Deserialize)]
pub struct GetKeySecretResponse {
pub key_id: String,
pub key_type: KeyType,
pub public_key_multibase: String,
pub private_key_multibase: String,
}
#[derive(Debug, Deserialize)]
pub struct SignResponse {
pub key_id: String,
pub signature: String,
pub algorithm: SignAlgorithm,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct ListKeysResponse {
pub keys: Vec<KeyRecord>,
pub total: u64,
}
#[derive(Debug, Deserialize)]
pub struct ErrorResponse {
pub error: String,
}
#[derive(Debug, Deserialize)]
pub struct SeedInfoResponse {
pub id: u32,
pub status: String,
pub created_at: DateTime<Utc>,
pub retired_at: Option<DateTime<Utc>>,
}
#[derive(Debug, Deserialize)]
pub struct ListSeedsResponse {
pub seeds: Vec<SeedInfoResponse>,
pub active_seed_id: u32,
}
#[derive(Debug, Serialize)]
pub struct RotateSeedRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub mnemonic: Option<String>,
}
#[derive(Debug, Deserialize)]
pub struct RotateSeedResponse {
pub previous_seed_id: u32,
pub new_seed_id: u32,
}
#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct AclEntryResponse {
#[serde(rename = "subject")]
pub did: String,
pub role: String,
#[serde(default)]
pub label: Option<String>,
#[serde(rename = "scopes", default)]
pub allowed_contexts: Vec<String>,
#[serde(
default,
deserialize_with = "de_epoch_opt",
serialize_with = "ser_epoch"
)]
pub created_at: u64,
#[serde(default)]
pub created_by: String,
#[serde(
default,
deserialize_with = "de_epoch_opt_option",
serialize_with = "ser_epoch_opt"
)]
pub expires_at: Option<u64>,
#[serde(
default,
rename = "allowedKeys",
skip_serializing_if = "Option::is_none"
)]
pub allowed_keys: Option<Vec<String>>,
#[serde(default, rename = "stepUp")]
step_up: Option<StepUpWire>,
#[serde(default)]
approve: Option<ApproveWire>,
}
#[derive(Debug, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
struct StepUpWire {
#[serde(default)]
approver: Option<String>,
#[serde(default)]
require: Option<String>,
}
#[derive(Debug, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
struct ApproveWire {
#[serde(default)]
all: bool,
#[serde(default)]
scopes: Vec<String>,
}
impl AclEntryResponse {
pub fn step_up_require(&self) -> Option<&str> {
self.step_up.as_ref().and_then(|s| s.require.as_deref())
}
pub fn step_up_approver(&self) -> Option<&str> {
self.step_up.as_ref().and_then(|s| s.approver.as_deref())
}
pub fn approve_all_contexts(&self) -> bool {
self.approve.as_ref().is_some_and(|a| a.all)
}
pub fn approve_contexts(&self) -> &[String] {
self.approve.as_ref().map_or(&[], |a| a.scopes.as_slice())
}
}
fn ser_epoch<S: serde::Serializer>(v: &u64, s: S) -> Result<S::Ok, S::Error> {
ser_epoch_opt(&Some(*v), s)
}
fn ser_epoch_opt<S: serde::Serializer>(v: &Option<u64>, s: S) -> Result<S::Ok, S::Error> {
use chrono::{TimeZone, Utc};
match v.and_then(|e| {
i64::try_from(e)
.ok()
.and_then(|x| Utc.timestamp_opt(x, 0).single())
}) {
Some(t) => s.serialize_str(&t.to_rfc3339()),
None => s.serialize_none(),
}
}
fn de_epoch_opt<'de, D>(d: D) -> Result<u64, D::Error>
where
D: serde::Deserializer<'de>,
{
Ok(de_epoch_opt_option(d)?.unwrap_or(0))
}
fn de_epoch_opt_option<'de, D>(d: D) -> Result<Option<u64>, D::Error>
where
D: serde::Deserializer<'de>,
{
let raw = Option::<String>::deserialize(d)?;
Ok(raw.and_then(|s| {
chrono::DateTime::parse_from_rfc3339(&s)
.ok()
.map(|t| u64::try_from(t.timestamp()).unwrap_or(0))
}))
}
#[derive(Debug, Deserialize)]
pub(crate) struct AclEntryEnvelope {
pub entry: AclEntryResponse,
}
#[derive(Debug, Deserialize)]
pub struct AclListResponse {
pub entries: Vec<AclEntryResponse>,
}
#[derive(Debug)]
#[must_use]
pub struct CreateAclRequest {
pub did: String,
pub role: String,
pub label: Option<String>,
pub allowed_contexts: Vec<String>,
pub expires_at: Option<u64>,
pub step_up_approver: Option<String>,
pub step_up_require: Option<String>,
pub approve_all_contexts: bool,
pub approve_contexts: Vec<String>,
pub allowed_keys: Option<Vec<String>>,
}
impl serde::Serialize for CreateAclRequest {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
use crate::protocols::acl_management::create::CreateAclBody;
use crate::protocols::acl_management::entry::{AclEntry, Approve, StepUp};
use chrono::{TimeZone, Utc};
let step_up = StepUp {
approver: self.step_up_approver.clone(),
require: self.step_up_require.clone(),
};
let approve = Approve {
all: self.approve_all_contexts,
scopes: self.approve_contexts.clone(),
};
let has_step_up = step_up.approver.is_some() || step_up.require.is_some();
let has_approve = approve.all || !approve.scopes.is_empty();
let body = CreateAclBody {
entry: AclEntry {
subject: self.did.clone(),
role: self.role.clone(),
scopes: self.allowed_contexts.clone(),
allowed_keys: self.allowed_keys.clone(),
label: self.label.clone(),
created_at: None,
created_by: None,
updated_at: None,
updated_by: None,
expires_at: self.expires_at.and_then(|e| {
i64::try_from(e)
.ok()
.and_then(|s| Utc.timestamp_opt(s, 0).single())
}),
step_up: has_step_up.then_some(step_up),
approve: has_approve.then_some(approve),
},
reason: None,
};
body.serialize(s)
}
}
impl CreateAclRequest {
pub fn new(did: impl Into<String>, role: impl Into<String>) -> Self {
Self {
did: did.into(),
role: role.into(),
label: None,
allowed_contexts: Vec::new(),
expires_at: None,
step_up_approver: None,
step_up_require: None,
approve_all_contexts: false,
approve_contexts: Vec::new(),
allowed_keys: None,
}
}
pub fn label(mut self, label: impl Into<String>) -> Self {
self.label = Some(label.into());
self
}
pub fn contexts(mut self, contexts: Vec<String>) -> Self {
self.allowed_contexts = contexts;
self
}
pub fn expires_at(mut self, unix_secs: u64) -> Self {
self.expires_at = Some(unix_secs);
self
}
pub fn step_up_approver(mut self, approver: impl Into<String>) -> Self {
self.step_up_approver = Some(approver.into());
self
}
pub fn step_up_require(mut self, require: impl Into<String>) -> Self {
self.step_up_require = Some(require.into());
self
}
pub fn approve_all(mut self) -> Self {
self.approve_all_contexts = true;
self
}
pub fn approve_contexts(mut self, contexts: Vec<String>) -> Self {
self.approve_contexts = contexts;
self
}
pub fn allowed_keys(mut self, keys: Vec<String>) -> Self {
self.allowed_keys = Some(keys);
self
}
}
#[derive(Debug, Serialize)]
#[must_use]
pub struct SwapAclRequest {
pub presentation: String,
}
impl SwapAclRequest {
pub fn new(presentation: impl Into<String>) -> Self {
Self {
presentation: presentation.into(),
}
}
}
#[derive(Debug, Serialize)]
pub struct UpdateAclRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub label: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub allowed_contexts: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub step_up_approver: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub step_up_require: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub approve_scope: Option<crate::acl::ApproveScope>,
#[serde(rename = "allowedKeys", skip_serializing_if = "Option::is_none")]
pub allowed_keys: Option<Option<Vec<String>>>,
}
#[derive(Debug, Serialize)]
pub struct AddWebvhServerRequest {
pub id: String,
pub did: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub label: Option<String>,
}
#[derive(Debug, Serialize)]
pub struct UpdateWebvhServerRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub label: Option<String>,
}
#[derive(Debug, Serialize)]
pub struct CreateDidWebvhRequest {
pub context_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub server_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub url: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub path: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub path_mode: Option<crate::protocols::did_management::create::WebvhPathMode>,
#[serde(skip_serializing_if = "Option::is_none")]
pub domain: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub label: Option<String>,
pub portable: bool,
pub add_mediator_service: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub additional_services: Option<Vec<serde_json::Value>>,
pub pre_rotation_count: u32,
#[serde(skip_serializing_if = "Option::is_none")]
pub did_document: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub did_log: Option<String>,
pub set_primary: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub signing_key_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ka_key_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub template: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub template_context: Option<String>,
#[serde(default, skip_serializing_if = "std::collections::HashMap::is_empty")]
pub template_vars: std::collections::HashMap<String, serde_json::Value>,
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ChangeAclRoleRequest {
pub from_role: String,
pub to_role: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub reason: Option<String>,
}
#[derive(Debug, Deserialize)]
pub struct GetDidLogResponse {
pub did: String,
pub log: Option<String>,
}