mirror of
https://github.com/perstarkse/minne.git
synced 2026-04-19 23:41:22 +02:00
feat: rudimentary password change
This commit is contained in:
@@ -84,7 +84,7 @@ impl User {
|
|||||||
CREATE type::thing('user', $id) SET
|
CREATE type::thing('user', $id) SET
|
||||||
email = $email,
|
email = $email,
|
||||||
password = crypto::argon2::generate($password),
|
password = crypto::argon2::generate($password),
|
||||||
admin = $count < 1, // Changed from == 0 to < 1
|
admin = $count < 1,
|
||||||
anonymous = false,
|
anonymous = false,
|
||||||
created_at = $created_at,
|
created_at = $created_at,
|
||||||
updated_at = $updated_at,
|
updated_at = $updated_at,
|
||||||
@@ -103,6 +103,24 @@ impl User {
|
|||||||
user.ok_or(AppError::Auth("User failed to create".into()))
|
user.ok_or(AppError::Auth("User failed to create".into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn patch_password(
|
||||||
|
email: &str,
|
||||||
|
password: &str,
|
||||||
|
db: &SurrealDbClient,
|
||||||
|
) -> Result<(), AppError> {
|
||||||
|
db.client
|
||||||
|
.query(
|
||||||
|
"UPDATE user
|
||||||
|
SET password = crypto::argon2::generate($password)
|
||||||
|
WHERE email = $email",
|
||||||
|
)
|
||||||
|
.bind(("email", email.to_owned()))
|
||||||
|
.bind(("password", password.to_owned()))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn authenticate(
|
pub async fn authenticate(
|
||||||
email: String,
|
email: String,
|
||||||
password: String,
|
password: String,
|
||||||
|
|||||||
@@ -18,7 +18,10 @@ use html_state::HtmlState;
|
|||||||
use middleware_analytics::analytics_middleware;
|
use middleware_analytics::analytics_middleware;
|
||||||
use middleware_auth::require_auth;
|
use middleware_auth::require_auth;
|
||||||
use routes::{
|
use routes::{
|
||||||
account::{delete_account, set_api_key, show_account_page, update_timezone},
|
account::{
|
||||||
|
change_password, delete_account, set_api_key, show_account_page, show_change_password,
|
||||||
|
update_timezone,
|
||||||
|
},
|
||||||
admin_panel::{show_admin_panel, toggle_registration_status},
|
admin_panel::{show_admin_panel, toggle_registration_status},
|
||||||
chat::{
|
chat::{
|
||||||
message_response_stream::get_response_stream, new_chat_user_message, new_user_message,
|
message_response_stream::get_response_stream, new_chat_user_message, new_user_message,
|
||||||
@@ -109,6 +112,10 @@ where
|
|||||||
.route("/toggle-registrations", patch(toggle_registration_status))
|
.route("/toggle-registrations", patch(toggle_registration_status))
|
||||||
.route("/set-api-key", post(set_api_key))
|
.route("/set-api-key", post(set_api_key))
|
||||||
.route("/update-timezone", patch(update_timezone))
|
.route("/update-timezone", patch(update_timezone))
|
||||||
|
.route(
|
||||||
|
"/change-password",
|
||||||
|
get(show_change_password).patch(change_password),
|
||||||
|
)
|
||||||
.route("/delete-account", delete(delete_account))
|
.route("/delete-account", delete(delete_account))
|
||||||
.route_layer(from_fn_with_state(app_state.clone(), require_auth));
|
.route_layer(from_fn_with_state(app_state.clone(), require_auth));
|
||||||
|
|
||||||
|
|||||||
@@ -104,3 +104,38 @@ pub async fn update_timezone(
|
|||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn show_change_password(
|
||||||
|
RequireUser(_user): RequireUser,
|
||||||
|
) -> Result<impl IntoResponse, HtmlError> {
|
||||||
|
Ok(TemplateResponse::new_template(
|
||||||
|
"auth/change_password_form.html",
|
||||||
|
{},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct NewPasswordForm {
|
||||||
|
old_password: String,
|
||||||
|
new_password: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn change_password(
|
||||||
|
State(state): State<HtmlState>,
|
||||||
|
RequireUser(user): RequireUser,
|
||||||
|
auth: AuthSessionType,
|
||||||
|
Form(form): Form<NewPasswordForm>,
|
||||||
|
) -> Result<impl IntoResponse, HtmlError> {
|
||||||
|
// Authenticate to make sure the password matches
|
||||||
|
let authenticated_user = User::authenticate(user.email, form.old_password, &state.db).await?;
|
||||||
|
|
||||||
|
User::patch_password(&authenticated_user.email, &form.new_password, &state.db).await?;
|
||||||
|
|
||||||
|
auth.cache_clear_user(user.id);
|
||||||
|
|
||||||
|
Ok(TemplateResponse::new_partial(
|
||||||
|
"auth/account_settings.html",
|
||||||
|
"change_password_section",
|
||||||
|
{},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|||||||
@@ -95,15 +95,17 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-control mt-4">
|
<div class="form-control mt-4 hidden">
|
||||||
<button hx-post="/verify-email" class="btn btn-secondary w-full">
|
<button hx-post="/verify-email" class="btn btn-secondary w-full">
|
||||||
Verify Email
|
Verify Email
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-control mt-4">
|
<div class="form-control mt-4">
|
||||||
<button hx-get="/change-password" class="btn btn-primary w-full">
|
{% block change_password_section %}
|
||||||
|
<button hx-get="/change-password" hx-swap="outerHTML" class="btn btn-primary w-full">
|
||||||
Change Password
|
Change Password
|
||||||
</button>
|
</button>
|
||||||
|
{% endblock %}
|
||||||
</div>
|
</div>
|
||||||
<div class="form-control mt-4">
|
<div class="form-control mt-4">
|
||||||
<button hx-delete="/delete-account"
|
<button hx-delete="/delete-account"
|
||||||
|
|||||||
5
templates/auth/change_password_form.html
Normal file
5
templates/auth/change_password_form.html
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<form hx-patch="/change-password" class="flex flex-col gap-1">
|
||||||
|
<input name="old_password" class="input w-full" type="password" placeholder="Enter old password"></input>
|
||||||
|
<input name="new_password" class="input w-full" type="password" placeholder="Enter new password"></input>
|
||||||
|
<button class="btn btn-primary w-full">Change Password</button>
|
||||||
|
</form>
|
||||||
Reference in New Issue
Block a user