use std::path::PathBuf;
use chrono::{DateTime, Local};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use crate::{
cipher::{Cipher, CipherKind, EncryptedContent},
env::EnvMap,
error::Result,
utils::save_serialized_profile,
};
#[derive(Clone, Serialize, Deserialize)]
pub struct ProfileMetadata {
pub uuid: String,
pub name: String,
pub version: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
pub cipher_kind: CipherKind,
#[serde(skip_serializing_if = "Option::is_none")]
pub cipher_metadata: Option<serde_json::Value>,
pub created_at: DateTime<Local>,
pub updated_at: DateTime<Local>,
}
#[derive(Clone)]
pub struct Profile {
pub metadata: ProfileMetadata,
pub file_path: PathBuf,
pub envs: EnvMap,
pub cipher: Box<dyn Cipher>,
}
#[derive(Serialize, Deserialize)]
pub struct SerializedProfile {
pub metadata: ProfileMetadata,
pub content: EncryptedContent,
}
impl Profile {
pub fn new(
name: String,
description: Option<String>,
file_path: impl Into<PathBuf>,
envs: EnvMap,
cipher: Box<dyn Cipher>,
) -> Self {
Self {
metadata: ProfileMetadata {
uuid: Uuid::new_v4().to_string(),
name,
version: env!("CARGO_PKG_VERSION").to_string(),
description,
cipher_kind: cipher.kind(),
cipher_metadata: cipher.export_metadata(),
created_at: Local::now(),
updated_at: Local::now(),
},
file_path: file_path.into(),
envs,
cipher,
}
}
pub fn save(&mut self) -> Result<()> {
let encrypted_envs = self.cipher.encrypt(&self.envs)?;
self.metadata.updated_at = Local::now();
self.metadata.cipher_metadata = self.cipher.export_metadata();
let serialized_profile = SerializedProfile {
metadata: self.metadata.clone(),
content: encrypted_envs,
};
save_serialized_profile(&self.file_path, serialized_profile)?;
Ok(())
}
}