diff options
| author | metamuffin <metamuffin@disroot.org> | 2026-02-25 17:20:58 +0100 |
|---|---|---|
| committer | metamuffin <metamuffin@disroot.org> | 2026-02-25 17:20:58 +0100 |
| commit | 7f7deec27e69ed110c52caddaa3a0c04430e71d9 (patch) | |
| tree | b0880d0407c09bc7fb0e83734c4d4683316fb429 /server | |
| parent | 3b9ba348c8e77a47786bfcc1af6756e8d3bc7499 (diff) | |
| download | jellything-7f7deec27e69ed110c52caddaa3a0c04430e71d9.tar jellything-7f7deec27e69ed110c52caddaa3a0c04430e71d9.tar.bz2 jellything-7f7deec27e69ed110c52caddaa3a0c04430e71d9.tar.zst | |
initial account setup
Diffstat (limited to 'server')
| -rw-r--r-- | server/src/auth.rs | 20 | ||||
| -rw-r--r-- | server/src/ui/account/mod.rs | 62 | ||||
| -rw-r--r-- | server/src/ui/admin/import.rs | 2 |
3 files changed, 68 insertions, 16 deletions
diff --git a/server/src/auth.rs b/server/src/auth.rs index 6463eb1..26da82b 100644 --- a/server/src/auth.rs +++ b/server/src/auth.rs @@ -8,8 +8,8 @@ use crate::State; use anyhow::{Result, anyhow, bail}; use argon2::{Argon2, PasswordHasher, password_hash::Salt}; use jellycommon::{ - USER_LOGIN, USER_PASSWORD, jellyobject::{ObjectBuffer, Path}, + *, }; use jellydb::{Filter, Query, Sort}; @@ -25,7 +25,12 @@ pub fn token_to_user(state: &State, token: &str) -> Result<ObjectBuffer> { user.ok_or(anyhow!("user was deleted")) } -pub fn login(state: &State, username: &str, password: &str, expire: Option<i64>) -> Result<String> { +pub fn login( + state: &State, + username: &str, + password: &str, + expire: Option<i64>, +) -> Result<(String, bool)> { let password = hash_password(username, password); let mut user_row = None; @@ -51,10 +56,13 @@ pub fn login(state: &State, username: &str, password: &str, expire: Option<i64>) bail!("incorrect password") } - Ok(token::create( - &state.session_key, - user_row, - expire.unwrap_or(60 * 60 * 24 * 30), + Ok(( + token::create( + &state.session_key, + user_row, + expire.unwrap_or(60 * 60 * 24 * 30), + ), + user.as_object().has(USER_PASSWORD_REQUIRE_CHANGE.0), )) } 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, ()); } |