alibi_core/config/
secrets.rs1use crate::AuthError;
2use indexmap::IndexMap;
3
4#[derive(Clone)]
9pub struct ManagedSecrets {
10 current_version: u64,
11 keys: IndexMap<u64, String>,
12}
13
14impl ManagedSecrets {
15 #[must_use]
16 pub fn new(version: u64, secret: impl Into<String>) -> Self {
17 Self {
18 current_version: version,
19 keys: IndexMap::from([(version, secret.into())]),
20 }
21 }
22
23 #[must_use]
26 pub fn retain(mut self, version: u64, secret: impl Into<String>) -> Self {
27 _ = self.keys.insert(version, secret.into());
28 self
29 }
30
31 #[must_use]
34 pub fn retire(mut self, version: u64) -> Self {
35 if version != self.current_version {
36 _ = self.keys.shift_remove(&version);
37 }
38 self
39 }
40
41 #[must_use]
42 pub const fn current_version(&self) -> u64 {
43 self.current_version
44 }
45
46 #[must_use]
47 pub fn current_secret(&self) -> &str {
48 self.key(self.current_version).unwrap_or_default()
49 }
50
51 #[must_use]
52 pub fn key(&self, version: u64) -> Option<&str> {
53 self.keys.get(&version).map(String::as_str)
54 }
55
56 pub fn verification_secrets(&self) -> impl Iterator<Item = &str> {
57 self.keys.values().map(String::as_str)
58 }
59
60 pub fn validate(&self) -> Result<(), AuthError> {
63 if self
64 .keys
65 .iter()
66 .any(|(version, key)| *version > 9_007_199_254_740_991 || key.is_empty())
67 {
68 return Err(AuthError::config(
69 "Secret versions must be safe nonnegative integers with nonempty keys",
70 ));
71 }
72 if self.current_secret().len() < 32 {
73 return Err(AuthError::config(
74 "Current secret key must be at least 32 characters",
75 ));
76 }
77 Ok(())
78 }
79}
80
81impl std::fmt::Debug for ManagedSecrets {
82 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83 f.debug_struct("ManagedSecrets")
84 .field("current_version", &self.current_version)
85 .field("versions", &self.keys.keys())
86 .finish_non_exhaustive()
87 }
88}