1use serde::Deserialize;
2use serde_with::serde_as;
3use serde_with::NoneAsEmptyString;
4
5use super::request::Parameters;
6
7structstruck::strike! {
8 #[strikethrough[serde_as]]
9 #[strikethrough[derive(Debug, Deserialize)]]
10 #[serde(rename_all = "snake_case")]
11 #[serde(tag = "result")]
12 pub enum PreauthResponse {
13 Auth {
14 devices: Vec<pub struct Device {
15 pub capabilities: Option<Vec<pub enum DeviceCapability {
16 #![derive(PartialEq, Eq, PartialOrd, Ord)]
17 #![serde(rename_all = "snake_case")]
18
19 Auto,
20 Push,
21 Sms,
22 Phone,
23 MobileOtp,
24 }>>,
25 pub device: String,
26 pub display_name: Option<String>,
27 #[serde_as(as = "NoneAsEmptyString")]
28 pub name: Option<String>,
29 #[serde_as(as = "NoneAsEmptyString")]
30 pub number: Option<String>,
31 pub sms_nextcode: Option<String>,
32 pub r#type: pub enum DeviceType {
33 #![derive(PartialEq, Eq, PartialOrd, Ord)]
34 #![serde(rename_all = "snake_case")]
35
36 Phone,
37 Token,
38 },
39
40 }>,
41 },
42 Enroll {
43 enroll_portal_url: String,
44 },
45 Allow,
46 Deny,
47 }
48}
49
50structstruck::strike! {
51 #[strikethrough[serde_as]]
52 #[strikethrough[derive(Deserialize, Debug)]]
53 pub struct AuthStatusResponse {
54 pub result: pub enum AuthResult {
55 #![serde(rename_all = "snake_case")]
56
57 Allow,
58 Deny,
59 Waiting,
60 },
61 pub status: pub enum AuthStatus {
62 #![serde(rename_all = "snake_case")]
63
64 Calling,
65 Answered,
66 Pushed,
67 PushFailed,
68 Timeout,
69 Fraud,
70 Allow,
71 Bypass,
72 Deny,
73 LockedOut,
74 Sent,
75 },
76 pub status_msg: String,
77 pub trusted_device_token: Option<String>,
78 }
79}
80
81impl AuthStatusResponse {
82 pub fn ready(&self) -> Option<bool> {
83 match self.result {
84 AuthResult::Allow => Some(true),
85 AuthResult::Deny => Some(false),
86 AuthResult::Waiting => None,
87 }
88 }
89}
90
91#[derive(Clone, Debug)]
92pub enum User {
93 UserId { id: String },
94 Username { username: String },
95}
96
97impl User {
98 pub(crate) fn apply(self, parameters: &mut Parameters) {
99 match self {
100 Self::UserId { id } => parameters.set("user_id", id),
101 Self::Username { username } => parameters.set("username", username),
102 };
103 }
104
105 pub fn user_id<S: Into<String>>(id: S) -> Self {
106 Self::UserId { id: id.into() }
107 }
108
109 pub fn username<S: Into<String>>(username: S) -> Self {
110 Self::Username {
111 username: username.into(),
112 }
113 }
114}
115
116#[derive(Clone, Debug)]
117pub struct PreauthRequest {
118 pub user: User,
119 pub ipaddr: Option<String>,
120 pub hostname: Option<String>,
121 pub trusted_device_token: Option<String>,
122}
123
124impl PreauthRequest {
125 pub fn new(user: User) -> Self {
126 Self {
127 user,
128 ipaddr: None,
129 hostname: None,
130 trusted_device_token: None,
131 }
132 }
133
134 pub(crate) fn apply(self, parameters: &mut Parameters) {
135 self.user.apply(parameters);
136 parameters.set_opt("ipaddr", self.ipaddr);
137 parameters.set_opt("hostname", self.hostname);
138 parameters.set_opt("trusted_device_token", self.trusted_device_token);
139 }
140}
141
142structstruck::strike! {
143 #[strikethrough[derive(Clone, Debug)]]
144 pub struct AuthRequest {
145 pub user: User,
146 pub factor: pub enum AuthRequestFactor {
147 Auto {
148 device: Option<String>,
149 r#type: Option<String>,
150 display_username: Option<String>,
151 push_info: Option<String>,
152 },
153 Push {
154 device: String,
155 r#type: Option<String>,
156 display_username: Option<String>,
157 push_info: Option<String>,
158 },
159 Passcode { passcode: String },
160 Phone { device: String },
161 Sms { device: String },
162 },
163 pub ipaddr: Option<String>,
164 pub hostname: Option<String>,
165 }
166}
167
168impl AuthRequest {
169 pub fn new(user: User, factor: AuthRequestFactor) -> Self {
170 Self {
171 user,
172 factor,
173 ipaddr: None,
174 hostname: None,
175 }
176 }
177
178 pub(crate) fn apply(self, parameters: &mut Parameters) {
179 self.user.apply(parameters);
180 self.factor.apply(parameters);
181 parameters.set_opt("ipaddr", self.ipaddr);
182 parameters.set_opt("hostname", self.hostname);
183 }
184}
185
186impl AuthRequestFactor {
187 pub fn auto() -> Self {
188 Self::Auto {
189 device: Some("auto".into()),
190 r#type: None,
191 display_username: None,
192 push_info: None,
193 }
194 }
195
196 pub(crate) fn apply(self, parameters: &mut Parameters) {
197 match self {
198 Self::Auto {
199 device,
200 r#type,
201 display_username,
202 push_info,
203 } => {
204 parameters.set("factor", "auto");
205 parameters.set_opt("device", device);
206 parameters.set_opt("type", r#type);
207 parameters.set_opt("display_username", display_username);
208 parameters.set_opt("push_info", push_info);
209 }
210 Self::Push {
211 device,
212 r#type,
213 display_username,
214 push_info,
215 } => {
216 parameters.set("factor", "push");
217 parameters.set("device", device);
218 parameters.set_opt("type", r#type);
219 parameters.set_opt("display_username", display_username);
220 parameters.set_opt("push_info", push_info);
221 }
222 Self::Passcode { passcode } => {
223 parameters.set("factor", "passcode");
224 parameters.set("passcode", passcode);
225 }
226 Self::Phone { device } => {
227 parameters.set("factor", "phone");
228 parameters.set("device", device);
229 }
230 Self::Sms { device } => {
231 parameters.set("factor", "sms");
232 parameters.set("device", device);
233 }
234 };
235 }
236}
237
238#[derive(Debug, Deserialize)]
239pub struct EnrollResponse {
240 pub activation_barcode: String,
241 pub activation_code: String,
242 pub expiration: u64,
243 pub user_id: String,
244 pub username: String,
245}
246
247#[derive(Debug, Deserialize)]
248#[serde(rename_all = "snake_case")]
249pub enum EnrollStatusResponse {
250 Success,
251 Invalid,
252 Waiting,
253}