diff options
Diffstat (limited to 'src/server/database.rs')
| -rw-r--r-- | src/server/database.rs | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/src/server/database.rs b/src/server/database.rs new file mode 100644 index 0000000..c73aec5 --- /dev/null +++ b/src/server/database.rs | |||
| @@ -0,0 +1,74 @@ | |||
| 1 | use rusqlite::Connection; | ||
| 2 | |||
| 3 | pub fn init_db(conn: &Connection) { | ||
| 4 | conn.execute( | ||
| 5 | "CREATE TABLE IF NOT EXISTS users ( | ||
| 6 | username TEXT PRIMARY KEY, | ||
| 7 | hashed_password TEXT NOT NULL, | ||
| 8 | account_id INTEGER UNIQUE, | ||
| 9 | balance INTEGER DEFAULT 1000 | ||
| 10 | )", | ||
| 11 | [], | ||
| 12 | ) | ||
| 13 | .unwrap(); | ||
| 14 | // Add column if not exists (for migration) | ||
| 15 | let _ = conn.execute("ALTER TABLE users ADD COLUMN account_id INTEGER UNIQUE", []); | ||
| 16 | let _ = conn.execute( | ||
| 17 | "ALTER TABLE users ADD COLUMN balance INTEGER DEFAULT 1000", | ||
| 18 | [], | ||
| 19 | ); | ||
| 20 | } | ||
| 21 | |||
| 22 | pub fn add_user( | ||
| 23 | conn: &Connection, | ||
| 24 | username: &str, | ||
| 25 | hashed_password: &str, | ||
| 26 | ) -> Result<(), Box<dyn std::error::Error>> { | ||
| 27 | loop { | ||
| 28 | let account_id: u32 = rand::random::<u32>(); | ||
| 29 | match conn.execute( | ||
| 30 | "INSERT INTO users (username, hashed_password, account_id, balance) VALUES (?1, ?2, ?3, ?4)", | ||
| 31 | [username, hashed_password, &account_id.to_string(), "1000"], | ||
| 32 | ) { | ||
| 33 | Ok(_) => break, | ||
| 34 | Err(_) => continue, // Retry if account_id conflict | ||
| 35 | } | ||
| 36 | } | ||
| 37 | Ok(()) | ||
| 38 | } | ||
| 39 | |||
| 40 | pub fn get_hashed_password(conn: &Connection, username: &str) -> Option<String> { | ||
| 41 | let mut stmt = conn | ||
| 42 | .prepare("SELECT hashed_password FROM users WHERE username = ?1") | ||
| 43 | .unwrap(); | ||
| 44 | let mut rows = stmt.query([username]).unwrap(); | ||
| 45 | if let Ok(Some(row)) = rows.next() { | ||
| 46 | row.get(0).ok() | ||
| 47 | } else { | ||
| 48 | None | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 52 | pub fn get_account_id(conn: &Connection, username: &str) -> Option<u32> { | ||
| 53 | let mut stmt = conn | ||
| 54 | .prepare("SELECT account_id FROM users WHERE username = ?1") | ||
| 55 | .unwrap(); | ||
| 56 | let mut rows = stmt.query([username]).unwrap(); | ||
| 57 | if let Ok(Some(row)) = rows.next() { | ||
| 58 | Some(row.get::<_, u32>(0).ok()?) | ||
| 59 | } else { | ||
| 60 | None | ||
| 61 | } | ||
| 62 | } | ||
| 63 | |||
| 64 | pub fn get_balance(conn: &Connection, username: &str) -> Option<i64> { | ||
| 65 | let mut stmt = conn | ||
| 66 | .prepare("SELECT balance FROM users WHERE username = ?1") | ||
| 67 | .unwrap(); | ||
| 68 | let mut rows = stmt.query([username]).unwrap(); | ||
| 69 | if let Ok(Some(row)) = rows.next() { | ||
| 70 | Some(row.get::<_, i64>(0).ok()?) | ||
| 71 | } else { | ||
| 72 | None | ||
| 73 | } | ||
| 74 | } | ||
