use crate::constants::{
CONTENT_TYPE_GIF, CONTENT_TYPE_JPG, CONTENT_TYPE_PNG, CONTENT_TYPE_SVG, CONTENT_TYPE_WEBP,
};
use clap::ValueEnum;
use serde::{Deserialize, Serialize};
use std::fmt;
use std::str::FromStr;
use url::Url;
use utoipa::ToSchema;
use uuid::Uuid;
use num_enum::TryFromPrimitive;
mod credupdate;
mod error;
mod raw;
mod token;
pub use self::credupdate::*;
pub use self::error::*;
pub use self::raw::*;
pub use self::token::*;
pub const COOKIE_AUTH_SESSION_ID: &str = "auth-session-id";
pub const COOKIE_BEARER_TOKEN: &str = "bearer";
pub const COOKIE_CU_SESSION_TOKEN: &str = "cu-session-token";
pub const COOKIE_USERNAME: &str = "username";
pub const COOKIE_OAUTH2_REQ: &str = "o2-authreq";
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
pub enum AppLink {
Oauth2 {
name: String,
display_name: String,
redirect_url: Url,
has_image: bool,
},
}
#[derive(
Debug, Serialize, Deserialize, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, ToSchema,
)]
#[serde(rename_all = "lowercase")]
#[derive(TryFromPrimitive)]
#[repr(u16)]
pub enum UiHint {
ExperimentalFeatures = 0,
PosixAccount = 1,
CredentialUpdate = 2,
SynchronisedAccount = 3,
}
impl fmt::Display for UiHint {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
UiHint::PosixAccount => write!(f, "PosixAccount"),
UiHint::CredentialUpdate => write!(f, "CredentialUpdate"),
UiHint::ExperimentalFeatures => write!(f, "ExperimentalFeatures"),
UiHint::SynchronisedAccount => write!(f, "SynchronisedAccount"),
}
}
}
impl FromStr for UiHint {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"CredentialUpdate" => Ok(UiHint::CredentialUpdate),
"PosixAccount" => Ok(UiHint::PosixAccount),
"ExperimentalFeatures" => Ok(UiHint::ExperimentalFeatures),
"SynchronisedAccount" => Ok(UiHint::SynchronisedAccount),
_ => Err(()),
}
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, ToSchema)]
pub enum IdentifyUserRequest {
Start,
SubmitCode { other_totp: u32 },
DisplayCode,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, ToSchema)]
pub enum IdentifyUserResponse {
IdentityVerificationUnavailable,
IdentityVerificationAvailable,
ProvideCode { step: u32, totp: u32 },
WaitForCode,
Success,
CodeFailure,
InvalidUserId,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash, Ord, PartialOrd, ValueEnum)]
#[serde(rename_all = "lowercase")]
pub enum ImageType {
Png,
Jpg,
Gif,
Svg,
Webp,
}
impl TryFrom<&str> for ImageType {
type Error = &'static str;
fn try_from(value: &str) -> Result<Self, &'static str> {
#[allow(clippy::panic)]
match value {
"png" => Ok(Self::Png),
"jpg" => Ok(Self::Jpg),
"jpeg" => Ok(Self::Jpg), "gif" => Ok(Self::Gif),
"svg" => Ok(Self::Svg),
"webp" => Ok(Self::Webp),
_ => Err("Invalid image type!"),
}
}
}
impl ImageType {
pub fn try_from_content_type(content_type: &str) -> Result<Self, String> {
let content_type = content_type.to_lowercase();
match content_type.as_str() {
CONTENT_TYPE_JPG => Ok(ImageType::Jpg),
CONTENT_TYPE_PNG => Ok(ImageType::Png),
CONTENT_TYPE_GIF => Ok(ImageType::Gif),
CONTENT_TYPE_WEBP => Ok(ImageType::Webp),
CONTENT_TYPE_SVG => Ok(ImageType::Svg),
_ => Err(format!("Invalid content type: {}", content_type)),
}
}
pub fn as_content_type_str(&self) -> &'static str {
match &self {
ImageType::Jpg => CONTENT_TYPE_JPG,
ImageType::Png => CONTENT_TYPE_PNG,
ImageType::Gif => CONTENT_TYPE_GIF,
ImageType::Webp => CONTENT_TYPE_WEBP,
ImageType::Svg => CONTENT_TYPE_SVG,
}
}
}
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug, PartialOrd, Ord, Hash)]
pub struct ImageValue {
pub filename: String,
pub filetype: ImageType,
pub contents: Vec<u8>,
}
impl TryFrom<&str> for ImageValue {
type Error = String;
fn try_from(s: &str) -> Result<Self, String> {
serde_json::from_str(s)
.map_err(|e| format!("Failed to decode ImageValue from {} - {:?}", s, e))
}
}
impl ImageValue {
pub fn new(filename: String, filetype: ImageType, contents: Vec<u8>) -> Self {
Self {
filename,
filetype,
contents,
}
}
}
#[repr(u32)]
#[derive(Debug, Copy, Clone, Deserialize, Default, Eq, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum FsType {
Zfs = 65536,
#[default]
#[serde(other)]
Generic = 4096,
}
impl FsType {
pub fn checkpoint_pages(&self) -> u32 {
match self {
FsType::Generic => 2048,
FsType::Zfs => 256,
}
}
}
impl TryFrom<&str> for FsType {
type Error = ();
fn try_from(s: &str) -> Result<Self, Self::Error> {
match s {
"zfs" => Ok(FsType::Zfs),
"generic" => Ok(FsType::Generic),
_ => Err(()),
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone, Copy, ToSchema)]
pub enum Oauth2ClaimMapJoin {
#[serde(rename = "csv")]
Csv,
#[serde(rename = "ssv")]
Ssv,
#[serde(rename = "array")]
Array,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct DomainInfo {
pub name: String,
pub displayname: String,
pub uuid: Uuid,
pub level: u32,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct DomainUpgradeCheckReport {
pub name: String,
pub uuid: Uuid,
pub current_level: u32,
pub upgrade_level: u32,
pub report_items: Vec<DomainUpgradeCheckItem>,
}
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub enum DomainUpgradeCheckStatus {
Pass6To7Gidnumber,
Fail6To7Gidnumber,
Pass7To8SecurityKeys,
Fail7To8SecurityKeys,
Pass7To8Oauth2StrictRedirectUri,
Fail7To8Oauth2StrictRedirectUri,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct DomainUpgradeCheckItem {
pub from_level: u32,
pub to_level: u32,
pub status: DomainUpgradeCheckStatus,
pub affected_entries: Vec<String>,
}
#[test]
fn test_fstype_deser() {
assert_eq!(FsType::try_from("zfs"), Ok(FsType::Zfs));
assert_eq!(FsType::try_from("generic"), Ok(FsType::Generic));
assert_eq!(FsType::try_from(" "), Err(()));
assert_eq!(FsType::try_from("crab🦀"), Err(()));
}