86 lines
2.2 KiB
Rust
86 lines
2.2 KiB
Rust
use serde::{Deserialize, Serialize};
|
|
use uuid::Uuid;
|
|
use zeroize::Zeroize;
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
|
#[serde(rename_all = "snake_case")]
|
|
pub enum ItemKind {
|
|
Login,
|
|
SecureNote,
|
|
Card,
|
|
Identity,
|
|
}
|
|
|
|
/// A stored WebAuthn credential (docs/05 "Passkeys").
|
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Zeroize)]
|
|
pub struct Passkey {
|
|
pub credential_id: Vec<u8>,
|
|
pub rp_id: String,
|
|
pub user_handle: Vec<u8>,
|
|
pub user_name: String,
|
|
/// PKCS#8 DER of the P-256 private key.
|
|
pub private_key: Vec<u8>,
|
|
pub sign_count: u32,
|
|
pub created_at: i64,
|
|
}
|
|
|
|
/// One item. Field-level structure is what makes three-way merges possible (docs/03).
|
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
pub struct Item {
|
|
pub id: Uuid,
|
|
pub kind: ItemKind,
|
|
pub title: String,
|
|
#[serde(default)]
|
|
pub username: Option<String>,
|
|
#[serde(default)]
|
|
pub password: Option<String>,
|
|
#[serde(default)]
|
|
pub urls: Vec<String>,
|
|
/// `otpauth://` URI or a bare base32 secret.
|
|
#[serde(default)]
|
|
pub totp: Option<String>,
|
|
#[serde(default)]
|
|
pub notes: Option<String>,
|
|
#[serde(default)]
|
|
pub passkeys: Vec<Passkey>,
|
|
#[serde(default)]
|
|
pub tags: Vec<String>,
|
|
#[serde(default)]
|
|
pub favorite: bool,
|
|
/// Android package names this login may fill (verified via Digital Asset Links when possible).
|
|
#[serde(default)]
|
|
pub android_apps: Vec<String>,
|
|
pub created_at: i64,
|
|
pub modified_at: i64,
|
|
}
|
|
|
|
impl Item {
|
|
pub fn new_login(title: impl Into<String>, now: i64) -> Self {
|
|
Self {
|
|
id: Uuid::new_v4(),
|
|
kind: ItemKind::Login,
|
|
title: title.into(),
|
|
username: None,
|
|
password: None,
|
|
urls: vec![],
|
|
totp: None,
|
|
notes: None,
|
|
passkeys: vec![],
|
|
tags: vec![],
|
|
favorite: false,
|
|
android_apps: vec![],
|
|
created_at: now,
|
|
modified_at: now,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Drop for Item {
|
|
fn drop(&mut self) {
|
|
self.password.zeroize();
|
|
self.totp.zeroize();
|
|
self.notes.zeroize();
|
|
self.passkeys.zeroize();
|
|
}
|
|
}
|