diff options
Diffstat (limited to 'src/api/users.rs')
-rw-r--r-- | src/api/users.rs | 83 |
1 files changed, 48 insertions, 35 deletions
diff --git a/src/api/users.rs b/src/api/users.rs index e07bf7e..24bcf97 100644 --- a/src/api/users.rs +++ b/src/api/users.rs @@ -13,7 +13,7 @@ use uuid::Uuid; use crate::{ auth::{credentials::Credential, AccessClaims}, - state::AppState, + state::{AppState, KVStore}, }; use super::error::Error; @@ -40,54 +40,53 @@ pub struct Registration { } pub async fn create( - State(pool): State<PgPool>, + State(state): State<AppState>, Json(Registration { name, email, password, }): Json<Registration>, -) -> impl IntoResponse { +) -> Result<impl IntoResponse, Error> { email_address::EmailAddress::from_str(&email)?; - let exists: Option<bool> = sqlx::query_scalar!( - "SELECT EXISTS(SELECT 1 FROM user_ WHERE email = $1 LIMIT 1)", - email.to_ascii_lowercase() - ) - .fetch_one(&pool) - .await?; - - if exists.is_some_and(|b| b) { - return Err(Error::EmailExists); - } - // TODO: Move this into a micro service, possibly behind a feature flag. let (status, (access, refresh)) = - crate::auth::credentials::create(State(pool.clone()), Json(Credential { password })) + crate::auth::credentials::create(State(state.pool.clone()), Json(Credential { password })) .await?; - let user = sqlx::query_as!( - User, - "INSERT INTO user_ (id,name,email) VALUES ($1, $2, $3) RETURNING *", - refresh.sub, + let user = User { + id: refresh.sub, name, - email.to_ascii_lowercase(), - ) - .fetch_one(&pool) - .await?; + email, + created_at: OffsetDateTime::now_utc(), + updated_at: OffsetDateTime::now_utc(), + }; + + let tx = state.kv_store.transaction(); + tx.put(refresh.sub, serde_json::to_vec(&user).unwrap()) + .unwrap(); Ok((status, access, refresh, Json(user))) } pub async fn show( Path(uuid): Path<Uuid>, - State(pool): State<PgPool>, + State(state): State<AppState>, _: AccessClaims, -) -> Result<impl IntoResponse, Error> { - sqlx::query_as!(User, "SELECT * FROM user_ WHERE id = $1 LIMIT 1", uuid) - .fetch_optional(&pool) - .await? +) -> Result<Json<User>, Error> { + let tx = state.kv_store.transaction(); + Ok(tx + .get(uuid) + .unwrap() .ok_or_else(|| Error::UserNotFound) + .map(|s| serde_json::from_slice(&s))? .map(Json) + .unwrap()) + //sqlx::query_as!(User, "SELECT * FROM user_ WHERE id = $1 LIMIT 1", uuid) + // .fetch_optional(&pool) + // .await? + // .ok_or_else(|| Error::UserNotFound) + // .map(Json) } #[cfg(test)] @@ -120,7 +119,9 @@ mod tests { async fn test_get_ok_self(pool: PgPool) -> TestResult { setup_test_env(); - let router = Router::new().merge(router()).with_state(AppState { pool }); + let router = Router::new() + .merge(router()) + .with_state(AppState::with_pool(pool, "./rocks.db")); let request = Request::builder() .uri(format!("/users/{}", USER_ID)) @@ -150,7 +151,9 @@ mod tests { async fn test_get_ok_other(pool: PgPool) -> TestResult { setup_test_env(); - let router = Router::new().merge(router()).with_state(AppState { pool }); + let router = Router::new() + .merge(router()) + .with_state(AppState::with_pool(pool, "./rocks.db")); let request = Request::builder() .uri(format!("/users/{}", USER_ID)) @@ -182,7 +185,9 @@ mod tests { async fn test_get_not_found(pool: PgPool) -> TestResult { setup_test_env(); - let router = Router::new().merge(router()).with_state(AppState { pool }); + let router = Router::new() + .merge(router()) + .with_state(AppState::with_pool(pool, "./rocks.db")); let request = Request::builder() .uri(format!("/users/{}", USER_ID)) @@ -203,7 +208,9 @@ mod tests { async fn test_get_unauthorized_invalid_token_format(pool: PgPool) -> TestResult { setup_test_env(); - let router = Router::new().merge(router()).with_state(AppState { pool }); + let router = Router::new() + .merge(router()) + .with_state(AppState::with_pool(pool, "./rocks.db")); let request = Request::builder() .uri(format!("/users/{}", USER_ID)) @@ -221,7 +228,9 @@ mod tests { async fn test_get_unauthorized_missing_token(pool: PgPool) -> TestResult { setup_test_env(); - let router = Router::new().merge(router()).with_state(AppState { pool }); + let router = Router::new() + .merge(router()) + .with_state(AppState::with_pool(pool, "./rocks.db")); let request = Request::builder() .uri(format!("/users/{}", USER_ID)) @@ -238,7 +247,9 @@ mod tests { async fn test_post_created(pool: PgPool) -> TestResult { setup_test_env(); - let router = Router::new().merge(router()).with_state(AppState { pool }); + let router = Router::new() + .merge(router()) + .with_state(AppState::with_pool(pool, "./rocks.db")); let user = serde_json::json!( { "name": USER_NAME, @@ -269,7 +280,9 @@ mod tests { async fn test_post_conflict(pool: PgPool) -> TestResult { setup_test_env(); - let router = Router::new().merge(router()).with_state(AppState { pool }); + let router = Router::new() + .merge(router()) + .with_state(AppState::with_pool(pool, "./rocks.db")); let user = serde_json::json!( { "name": USER_NAME, |