Skip to main content

this_me/
me.rs

1//this.me/crate/src/me.rs
2//by suiGn
3use 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;  // Added this line
16/// Represents a local encrypted identity used in dApps or Web3 environments.
17#[derive(Serialize)]
18pub struct Me {
19    pub username: String,
20    pub public_key: String,
21    pub private_key: String, // stored encrypted
22    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    /// Changes the encryption hash of the private key.
40    pub fn change_password(&mut self, _old_password: &str, new_password: &str) -> Result<(), MeError> {
41        // Re-encrypt the private key using the new password, base64-encoded as in new()
42        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        // Update the database with the new encrypted private key
48        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    /// Returns a pretty-printed JSON representation of the Me struct.
56    pub fn display(&self) -> Result<String, MeError> {
57        serde_json::to_string_pretty(self).map_err(|e| MeError::Serialization(e))
58    }
59
60    /// Loads an existing Me instance from the local database using username and password.
61    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    /// Initializes a new Me instance with the given username and password.
109    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;