]>
Commit | Line | Data |
---|---|---|
0d942e81 WB |
1 | use serde::{Deserialize, Serialize}; |
2 | ||
3 | #[cfg(feature = "api-types")] | |
4 | use proxmox_schema::api; | |
5 | ||
6 | #[cfg_attr(feature = "api-types", api)] | |
7 | /// A TFA entry type. | |
34e86078 | 8 | #[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq)] |
0d942e81 WB |
9 | #[serde(rename_all = "lowercase")] |
10 | pub enum TfaType { | |
11 | /// A TOTP entry type. | |
12 | Totp, | |
13 | /// A U2F token entry. | |
14 | U2f, | |
15 | /// A Webauthn token entry. | |
16 | Webauthn, | |
17 | /// Recovery tokens. | |
18 | Recovery, | |
19 | /// Yubico authentication entry. | |
20 | Yubico, | |
21 | } | |
22 | serde_plain::derive_display_from_serialize!(TfaType); | |
23 | serde_plain::derive_fromstr_from_deserialize!(TfaType); | |
24 | ||
25 | #[cfg_attr(feature = "api-types", api)] | |
26 | /// Over the API we only provide this part when querying a user's second factor list. | |
27 | #[derive(Clone, Deserialize, Serialize)] | |
28 | #[serde(deny_unknown_fields)] | |
29 | pub struct TfaInfo { | |
30 | /// The id used to reference this entry. | |
31 | pub id: String, | |
32 | ||
33 | /// User chosen description for this entry. | |
34 | #[serde(default, skip_serializing_if = "String::is_empty")] | |
35 | pub description: String, | |
36 | ||
37 | /// Creation time of this entry as unix epoch. | |
38 | pub created: i64, | |
39 | ||
40 | /// Whether this TFA entry is currently enabled. | |
41 | #[serde(skip_serializing_if = "is_default_tfa_enable")] | |
42 | #[serde(default = "default_tfa_enable")] | |
43 | pub enable: bool, | |
44 | } | |
45 | ||
46 | const fn default_tfa_enable() -> bool { | |
47 | true | |
48 | } | |
49 | ||
50 | const fn is_default_tfa_enable(v: &bool) -> bool { | |
51 | *v | |
52 | } | |
53 | ||
54 | impl TfaInfo { | |
55 | /// For recovery keys we have a fixed entry. | |
56 | pub fn recovery(created: i64) -> Self { | |
57 | Self { | |
58 | id: "recovery".to_string(), | |
59 | description: String::new(), | |
60 | enable: true, | |
61 | created, | |
62 | } | |
63 | } | |
64 | } | |
65 | ||
66 | #[cfg_attr( | |
67 | feature = "api-types", | |
68 | api( | |
69 | properties: { | |
70 | type: { type: TfaType }, | |
71 | info: { type: TfaInfo }, | |
72 | }, | |
73 | ) | |
74 | )] | |
75 | /// A TFA entry for a user. | |
76 | #[derive(Deserialize, Serialize)] | |
77 | #[serde(deny_unknown_fields)] | |
78 | pub struct TypedTfaInfo { | |
79 | #[serde(rename = "type")] | |
80 | pub ty: TfaType, | |
81 | ||
82 | #[serde(flatten)] | |
83 | pub info: TfaInfo, | |
84 | } | |
85 | ||
86 | #[cfg_attr(feature = "api-types", api( | |
87 | properties: { | |
88 | recovery: { | |
89 | description: "A list of recovery codes as integers.", | |
90 | type: Array, | |
91 | items: { | |
92 | type: Integer, | |
93 | description: "A one-time usable recovery code entry.", | |
94 | }, | |
95 | }, | |
96 | }, | |
97 | ))] | |
98 | /// The result returned when adding TFA entries to a user. | |
99 | #[derive(Default, Deserialize, Serialize)] | |
100 | pub struct TfaUpdateInfo { | |
101 | /// The id if a newly added TFA entry. | |
102 | pub id: Option<String>, | |
103 | ||
104 | /// When adding u2f entries, this contains a challenge the user must respond to in order to | |
105 | /// finish the registration. | |
106 | #[serde(skip_serializing_if = "Option::is_none")] | |
107 | pub challenge: Option<String>, | |
108 | ||
109 | /// When adding recovery codes, this contains the list of codes to be displayed to the user | |
110 | /// this one time. | |
111 | #[serde(skip_serializing_if = "Vec::is_empty", default)] | |
112 | pub recovery: Vec<String>, | |
113 | } | |
114 | ||
3224f42f | 115 | #[cfg(feature = "api")] |
0d942e81 WB |
116 | impl TfaUpdateInfo { |
117 | pub(crate) fn with_id(id: String) -> Self { | |
118 | Self { | |
119 | id: Some(id), | |
120 | ..Default::default() | |
121 | } | |
122 | } | |
123 | } |