1use crate::utils::validate_input::validate_username;
4use crate::utils::validate_input::validate_password;
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;
15use std::convert::TryFrom; #[derive(Serialize)]
18pub struct Me {
19 pub username: String,
20 pub public_key: String,
21 pub private_key: String, pub context_id: String,
23 #[serde(skip_serializing)]
24 pub verbs: Verbs,
25 #[serde(skip)]
26 pub conn: Connection,
27}
28
29impl Me {
30 fn derive_key(username: &str, password: &str) -> Result<Vec<u8>, MeError> {
31 use sha2::{Sha256, Digest};
32 let mut hasher = Sha256::new();
33 hasher.update(username.as_bytes());
34 hasher.update(password.as_bytes());
35 let result = hasher.finalize();
36 Ok(result[..].to_vec())
37 }
38
39 pub fn change_password(&mut self, _old_password: &str, new_password: &str) -> Result<(), MeError> {
41 let key = Me::derive_key(&self.username, new_password)?;
43 let encoded_key = base64::engine::general_purpose::STANDARD.encode(&key);
44 let encrypted_binary = encrypt_string(&encoded_key, &self.private_key)
45 .map_err(|_| MeError::Crypto("Encryption failed".into()))?;
46 let new_encrypted = base64::engine::general_purpose::STANDARD.encode(&encrypted_binary);
47 self.conn.execute(
49 "UPDATE me SET encrypted_private_key = ?1 WHERE username = ?2",
50 (&new_encrypted, &self.username),
51 ).map_err(MeError::Database)?;
52 Ok(())
53 }
54
55 pub fn display(&self) -> Result<String, MeError> {
57 serde_json::to_string_pretty(self).map_err(|e| MeError::Serialization(e))
58 }
59
60 pub fn load(username: &str, password: &str) -> Result<Self, MeError> {
62 validate_username(username).map_err(|e| MeError::Validation(e.to_string()))?;
63 validate_password(password).map_err(|e| MeError::Validation(e.to_string()))?;
64 let home = dirs::home_dir().ok_or_else(|| MeError::Validation("No HOME dir".to_string()))?;
65 let db_path = home.join(".this").join("me").join(username).join(format!("{}.db", username));
66 if !db_path.exists() {
67 return Err(MeError::Validation("Identity does not exist.".to_string()));
68 }
69
70 let (conn, _) = connect(username, false).map_err(MeError::Database)?;
71 let (public_key, private_key_raw) = {
72 let mut stmt = conn
73 .prepare("SELECT public_key, encrypted_private_key FROM me WHERE username = ?1 LIMIT 1")
74 .map_err(MeError::Database)?;
75 let mut rows = stmt.query([username]).map_err(MeError::Database)?;
76 if let Some(row) = rows.next().map_err(MeError::Database)? {
77 let public_key: String = row.get(0).map_err(MeError::Database)?;
78 let encrypted_private_key: String = row.get(1).map_err(MeError::Database)?;
79 let encrypted_bytes = STANDARD
80 .decode(&encrypted_private_key)
81 .map_err(|_| MeError::Crypto("Base64 decode failed".into()))?;
82 let key = Me::derive_key(username, password)?;
83 let encoded_key = base64::engine::general_purpose::STANDARD.encode(&key);
84 let private_key_raw = crate::utils::crypto::decrypt_string(&encoded_key, &encrypted_bytes)
85 .map_err(|_| MeError::Crypto("Decryption failed".into()))?;
86 (public_key, private_key_raw)
87 } else {
88 return Err(MeError::Validation("Identity keys not found.".to_string()));
89 }
90 };
91
92 let context_id = {
93 use sha2::{Sha256, Digest};
94 let mut hasher = Sha256::new();
95 hasher.update(&private_key_raw);
96 base64::engine::general_purpose::STANDARD.encode(hasher.finalize())
97 };
98 Ok(Me {
99 username: username.to_string(),
100 public_key,
101 private_key: private_key_raw,
102 context_id,
103 verbs: Verbs::new(),
104 conn,
105 })
106 }
107
108 pub fn new(username: &str, password: &str) -> Result<(Self, bool), MeError> {
110 validate_username(username).map_err(|e| MeError::Validation(e.to_string()))?;
111 validate_password(password).map_err(|e| MeError::Validation(e.to_string()))?;
112 let home = dirs::home_dir().ok_or_else(|| MeError::Validation("No HOME dir".to_string()))?;
113 let db_path = home.join(".this").join("me").join(username).join(format!("{}.db", username));
114 if db_path.exists() {
115 return Err(MeError::Validation("Identity already exists.".to_string()));
116 }
117
118 let (conn, _) = connect(username, true).map_err(MeError::Database)?;
119 let mut csprng = OsRng {};
120 let mut secret_bytes = [0u8; 32];
121 csprng.fill_bytes(&mut secret_bytes);
122 let secret = SecretKey::try_from(&secret_bytes[..])
123 .map_err(|_| MeError::Crypto("Invalid secret key".into()))?;
124 let signing_key = SigningKey::from(&secret);
125 let verify_key = VerifyingKey::from(&signing_key);
126 let public_key = STANDARD.encode(verify_key.to_bytes());
127 let private_key_raw = STANDARD.encode(signing_key.to_bytes());
128 let key = Me::derive_key(username, password)?;
129 let encoded_key = base64::engine::general_purpose::STANDARD.encode(&key);
130 let encrypted_binary = encrypt_string(&encoded_key, &private_key_raw)
131 .map_err(|_| MeError::Crypto("Encryption failed".into()))?;
132 let encrypted_private_key = STANDARD.encode(&encrypted_binary);
133 conn.execute(
134 "CREATE TABLE IF NOT EXISTS me (
135 username TEXT PRIMARY KEY,
136 public_key TEXT NOT NULL,
137 encrypted_private_key TEXT NOT NULL,
138 created_at TEXT NOT NULL
139 )",
140 [],
141 ).map_err(MeError::Database)?;
142 use chrono::Utc;
143 let created_at = Utc::now().to_rfc3339();
144 conn.execute(
145 "INSERT INTO me (username, public_key, encrypted_private_key, created_at) VALUES (?1, ?2, ?3, ?4)",
146 (&username, &public_key, &encrypted_private_key, &created_at),
147 ).map_err(MeError::Database)?;
148 let context_id = {
149 use sha2::{Sha256, Digest};
150 let mut hasher = Sha256::new();
151 hasher.update(&private_key_raw);
152 base64::engine::general_purpose::STANDARD.encode(hasher.finalize())
153 };
154 Ok((Me {
155 username: username.to_string(),
156 public_key,
157 private_key: private_key_raw,
158 context_id,
159 verbs: Verbs::new(),
160 conn,
161 }, false))
162 }
163
164 pub fn be(&mut self, context_id: &str, key: &str, value: &str) -> Result<(), MeError> {
165 Ok(self.verbs.be(&self.conn, context_id, key, value)?)
166 }
167 pub fn do_(&mut self, context_id: &str, key: &str, value: &str) -> Result<(), MeError> {
168 Ok(self.verbs.do_(&self.conn, context_id, key, value)?)
169 }
170 pub fn have(&mut self, context_id: &str, key: &str, value: &str) -> Result<(), MeError> {
171 Ok(self.verbs.have(&self.conn, context_id, key, value)?)
172 }
173 pub fn at(&mut self, context_id: &str, key: &str, value: &str) -> Result<(), MeError> {
174 Ok(self.verbs.at(&self.conn, context_id, key, value)?)
175 }
176 pub fn relate(&mut self, context_id: &str, key: &str, value: &str) -> Result<(), MeError> {
177 Ok(self.verbs.relate(&self.conn, context_id, key, value)?)
178 }
179 pub fn react(&mut self, context_id: &str, key: &str, value: &str) -> Result<(), MeError> {
180 Ok(self.verbs.react(&self.conn, context_id, key, value)?)
181 }
182 pub fn communicate(&mut self, context_id: &str, key: &str, value: &str) -> Result<(), MeError> {
183 Ok(self.verbs.communicate(&self.conn, context_id, key, value)?)
184 }
185 pub fn get(
186 &self,
187 verb: &str,
188 context_id: Option<&str>,
189 key: Option<&str>,
190 value: Option<&str>,
191 json_path: Option<&str>,
192 limit: Option<usize>,
193 offset: Option<usize>,
194 since: Option<&str>,
195 until: Option<&str>,
196 ) -> Result<Vec<(String, String, String, String)>, MeError> {
197 self.verbs
198 .get(
199 &self.conn,
200 verb,
201 context_id,
202 key,
203 value,
204 json_path,
205 limit,
206 offset,
207 since,
208 until,
209 )
210 .map(|actions| actions.into_iter().map(|(v, a)| (v, a.key, a.value, a.timestamp)).collect())
211 .map_err(MeError::Io)
212 }
213}
214
215pub use crate::utils::me_error::MeError;