1use std::collections::BTreeMap;
6
7use salvo::prelude::*;
8use serde::{Deserialize, Serialize};
9
10use crate::{
11 EventEncryptionAlgorithm, OwnedDeviceId, OwnedDeviceKeyId, OwnedUserId, PrivOwnedStr,
12 serde::{Base64, StringEnum},
13};
14
15#[derive(ToSchema, Deserialize, Serialize, Clone, Debug)]
17pub struct DeviceKeys {
18 pub user_id: OwnedUserId,
22
23 pub device_id: OwnedDeviceId,
27
28 pub algorithms: Vec<EventEncryptionAlgorithm>,
30
31 pub keys: BTreeMap<OwnedDeviceKeyId, String>,
33
34 #[serde(default)]
36 pub signatures: BTreeMap<OwnedUserId, BTreeMap<OwnedDeviceKeyId, String>>,
37
38 #[serde(default, skip_serializing_if = "UnsignedDeviceInfo::is_empty")]
41 pub unsigned: UnsignedDeviceInfo,
42}
43
44impl DeviceKeys {
45 pub fn new(
48 user_id: OwnedUserId,
49 device_id: OwnedDeviceId,
50 algorithms: Vec<EventEncryptionAlgorithm>,
51 keys: BTreeMap<OwnedDeviceKeyId, String>,
52 signatures: BTreeMap<OwnedUserId, BTreeMap<OwnedDeviceKeyId, String>>,
53 ) -> Self {
54 Self {
55 user_id,
56 device_id,
57 algorithms,
58 keys,
59 signatures,
60 unsigned: Default::default(),
61 }
62 }
63}
64
65#[derive(ToSchema, Clone, Debug, Default, Deserialize, Serialize)]
67pub struct UnsignedDeviceInfo {
68 #[serde(skip_serializing_if = "Option::is_none")]
70 pub device_display_name: Option<String>,
71}
72
73impl UnsignedDeviceInfo {
74 pub fn new() -> Self {
76 Default::default()
77 }
78
79 pub fn is_empty(&self) -> bool {
81 self.device_display_name.is_none()
82 }
83}
84
85pub type SignedKeySignatures = BTreeMap<OwnedUserId, BTreeMap<OwnedDeviceKeyId, String>>;
87
88#[derive(ToSchema, Debug, Clone, Serialize, Deserialize)]
90pub struct SignedKey {
91 #[salvo(schema(value_type = String))]
93 pub key: Base64,
94
95 pub signatures: SignedKeySignatures,
97
98 #[serde(default, skip_serializing_if = "crate::serde::is_default")]
100 pub fallback: bool,
101}
102
103impl SignedKey {
104 pub fn new(key: Base64, signatures: SignedKeySignatures) -> Self {
106 Self {
107 key,
108 signatures,
109 fallback: false,
110 }
111 }
112
113 pub fn new_fallback(key: Base64, signatures: SignedKeySignatures) -> Self {
115 Self {
116 key,
117 signatures,
118 fallback: true,
119 }
120 }
121}
122
123#[derive(ToSchema, Debug, Clone, Serialize, Deserialize)]
125#[serde(untagged)]
126pub enum OneTimeKey {
127 SignedKey(SignedKey),
129
130 Key(String),
132}
133
134pub type CrossSigningKeySignatures = BTreeMap<OwnedUserId, BTreeMap<OwnedDeviceKeyId, String>>;
136
137#[derive(ToSchema, Deserialize, Serialize, Clone, Debug)]
139pub struct CrossSigningKey {
140 pub user_id: OwnedUserId,
142
143 pub usage: Vec<KeyUsage>,
145
146 pub keys: BTreeMap<OwnedDeviceKeyId, String>,
150
151 #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
155 pub signatures: CrossSigningKeySignatures,
156}
157
158impl CrossSigningKey {
159 pub fn new(
161 user_id: OwnedUserId,
162 usage: Vec<KeyUsage>,
163 keys: BTreeMap<OwnedDeviceKeyId, String>,
164 signatures: CrossSigningKeySignatures,
165 ) -> Self {
166 Self {
167 user_id,
168 usage,
169 keys,
170 signatures,
171 }
172 }
173}
174
175#[doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/doc/string_enum.md"))]
177#[derive(ToSchema, Clone, PartialEq, Eq, StringEnum)]
178#[palpo_enum(rename_all = "snake_case")]
179pub enum KeyUsage {
180 Master,
182
183 SelfSigning,
185
186 UserSigning,
188
189 #[doc(hidden)]
190 #[salvo(schema(skip))]
191 _Custom(PrivOwnedStr),
192}