use std::collections::BTreeSet;
use holo_hash::*;
use holochain_types::prelude::*;
use holochain_types::websocket::AllowedOrigins;
use holochain_zome_types::cell::CellId;
use kitsune_p2p_types::agent_info::AgentInfoSigned;
use crate::{AppInfo, FullStateDump, RevokeAgentKeyPayload, StorageInfo};
#[derive(Debug, serde::Serialize, serde::Deserialize, SerializedBytes)]
#[serde(rename_all = "snake_case", tag = "type", content = "data")]
pub enum AdminRequest {
AddAdminInterfaces(Vec<crate::config::AdminInterfaceConfig>),
RegisterDna(Box<RegisterDnaPayload>),
GetDnaDefinition(Box<DnaHash>),
UpdateCoordinators(Box<UpdateCoordinatorsPayload>),
InstallApp(Box<InstallAppPayload>),
UninstallApp {
installed_app_id: InstalledAppId,
#[serde(default)]
force: bool,
},
ListDnas,
GenerateAgentPubKey,
RevokeAgentKey(Box<RevokeAgentKeyPayload>),
ListCellIds,
ListApps {
status_filter: Option<AppStatusFilter>,
},
EnableApp {
installed_app_id: InstalledAppId,
},
DisableApp {
installed_app_id: InstalledAppId,
},
AttachAppInterface {
port: Option<u16>,
allowed_origins: AllowedOrigins,
installed_app_id: Option<InstalledAppId>,
},
ListAppInterfaces,
DumpState {
cell_id: Box<CellId>,
},
DumpConductorState,
DumpFullState {
cell_id: Box<CellId>,
dht_ops_cursor: Option<u64>,
},
DumpNetworkMetrics {
dna_hash: Option<DnaHash>,
},
DumpNetworkStats,
AddAgentInfo {
agent_infos: Vec<AgentInfoSigned>,
},
AgentInfo {
cell_id: Option<CellId>,
},
GraftRecords {
cell_id: CellId,
validate: bool,
records: Vec<Record>,
},
GrantZomeCallCapability(Box<GrantZomeCallCapabilityPayload>),
DeleteCloneCell(Box<DeleteCloneCellPayload>),
StorageInfo,
IssueAppAuthenticationToken(IssueAppAuthenticationTokenPayload),
RevokeAppAuthenticationToken(AppAuthenticationToken),
GetCompatibleCells(DnaHash),
}
#[derive(Debug, serde::Serialize, serde::Deserialize, SerializedBytes)]
#[cfg_attr(test, derive(Clone))]
#[serde(rename_all = "snake_case", tag = "type", content = "data")]
pub enum AdminResponse {
Error(ExternalApiWireError),
DnaRegistered(DnaHash),
DnaDefinitionReturned(DnaDef),
CoordinatorsUpdated,
AppInstalled(AppInfo),
AppUninstalled,
AdminInterfacesAdded,
AgentPubKeyGenerated(AgentPubKey),
AgentKeyRevoked(Vec<(CellId, String)>),
DnasListed(Vec<DnaHash>),
CellIdsListed(Vec<CellId>),
AppsListed(Vec<AppInfo>),
AppInterfaceAttached {
port: u16,
},
AppInterfacesListed(Vec<AppInterfaceInfo>),
AppEnabled {
app: AppInfo,
errors: Vec<(CellId, String)>,
},
AppDisabled,
StateDumped(String),
FullStateDumped(FullStateDump),
ConductorStateDumped(String),
NetworkMetricsDumped(String),
NetworkStatsDumped(String),
AgentInfoAdded,
AgentInfo(Vec<AgentInfoSigned>),
RecordsGrafted,
ZomeCallCapabilityGranted,
CloneCellDeleted,
StorageInfo(StorageInfo),
AppAuthenticationTokenIssued(AppAuthenticationTokenIssued),
AppAuthenticationTokenRevoked,
CompatibleCells(CompatibleCells),
}
pub type CompatibleCells = BTreeSet<(InstalledAppId, BTreeSet<CellId>)>;
#[derive(Debug, serde::Serialize, serde::Deserialize, SerializedBytes, Clone)]
#[serde(rename_all = "snake_case", tag = "type", content = "data")]
pub enum ExternalApiWireError {
InternalError(String),
Deserialization(String),
DnaReadError(String),
RibosomeError(String),
ActivateApp(String),
ZomeCallUnauthorized(String),
CountersigningSessionError(String),
}
impl ExternalApiWireError {
pub fn internal<T: std::fmt::Display>(e: T) -> Self {
ExternalApiWireError::InternalError(e.to_string())
}
}
#[derive(Debug, serde::Serialize, serde::Deserialize, SerializedBytes, Clone)]
pub enum AppStatusFilter {
Enabled,
Disabled,
Running,
Stopped,
Paused,
}
#[derive(Debug, serde::Serialize, serde::Deserialize, SerializedBytes, Clone)]
pub struct AppInterfaceInfo {
pub port: u16,
pub allowed_origins: AllowedOrigins,
pub installed_app_id: Option<InstalledAppId>,
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct IssueAppAuthenticationTokenPayload {
pub installed_app_id: InstalledAppId,
#[serde(default = "default_expiry_seconds")]
pub expiry_seconds: u64,
#[serde(default = "default_single_use")]
pub single_use: bool,
}
fn default_expiry_seconds() -> u64 {
30
}
fn default_single_use() -> bool {
true
}
impl IssueAppAuthenticationTokenPayload {
pub fn for_installed_app_id(installed_app_id: InstalledAppId) -> Self {
installed_app_id.into()
}
pub fn expiry_seconds(mut self, expiry_seconds: u64) -> Self {
self.expiry_seconds = expiry_seconds;
self
}
pub fn single_use(mut self, single_use: bool) -> Self {
self.single_use = single_use;
self
}
}
impl From<InstalledAppId> for IssueAppAuthenticationTokenPayload {
fn from(installed_app_id: InstalledAppId) -> Self {
Self {
installed_app_id,
expiry_seconds: 30,
single_use: true,
}
}
}
pub type AppAuthenticationToken = Vec<u8>;
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
pub struct AppAuthenticationTokenIssued {
pub token: AppAuthenticationToken,
pub expires_at: Option<Timestamp>,
}
#[cfg(test)]
mod tests {
use serde::Deserialize;
use crate::{AdminRequest, AdminResponse, ExternalApiWireError};
#[test]
fn admin_request_serialization() {
use rmp_serde::Deserializer;
let request = AdminRequest::DisableApp {
installed_app_id: "some_id".to_string(),
};
let serialized_request = holochain_serialized_bytes::encode(&request).unwrap();
assert_eq!(
serialized_request,
vec![
130, 164, 116, 121, 112, 101, 171, 100, 105, 115, 97, 98, 108, 101, 95, 97, 112,
112, 164, 100, 97, 116, 97, 129, 176, 105, 110, 115, 116, 97, 108, 108, 101, 100,
95, 97, 112, 112, 95, 105, 100, 167, 115, 111, 109, 101, 95, 105, 100
]
);
let json_expected = r#"{"type":"disable_app","data":{"installed_app_id":"some_id"}}"#;
let mut deserializer = Deserializer::new(&*serialized_request);
let json_value: serde_json::Value = Deserialize::deserialize(&mut deserializer).unwrap();
let json_actual = serde_json::to_string(&json_value).unwrap();
assert_eq!(json_actual, json_expected);
let response = AdminResponse::Error(ExternalApiWireError::RibosomeError(
"error_text".to_string(),
));
let serialized_response = holochain_serialized_bytes::encode(&response).unwrap();
assert_eq!(
serialized_response,
vec![
130, 164, 116, 121, 112, 101, 165, 101, 114, 114, 111, 114, 164, 100, 97, 116, 97,
130, 164, 116, 121, 112, 101, 174, 114, 105, 98, 111, 115, 111, 109, 101, 95, 101,
114, 114, 111, 114, 164, 100, 97, 116, 97, 170, 101, 114, 114, 111, 114, 95, 116,
101, 120, 116
]
);
let json_expected =
r#"{"type":"error","data":{"type":"ribosome_error","data":"error_text"}}"#;
let mut deserializer = Deserializer::new(&*serialized_response);
let json_value: serde_json::Value = Deserialize::deserialize(&mut deserializer).unwrap();
let json_actual = serde_json::to_string(&json_value).unwrap();
assert_eq!(json_actual, json_expected);
}
}