kanidm_proto/messages.rs
1// User-facing output things
2
3use std::fmt;
4use std::str::FromStr;
5
6use serde::{Deserialize, Serialize};
7
8/// This is used in user-facing CLIs to set the formatting for output,
9/// and defaults to text.
10#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Default)]
11#[serde(rename_all = "lowercase")]
12pub enum ConsoleOutputMode {
13 #[default]
14 Text,
15 JSON,
16}
17
18impl FromStr for ConsoleOutputMode {
19 type Err = &'static str;
20
21 /// This can be safely unwrap'd because it'll always return a default of text
22 /// ```
23 /// use kanidm_proto::messages::ConsoleOutputMode;
24 ///
25 /// let mode: ConsoleOutputMode = "🦀".into();
26 /// assert_eq!(ConsoleOutputMode::Text, mode);
27 /// let mode: ConsoleOutputMode = "".into();
28 /// assert_eq!(ConsoleOutputMode::Text, mode);
29 ///
30 /// let mode: ConsoleOutputMode = "json".into();
31 /// assert_eq!(ConsoleOutputMode::JSON, mode);
32 /// ```
33 fn from_str(s: &str) -> Result<Self, Self::Err> {
34 match s {
35 "json" => Ok(ConsoleOutputMode::JSON),
36 "text" => Ok(ConsoleOutputMode::Text),
37 _ => {
38 eprintln!(
39 "Supplied output mode ({:?}) was invalid, defaulting to text",
40 s
41 );
42 Ok(ConsoleOutputMode::Text)
43 }
44 }
45 }
46}
47
48/// This will take any string, if it's 'text' or 'json' then you'll get
49/// what you asked for, else you'll get a text version.
50///
51/// ```
52/// use kanidm_proto::messages::ConsoleOutputMode;
53/// let bork = "text";
54/// let com: ConsoleOutputMode = bork.into();
55/// matches!(ConsoleOutputMode::Text, com);
56/// ```
57impl From<&str> for ConsoleOutputMode {
58 fn from(input: &str) -> Self {
59 match ConsoleOutputMode::from_str(input) {
60 Ok(val) => val,
61 Err(_) => Self::Text,
62 }
63 }
64}
65
66/// This will take any string, if it's 'text' or 'json' then you'll get
67/// what you asked for, else you'll get a text version.
68///
69/// ```
70/// use kanidm_proto::messages::ConsoleOutputMode;
71/// let bork = String::from("cr4bz");
72/// let com: ConsoleOutputMode = bork.into();
73/// matches!(ConsoleOutputMode::Text, com);
74/// ```
75impl From<String> for ConsoleOutputMode {
76 fn from(input: String) -> Self {
77 match ConsoleOutputMode::from_str(input.as_str()) {
78 Ok(val) => val,
79 Err(_) => Self::Text,
80 }
81 }
82}
83
84#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
85#[serde(rename_all = "lowercase")]
86pub enum MessageStatus {
87 Failure,
88 Success,
89}
90
91impl fmt::Display for MessageStatus {
92 fn fmt(&self, f: &mut fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
93 match *self {
94 MessageStatus::Failure => f.write_str("failure"),
95 MessageStatus::Success => f.write_str("success"),
96 }
97 }
98}
99
100#[derive(Debug, Serialize, Deserialize)]
101pub struct AccountChangeMessage {
102 #[serde(skip_serializing)]
103 pub output_mode: ConsoleOutputMode,
104 pub action: String,
105 pub result: String,
106 pub status: MessageStatus,
107 pub src_user: String,
108 pub dest_user: String,
109}
110
111impl Default for AccountChangeMessage {
112 fn default() -> Self {
113 AccountChangeMessage {
114 output_mode: ConsoleOutputMode::Text,
115 action: String::from(""),
116 result: String::from(""),
117 status: MessageStatus::Success,
118 src_user: String::from(""),
119 dest_user: String::from(""),
120 }
121 }
122}
123
124/// This outputs in either JSON or Text depending on the output_mode setting
125/// ```
126/// use std::fmt::format;
127/// use kanidm_proto::messages::*;
128/// let mut msg = AccountChangeMessage::default();
129/// msg.action=String::from("cake_eating");
130/// msg.src_user=String::from("Kani");
131/// msg.dest_user=String::from("Krabby");
132/// msg.result=String::from("It was amazing");
133/// assert_eq!(msg.status, MessageStatus::Success);
134///
135/// let expected_result = "success - cake_eating for Krabby: It was amazing";
136/// assert_eq!(format!("{}", msg), expected_result);
137///
138/// msg.output_mode = ConsoleOutputMode::JSON;
139/// let expected_result = "{\"action\":\"cake_eating\",\"result\":\"It was amazing\",\"status\":\"success\",\"src_user\":\"Kani\",\"dest_user\":\"Krabby\"}";
140/// assert_eq!(format!("{}", msg), expected_result);
141/// ```
142impl fmt::Display for AccountChangeMessage {
143 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
144 match self.output_mode {
145 ConsoleOutputMode::JSON => write!(
146 f,
147 "{}",
148 serde_json::to_string(self).unwrap_or(format!("{:?}", self)) /* if it fails to JSON serialize, just debug-dump it */
149 ),
150 ConsoleOutputMode::Text => write!(
151 f,
152 "{} - {} for {}: {}",
153 self.status, self.action, self.dest_user, self.result,
154 ),
155 }
156 }
157}
158
159#[derive(Debug, Serialize, Deserialize)]
160pub struct BasicMessage {
161 #[serde(skip_serializing)]
162 pub output_mode: ConsoleOutputMode,
163 pub action: String,
164 pub result: String,
165 pub status: MessageStatus,
166}
167
168impl Default for BasicMessage {
169 fn default() -> Self {
170 BasicMessage {
171 output_mode: ConsoleOutputMode::Text,
172 action: String::from(""),
173 result: String::from(""),
174 status: MessageStatus::Success,
175 }
176 }
177}
178
179/// This outputs in either JSON or Text depending on the output_mode setting
180/// ```
181/// use kanidm_proto::messages::*;
182/// use std::fmt::format;
183/// let mut msg = BasicMessage::default();
184/// msg.action = String::from("cake_eating");
185/// msg.result = String::from("It was amazing");
186/// assert_eq!(msg.status, MessageStatus::Success);
187///
188/// let expected_result = "success - cake_eating: It was amazing";
189/// assert_eq!(format!("{}", msg), expected_result);
190///
191/// msg.output_mode = ConsoleOutputMode::JSON;
192/// let expected_result =
193/// "{\"action\":\"cake_eating\",\"result\":\"It was amazing\",\"status\":\"success\"}";
194/// assert_eq!(format!("{}", msg), expected_result);
195/// ```
196impl fmt::Display for BasicMessage {
197 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
198 match self.output_mode {
199 ConsoleOutputMode::JSON => write!(
200 f,
201 "{}",
202 serde_json::to_string(self).unwrap_or(format!("{:?}", self)) /* if it fails to JSON serialize, just debug-dump it */
203 ),
204 ConsoleOutputMode::Text => {
205 write!(f, "{} - {}: {}", self.status, self.action, self.result,)
206 }
207 }
208 }
209}