]> git.proxmox.com Git - proxmox.git/blame - proxmox-tfa/src/types.rs
proxmox-tfa: derive Copy, Clone and PartialEq on TfaType (for GUI)
[proxmox.git] / proxmox-tfa / src / types.rs
CommitLineData
0d942e81
WB
1use serde::{Deserialize, Serialize};
2
3#[cfg(feature = "api-types")]
4use 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")]
10pub 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}
22serde_plain::derive_display_from_serialize!(TfaType);
23serde_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)]
29pub 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
46const fn default_tfa_enable() -> bool {
47 true
48}
49
50const fn is_default_tfa_enable(v: &bool) -> bool {
51 *v
52}
53
54impl 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)]
78pub 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)]
100pub 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
116impl TfaUpdateInfo {
117 pub(crate) fn with_id(id: String) -> Self {
118 Self {
119 id: Some(id),
120 ..Default::default()
121 }
122 }
123}