use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use sqlx::types::Json;
use sqlx::FromRow;
pub const BACKUP_SECRET_KEYS: &[&str] = &["pass", "password", "secret_key", "secret"];
#[derive(Debug, Clone, FromRow)]
pub struct BackupDestination {
pub id: String,
pub name: String,
pub kind: String,
pub config: Json<Value>,
pub enabled: bool,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
#[derive(Debug, Clone, Serialize)]
pub struct BackupDestinationView {
pub id: String,
pub name: String,
pub kind: String,
pub config: Value,
pub has_credentials: bool,
pub enabled: bool,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
pub fn mask_backup_config(mut config: Value) -> (Value, bool) {
let mut has_credentials = false;
if let Some(obj) = config.as_object_mut() {
for key in BACKUP_SECRET_KEYS {
if let Some(v) = obj.get_mut(*key) {
if v.as_str().map(|s| !s.is_empty()).unwrap_or(false) {
has_credentials = true;
*v = Value::String("***".to_string());
}
}
}
}
(config, has_credentials)
}
impl From<BackupDestination> for BackupDestinationView {
fn from(d: BackupDestination) -> Self {
let (config, has_credentials) = mask_backup_config(d.config.0);
BackupDestinationView {
id: d.id,
name: d.name,
kind: d.kind,
config,
has_credentials,
enabled: d.enabled,
created_at: d.created_at,
updated_at: d.updated_at,
}
}
}
#[derive(Debug, Deserialize)]
pub struct BackupDestinationCreate {
pub name: String,
pub kind: String,
pub config: Option<Value>,
pub enabled: Option<bool>,
}
#[derive(Debug, Deserialize, Default)]
pub struct BackupDestinationUpdate {
pub name: Option<String>,
pub kind: Option<String>,
pub config: Option<Value>,
pub enabled: Option<bool>,
}
#[derive(Debug, Clone, Serialize)]
pub struct BackupTestResult {
pub ok: bool,
pub error: Option<String>,
pub latency_ms: i64,
}
#[derive(Debug, Clone, Serialize, FromRow)]
pub struct BackupPolicy {
pub id: String,
pub name: String,
pub destination_id: String,
pub camera_ids: Json<Value>,
pub incident_lock_only: bool,
pub schedule_interval_s: i64,
pub lookback_hours: i64,
pub last_run_at: Option<DateTime<Utc>>,
pub last_job_id: Option<String>,
pub enabled: bool,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
#[derive(Debug, Deserialize)]
pub struct BackupPolicyCreate {
pub name: String,
pub destination_id: String,
pub camera_ids: Option<Value>,
pub incident_lock_only: Option<bool>,
pub schedule_interval_s: Option<i64>,
pub lookback_hours: Option<i64>,
pub enabled: Option<bool>,
}
#[derive(Debug, Deserialize, Default)]
pub struct BackupPolicyUpdate {
pub name: Option<String>,
pub destination_id: Option<String>,
pub camera_ids: Option<Value>,
pub incident_lock_only: Option<bool>,
pub schedule_interval_s: Option<i64>,
pub lookback_hours: Option<i64>,
pub enabled: Option<bool>,
}
#[derive(Debug, Clone, Serialize, FromRow)]
pub struct BackupJob {
pub id: String,
pub policy_id: Option<String>,
pub destination_id: Option<String>,
pub kind: String,
pub camera_ids: Json<Value>,
pub from_time: Option<DateTime<Utc>>,
pub to_time: Option<DateTime<Utc>>,
pub incident_lock_only: bool,
pub status: String,
pub files_total: i64,
pub files_copied: i64,
pub bytes_copied: i64,
pub error: Option<String>,
pub output_path: Option<String>,
pub output_url: Option<String>,
pub started_at: Option<DateTime<Utc>>,
pub finished_at: Option<DateTime<Utc>>,
pub created_at: DateTime<Utc>,
}
#[derive(Debug, Deserialize)]
pub struct ArchiveExportRequest {
#[serde(default)]
pub camera_ids: Vec<String>,
pub from: Option<String>,
pub to: Option<String>,
pub incident_lock_only: Option<bool>,
pub trim: Option<bool>,
}