diff options
Diffstat (limited to 'server/src/ui')
| -rw-r--r-- | server/src/ui/account/mod.rs | 62 | ||||
| -rw-r--r-- | server/src/ui/admin/import.rs | 2 |
2 files changed, 54 insertions, 10 deletions
diff --git a/server/src/ui/account/mod.rs b/server/src/ui/account/mod.rs index 1c44914..837d49a 100644 --- a/server/src/ui/account/mod.rs +++ b/server/src/ui/account/mod.rs @@ -9,16 +9,20 @@ pub mod settings; use super::error::MyError; use crate::{ - auth::login, request_info::RequestInfo, ui::error::MyResult, ui_responder::UiResponse, + auth::{hash_password, login}, + request_info::RequestInfo, + ui::error::MyResult, + ui_responder::UiResponse, }; use anyhow::anyhow; use jellycommon::{ - VIEW_ACCOUNT_LOGIN, VIEW_ACCOUNT_LOGOUT, - jellyobject::OBB, + jellyobject::{OBB, Path}, routes::{u_account_login, u_home}, + *, }; +use jellydb::{Filter, Query, Sort}; use rocket::{ - FromForm, + Either, FromForm, form::{Contextual, Form}, get, http::{Cookie, CookieJar}, @@ -39,10 +43,14 @@ pub fn r_account_logout(ri: RequestInfo<'_>) -> UiResponse { #[derive(FromForm, Serialize, Deserialize)] pub struct LoginForm { - #[field(validate = len(4..32))] + #[field(validate = len(..32))] pub username: String, #[field(validate = len(..64))] pub password: String, + #[field(validate = len(..64))] + pub new_password: Option<String>, + #[field(validate = len(..64))] + pub display_name: Option<String>, #[field(default = 604800)] // one week pub expire: u64, } @@ -52,15 +60,51 @@ pub fn r_account_login_post( ri: RequestInfo<'_>, jar: &CookieJar, form: Form<Contextual<LoginForm>>, -) -> MyResult<Redirect> { +) -> MyResult<Either<Redirect, UiResponse>> { let form = match &form.value { Some(v) => v, None => return Err(MyError(anyhow!(format_form_error(form)))), }; - let session = login(&ri.state, &form.username, &form.password, None)?; - jar.add(Cookie::build(("session", session)).permanent().build()); - Ok(Redirect::found(u_home())) + let (session, need_pw_change) = login(&ri.state, &form.username, &form.password, None)?; + + if need_pw_change { + if let Some(new_password) = &form.new_password { + let password_hash = hash_password(&form.username, &new_password); + ri.state.database.transaction(&mut |txn| { + let user_row = txn.query_single(Query { + filter: Filter::Match(Path(vec![USER_LOGIN.0]), form.username.clone().into()), + sort: Sort::None, + })?; + if let Some(ur) = user_row { + let mut user = txn.get(ur)?.unwrap(); + user = user.as_object().remove(USER_PASSWORD_REQUIRE_CHANGE); + user = user.as_object().insert(USER_PASSWORD, &password_hash); + if let Some(name) = &form.display_name { + user = user.as_object().insert(USER_NAME, &name); + } + txn.update(ur, user)?; + } + Ok(()) + })?; + } else { + return Ok(Either::Right( + ri.respond_ui( + OBB::new().with( + VIEW_ACCOUNT_SET_PASSWORD, + OBB::new() + .with(SETPW_USERNAME, &form.username) + .with(SETPW_PASSWORD, &form.password) + .finish() + .as_object(), + ), + ), + )); + } + } + + jar.add(Cookie::build(("session", session)).permanent().build()); + Ok(Either::Left(Redirect::found(u_home()))) } #[post("/account/logout")] diff --git a/server/src/ui/admin/import.rs b/server/src/ui/admin/import.rs index eba2a3b..78db4a4 100644 --- a/server/src/ui/admin/import.rs +++ b/server/src/ui/admin/import.rs @@ -32,8 +32,8 @@ pub async fn r_admin_import(ri: RequestInfo<'_>) -> MyResult<UiResponse> { .iter() .map(|e| e.as_str()) .collect::<Vec<_>>(); - let mut data = ObjectBuffer::empty(); + let mut data = ObjectBuffer::empty(); if is_importing() { data = data.as_object().insert(ADMIN_IMPORT_BUSY, ()); } |