2026-01-31 15:24:36 +01:00
|
|
|
use alloc::{string::String, vec::Vec};
|
|
|
|
|
use chrono::NaiveDateTime;
|
|
|
|
|
use password_hash::Key;
|
|
|
|
|
use serde::{Deserialize, Serialize};
|
2026-02-04 03:14:21 +01:00
|
|
|
use slint::SharedString;
|
2026-01-31 15:24:36 +01:00
|
|
|
use spectre_api_sys::{SpectreAlgorithm, SpectreCounter, SpectreResultType};
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Default, Clone, Debug, PartialEq, Eq)]
|
|
|
|
|
pub struct SpectreUsersConfig {
|
|
|
|
|
pub users: Vec<SpectreUserConfig>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq)]
|
|
|
|
|
pub struct SpectreUserConfig {
|
2026-02-04 03:14:21 +01:00
|
|
|
pub username: SharedString,
|
2026-01-31 15:24:36 +01:00
|
|
|
#[serde(with = "serde_bytes")]
|
|
|
|
|
pub encrypted_key: Key,
|
|
|
|
|
#[serde(with = "serde_bytes")]
|
|
|
|
|
pub key_id: [u8; 32],
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq)]
|
|
|
|
|
pub struct SpectreSiteConfig {
|
|
|
|
|
#[serde(with = "with_repr")]
|
|
|
|
|
pub algorithm: SpectreAlgorithm,
|
|
|
|
|
pub counter: SpectreCounter::Type,
|
|
|
|
|
#[serde(rename = "type")]
|
|
|
|
|
#[serde(with = "with_repr")]
|
|
|
|
|
pub result_type: SpectreResultType,
|
2026-02-04 03:14:21 +01:00
|
|
|
pub password: Option<SharedString>,
|
2026-01-31 15:24:36 +01:00
|
|
|
#[serde(with = "with_repr")]
|
|
|
|
|
pub login_type: SpectreResultType,
|
2026-02-04 03:14:21 +01:00
|
|
|
pub login_name: Option<SharedString>,
|
2026-01-31 15:24:36 +01:00
|
|
|
pub uses: u32,
|
|
|
|
|
pub last_used: NaiveDateTime,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Default for SpectreSiteConfig {
|
|
|
|
|
fn default() -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
algorithm: SpectreAlgorithm::Current,
|
|
|
|
|
counter: SpectreCounter::Default,
|
|
|
|
|
result_type: SpectreResultType::SpectreResultDefaultResult,
|
|
|
|
|
password: None,
|
|
|
|
|
login_type: SpectreResultType::SpectreResultDefaultLogin,
|
|
|
|
|
login_name: None,
|
|
|
|
|
uses: 0,
|
|
|
|
|
last_used: Default::default(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
2026-01-31 15:36:36 +01:00
|
|
|
pub struct SpectreSite {
|
2026-02-04 03:14:21 +01:00
|
|
|
pub username: SharedString,
|
|
|
|
|
pub site_name: SharedString,
|
2026-01-31 15:24:36 +01:00
|
|
|
pub config: SpectreSiteConfig,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mod with_repr {
|
|
|
|
|
use serde::{Deserialize, Deserializer, Serializer};
|
|
|
|
|
use spectre_api_sys::{SpectreAlgorithm, SpectreResultType};
|
|
|
|
|
|
|
|
|
|
pub trait ReprConvert: Copy {
|
|
|
|
|
type Repr: Copy;
|
|
|
|
|
|
|
|
|
|
fn into_repr(self) -> Self::Repr;
|
|
|
|
|
fn from_repr(repr: Self::Repr) -> Self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ReprConvert for SpectreAlgorithm {
|
|
|
|
|
type Repr = u32;
|
|
|
|
|
|
|
|
|
|
fn from_repr(repr: Self::Repr) -> Self {
|
|
|
|
|
unsafe { core::mem::transmute::<Self::Repr, Self>(repr) }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn into_repr(self) -> Self::Repr {
|
|
|
|
|
self as Self::Repr
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ReprConvert for SpectreResultType {
|
|
|
|
|
type Repr = u32;
|
|
|
|
|
|
|
|
|
|
fn from_repr(repr: Self::Repr) -> Self {
|
|
|
|
|
unsafe { core::mem::transmute::<Self::Repr, Self>(repr) }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn into_repr(self) -> Self::Repr {
|
|
|
|
|
self as Self::Repr
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-31 15:36:36 +01:00
|
|
|
#[allow(unused)]
|
2026-01-31 15:24:36 +01:00
|
|
|
pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
|
|
|
|
|
where
|
|
|
|
|
T: ReprConvert<Repr = u32>,
|
|
|
|
|
S: Serializer,
|
|
|
|
|
{
|
|
|
|
|
serializer.serialize_u32(value.into_repr())
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-31 15:36:36 +01:00
|
|
|
#[allow(unused)]
|
2026-01-31 15:24:36 +01:00
|
|
|
pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
|
|
|
|
|
where
|
|
|
|
|
T: ReprConvert<Repr = u32>,
|
|
|
|
|
D: Deserializer<'de>,
|
|
|
|
|
{
|
|
|
|
|
<u32 as Deserialize>::deserialize(deserializer).map(T::from_repr)
|
|
|
|
|
}
|
|
|
|
|
}
|