kanidmd_lib/be/
dbentry.rs

1use std::collections::BTreeMap;
2use std::time::Duration;
3
4use serde::{Deserialize, Serialize};
5use uuid::Uuid;
6
7use super::dbrepl::{DbEntryChangeState, DbReplMeta};
8use super::dbvalue::DbValueSetV2;
9use super::keystorage::{KeyHandle, KeyHandleId};
10use crate::prelude::entries::Attribute;
11
12// REMEMBER: If you add a new version here, you MUST
13// update entry.rs to_dbentry to export to the latest
14// type always!!
15#[derive(Serialize, Deserialize, Debug)]
16pub enum DbEntryVers {
17    V3 {
18        changestate: DbEntryChangeState,
19        attrs: BTreeMap<Attribute, DbValueSetV2>,
20    },
21}
22
23#[derive(Serialize, Deserialize, Debug)]
24// This doesn't need a version since uuid2spn is reindexed - remember if you change this
25// though, to change the index version!
26pub enum DbIdentSpn {
27    #[serde(rename = "SP")]
28    Spn(String, String),
29    #[serde(rename = "N8")]
30    Iname(String),
31    #[serde(rename = "UU")]
32    Uuid(Uuid),
33}
34
35// This is actually what we store into the DB.
36#[derive(Serialize, Deserialize)]
37pub struct DbEntry {
38    pub ent: DbEntryVers,
39}
40
41#[derive(Serialize, Deserialize)]
42#[serde(untagged)]
43pub enum DbBackup {
44    // Because of untagged, this has to be in order of newest
45    // to oldest as untagged does a first-match when deserialising.
46    V5 {
47        version: String,
48        db_s_uuid: Uuid,
49        db_d_uuid: Uuid,
50        db_ts_max: Duration,
51        keyhandles: BTreeMap<KeyHandleId, KeyHandle>,
52        repl_meta: DbReplMeta,
53        entries: Vec<DbEntry>,
54    },
55    V4 {
56        db_s_uuid: Uuid,
57        db_d_uuid: Uuid,
58        db_ts_max: Duration,
59        keyhandles: BTreeMap<KeyHandleId, KeyHandle>,
60        repl_meta: DbReplMeta,
61        entries: Vec<DbEntry>,
62    },
63    V3 {
64        db_s_uuid: Uuid,
65        db_d_uuid: Uuid,
66        db_ts_max: Duration,
67        keyhandles: BTreeMap<KeyHandleId, KeyHandle>,
68        entries: Vec<DbEntry>,
69    },
70    V2 {
71        db_s_uuid: Uuid,
72        db_d_uuid: Uuid,
73        db_ts_max: Duration,
74        entries: Vec<DbEntry>,
75    },
76    V1(Vec<DbEntry>),
77}
78
79impl std::fmt::Debug for DbEntry {
80    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
81        match &self.ent {
82            DbEntryVers::V3 { changestate, attrs } => {
83                write!(f, "v3 - {{ ")?;
84                match changestate {
85                    DbEntryChangeState::V1Live { at, changes } => {
86                        writeln!(f, "\nlive {at:>32}")?;
87                        for (attr, cid) in changes {
88                            write!(f, "\n{attr:>32} - {cid} ")?;
89                            if let Some(vs) = attrs.get(attr) {
90                                write!(f, "{vs:?}")?;
91                            } else {
92                                write!(f, "-")?;
93                            }
94                        }
95                    }
96                    DbEntryChangeState::V1Tombstone { at } => {
97                        writeln!(f, "\ntombstone {at:>32?}")?;
98                    }
99                }
100                write!(f, "\n        }}")
101            }
102        }
103    }
104}
105
106impl std::fmt::Display for DbEntry {
107    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
108        match &self.ent {
109            DbEntryVers::V3 { changestate, attrs } => {
110                write!(f, "v3 - {{ ")?;
111                match attrs.get(&Attribute::Uuid) {
112                    Some(uuids) => {
113                        write!(f, "{uuids:?}, ")?;
114                    }
115                    None => write!(f, "Uuid(INVALID), ")?,
116                };
117
118                match changestate {
119                    DbEntryChangeState::V1Live { at, changes: _ } => {
120                        write!(f, "created: {at}, ")?;
121                        if let Some(names) = attrs.get(&Attribute::Name) {
122                            write!(f, "{names:?}, ")?;
123                        }
124                        if let Some(names) = attrs.get(&Attribute::AttributeName) {
125                            write!(f, "{names:?}, ")?;
126                        }
127                        if let Some(names) = attrs.get(&Attribute::ClassName) {
128                            write!(f, "{names:?}, ")?;
129                        }
130                    }
131                    DbEntryChangeState::V1Tombstone { at } => {
132                        write!(f, "tombstoned: {at}, ")?;
133                    }
134                }
135                write!(f, "}}")
136            }
137        }
138    }
139}