meta_secret_core/sdk/
api.rs1use serde::{Deserialize, Serialize};
2
3use crate::models::{
4 MembershipStatus, MetaPasswordsData, PasswordRecoveryRequest, RegistrationStatus,
5 SecretDistributionDocData, VaultInfoData, VaultInfoStatus, FindSharesResult
6};
7
8#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
9#[serde(rename_all = "camelCase")]
10pub enum MessageType {
11 Ok,
12 Err,
13}
14
15#[derive(Debug, Serialize, Deserialize)]
16#[serde(rename_all = "camelCase")]
17pub struct GenericMessage<T> {
18 pub msg_type: MessageType,
19 #[serde(skip_serializing_if = "Option::is_none")]
20 pub data: Option<T>,
21 #[serde(skip_serializing_if = "Option::is_none")]
22 pub err: Option<ErrorMessage>,
23}
24
25#[derive(Debug, Serialize, Deserialize)]
26#[serde(rename_all = "camelCase")]
27pub struct ErrorMessage {
28 stacktrace: Vec<String>,
29}
30
31impl From<&anyhow::Error> for ErrorMessage {
32 fn from(err: &anyhow::Error) -> Self {
33 let mut stacktrace = vec![];
34 for cause in err.chain() {
35 stacktrace.push(cause.to_string().trim().to_string());
36 }
37
38 Self { stacktrace }
39 }
40}
41
42impl From<&dyn std::error::Error> for ErrorMessage {
43 fn from(err: &dyn std::error::Error) -> Self {
44 let mut stacktrace = vec![];
45
46 let mut current_error = err;
47 while let Some(source) = current_error.source() {
48 let err_msg = format!("{}", current_error);
49 stacktrace.push(err_msg);
50
51 current_error = source;
52 }
53
54 Self { stacktrace }
55 }
56}
57
58impl<T> GenericMessage<T> {
59 pub fn just_ok() -> Self {
60 GenericMessage {
61 msg_type: MessageType::Ok,
62 data: None,
63 err: None,
64 }
65 }
66
67 pub fn data(data: T) -> Self {
68 GenericMessage {
69 msg_type: MessageType::Ok,
70 data: Some(data),
71 err: None,
72 }
73 }
74
75 pub fn err(err: anyhow::Error) -> Self {
76 let err_msg = ErrorMessage::from(&err);
77
78 GenericMessage {
79 msg_type: MessageType::Err,
80 data: None,
81 err: Some(err_msg),
82 }
83 }
84
85 pub fn std_err(err: &dyn std::error::Error) -> Self {
86 let err_msg = ErrorMessage::from(err);
87
88 GenericMessage {
89 msg_type: MessageType::Err,
90 data: None,
91 err: Some(err_msg),
92 }
93 }
94}
95
96pub type SecretDistributionDocResponse = GenericMessage<SecretDistributionDocData>;
97
98pub type RegistrationResponse = GenericMessage<RegistrationStatus>;
99
100pub type VaultInfoResponse = GenericMessage<VaultInfoData>;
101
102
103impl VaultInfoData {
104 pub fn pending() -> Self {
105 Self::empty(VaultInfoStatus::Pending)
106 }
107
108 pub fn declined() -> Self {
109 Self::empty(VaultInfoStatus::Declined)
110 }
111
112 pub fn unknown() -> Self {
113 Self::empty(VaultInfoStatus::Unknown)
114 }
115
116 pub fn empty(vault_info: VaultInfoStatus) -> Self {
117 Self {
118 vault_info: Some(vault_info),
119 vault: None,
120 }
121 }
122}
123
124pub type MetaPasswordsResponse = GenericMessage<MetaPasswordsData>;
125
126pub type PasswordRecoveryClaimsResponse = GenericMessage<Vec<PasswordRecoveryRequest>>;
127
128pub type UserSharesResponse = GenericMessage<FindSharesResult>;
129
130pub mod basic {
131 use serde::{Deserialize, Serialize};
132
133 #[derive(Debug, Serialize, Deserialize)]
134 #[serde(rename_all = "camelCase")]
135 pub struct MongoDbStats {
136 pub connection: bool,
137 pub registrations: usize,
138 }
139
140 #[derive(Debug, Serialize, Deserialize)]
141 #[serde(rename_all = "camelCase")]
142 pub struct HttpStatusDetails {
143 pub http_status: String,
144 pub http_status_code: u16,
145 pub uri: String,
146 pub method: String,
147 #[serde(skip_serializing_if = "Option::is_none")]
148 pub content_type: Option<String>,
149 }
150}
151
152pub type MembershipResponse = GenericMessage<MembershipStatus>;
153
154#[cfg(test)]
155mod test {
156 use anyhow::anyhow;
157 use serde::{Deserialize, Serialize};
158 use serde_json::error::Result;
159 use thiserror::__private::AsDynError;
160 use crate::models::MembershipStatus;
161
162 use crate::sdk::api::{ErrorMessage, GenericMessage, MembershipResponse};
163
164 #[test]
165 fn test_generic_message() -> Result<()> {
166 let msg: GenericMessage<String> = GenericMessage::just_ok();
167 let msg = serde_json::to_string(&msg)?;
168 assert_eq!(r#"{"msgType":"ok"}"#.to_string(), msg);
169
170 let msg = MembershipResponse::data(MembershipStatus::AlreadyMember);
171 let msg = serde_json::to_string(&msg)?;
172 assert_eq!(r#"{"msgType":"ok","data":"AlreadyMember"}"#, msg);
173
174 #[derive(Debug, Serialize, Deserialize)]
175 #[serde(rename_all = "camelCase")]
176 struct TestTest {
177 pub xxx: String,
178 }
179
180 let msg = GenericMessage::data(TestTest { xxx: "yay".to_string() });
181 let msg = serde_json::to_string(&msg)?;
182 assert_eq!(r#"{"msgType":"ok","data":{"xxx":"yay"}}"#, msg);
183
184 Ok(())
185 }
186
187 #[test]
188 fn error_message_test() -> Result<()> {
189 let err_msg = ErrorMessage::from(anyhow!("yay").context("my root cause").as_dyn_error());
190 assert_eq!(r#"{"stacktrace":["my root cause"]}"#, serde_json::to_string(&err_msg)?);
191
192 Ok(())
193 }
194}