Merge pull request #1539 from LemmyNet/change_password_api

Moving ChangePassword to its own API action. Fixes #1471
pull/1559/head
Dessalines 2021-04-06 12:21:41 -04:00 committed by GitHub
commit 8df102ff4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 61 additions and 37 deletions

View File

@ -63,6 +63,9 @@ pub async fn match_websocket_operation(
UserOperation::SaveUserSettings => { UserOperation::SaveUserSettings => {
do_websocket_operation::<SaveUserSettings>(context, id, op, data).await do_websocket_operation::<SaveUserSettings>(context, id, op, data).await
} }
UserOperation::ChangePassword => {
do_websocket_operation::<ChangePassword>(context, id, op, data).await
}
UserOperation::GetReportCount => { UserOperation::GetReportCount => {
do_websocket_operation::<GetReportCount>(context, id, op, data).await do_websocket_operation::<GetReportCount>(context, id, op, data).await
} }

View File

@ -189,44 +189,9 @@ impl Perform for SaveUserSettings {
let local_user_id = local_user_view.local_user.id; let local_user_id = local_user_view.local_user.id;
let person_id = local_user_view.person.id; let person_id = local_user_view.person.id;
let password_encrypted = match &data.new_password {
Some(new_password) => {
match &data.new_password_verify {
Some(new_password_verify) => {
password_length_check(&new_password)?;
// Make sure passwords match
if new_password != new_password_verify {
return Err(ApiError::err("passwords_dont_match").into());
}
// Check the old password
match &data.old_password {
Some(old_password) => {
let valid: bool =
verify(old_password, &local_user_view.local_user.password_encrypted)
.unwrap_or(false);
if !valid {
return Err(ApiError::err("password_incorrect").into());
}
let new_password = new_password.to_owned();
let user = blocking(context.pool(), move |conn| {
LocalUser::update_password(conn, local_user_id, &new_password)
})
.await??;
user.password_encrypted
}
None => return Err(ApiError::err("password_incorrect").into()),
}
}
None => return Err(ApiError::err("passwords_dont_match").into()),
}
}
None => local_user_view.local_user.password_encrypted,
};
let default_listing_type = data.default_listing_type; let default_listing_type = data.default_listing_type;
let default_sort_type = data.default_sort_type; let default_sort_type = data.default_sort_type;
let password_encrypted = local_user_view.local_user.password_encrypted;
let person_form = PersonForm { let person_form = PersonForm {
name: local_user_view.person.name, name: local_user_view.person.name,
@ -300,6 +265,49 @@ impl Perform for SaveUserSettings {
} }
} }
#[async_trait::async_trait(?Send)]
impl Perform for ChangePassword {
type Response = LoginResponse;
async fn perform(
&self,
context: &Data<LemmyContext>,
_websocket_id: Option<ConnectionId>,
) -> Result<LoginResponse, LemmyError> {
let data: &ChangePassword = &self;
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
password_length_check(&data.new_password)?;
// Make sure passwords match
if data.new_password != data.new_password_verify {
return Err(ApiError::err("passwords_dont_match").into());
}
// Check the old password
let valid: bool = verify(
&data.old_password,
&local_user_view.local_user.password_encrypted,
)
.unwrap_or(false);
if !valid {
return Err(ApiError::err("password_incorrect").into());
}
let local_user_id = local_user_view.local_user.id;
let new_password = data.new_password.to_owned();
let updated_local_user = blocking(context.pool(), move |conn| {
LocalUser::update_password(conn, local_user_id, &new_password)
})
.await??;
// Return the jwt
Ok(LoginResponse {
jwt: Claims::jwt(updated_local_user.id.0)?,
})
}
}
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
impl Perform for AddAdmin { impl Perform for AddAdmin {
type Response = AddAdminResponse; type Response = AddAdminResponse;

View File

@ -48,7 +48,6 @@ pub struct CaptchaResponse {
pub struct SaveUserSettings { pub struct SaveUserSettings {
pub show_nsfw: Option<bool>, pub show_nsfw: Option<bool>,
pub show_scores: Option<bool>, pub show_scores: Option<bool>,
pub show_avatars: Option<bool>,
pub theme: Option<String>, pub theme: Option<String>,
pub default_sort_type: Option<i16>, pub default_sort_type: Option<i16>,
pub default_listing_type: Option<i16>, pub default_listing_type: Option<i16>,
@ -59,6 +58,7 @@ pub struct SaveUserSettings {
pub email: Option<String>, pub email: Option<String>,
pub bio: Option<String>, pub bio: Option<String>,
pub matrix_user_id: Option<String>, pub matrix_user_id: Option<String>,
pub show_avatars: Option<bool>,
pub new_password: Option<String>, pub new_password: Option<String>,
pub new_password_verify: Option<String>, pub new_password_verify: Option<String>,
pub old_password: Option<String>, pub old_password: Option<String>,
@ -66,6 +66,14 @@ pub struct SaveUserSettings {
pub auth: String, pub auth: String,
} }
#[derive(Deserialize)]
pub struct ChangePassword {
pub new_password: String,
pub new_password_verify: String,
pub old_password: String,
pub auth: String,
}
#[derive(Serialize)] #[derive(Serialize)]
pub struct LoginResponse { pub struct LoginResponse {
pub jwt: String, pub jwt: String,

View File

@ -123,6 +123,7 @@ pub enum UserOperation {
PostJoin, PostJoin,
CommunityJoin, CommunityJoin,
ModJoin, ModJoin,
ChangePassword,
} }
#[derive(EnumString, ToString, Debug, Clone)] #[derive(EnumString, ToString, Debug, Clone)]

View File

@ -182,6 +182,10 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimit) {
"/save_user_settings", "/save_user_settings",
web::put().to(route_post::<SaveUserSettings>), web::put().to(route_post::<SaveUserSettings>),
) )
.route(
"/change_password",
web::put().to(route_post::<ChangePassword>),
)
.route("/report_count", web::get().to(route_get::<GetReportCount>)), .route("/report_count", web::get().to(route_get::<GetReportCount>)),
) )
// Admin Actions // Admin Actions