diff --git a/crates/database/queries/users/set_password.sql b/crates/database/queries/users/set_password.sql new file mode 100644 index 0000000..140ee93 --- /dev/null +++ b/crates/database/queries/users/set_password.sql @@ -0,0 +1,5 @@ +update users + +set password = ? + +where id is ? \ No newline at end of file diff --git a/crates/database/sqlx-data.json b/crates/database/sqlx-data.json index d2980fb..1dfb7f0 100644 --- a/crates/database/sqlx-data.json +++ b/crates/database/sqlx-data.json @@ -558,6 +558,16 @@ }, "query": "update refresh_tokens\n\nset revoked_at = CURRENT_TIMESTAMP\n\nwhere app is ?\n and revoked_at is null" }, + "9784afe2dcff4db86908175d4e3145baf72b3361f43e4127350a14a183ef63f7": { + "describe": { + "columns": [], + "nullable": [], + "parameters": { + "Right": 2 + } + }, + "query": "update users\n\nset password = ?\n\nwhere id is ?" + }, "9f1885c4786f73335b4d614f562bb7cad49c91bfe7f084d8c25c6c571673ab90": { "describe": { "columns": [], diff --git a/crates/database/src/tables/users.rs b/crates/database/src/tables/users.rs index e894b96..de55739 100644 --- a/crates/database/src/tables/users.rs +++ b/crates/database/src/tables/users.rs @@ -149,4 +149,18 @@ impl Users { Ok((query.rows_affected() == 1).then_some(())) } + + pub async fn set_password( + conn: impl SqliteExecutor<'_>, + id: &str, + password: Option<&str>, + ) -> Result, Error> { + let query: SqliteQueryResult = + sqlx::query_file!("queries/users/set_password.sql", password, id) + .execute(conn) + .await + .map_err(handle_error)?; + + Ok((query.rows_affected() == 1).then_some(())) + } } diff --git a/crates/ezidam/src/routes/settings.rs b/crates/ezidam/src/routes/settings.rs index 96a039d..02b5b53 100644 --- a/crates/ezidam/src/routes/settings.rs +++ b/crates/ezidam/src/routes/settings.rs @@ -14,6 +14,7 @@ pub fn routes() -> Vec { user_settings_security, user_settings_security_logout_everywhere, user_settings_security_paper_key, + user_settings_security_password, ] } diff --git a/crates/ezidam/src/routes/settings/security.rs b/crates/ezidam/src/routes/settings/security.rs index 18b6532..1db3a8e 100644 --- a/crates/ezidam/src/routes/settings/security.rs +++ b/crates/ezidam/src/routes/settings/security.rs @@ -176,3 +176,43 @@ pub async fn user_settings_security_paper_key( flash_message, )) } + +#[derive(Debug, FromForm)] +pub struct PasswordForm<'r> { + pub password: &'r str, +} + +#[post("/settings/security/password", data = "
")] +pub async fn user_settings_security_password( + mut db: Connection, + jwt_user: JwtUser, + form: Form>, +) -> Result> { + let (flash_kind, flash_message) = if !form.password.is_empty() { + // Hash password + let password = form.password.to_string(); + let password = task::spawn_blocking(move || Password::new(&password)).await??; + + let mut transaction = db.begin().await?; + + // Get user info + let user = User::get_by_login(&mut transaction, &jwt_user.0.subject) + .await? + .ok_or_else(|| Error::not_found("Could not find user"))?; + + // Set password + user.set_password(&mut transaction, Some(&password)).await?; + + transaction.commit().await?; + + (FlashKind::Success, "Your new password has been saved.") + } else { + (FlashKind::Warning, "Nothing to do.") + }; + + Ok(Flash::new( + Redirect::to(uri!(user_settings_security)), + flash_kind, + flash_message, + )) +} diff --git a/crates/ezidam/templates/pages/settings/security.html.tera b/crates/ezidam/templates/pages/settings/security.html.tera index 4834b65..95a0046 100644 --- a/crates/ezidam/templates/pages/settings/security.html.tera +++ b/crates/ezidam/templates/pages/settings/security.html.tera @@ -43,7 +43,7 @@

Password

@@ -79,6 +79,44 @@
+ + +