1use crate::custom_error::KSMRError;
14use serde::{Deserialize, Serialize};
15use std::any::Any;
16
17fn custom_pretty_json<T: Serialize>(
18 value: &T,
19 indent_size: usize,
20) -> Result<String, serde_json::Error> {
21 let raw_json = serde_json::to_value(value)?;
22 let mut result = String::new();
23 format_json(&raw_json, &mut result, 0, indent_size);
24 Ok(result)
25}
26
27fn format_json(value: &serde_json::Value, result: &mut String, level: usize, indent_size: usize) {
28 let indent = " ".repeat(level * indent_size);
29 let next_indent = " ".repeat((level + 1) * indent_size);
30
31 match value {
32 serde_json::Value::Object(map) => {
33 result.push_str("{\n");
34 for (i, (key, val)) in map.iter().enumerate() {
35 result.push_str(&next_indent);
36 result.push('"');
37 result.push_str(key);
38 result.push_str("\": ");
39 format_json(val, result, level + 1, indent_size);
40 if i < map.len() - 1 {
41 result.push(',');
42 }
43 result.push('\n');
44 }
45 result.push_str(&indent);
46 result.push('}');
47 }
48 serde_json::Value::Array(array) => {
49 result.push_str("[\n");
50 for (i, val) in array.iter().enumerate() {
51 result.push_str(&next_indent);
52 format_json(val, result, level + 1, indent_size);
53 if i < array.len() - 1 {
54 result.push(',');
55 }
56 result.push('\n');
57 }
58 result.push_str(&indent);
59 result.push(']');
60 }
61 serde_json::Value::String(s) => {
62 result.push('"');
63 result.push_str(s);
64 result.push('"');
65 }
66 serde_json::Value::Number(num) => {
67 result.push_str(&num.to_string());
68 }
69 serde_json::Value::Bool(b) => {
70 result.push_str(&b.to_string());
71 }
72 serde_json::Value::Null => {
73 result.push_str("null");
74 }
75 }
76}
77
78#[derive(Serialize, Deserialize, Debug)]
79pub struct Context {
80 transmission_key: TransmissionKey,
81 client_id: String,
82 client_key: String,
83}
84
85impl Context {
86 pub fn new(transmission_key: TransmissionKey, client_id: String, client_key: String) -> Self {
87 Context {
88 transmission_key,
89 client_id,
90 client_key,
91 }
92 }
93}
94
95#[derive(Serialize, Deserialize, Debug)]
96pub struct TransmissionKey {
97 pub public_key_id: String,
98 pub key: Vec<u8>,
99 pub encrypted_key: Vec<u8>,
100}
101
102impl TransmissionKey {
103 pub fn new(public_key_id: String, key: Vec<u8>, encrypted_key: Vec<u8>) -> Self {
104 TransmissionKey {
105 public_key_id,
106 key,
107 encrypted_key,
108 }
109 }
110}
111
112impl Clone for TransmissionKey {
113 fn clone(&self) -> Self {
114 TransmissionKey {
115 public_key_id: self.public_key_id.clone(),
117 key: self.key.clone(),
118 encrypted_key: self.encrypted_key.clone(),
119 }
120 }
121}
122
123#[derive(Serialize, Deserialize)]
124#[serde(rename_all = "camelCase")]
125pub struct GetPayload {
126 client_version: String,
127 client_id: String,
128 public_key: Option<String>,
129 requested_records: Option<Vec<String>>,
130 requested_folders: Option<Vec<String>>,
131}
132
133impl GetPayload {
134 pub fn new(
135 client_version: String,
136 client_id: String,
137 public_key: Option<String>,
138 requested_records: Option<Vec<String>>,
139 requested_folders: Option<Vec<String>>,
140 ) -> GetPayload {
141 GetPayload {
142 client_version,
143 client_id,
144 public_key,
145 requested_records,
146 requested_folders,
147 }
148 }
149
150 pub fn set_optional_field<T>(&mut self, field: &str, value: T)
151 where
152 T: Into<Option<Vec<String>>>,
153 {
154 match field {
155 "records_filter" => self.requested_records = value.into(),
156 "folders_filter" => self.requested_folders = value.into(),
157 _ => (),
158 }
159 }
160
161 pub fn to_json(&self) -> Result<String, KSMRError> {
162 Ok(custom_pretty_json(&self, 4).unwrap())
163 }
164
165 pub fn from_json(json_data: &str) -> Result<Self, KSMRError> {
166 serde_json::from_str(json_data).map_err(|e| {
167 log::error!("Error deserializing GetPayload from JSON: {}", e);
168 KSMRError::DeserializationError(format!(
169 "Error deserializing GetPayload from JSON: {}",
170 e
171 ))
172 })
173 }
174}
175
176#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, Default)]
177pub enum UpdateTransactionType {
178 #[default]
179 None,
180 General,
181 Rotation,
182}
183
184impl UpdateTransactionType {
191 pub fn as_str(&self) -> &'static str {
192 match self {
193 UpdateTransactionType::None => "",
194 UpdateTransactionType::General => "general",
195 UpdateTransactionType::Rotation => "rotation",
196 }
197 }
198}
199
200impl std::str::FromStr for UpdateTransactionType {
201 type Err = ();
202
203 fn from_str(s: &str) -> Result<Self, Self::Err> {
204 match s {
205 "" => Ok(UpdateTransactionType::None),
206 "general" => Ok(UpdateTransactionType::General),
207 "rotation" => Ok(UpdateTransactionType::Rotation),
208 _ => Err(()),
209 }
210 }
211}
212
213#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
214#[serde(rename_all = "camelCase")]
215pub struct UpdatePayload {
216 pub client_version: String,
217 pub client_id: String,
218 pub record_uid: String,
219 pub revision: i64,
220 pub data: String,
221 #[serde(skip_serializing_if = "Option::is_none")]
222 pub transaction_type: Option<UpdateTransactionType>,
223}
224
225impl UpdatePayload {
226 pub fn new(
227 client_version: String,
228 client_id: String,
229 record_uid: String,
230 revision: i64,
231 data: String,
232 ) -> Self {
233 UpdatePayload {
234 client_version,
235 client_id,
236 record_uid,
237 revision,
238 data,
239 transaction_type: None,
240 }
241 }
242
243 pub fn set_transaction_type(&mut self, transaction_type: UpdateTransactionType) {
244 if transaction_type != UpdateTransactionType::None {
245 self.transaction_type = Some(transaction_type);
246 } else {
247 self.transaction_type = None;
248 }
249 }
250
251 pub fn to_json(&self) -> Result<String, KSMRError> {
253 serde_json::to_string(self).map_err(|err| {
254 KSMRError::SerializationError(format!(
255 "Error serializing UpdatePayload to JSON: {}",
256 err
257 ))
258 })
259 }
260
261 pub fn from_json(json_data: &str) -> Result<Self, KSMRError> {
263 serde_json::from_str(json_data).map_err(|err| {
264 KSMRError::DeserializationError(format!(
265 "Error deserializing UpdatePayload from JSON: {}",
266 err
267 ))
268 })
269 }
270}
271
272#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
273pub struct CompleteTransactionPayload {
274 pub client_version: String,
275 pub client_id: String,
276 pub record_uid: String,
277}
278
279impl CompleteTransactionPayload {
280 pub fn new(client_version: String, client_id: String, record_uid: String) -> Self {
281 CompleteTransactionPayload {
282 client_version,
283 client_id,
284 record_uid,
285 }
286 }
287
288 pub fn to_json(&self) -> Result<String, KSMRError> {
290 serde_json::to_string(self).map_err(|err| {
291 KSMRError::SerializationError(format!(
292 "Error serializing CompleteTransactionPayload to JSON: {}",
293 err
294 ))
295 })
296 }
297
298 pub fn from_json(json_data: &str) -> Result<Self, KSMRError> {
300 serde_json::from_str(json_data).map_err(|err| {
301 KSMRError::DeserializationError(format!(
302 "Error deserializing CompleteTransactionPayload from JSON: {}",
303 err
304 ))
305 })
306 }
307}
308
309#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
310#[serde(rename_all = "camelCase")]
311pub struct CreatePayload {
312 pub client_version: String,
313 pub client_id: String,
314 pub record_uid: String,
315 pub record_key: String,
316 pub folder_uid: String,
317 pub folder_key: String,
318 pub data: String,
319 #[serde(skip_serializing_if = "Option::is_none")]
320 pub sub_folder_uid: Option<String>,
321}
322
323impl CreatePayload {
324 #[allow(clippy::too_many_arguments)]
326 pub fn new(
327 client_version: String,
328 client_id: String,
329 record_uid: String,
330 record_key: String,
331 folder_uid: String,
332 folder_key: String,
333 data: String,
334 sub_folder_uid: Option<String>,
335 ) -> Self {
336 Self {
337 client_version,
338 client_id,
339 record_uid,
340 record_key,
341 folder_uid,
342 folder_key,
343 data,
344 sub_folder_uid,
345 }
346 }
347
348 pub fn to_json(&self) -> Result<String, KSMRError> {
350 serde_json::to_string(self).map_err(|err| {
351 KSMRError::SerializationError(format!(
352 "Error serializing CreatePayload to JSON: {}",
353 err
354 ))
355 })
356 }
357
358 pub fn from_json(json_data: &str) -> Result<Self, KSMRError> {
360 serde_json::from_str(json_data).map_err(|err| {
361 KSMRError::DeserializationError(format!(
362 "Error deserializing CreatePayload from JSON: {}",
363 err
364 ))
365 })
366 }
367}
368
369#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
370#[serde(rename_all = "camelCase")]
371pub struct DeletePayload {
372 pub client_version: String,
373 pub client_id: String,
374 pub record_uids: Vec<String>,
375}
376
377impl DeletePayload {
378 pub fn new(client_version: String, client_id: String, record_uids: Vec<String>) -> Self {
380 Self {
381 client_version,
382 client_id,
383 record_uids,
384 }
385 }
386
387 pub fn to_json(&self) -> Result<String, KSMRError> {
389 serde_json::to_string(self).map_err(|err| {
390 KSMRError::SerializationError(format!(
391 "Error serializing DeletePayload to JSON: {}",
392 err
393 ))
394 })
395 }
396
397 pub fn from_json(json_data: &str) -> Result<Self, KSMRError> {
399 serde_json::from_str(json_data).map_err(|err| {
400 KSMRError::DeserializationError(format!(
401 "Error deserializing DeletePayload from JSON: {}",
402 err
403 ))
404 })
405 }
406}
407
408#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
409#[serde(rename_all = "camelCase")]
410pub struct CreateFolderPayload {
411 pub client_version: String,
412 pub client_id: String,
413 pub folder_uid: String,
414 pub shared_folder_uid: String,
415 pub shared_folder_key: String,
416 pub data: String,
417 pub parent_uid: String,
418}
419
420impl CreateFolderPayload {
421 pub fn new(
422 client_version: String,
423 client_id: String,
424 folder_uid: String,
425 shared_folder_uid: String,
426 shared_folder_key: String,
427 data: String,
428 parent_uid: Option<String>,
429 ) -> Self {
430 match parent_uid {
431 Some(uid) => Self {
432 client_version,
433 client_id,
434 folder_uid,
435 shared_folder_uid,
436 shared_folder_key,
437 data,
438 parent_uid: uid,
439 },
440 None => Self {
441 client_version,
442 client_id,
443 folder_uid,
444 shared_folder_uid,
445 shared_folder_key,
446 data,
447 parent_uid: "".to_string(),
448 },
449 }
450 }
451
452 pub fn to_json(&self) -> Result<String, KSMRError> {
454 Ok(custom_pretty_json(&self, 4).unwrap())
455 }
456
457 pub fn from_json(json_data: &str) -> Result<Self, KSMRError> {
459 serde_json::from_str(json_data).map_err(|err| {
460 KSMRError::DeserializationError(format!(
461 "Error deserializing CreateFolderPayload from JSON: {}",
462 err
463 ))
464 })
465 }
466}
467
468#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
469#[serde(rename_all = "camelCase")]
470pub struct UpdateFolderPayload {
471 pub client_version: String,
472 pub client_id: String,
473 pub folder_uid: String,
474 pub data: String,
475}
476
477impl UpdateFolderPayload {
478 pub fn new(
480 client_version: String,
481 client_id: String,
482 folder_uid: String,
483 data: String,
484 ) -> Self {
485 Self {
486 client_version,
487 client_id,
488 folder_uid,
489 data,
490 }
491 }
492
493 pub fn to_json(&self) -> Result<String, KSMRError> {
495 serde_json::to_string(self).map_err(|err| {
496 KSMRError::SerializationError(format!(
497 "Error serializing UpdateFolderPayload to JSON: {}",
498 err
499 ))
500 })
501 }
502
503 pub fn from_json(json_data: &str) -> Result<Self, KSMRError> {
505 serde_json::from_str(json_data).map_err(|err| {
506 KSMRError::DeserializationError(format!(
507 "Error deserializing UpdateFolderPayload from JSON: {}",
508 err
509 ))
510 })
511 }
512}
513
514#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
515#[serde(rename_all = "camelCase")]
516pub struct DeleteFolderPayload {
517 pub client_version: String,
518 pub client_id: String,
519 pub folder_uids: Vec<String>,
520 pub force_deletion: bool,
521}
522
523impl DeleteFolderPayload {
524 pub fn new(
526 client_version: String,
527 client_id: String,
528 folder_uids: Vec<String>,
529 force_deletion: bool,
530 ) -> Self {
531 Self {
532 client_version,
533 client_id,
534 folder_uids,
535 force_deletion,
536 }
537 }
538
539 pub fn to_json(&self) -> Result<String, KSMRError> {
541 serde_json::to_string(self).map_err(|err| {
542 KSMRError::SerializationError(format!(
543 "Error serializing DeleteFolderPayload to JSON: {}",
544 err
545 ))
546 })
547 }
548
549 pub fn from_json(json_data: &str) -> Result<Self, KSMRError> {
551 serde_json::from_str(json_data).map_err(|err| {
552 KSMRError::DeserializationError(format!(
553 "Error deserializing DeleteFolderPayload from JSON: {}",
554 err
555 ))
556 })
557 }
558}
559
560#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
561#[serde(rename_all = "camelCase")]
562pub struct FileUploadPayload {
563 pub client_version: String,
564 pub client_id: String,
565 pub file_record_uid: String,
566 pub file_record_key: String,
567 pub file_record_data: String,
568 pub owner_record_uid: String,
569 pub owner_record_data: String,
570 pub link_key: String,
571 pub file_size: i32,
572}
573
574impl FileUploadPayload {
575 #[allow(clippy::too_many_arguments)]
577 pub fn new(
578 client_version: String,
579 client_id: String,
580 file_record_uid: String,
581 file_record_key: String,
582 file_record_data: String,
583 owner_record_uid: String,
584 owner_record_data: String,
585 link_key: String,
586 file_size: i32,
587 ) -> Self {
588 Self {
589 client_version,
590 client_id,
591 file_record_uid,
592 file_record_key,
593 file_record_data,
594 owner_record_uid,
595 owner_record_data,
596 link_key,
597 file_size,
598 }
599 }
600
601 pub fn to_json(&self) -> Result<String, KSMRError> {
603 serde_json::to_string(self).map_err(|err| {
604 KSMRError::SerializationError(format!(
605 "Error serializing FileUploadPayload to JSON: {}",
606 err
607 ))
608 })
609 }
610
611 pub fn from_json(json_data: &str) -> Result<Self, KSMRError> {
613 serde_json::from_str(json_data).map_err(|err| {
614 KSMRError::DeserializationError(format!(
615 "Error deserializing FileUploadPayload from JSON: {}",
616 err
617 ))
618 })
619 }
620}
621
622#[derive(Debug, Clone)]
623pub struct EncryptedPayload {
624 pub encrypted_payload: Vec<u8>,
625 pub signature: ecdsa::der::Signature<p256::NistP256>,
626}
627
628impl EncryptedPayload {
629 pub fn new(
631 encrypted_payload: Vec<u8>,
632 signature: ecdsa::der::Signature<p256::NistP256>,
633 ) -> Self {
634 EncryptedPayload {
635 encrypted_payload,
636 signature,
637 }
638 }
639
640 pub fn to_json(&self) -> Result<String, KSMRError> {
641 Err(KSMRError::NotImplemented(
642 "serialization has not been implemented for private keys".to_string(),
643 ))
644 }
645
646 pub fn from_json(json_data: &str) -> Result<Self, KSMRError> {
647 let _ = json_data;
648 Err(KSMRError::NotImplemented(
649 "de-serialization has not been implemented for private keys".to_string(),
650 ))
651 }
652}
653
654#[derive(Debug, Clone)]
655pub struct KsmHttpResponse {
656 pub status_code: u16,
657 pub data: Vec<u8>,
658 pub http_response: Option<String>,
659}
660
661impl KsmHttpResponse {
662 pub fn new(status_code: u16, data: Vec<u8>, http_response: String) -> Self {
664 KsmHttpResponse {
665 status_code,
666 data,
667 http_response: Some(http_response),
668 }
669 }
670}
671
672#[derive(Debug, Clone)]
673pub struct QueryOptions {
674 pub records_filter: Vec<String>,
675 pub folders_filter: Vec<String>,
676}
677
678impl QueryOptions {
679 pub fn new(records_filter: Vec<String>, folders_filter: Vec<String>) -> Self {
680 QueryOptions {
681 records_filter,
682 folders_filter,
683 }
684 }
685
686 pub fn get_records_filter(&self) -> Option<Vec<String>> {
687 match self.records_filter.len() {
688 0 => None,
689 _ => Some(self.records_filter.clone()),
690 }
691 }
692
693 pub fn get_folders_filter(&self) -> Option<Vec<String>> {
694 match self.folders_filter.len() {
695 0 => None,
696 _ => Some(self.folders_filter.clone()),
697 }
698 }
699}
700
701#[derive(Debug, Clone)]
702pub struct CreateOptions {
703 pub folder_uid: String,
704 pub sub_folder_uid: Option<String>,
705}
706
707impl CreateOptions {
708 pub fn new(folder_uid: String, sub_folder_uid: Option<String>) -> Self {
709 CreateOptions {
710 folder_uid,
711 sub_folder_uid,
712 }
713 }
714}
715
716pub trait Payload: Any {
717 fn as_any(&self) -> &dyn Any;
718 fn to_json(&self) -> Result<String, KSMRError>;
719}
720
721macro_rules! impl_payload {
722 ($($type:ty),*) => {
723 $(
724 impl Payload for $type {
725 fn as_any(&self) -> &dyn Any {
726 self
727 }
728
729 fn to_json(&self) -> Result<String, KSMRError> {
730 self.to_json()
731 }
732 }
733 )*
734 };
735}
736
737impl_payload!(
738 GetPayload,
739 UpdatePayload,
740 CreatePayload,
741 FileUploadPayload,
742 CompleteTransactionPayload,
743 DeletePayload,
744 CreateFolderPayload,
745 UpdateFolderPayload,
746 DeleteFolderPayload
747);
748
749fn is_instance_of<T: Any>(payload: &dyn Payload) -> bool {
751 payload.as_any().is::<T>()
752}
753
754pub fn validate_payload(payload: &dyn Payload) -> Result<(), KSMRError> {
756 if is_instance_of::<GetPayload>(payload)
757 || is_instance_of::<UpdatePayload>(payload)
758 || is_instance_of::<CreatePayload>(payload)
759 || is_instance_of::<FileUploadPayload>(payload)
760 || is_instance_of::<CompleteTransactionPayload>(payload)
761 || is_instance_of::<DeletePayload>(payload)
762 || is_instance_of::<CreateFolderPayload>(payload)
763 || is_instance_of::<UpdateFolderPayload>(payload)
764 || is_instance_of::<DeleteFolderPayload>(payload)
765 {
766 Ok(())
767 } else {
768 Err(KSMRError::InvalidPayloadError(format!(
769 "Unknown payload type: {:?}",
770 payload.as_any().type_id()
771 )))
772 }
773}
774
775#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
776#[serde(rename_all = "camelCase")]
777pub struct FileUploadFunctionResult {
778 payload: FileUploadPayload,
779 encrypted_file_data: Vec<u8>,
780}
781
782impl FileUploadFunctionResult {
783 pub fn new(payload: FileUploadPayload, encrypted_file_data: Vec<u8>) -> Self {
784 FileUploadFunctionResult {
785 payload,
786 encrypted_file_data,
787 }
788 }
789
790 pub fn get_encrypted_data(&self) -> Vec<u8> {
791 self.encrypted_file_data.clone()
792 }
793
794 pub fn get_payload(&self) -> FileUploadPayload {
795 self.payload.clone()
796 }
797}