Skip to main content

webdav_server/api/auth/
register.rs

1use crate::api::Error::BadRequest;
2use crate::app::State as AppState;
3use crate::logger::Module;
4use crate::model::{error::Error as ModelErr, user::User};
5use crate::{Error as AppErr, Result, info};
6use axum::{Json, extract::State};
7use hyper::StatusCode;
8use serde::Deserialize;
9use sqlx::Error as SqlErr;
10
11/// The JSON body expected by the registration endpoint.
12#[derive(Deserialize)]
13pub struct RegisterRequest {
14    /// A hex-encoded BLAKE3 hash of the user's public identity.
15    ///
16    /// The server stores this as the user's identifier. It must be unique across
17    /// all registered users; a duplicate triggers a `409 Conflict` response.
18    pub identity_hash: String,
19    /// The authentication verifier derived from the user's credentials on the client side.
20    ///
21    /// The server stores this string verbatim and compares it on login. It is the
22    /// client's responsibility to derive a strong verifier (e.g., using Argon2id)
23    /// before sending it — the server does not perform any additional hashing.
24    pub auth_verifier: String,
25}
26
27/// Registers a new user with the provided credentials.
28///
29/// # Errors
30/// - Returns a `BadRequest` if the identity hash cannot be decoded from hex.
31/// - Returns a `Conflict` if a user with the same identity hash already exists.
32/// - Returns an internal error if a database query fails.
33pub async fn register(
34    State(state): State<AppState>,
35    Json(register_request): Json<RegisterRequest>,
36) -> Result<StatusCode> {
37    let Ok(identity_hash) = hex::decode(&register_request.identity_hash) else {
38        Err(BadRequest("identity_hash failed to decode".into()))?
39    };
40
41    let result =
42        User::create(&state.db, &identity_hash, register_request.auth_verifier)
43            .await;
44
45    match result {
46        Ok(()) => {
47            info!(
48                Module::Api,
49                "New user reggistered with id: {:?}",
50                hex::encode(identity_hash)
51            );
52            Ok(StatusCode::CREATED)
53        }
54        Err(ModelErr::Database(SqlErr::Database(err)))
55            if err.is_unique_violation() =>
56        {
57            Err(AppErr::Conflict("User already exists".into()))
58        }
59        Err(e) => Err(e.into()),
60    }
61}