Skip to main content

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}