1use crate::id::Uid;
2use serde::{Deserialize, Serialize};
3use std::collections::BTreeMap;
4
5#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
11#[serde(try_from = "ValueRepr", into = "ValueRepr")]
12pub enum Value {
13 Text(String),
14 Number(f64),
15 Json(serde_json::Value),
16}
17
18#[derive(Serialize, Deserialize)]
19enum ValueRepr {
20 Text(String),
21 Number(f64),
22 Json(String),
23}
24
25impl From<Value> for ValueRepr {
26 fn from(v: Value) -> Self {
27 match v {
28 Value::Text(s) => ValueRepr::Text(s),
29 Value::Number(n) => ValueRepr::Number(n),
30 Value::Json(j) => ValueRepr::Json(j.to_string()),
31 }
32 }
33}
34
35impl TryFrom<ValueRepr> for Value {
36 type Error = String;
37
38 fn try_from(r: ValueRepr) -> Result<Self, Self::Error> {
39 Ok(match r {
40 ValueRepr::Text(s) => Value::Text(s),
41 ValueRepr::Number(n) => Value::Number(n),
42 ValueRepr::Json(s) => Value::Json(serde_json::from_str(&s).map_err(|e| e.to_string())?),
43 })
44 }
45}
46
47impl Value {
48 pub fn kind(&self) -> ValueKind {
49 match self {
50 Value::Text(_) => ValueKind::Text,
51 Value::Number(_) => ValueKind::Number,
52 Value::Json(_) => ValueKind::Json,
53 }
54 }
55
56 pub fn canonical_bytes(&self) -> Vec<u8> {
58 match self {
59 Value::Text(s) => s.as_bytes().to_vec(),
60 Value::Number(n) => format!("{n}").into_bytes(),
61 Value::Json(v) => v.to_string().into_bytes(),
62 }
63 }
64}
65
66#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
67pub enum ValueKind {
68 Text,
69 Number,
70 Json,
71}
72
73#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
75pub enum StoredValue {
76 Plain(Value),
77 Sha256(String),
82 Hmac {
88 key_version: u32,
91 digest: String,
92 },
93 Rsa {
99 key_version: u32,
102 wrapped_key: String,
103 nonce: String,
104 ciphertext: String,
105 },
106}
107
108#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
110#[serde(try_from = "ContentRepr", into = "ContentRepr")]
111pub enum Content {
112 Text(String),
113 Json(serde_json::Value),
114}
115
116#[derive(Serialize, Deserialize)]
117enum ContentRepr {
118 Text(String),
119 Json(String),
120}
121
122impl From<Content> for ContentRepr {
123 fn from(c: Content) -> Self {
124 match c {
125 Content::Text(s) => ContentRepr::Text(s),
126 Content::Json(j) => ContentRepr::Json(j.to_string()),
127 }
128 }
129}
130
131impl TryFrom<ContentRepr> for Content {
132 type Error = String;
133
134 fn try_from(r: ContentRepr) -> Result<Self, Self::Error> {
135 Ok(match r {
136 ContentRepr::Text(s) => Content::Text(s),
137 ContentRepr::Json(s) => {
138 Content::Json(serde_json::from_str(&s).map_err(|e| e.to_string())?)
139 }
140 })
141 }
142}
143
144#[derive(Debug, Clone, Serialize, Deserialize)]
149pub struct AuditLog {
150 pub log_id: Uid,
151 pub timestamp: u64,
153 pub actor: Uid,
155 pub actor_type: String,
156 pub method: String,
158 pub url: String,
160 pub content: Content,
161 pub custom: BTreeMap<String, Value>,
164}
165
166#[derive(Debug, Clone, Serialize, Deserialize)]
170pub struct TargetRelation {
171 pub log_id: Uid,
172 pub entity_registry_uid: Uid,
173 pub entity_type: String,
174}