dtz_identifier/
apikey_id.rs1static PREFIX: &str = "apikey-";
2
3#[derive(Debug, Clone, PartialEq, Copy)]
4pub struct ApiKeyId {
5 pub id: uuid::Uuid,
6}
7
8impl Default for ApiKeyId {
9 fn default() -> Self {
10 Self {
11 id: uuid::Uuid::new_v4(),
12 }
13 }
14}
15
16impl std::fmt::Display for ApiKeyId {
17 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18 f.write_str(&format!("{PREFIX}{}", self.id))
19 }
20}
21
22impl<'de> serde::Deserialize<'de> for ApiKeyId {
23 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
24 where
25 D: serde::Deserializer<'de>,
26 {
27 struct ApiKeyIdVisitor;
28
29 impl serde::de::Visitor<'_> for ApiKeyIdVisitor {
30 type Value = ApiKeyId;
31
32 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
33 formatter.write_str("a string starting with 'apikey-' followed by a UUID")
34 }
35
36 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
37 where
38 E: serde::de::Error,
39 {
40 if let Some(uuid_str) = value.strip_prefix(PREFIX) {
41 let uuid = uuid::Uuid::parse_str(uuid_str).map_err(E::custom)?;
42 Ok(ApiKeyId { id: uuid })
43 } else {
44 Err(E::custom("invalid format"))
45 }
46 }
47 }
48
49 deserializer.deserialize_str(ApiKeyIdVisitor)
50 }
51}
52
53impl serde::Serialize for ApiKeyId {
54 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
55 where
56 S: serde::Serializer,
57 {
58 serializer.serialize_str(&self.to_string())
59 }
60}
61
62impl From<uuid::Uuid> for ApiKeyId {
63 fn from(id: uuid::Uuid) -> Self {
64 ApiKeyId { id }
65 }
66}
67
68impl TryFrom<&str> for ApiKeyId {
69 type Error = String;
70
71 fn try_from(value: &str) -> Result<Self, Self::Error> {
72 if let Some(uuid_str) = value.strip_prefix(PREFIX) {
73 let uuid =
74 uuid::Uuid::parse_str(uuid_str).map_err(|_e| "invalid format".to_string())?;
75 Ok(ApiKeyId { id: uuid })
76 } else {
77 Err("invalid format".to_string())
78 }
79 }
80}
81
82#[test]
83fn key_invalid_1() {
84 let k = "abc-dsfdg";
85 let apikey: Result<ApiKeyId, String> = ApiKeyId::try_from(k);
86 assert!(apikey.is_err())
87}
88
89#[test]
90fn key_invalid_2() {
91 let k = "apikey-dsfdg";
92 let apikey: Result<ApiKeyId, String> = ApiKeyId::try_from(k);
93 assert!(apikey.is_err())
94}
95
96#[test]
97fn key_valid_1() {
98 let k = "apikey-0190c589-eb70-7980-97cf-af67b3a84116";
99 let apikey: Result<ApiKeyId, String> = ApiKeyId::try_from(k);
100 assert!(apikey.is_ok())
101}
102
103#[test]
104fn key_invalid_3() {
105 let k = "abc-0190c589-eb70-7980-97cf-af67b3a84116";
106 let apikey: Result<ApiKeyId, String> = ApiKeyId::try_from(k);
107 assert!(apikey.is_err())
108}