webdav_server/model/user.rs
1use crate::model::Result;
2use sqlx::SqlitePool;
3
4/// Represents a registered user in the system.
5///
6/// Users are identified by an `identity_hash` (a hash of their public identity)
7/// and authenticated via an `auth_verifier`. Neither field stores a raw password.
8/// This keeps the server from ever knowing who the user actually is.
9pub struct User {
10 pub id: i64,
11 pub identity_hash: [u8; 32],
12 pub auth_verifier: String,
13}
14
15impl User {
16 /// Inserts a new user into the `users` table via the provided `SqlitePool`.
17 ///
18 /// Both `identity_hash` and `auth_verifier` are expected to be pre-processed
19 /// on the client side before being sent to this function.
20 ///
21 /// # Errors
22 /// - Returns [`sqlx::Error::Database`] on a uniqueness violation, meaning a user
23 /// with the same `identity_hash` already exists.
24 /// - Returns [`sqlx::Error`] if the database query fails for any other reason.
25 pub async fn create(
26 pool: &SqlitePool,
27 identity_hash: &Vec<u8>,
28 auth_verifier: String,
29 ) -> Result<()> {
30 sqlx::query!(
31 r#"
32 INSERT INTO users (identity_hash, auth_verifier) VALUES(?, ?)
33 "#,
34 identity_hash,
35 auth_verifier,
36 )
37 .execute(pool)
38 .await?;
39
40 Ok(())
41 }
42
43 /// Verifies the credential pair (`identity_hash` and `auth_verifier`) against the database.
44 ///
45 /// Returns `Some(user_id)` if a matching user is found, or `None` if the
46 /// credentials do not match any existing record. This is the primary authentication
47 /// check used by the login endpoint.
48 ///
49 /// # Errors
50 /// - Returns [`sqlx::Error`] if the database query fails.
51 pub async fn verify(
52 pool: &SqlitePool,
53 identity_hash: Vec<u8>,
54 auth_verifier: String,
55 ) -> Result<Option<i64>> {
56 let result = sqlx::query!(
57 r#"
58 SELECT id FROM users WHERE identity_hash = ? AND auth_verifier = ?
59 "#,
60 identity_hash,
61 auth_verifier,
62 )
63 .fetch_optional(pool)
64 .await?;
65
66 Ok(result.map(|rec| rec.id))
67 }
68}