Skip to main content

idkollen_client/models/
freja.rs

1use serde::{Deserialize, Serialize};
2
3use super::common::{ApiErrorCode, Country};
4use super::org_number::OrgNumber;
5use super::url::Url;
6
7/// Minimum required Freja eID registration level.
8#[non_exhaustive]
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub enum FrejaRegistrationLevel {
11    /// Standard Freja eID registration (default).
12    #[serde(rename = "EXTENDED")]
13    Extended,
14    /// Enhanced Freja eID+ registration.
15    #[serde(rename = "PLUS")]
16    Plus,
17}
18
19impl Default for FrejaRegistrationLevel {
20    #[inline]
21    fn default() -> Self {
22        Self::Extended
23    }
24}
25
26/// Request body for starting a Freja eID authentication session.
27#[must_use]
28#[derive(Debug, Clone, Default, Serialize)]
29#[serde(rename_all = "camelCase")]
30pub struct FrejaAuthRequest {
31    /// Personal number of the user to authenticate.
32    #[serde(skip_serializing_if = "Option::is_none")]
33    pub ssn: Option<String>,
34    /// URL to receive the result callback on success or failure.
35    #[serde(skip_serializing_if = "Option::is_none")]
36    pub callback_url: Option<Url>,
37    /// Minimum required Freja registration level.
38    #[serde(skip_serializing_if = "Option::is_none")]
39    pub min_registration_level: Option<FrejaRegistrationLevel>,
40    /// Organisation number — enables company signatory check.
41    #[serde(skip_serializing_if = "Option::is_none")]
42    pub org_number: Option<OrgNumber>,
43    /// Fetch the user's registered address on completion.
44    #[serde(skip_serializing_if = "Option::is_none")]
45    pub request_address: Option<bool>,
46    /// Reference ID returned verbatim in the result and callback.
47    #[serde(skip_serializing_if = "Option::is_none")]
48    pub ref_id: Option<String>,
49}
50
51impl FrejaAuthRequest {
52    #[inline]
53    pub fn new() -> Self {
54        Self::default()
55    }
56
57    #[inline]
58    pub fn ssn(mut self, v: impl Into<String>) -> Self {
59        self.ssn = Some(v.into());
60        self
61    }
62
63    #[inline]
64    pub fn callback_url(mut self, url: Url) -> Self {
65        self.callback_url = Some(url);
66        self
67    }
68
69    #[inline]
70    pub fn min_registration_level(mut self, v: FrejaRegistrationLevel) -> Self {
71        self.min_registration_level = Some(v);
72        self
73    }
74
75    #[inline]
76    pub fn org_number(mut self, org_number: OrgNumber) -> Self {
77        self.org_number = Some(org_number);
78        self
79    }
80
81    #[inline]
82    pub fn request_address(mut self, v: bool) -> Self {
83        self.request_address = Some(v);
84        self
85    }
86
87    #[inline]
88    pub fn ref_id(mut self, ref_id: impl Into<String>) -> Self {
89        self.ref_id = Some(ref_id.into());
90        self
91    }
92}
93
94/// Request body for starting a Freja eID backchannel authentication session.
95#[must_use]
96#[derive(Debug, Clone, Serialize)]
97#[serde(rename_all = "camelCase")]
98pub struct FrejaBackchannelAuthRequest {
99    /// Personal number of the user to authenticate.
100    pub ssn: String,
101    /// Country of the user's Freja identity document.
102    pub country: Country,
103    /// URL to receive the result callback on success or failure.
104    #[serde(skip_serializing_if = "Option::is_none")]
105    pub callback_url: Option<Url>,
106    /// Minimum required Freja registration level.
107    pub min_registration_level: FrejaRegistrationLevel,
108    /// Organisation number — enables company signatory check.
109    #[serde(skip_serializing_if = "Option::is_none")]
110    pub org_number: Option<OrgNumber>,
111    /// Fetch the user's registered address on completion.
112    #[serde(skip_serializing_if = "Option::is_none")]
113    pub request_address: Option<bool>,
114    /// Reference ID returned verbatim in the result and callback.
115    #[serde(skip_serializing_if = "Option::is_none")]
116    pub ref_id: Option<String>,
117}
118
119impl FrejaBackchannelAuthRequest {
120    #[inline]
121    pub fn new(
122        ssn: impl Into<String>,
123        country: Country,
124        min_registration_level: FrejaRegistrationLevel,
125    ) -> Self {
126        Self {
127            ssn: ssn.into(),
128            country,
129            min_registration_level,
130            callback_url: None,
131            org_number: None,
132            request_address: None,
133            ref_id: None,
134        }
135    }
136
137    #[inline]
138    pub fn callback_url(mut self, url: Url) -> Self {
139        self.callback_url = Some(url);
140        self
141    }
142
143    #[inline]
144    pub fn org_number(mut self, org_number: OrgNumber) -> Self {
145        self.org_number = Some(org_number);
146        self
147    }
148
149    #[inline]
150    pub fn request_address(mut self, v: bool) -> Self {
151        self.request_address = Some(v);
152        self
153    }
154
155    #[inline]
156    pub fn ref_id(mut self, ref_id: impl Into<String>) -> Self {
157        self.ref_id = Some(ref_id.into());
158        self
159    }
160}
161
162/// Request body for starting a Freja eID signing session.
163#[must_use]
164#[derive(Debug, Clone, Serialize)]
165#[serde(rename_all = "camelCase")]
166pub struct FrejaSignRequest {
167    /// Text to sign, displayed to the user in the Freja app.
168    pub text: String,
169    /// Personal number of the user to sign.
170    #[serde(skip_serializing_if = "Option::is_none")]
171    pub ssn: Option<String>,
172    /// URL to receive the result callback on success or failure.
173    #[serde(skip_serializing_if = "Option::is_none")]
174    pub callback_url: Option<Url>,
175    /// Minimum required Freja registration level.
176    #[serde(skip_serializing_if = "Option::is_none")]
177    pub min_registration_level: Option<FrejaRegistrationLevel>,
178    /// Organisation number — enables company signatory check.
179    #[serde(skip_serializing_if = "Option::is_none")]
180    pub org_number: Option<OrgNumber>,
181    /// Fetch the user's registered address on completion.
182    #[serde(skip_serializing_if = "Option::is_none")]
183    pub request_address: Option<bool>,
184    /// Reference ID returned verbatim in the result and callback.
185    #[serde(skip_serializing_if = "Option::is_none")]
186    pub ref_id: Option<String>,
187}
188
189impl FrejaSignRequest {
190    #[inline]
191    pub fn new(text: impl Into<String>) -> Self {
192        Self {
193            text: text.into(),
194            ssn: None,
195            callback_url: None,
196            min_registration_level: None,
197            org_number: None,
198            request_address: None,
199            ref_id: None,
200        }
201    }
202
203    #[inline]
204    pub fn ssn(mut self, v: impl Into<String>) -> Self {
205        self.ssn = Some(v.into());
206        self
207    }
208
209    #[inline]
210    pub fn callback_url(mut self, url: Url) -> Self {
211        self.callback_url = Some(url);
212        self
213    }
214
215    #[inline]
216    pub fn min_registration_level(mut self, v: FrejaRegistrationLevel) -> Self {
217        self.min_registration_level = Some(v);
218        self
219    }
220
221    #[inline]
222    pub fn org_number(mut self, org_number: OrgNumber) -> Self {
223        self.org_number = Some(org_number);
224        self
225    }
226
227    #[inline]
228    pub fn request_address(mut self, v: bool) -> Self {
229        self.request_address = Some(v);
230        self
231    }
232
233    #[inline]
234    pub fn ref_id(mut self, ref_id: impl Into<String>) -> Self {
235        self.ref_id = Some(ref_id.into());
236        self
237    }
238}
239
240/// Request body for starting a Freja eID backchannel signing session.
241#[must_use]
242#[derive(Debug, Clone, Serialize)]
243#[serde(rename_all = "camelCase")]
244pub struct FrejaBackchannelSignRequest {
245    /// Personal number of the user to sign.
246    pub ssn: String,
247    /// Country of the user's Freja identity document.
248    pub country: Country,
249    /// Text to sign, displayed to the user in the Freja app.
250    pub text: String,
251    /// URL to receive the result callback on success or failure.
252    #[serde(skip_serializing_if = "Option::is_none")]
253    pub callback_url: Option<Url>,
254    /// Minimum required Freja registration level.
255    #[serde(skip_serializing_if = "Option::is_none")]
256    pub min_registration_level: Option<FrejaRegistrationLevel>,
257    /// Organisation number — enables company signatory check.
258    #[serde(skip_serializing_if = "Option::is_none")]
259    pub org_number: Option<OrgNumber>,
260    /// Fetch the user's registered address on completion.
261    #[serde(skip_serializing_if = "Option::is_none")]
262    pub request_address: Option<bool>,
263    /// Reference ID returned verbatim in the result and callback.
264    #[serde(skip_serializing_if = "Option::is_none")]
265    pub ref_id: Option<String>,
266}
267
268impl FrejaBackchannelSignRequest {
269    #[inline]
270    pub fn new(ssn: impl Into<String>, country: Country, text: impl Into<String>) -> Self {
271        Self {
272            ssn: ssn.into(),
273            country,
274            text: text.into(),
275            callback_url: None,
276            min_registration_level: None,
277            org_number: None,
278            request_address: None,
279            ref_id: None,
280        }
281    }
282
283    #[inline]
284    pub fn callback_url(mut self, url: Url) -> Self {
285        self.callback_url = Some(url);
286        self
287    }
288
289    #[inline]
290    pub fn min_registration_level(mut self, v: FrejaRegistrationLevel) -> Self {
291        self.min_registration_level = Some(v);
292        self
293    }
294
295    #[inline]
296    pub fn org_number(mut self, org_number: OrgNumber) -> Self {
297        self.org_number = Some(org_number);
298        self
299    }
300
301    #[inline]
302    pub fn request_address(mut self, v: bool) -> Self {
303        self.request_address = Some(v);
304        self
305    }
306
307    #[inline]
308    pub fn ref_id(mut self, ref_id: impl Into<String>) -> Self {
309        self.ref_id = Some(ref_id.into());
310        self
311    }
312}
313
314/// Freja eID session status.
315#[non_exhaustive]
316#[derive(Debug, Clone, Deserialize)]
317#[serde(tag = "status")]
318pub enum FrejaStatus {
319    #[serde(rename = "PENDING")]
320    Pending(FrejaPending),
321    #[serde(rename = "COMPLETED")]
322    Completed(FrejaCompleted),
323    #[serde(rename = "FAILED")]
324    Failed(FrejaFailed),
325}
326
327/// Returned while the user has not yet acted in the Freja app.
328#[derive(Debug, Clone, Deserialize)]
329#[serde(rename_all = "camelCase")]
330pub struct FrejaPending {
331    pub id: String,
332    pub ref_id: Option<String>,
333    /// Freja transaction reference — also used as the autostart token. Absent in backchannel flows.
334    pub auto_start_token: Option<String>,
335    /// Data string to render as the Freja QR code. Absent in backchannel flows.
336    pub qr_data: Option<String>,
337}
338
339/// Returned when the Freja eID session has completed successfully.
340#[derive(Debug, Clone, Deserialize)]
341#[serde(rename_all = "camelCase")]
342pub struct FrejaCompleted {
343    pub id: String,
344    pub ref_id: Option<String>,
345    pub ssn: String,
346    /// Country of the user's identity document (e.g. `SWEDEN`).
347    pub country: Country,
348    pub name: String,
349    pub given_name: String,
350    pub surname: String,
351    /// Present only when `request_address` was `true`.
352    pub address: Option<String>,
353    /// Present only when `org_number` was provided.
354    pub company_signatory_text: Option<String>,
355}
356
357/// Returned when the Freja eID session has failed.
358#[derive(Debug, Clone, Deserialize)]
359#[serde(rename_all = "camelCase")]
360pub struct FrejaFailed {
361    pub id: String,
362    pub ref_id: Option<String>,
363    pub error: ApiErrorCode,
364}