From 679cc2ce1a4e97c70903893a8d4cf3643e7f8774 Mon Sep 17 00:00:00 2001 From: Nevernown Date: Fri, 21 Nov 2025 22:27:04 +0100 Subject: [PATCH] Database setup stage 1 done --- .gitignore | 1 + Cargo.lock | 126 ++++++++++++++++++++++++++++++++++++++++++ identity.db | Bin 12288 -> 0 bytes identity/Cargo.toml | 1 + identity/src/lib.rs | 128 +++++++++++++++++++++++++++++++++++++++---- identity/src/user.rs | 47 ++++++++++++++++ 6 files changed, 291 insertions(+), 12 deletions(-) delete mode 100644 identity.db create mode 100644 identity/src/user.rs diff --git a/.gitignore b/.gitignore index ea8c4bf..d9b2525 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +*.db \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index ceace74..b862bb8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,18 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "argon2" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072" +dependencies = [ + "base64ct", + "blake2", + "cpufeatures", + "password-hash", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -60,12 +72,36 @@ dependencies = [ "tracing", ] +[[package]] +name = "base64ct" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" + [[package]] name = "bitflags" version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "bytes" version = "1.11.0" @@ -78,6 +114,36 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + [[package]] name = "fallible-iterator" version = "0.3.0" @@ -144,6 +210,27 @@ dependencies = [ "pin-utils", ] +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "hashbrown" version = "0.15.5" @@ -249,6 +336,7 @@ dependencies = [ name = "identity" version = "0.1.0" dependencies = [ + "argon2", "axum", "log", "rusqlite", @@ -369,6 +457,17 @@ dependencies = [ "windows-link", ] +[[package]] +name = "password-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" +dependencies = [ + "base64ct", + "rand_core", + "subtle", +] + [[package]] name = "percent-encoding" version = "2.3.2" @@ -411,6 +510,15 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + [[package]] name = "redox_syscall" version = "0.5.18" @@ -553,6 +661,12 @@ dependencies = [ "windows-sys 0.60.2", ] +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "syn" version = "2.0.110" @@ -707,6 +821,12 @@ dependencies = [ "tracing-log", ] +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + [[package]] name = "unicode-ident" version = "1.0.22" @@ -725,6 +845,12 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" diff --git a/identity.db b/identity.db deleted file mode 100644 index ca644740b6ba763ded5a4905cf5a29933e31d449..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI#!AiqG5P;#`R1^fMw_NAg(&9m1z$l9Z)3l~rFeiz+LZPjsX)nDAKDe9E7VO2d zb$+r-{8{IJg;rOa^1@dI z?Q7Nk_8Wl!0tg_000IagfB*srAb`NX5EuogVXvq2Rq;A=RXOwH^GoH*wOhO$rmg$T zMAnFn?h+#hwVg#VcYWX4-RQG04E5KzdE~ls%c|LeU+v8$>72_prtcD`);yR@Mp-iT73&9jws=+`7knp@p^Hupn6fdB#sAb Router { @@ -38,19 +55,49 @@ async fn setup() -> Result { error!("{:?}", e); return Err(StatusCode::INTERNAL_SERVER_ERROR) } - let connection = connection.expect("Connection cannot be an error here."); + let connection = connection.expect("Connection always exists here."); + info!("Connected to identity database"); if let Err(e) = connection.execute(DB_CREATE_USER_TABLE, [],) { error!("{:?}", e); return Err(StatusCode::INTERNAL_SERVER_ERROR) } + info!("Created user table"); - if let Err(e) = connection.execute(DB_CREATE_META_TABLE, [],) { + if let Err(e) = connection.execute(DB_CREATE_SETTINGS_TABLE, [],) { error!("{:?}", e); return Err(StatusCode::INTERNAL_SERVER_ERROR) } + info!("Created settings table"); - Ok(StatusCode::OK) + let stage = match SetupStage::get(&connection) { + Ok(stage) => stage, + Err(_) => { + error!("Coud, not retrieve setup status"); + return Err(StatusCode::INTERNAL_SERVER_ERROR); + }, + }; + info!("Retreived setup status setting: {stage:?}"); + + if stage != SetupStage::New { + error!("{NAME} is already set up"); + return Err(StatusCode::CONFLICT) + } + info!("Proceeding with setup steps because setup status is {stage:?}"); + + if let Err(e) = connection.execute(DB_INSERT_SETUP_STAGE_SETTING, [],) { + error!("{:?}", e); + return Err(StatusCode::INTERNAL_SERVER_ERROR) + } + info!("Updated setup stage setting"); + + if let Err(_) = user::create(&connection, "admin", "changeme") { + Err(StatusCode::INTERNAL_SERVER_ERROR) + } else if let Err(_) = stage.next().set(&connection) { + Err(StatusCode::INTERNAL_SERVER_ERROR) + } else { + Ok(StatusCode::OK) + } } #[instrument] @@ -61,4 +108,61 @@ async fn dummy() -> Json<()> { #[instrument] async fn information() -> Json { Json(SigmaInformation::new(NAME, VERSION)) +} + +#[repr(u32)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum SetupStage { + New, + Finished +} +impl SetupStage { + fn get(connection: &Connection) -> Result { + let result = connection.query_one(SELECT_SETUP_STATUS, [], |row| { + row.get::<&str, String>("value") + }); + match result { + Ok(value) => SetupStage::try_from(value), + Err(rusqlite::Error::QueryReturnedNoRows) => return Ok(SetupStage::New), + Err(e) => { + error!("{e:}"); + return Err(()) + }, + } + } + fn set(&self, connection: &Connection) -> Result<(), ()>{ + let value = format!("{}", *self as u32); + if let Err(e) = connection.execute(UPDATE_SETUP_STATUS, params![value]) { + error!("{e:?}"); + Err(()) + } else { + Ok(()) + } + } + + fn next(&self) -> Self { + match &self { + Self::New => Self::Finished, + Self::Finished => Self::Finished, + } + } +} +impl TryFrom for SetupStage { + type Error = (); + + fn try_from(value: String) -> Result { + if let Ok(value) = value.parse::() { + match value { + 0 => Ok(Self::New), + 1 => Ok(Self::Finished), + _ => { + error!("Unknown setup stage value {value}"); + Err(()) + } + } + } else { + error!("Could not parse server status '{value}' to u32 (SetupStage)"); + Err(()) + } + } } \ No newline at end of file diff --git a/identity/src/user.rs b/identity/src/user.rs new file mode 100644 index 0000000..b7f3724 --- /dev/null +++ b/identity/src/user.rs @@ -0,0 +1,47 @@ +use argon2::password_hash::SaltString; +use argon2::PasswordHasher; +use argon2::password_hash::rand_core::OsRng; +use log::{error, info}; +use rusqlite::{Connection, params}; + +const CREATE_USER: &str = " + INSERT INTO users (name, pass) VALUES (?1, ?2) +"; + +const SELECT_USER: &str =" + SELECT * FROM users WHERE name = ?1 +"; + +struct User { + id: u64, + name: String, + pass: String +} + +pub fn create(connection: &Connection, name: &str, pass: &str) -> Result<(), ()> { + let argon2 = argon2::Argon2::default(); + let salt = SaltString::generate(&mut OsRng); + + let pass = match argon2.hash_password(pass.as_bytes(), &salt) { + Ok(pass) => pass.to_string(), + Err(e) => { + error!("{e:?}"); + return Err(()); + }, + }; + info!("Hashed password for user {}", name); + + match connection.execute(CREATE_USER, params![name, pass]) { + Ok(_) => return Ok(()), + Err(e) => { + error!("{e:?}"); + return Err(()) + }, + } +} + +pub fn verify(connection: &Connection, name: &str, pass: &str) { + // match connection.query_one(SELECT_USER, params![name], |row| {})) { + + // } +} \ No newline at end of file