1use crate::utils::validate_input::validate_alias;
4use crate::utils::validate_input::validate_hash;
5use rusqlite::Connection;
6use crate::db::connect;
7use serde::Serialize;
8use crate::verbs::Verbs;
9use ed25519_dalek::{SigningKey, SecretKey, VerifyingKey};
10use rand::rngs::OsRng;
11use rand::RngCore;
12use base64::engine::general_purpose::STANDARD;
13use base64::Engine as _;
14use crate::utils::crypto::{encrypt_string, decrypt_string};
15use std::convert::TryFrom; #[derive(Serialize)]
18pub struct Me {
19 pub alias: String,
20 pub public_key: String,
21 pub private_key: String, pub verbs: Verbs,
23 #[serde(skip)]
24 pub conn: Connection,
25}
26
27impl Me {
28 pub fn display(&self) -> Result<String, MeError> {
30 serde_json::to_string_pretty(self).map_err(|e| MeError::Serialization(e))
31 }
32
33pub fn new(alias: &str, _hash: &str) -> Result<(Self, bool), MeError> {
35 validate_alias(alias).map_err(|e| MeError::Validation(e.to_string()))?;
36 validate_hash(_hash).map_err(|e| MeError::Validation(e.to_string()))?;
37 let home = dirs::home_dir().ok_or_else(|| MeError::Validation("No HOME dir".to_string()))?;
38 let db_path = home.join(".this").join("me").join(alias).join(format!("{}.db", alias));
39 if db_path.exists() {
40 return Err(MeError::Validation("Identity already exists.".to_string()));
41 }
42
43 let (conn, _) = connect(alias, true).map_err(MeError::Database)?;
44
45 let mut csprng = OsRng {};
46 let mut secret_bytes = [0u8; 32];
47 csprng.fill_bytes(&mut secret_bytes);
48 let secret = SecretKey::try_from(&secret_bytes[..])
49 .map_err(|_| MeError::Crypto("Invalid secret key".into()))?;
50 let signing_key = SigningKey::from(&secret);
51 let verify_key = VerifyingKey::from(&signing_key);
52 let public_key = STANDARD.encode(verify_key.to_bytes());
53 let private_key_raw = STANDARD.encode(signing_key.to_bytes());
54 let encrypted_private_key = encrypt_string(_hash, &private_key_raw).map_err(|_| MeError::Crypto("Encryption failed".into()))?;
55
56 conn.execute(
57 "CREATE TABLE IF NOT EXISTS identity_keys (public_key TEXT NOT NULL, private_key BLOB NOT NULL)",
58 [],
59 ).map_err(MeError::Database)?;
60
61 conn.execute(
62 "INSERT INTO identity_keys (public_key, private_key) VALUES (?1, ?2)",
63 (&public_key, &encrypted_private_key),
64 ).map_err(MeError::Database)?;
65
66 Ok((Me {
67 alias: alias.to_string(),
68 public_key,
69 private_key: private_key_raw,
70 verbs: Verbs::new(),
71 conn,
72 }, false))
73}
74
75 pub fn be(&mut self, key: &str, value: &str) -> Result<(), MeError> {
76 Ok(self.verbs.be(&self.conn, key, value)?)}
77 pub fn do_(&mut self, key: &str, value: &str) -> Result<(), MeError> {
78 Ok(self.verbs.do_(&self.conn, key, value)?)}
79 pub fn have(&mut self, key: &str, value: &str) -> Result<(), MeError> {
80 Ok(self.verbs.have(&self.conn, key, value)?)}
81 pub fn at(&mut self, key: &str, value: &str) -> Result<(), MeError> {
82 Ok(self.verbs.at(&self.conn, key, value)?)}
83 pub fn relate(&mut self, key: &str, value: &str) -> Result<(), MeError> {
84 Ok(self.verbs.relate(&self.conn, key, value)?) }
85 pub fn react(&mut self, key: &str, value: &str) -> Result<(), MeError> {
86 Ok(self.verbs.react(&self.conn, key, value)?) }
87 pub fn communication(&mut self, key: &str, value: &str) -> Result<(), MeError> {
88 Ok(self.verbs.communication(&self.conn, key, value)?)
89 }
90
91 pub fn load(alias: &str, _hash: &str) -> Result<Self, MeError> {
93 validate_alias(alias).map_err(|e| MeError::Validation(e.to_string()))?;
94 let home = dirs::home_dir().ok_or_else(|| MeError::Validation("No HOME dir".to_string()))?;
95 let db_path = home.join(".this").join("me").join(alias).join(format!("{}.db", alias));
96 let conn = rusqlite::Connection::open(db_path).map_err(MeError::Database)?;
97 let (public_key, private_key_encrypted): (String, Vec<u8>) = {
98 let mut stmt = conn.prepare("SELECT public_key, private_key FROM identity_keys LIMIT 1")
99 .map_err(MeError::Database)?;
100
101 stmt.query_row([], |row| {
102 Ok((row.get(0)?, row.get(1)?))
103 }).map_err(MeError::Database)?
104 };
105
106 let private_key = decrypt_string(_hash, &private_key_encrypted)
107 .map_err(|_| MeError::Crypto("Decryption failed".into()))?;
108
109 Ok(Me {
110 alias: alias.to_string(),
111 public_key,
112 private_key,
113 verbs: Verbs::new(),
114 conn,
115 })
116 }
117}
118
119pub use crate::utils::me_error::MeError;