Add the ability for a user to set their password

This commit is contained in:
Savanni D'Gerinel 2025-01-01 00:19:12 -05:00
parent d9f1efb8d3
commit 792437af44
2 changed files with 93 additions and 5 deletions

View File

@ -141,7 +141,7 @@ pub async fn get_user(
ResultExt::Ok(None) => (StatusCode::NOT_FOUND, Json(None)),
ResultExt::Err(_err) => (StatusCode::BAD_REQUEST, Json(None)),
ResultExt::Fatal(err) => panic!("{}", err),
}
},
None => (
StatusCode::OK,
Json(Some(UserProfile {
@ -169,13 +169,39 @@ pub async fn create_user(
admin_required(core.clone(), headers, |_admin| async {
match core.create_user(&req.username).await {
ResultExt::Ok(_) => (StatusCode::OK, Json(None)),
ResultExt::Err(err) => (StatusCode::BAD_REQUEST, Json(None)),
ResultExt::Err(_err) => (StatusCode::BAD_REQUEST, Json(None)),
ResultExt::Fatal(fatal) => panic!("{}", fatal),
}
})
.await
}
#[derive(Deserialize, Serialize)]
#[typeshare]
pub struct SetPasswordRequest {
pub password_1: String,
pub password_2: String,
}
pub async fn set_password(
core: Core,
headers: HeaderMap,
req: SetPasswordRequest,
) -> (StatusCode, Json<Option<()>>) {
auth_required(core.clone(), headers, |user| async {
if req.password_1 == req.password_2 {
match core.set_password(user.id, req.password_1).await {
ResultExt::Ok(_) => (StatusCode::OK, Json(None)),
ResultExt::Err(_err) => (StatusCode::BAD_REQUEST, Json(None)),
ResultExt::Fatal(fatal) => panic!("{}", fatal),
}
} else {
(StatusCode::BAD_REQUEST, Json(None))
}
})
.await
}
/*
pub async fn handle_auth(
auth_ctx: &AuthDB,

View File

@ -3,7 +3,7 @@ use std::fmt;
use axum::{
extract::Path,
http::{HeaderMap, StatusCode},
routing::{get, post},
routing::{get, post, put},
Json, Router,
};
@ -11,7 +11,8 @@ use crate::{
core::Core,
database::UserId,
handlers::{
check_password, create_user, get_user, healthcheck, AuthRequest, CreateUserRequest,
check_password, create_user, get_user, healthcheck, set_password, AuthRequest,
CreateUserRequest, SetPasswordRequest,
},
};
@ -46,6 +47,16 @@ pub fn routes(core: Core) -> Router {
}
}),
)
.route(
"/api/v1/user/password",
put({
let core = core.clone();
move |headers: HeaderMap, req: Json<SetPasswordRequest>| {
let Json(req) = req;
set_password(core, headers, req)
}
}),
)
.route(
"/api/v1/user/:user_id",
get({
@ -253,9 +264,60 @@ mod test {
assert_eq!(profile.username, "admin");
}
#[tokio::test]
async fn a_user_can_change_their_password() {
let (_core, server) = setup_with_user().await;
let response = server
.post("/api/v1/auth")
.json(&AuthRequest {
username: "savanni".to_owned(),
password: "".to_owned(),
})
.await;
let session_id: Option<SessionId> = response.json();
let session_id = session_id.unwrap();
let response = server
.get("/api/v1/user")
.add_header("Authorization", format!("Bearer {}", session_id))
.await;
let profile = response.json::<Option<UserProfile>>().unwrap();
assert_eq!(profile.username, "savanni");
let response = server
.put("/api/v1/user/password")
.json(&SetPasswordRequest {
password_1: "abcdefg".to_owned(),
password_2: "abcd".to_owned(),
})
.await;
response.assert_status(StatusCode::UNAUTHORIZED);
let response = server
.put("/api/v1/user/password")
.add_header("Authorization", format!("Bearer {}", session_id))
.json(&SetPasswordRequest {
password_1: "abcdefg".to_owned(),
password_2: "abcd".to_owned(),
})
.await;
response.assert_status(StatusCode::BAD_REQUEST);
let response = server
.put(&format!("/api/v1/user/password"))
.add_header("Authorization", format!("Bearer {}", session_id))
.json(&SetPasswordRequest {
password_1: "abcdefg".to_owned(),
password_2: "abcdefg".to_owned(),
})
.await;
response.assert_status(StatusCode::OK);
}
#[ignore]
#[tokio::test]
async fn a_user_can_get_change_their_password() {
async fn a_user_cannot_change_another_users_password() {
unimplemented!();
}