1use crate::constants::{
6 CONTENT_TYPE_GIF, CONTENT_TYPE_JPG, CONTENT_TYPE_PNG, CONTENT_TYPE_SVG, CONTENT_TYPE_WEBP,
7};
8use clap::ValueEnum;
9use serde::{Deserialize, Serialize};
10use std::fmt;
11use std::str::FromStr;
12use url::Url;
13use utoipa::ToSchema;
14use uuid::Uuid;
15
16use num_enum::TryFromPrimitive;
17
18mod credupdate;
19mod error;
20mod raw;
21mod token;
22
23pub use self::credupdate::*;
24pub use self::error::*;
25pub use self::raw::*;
26pub use self::token::*;
27
28pub const COOKIE_AUTH_SESSION_ID: &str = "auth-session-id";
29pub const COOKIE_BEARER_TOKEN: &str = "bearer";
30pub const COOKIE_CU_SESSION_TOKEN: &str = "cu-session-token";
31pub const COOKIE_USERNAME: &str = "username";
32pub const COOKIE_OAUTH2_REQ: &str = "o2-authreq";
33
34#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
35pub enum AppLink {
38 Oauth2 {
39 name: String,
40 display_name: String,
41 redirect_url: Url,
42 has_image: bool,
44 },
45}
46
47#[derive(
48 Debug, Serialize, Deserialize, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, ToSchema,
49)]
50#[serde(rename_all = "lowercase")]
51#[derive(TryFromPrimitive)]
52#[repr(u16)]
53pub enum UiHint {
54 ExperimentalFeatures = 0,
55 PosixAccount = 1,
56 CredentialUpdate = 2,
57 SynchronisedAccount = 3,
58}
59
60impl fmt::Display for UiHint {
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 match self {
63 UiHint::PosixAccount => write!(f, "PosixAccount"),
64 UiHint::CredentialUpdate => write!(f, "CredentialUpdate"),
65 UiHint::ExperimentalFeatures => write!(f, "ExperimentalFeatures"),
66 UiHint::SynchronisedAccount => write!(f, "SynchronisedAccount"),
67 }
68 }
69}
70
71impl FromStr for UiHint {
72 type Err = ();
73
74 fn from_str(s: &str) -> Result<Self, Self::Err> {
75 match s {
76 "CredentialUpdate" => Ok(UiHint::CredentialUpdate),
77 "PosixAccount" => Ok(UiHint::PosixAccount),
78 "ExperimentalFeatures" => Ok(UiHint::ExperimentalFeatures),
79 "SynchronisedAccount" => Ok(UiHint::SynchronisedAccount),
80 _ => Err(()),
81 }
82 }
83}
84
85#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, ToSchema)]
87pub enum IdentifyUserRequest {
88 Start,
89 SubmitCode { other_totp: u32 },
90 DisplayCode,
91}
92
93#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, ToSchema)]
94pub enum IdentifyUserResponse {
95 IdentityVerificationUnavailable,
96 IdentityVerificationAvailable,
97 ProvideCode { step: u32, totp: u32 },
98 WaitForCode,
99 Success,
100 CodeFailure,
101 InvalidUserId,
102}
103
104#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash, Ord, PartialOrd, ValueEnum)]
105#[serde(rename_all = "lowercase")]
106pub enum ImageType {
107 Png,
108 Jpg,
109 Gif,
110 Svg,
111 Webp,
112}
113
114impl TryFrom<&str> for ImageType {
115 type Error = &'static str;
116 fn try_from(value: &str) -> Result<Self, &'static str> {
122 #[allow(clippy::panic)]
123 match value {
124 "png" => Ok(Self::Png),
125 "jpg" => Ok(Self::Jpg),
126 "jpeg" => Ok(Self::Jpg), "gif" => Ok(Self::Gif),
128 "svg" => Ok(Self::Svg),
129 "webp" => Ok(Self::Webp),
130 _ => Err("Invalid image type!"),
131 }
132 }
133}
134
135impl ImageType {
136 pub fn try_from_content_type(content_type: &str) -> Result<Self, String> {
137 let content_type = content_type.to_lowercase();
138 match content_type.as_str() {
139 CONTENT_TYPE_JPG => Ok(ImageType::Jpg),
140 CONTENT_TYPE_PNG => Ok(ImageType::Png),
141 CONTENT_TYPE_GIF => Ok(ImageType::Gif),
142 CONTENT_TYPE_WEBP => Ok(ImageType::Webp),
143 CONTENT_TYPE_SVG => Ok(ImageType::Svg),
144 _ => Err(format!("Invalid content type: {content_type}")),
145 }
146 }
147
148 pub fn as_content_type_str(&self) -> &'static str {
149 match &self {
150 ImageType::Jpg => CONTENT_TYPE_JPG,
151 ImageType::Png => CONTENT_TYPE_PNG,
152 ImageType::Gif => CONTENT_TYPE_GIF,
153 ImageType::Webp => CONTENT_TYPE_WEBP,
154 ImageType::Svg => CONTENT_TYPE_SVG,
155 }
156 }
157}
158
159#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug, PartialOrd, Ord, Hash)]
160pub struct ImageValue {
161 pub filename: String,
162 pub filetype: ImageType,
163 pub contents: Vec<u8>,
164}
165
166impl TryFrom<&str> for ImageValue {
167 type Error = String;
168 fn try_from(s: &str) -> Result<Self, String> {
169 serde_json::from_str(s).map_err(|e| format!("Failed to decode ImageValue from {s} - {e:?}"))
170 }
171}
172
173impl ImageValue {
174 pub fn new(filename: String, filetype: ImageType, contents: Vec<u8>) -> Self {
175 Self {
176 filename,
177 filetype,
178 contents,
179 }
180 }
181}
182
183#[repr(u32)]
184#[derive(Debug, Copy, Clone, Deserialize, Default, Eq, PartialEq)]
185#[serde(rename_all = "lowercase")]
186pub enum FsType {
188 Zfs = 65536,
189 #[default]
190 #[serde(other)]
191 Generic = 4096,
193}
194
195impl FsType {
196 pub fn checkpoint_pages(&self) -> u32 {
197 match self {
198 FsType::Generic => 2048,
199 FsType::Zfs => 256,
200 }
201 }
202}
203
204impl TryFrom<&str> for FsType {
205 type Error = ();
206
207 fn try_from(s: &str) -> Result<Self, Self::Error> {
208 match s {
209 "zfs" => Ok(FsType::Zfs),
210 "generic" => Ok(FsType::Generic),
211 _ => Err(()),
212 }
213 }
214}
215
216#[derive(Debug, Serialize, Deserialize, Clone, Copy, ToSchema)]
217pub enum Oauth2ClaimMapJoin {
218 #[serde(rename = "csv")]
219 Csv,
220 #[serde(rename = "ssv")]
221 Ssv,
222 #[serde(rename = "array")]
223 Array,
224}
225
226#[derive(Debug, Serialize, Deserialize, Clone)]
227pub struct DomainInfo {
228 pub name: String,
229 pub displayname: String,
230 pub uuid: Uuid,
231 pub level: u32,
232}
233
234#[derive(Debug, Serialize, Deserialize, Clone)]
235pub struct DomainUpgradeCheckReport {
236 pub name: String,
237 pub uuid: Uuid,
238 pub current_level: u32,
239 pub upgrade_level: u32,
240 pub report_items: Vec<DomainUpgradeCheckItem>,
241}
242
243#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
244pub enum DomainUpgradeCheckStatus {
245 Pass6To7Gidnumber,
246 Fail6To7Gidnumber,
247
248 Pass7To8SecurityKeys,
249 Fail7To8SecurityKeys,
250
251 Pass7To8Oauth2StrictRedirectUri,
252 Fail7To8Oauth2StrictRedirectUri,
253}
254
255#[derive(Debug, Serialize, Deserialize, Clone)]
256pub struct DomainUpgradeCheckItem {
257 pub from_level: u32,
258 pub to_level: u32,
259 pub status: DomainUpgradeCheckStatus,
260 pub affected_entries: Vec<String>,
261}
262
263#[test]
264fn test_fstype_deser() {
265 assert_eq!(FsType::try_from("zfs"), Ok(FsType::Zfs));
266 assert_eq!(FsType::try_from("generic"), Ok(FsType::Generic));
267 assert_eq!(FsType::try_from(" "), Err(()));
268 assert_eq!(FsType::try_from("crab🦀"), Err(()));
269}