Add change password feature to settings page
- Add PUT /api/me/password endpoint in backend - Add changePassword API function in frontend - Add change password form UI in SettingsPanel - Add i18n translations for change password (zh/en) - Fix TypeScript type error in i18n context Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,7 @@ use sea_orm::{ActiveModelTrait, EntityTrait, Set};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io::Write;
|
||||
use uuid::Uuid;
|
||||
use bcrypt;
|
||||
|
||||
use crate::app_data::AppData;
|
||||
use crate::entity::user;
|
||||
@@ -33,6 +34,13 @@ pub struct UpdateSettingsRequest {
|
||||
pub bark_enabled: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ChangePasswordRequest {
|
||||
pub current_password: String,
|
||||
pub new_password: String,
|
||||
}
|
||||
|
||||
#[get("")]
|
||||
async fn get_me(
|
||||
app_data: web::Data<AppData>,
|
||||
@@ -208,9 +216,46 @@ async fn upload_avatar(
|
||||
Ok(HttpResponse::Ok().json(UploadAvatarResponse { avatar_url }))
|
||||
}
|
||||
|
||||
#[put("/password")]
|
||||
async fn change_password(
|
||||
app_data: web::Data<AppData>,
|
||||
auth: AuthUser,
|
||||
body: web::Json<ChangePasswordRequest>,
|
||||
) -> Result<impl Responder, ApiError> {
|
||||
if body.new_password.len() < 6 {
|
||||
return Err(ApiError::BadRequest("New password must be at least 6 characters".to_string()));
|
||||
}
|
||||
|
||||
let user = user::Entity::find_by_id(auth.user_id)
|
||||
.one(&app_data.db)
|
||||
.await?
|
||||
.ok_or_else(|| ApiError::NotFound("User not found".to_string()))?;
|
||||
|
||||
// Verify current password
|
||||
let valid = bcrypt::verify(&body.current_password, &user.password_hash)
|
||||
.map_err(|_| ApiError::Internal("Password verification failed".to_string()))?;
|
||||
|
||||
if !valid {
|
||||
return Err(ApiError::BadRequest("Current password is incorrect".to_string()));
|
||||
}
|
||||
|
||||
// Hash new password
|
||||
let new_password_hash = bcrypt::hash(&body.new_password, 10)
|
||||
.map_err(|_| ApiError::Internal("Password hashing failed".to_string()))?;
|
||||
|
||||
// Update password
|
||||
let mut active: user::ActiveModel = user.into();
|
||||
active.password_hash = Set(new_password_hash);
|
||||
active.updated_at = Set(chrono::Utc::now().fixed_offset());
|
||||
active.update(&app_data.db).await?;
|
||||
|
||||
Ok(HttpResponse::Ok().json(serde_json::json!({"success": true})))
|
||||
}
|
||||
|
||||
pub fn routes() -> Scope {
|
||||
web::scope("/api/me")
|
||||
.service(get_me)
|
||||
.service(update_settings)
|
||||
.service(upload_avatar)
|
||||
.service(change_password)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user