]> Untitled Git - lemmy.git/commitdiff
Merge branch 'main' into change_password_api
authorDessalines <tyhou13@gmx.com>
Tue, 6 Apr 2021 16:09:26 +0000 (12:09 -0400)
committerDessalines <tyhou13@gmx.com>
Tue, 6 Apr 2021 16:09:26 +0000 (12:09 -0400)
1  2 
crates/api/src/lib.rs
crates/api/src/local_user.rs
crates/api_common/src/person.rs

diff --combined crates/api/src/lib.rs
index d25d0bbcd34d583fef8e4bda2aa34e5bdb6982b0,c9de749ef36e9a9999392b99738b3b57cc912372..0ba3fbea21370913f7b533ddb1afaec718fb1576
@@@ -1,9 -1,9 +1,9 @@@
  use actix_web::{web, web::Data};
+ use captcha::Captcha;
  use lemmy_api_common::{comment::*, community::*, person::*, post::*, site::*, websocket::*};
  use lemmy_utils::{ConnectionId, LemmyError};
  use lemmy_websocket::{serialize_websocket_message, LemmyContext, UserOperation};
  use serde::Deserialize;
- use std::{env, process::Command};
  
  mod comment;
  mod comment_report;
@@@ -63,9 -63,6 +63,9 @@@ pub async fn match_websocket_operation
      UserOperation::SaveUserSettings => {
        do_websocket_operation::<SaveUserSettings>(context, id, op, data).await
      }
 +    UserOperation::ChangePassword => {
 +      do_websocket_operation::<ChangePassword>(context, id, op, data).await
 +    }
      UserOperation::GetReportCount => {
        do_websocket_operation::<GetReportCount>(context, id, op, data).await
      }
@@@ -161,60 -158,23 +161,23 @@@ wher
    serialize_websocket_message(&op, &res)
  }
  
- pub(crate) fn captcha_espeak_wav_base64(captcha: &str) -> Result<String, LemmyError> {
-   let mut built_text = String::new();
+ /// Converts the captcha to a base64 encoded wav audio file
+ pub(crate) fn captcha_as_wav_base64(captcha: &Captcha) -> String {
+   let letters = captcha.as_wav();
  
-   // Building proper speech text for espeak
-   for mut c in captcha.chars() {
-     let new_str = if c.is_alphabetic() {
-       if c.is_lowercase() {
-         c.make_ascii_uppercase();
-         format!("lower case {} ... ", c)
-       } else {
-         c.make_ascii_uppercase();
-         format!("capital {} ... ", c)
-       }
-     } else {
-       format!("{} ...", c)
-     };
+   let mut concat_letters: Vec<u8> = Vec::new();
  
-     built_text.push_str(&new_str);
+   for letter in letters {
+     let bytes = letter.unwrap_or_default();
+     concat_letters.extend(bytes);
    }
  
-   espeak_wav_base64(&built_text)
- }
- pub(crate) fn espeak_wav_base64(text: &str) -> Result<String, LemmyError> {
-   // Make a temp file path
-   let uuid = uuid::Uuid::new_v4().to_string();
-   let file_path = format!(
-     "{}/lemmy_espeak_{}.wav",
-     env::temp_dir().to_string_lossy(),
-     &uuid
-   );
-   // Write the wav file
-   Command::new("espeak")
-     .arg("-w")
-     .arg(&file_path)
-     .arg(text)
-     .status()?;
-   // Read the wav file bytes
-   let bytes = std::fs::read(&file_path)?;
-   // Delete the file
-   std::fs::remove_file(file_path)?;
    // Convert to base64
-   let base64 = base64::encode(bytes);
-   Ok(base64)
+   base64::encode(concat_letters)
  }
  
  #[cfg(test)]
  mod tests {
-   use crate::captcha_espeak_wav_base64;
    use lemmy_api_common::check_validator_time;
    use lemmy_db_queries::{establish_unpooled_connection, source::local_user::LocalUser_, Crud};
    use lemmy_db_schema::source::{
      let num_deleted = Person::delete(&conn, inserted_person.id).unwrap();
      assert_eq!(1, num_deleted);
    }
-   #[test]
-   fn test_espeak() {
-     assert!(captcha_espeak_wav_base64("WxRt2l").is_ok())
-   }
  }
index d19171496fd6a08a9e932c2f334917ee74bbf3e7,6a319dcd5741494ac1bf4ad5e036ed82a34003e7..43954aa83cc320b13be545ba8cfe2235b1185b91
@@@ -1,4 -1,4 +1,4 @@@
- use crate::{captcha_espeak_wav_base64, Perform};
+ use crate::{captcha_as_wav_base64, Perform};
  use actix_web::web::Data;
  use anyhow::Context;
  use bcrypt::verify;
@@@ -60,7 -60,7 +60,7 @@@ use lemmy_utils::
    email::send_email,
    location_info,
    settings::structs::Settings,
-   utils::{generate_random_string, is_valid_preferred_username, naive_from_unix},
+   utils::{generate_random_string, is_valid_display_name, naive_from_unix},
    ApiError,
    ConnectionId,
    LemmyError,
@@@ -135,13 -135,11 +135,11 @@@ impl Perform for GetCaptcha 
  
      let answer = captcha.chars_as_string();
  
-     let png_byte_array = captcha.as_png().expect("failed to generate captcha");
-     let png = base64::encode(png_byte_array);
+     let png = captcha.as_base64().expect("failed to generate captcha");
  
      let uuid = uuid::Uuid::new_v4().to_string();
  
-     let wav = captcha_espeak_wav_base64(&answer).ok();
+     let wav = captcha_as_wav_base64(&captcha);
  
      let captcha_item = CaptchaItem {
        answer,
@@@ -174,7 -172,7 +172,7 @@@ impl Perform for SaveUserSettings 
      let banner = diesel_option_overwrite_to_url(&data.banner)?;
      let email = diesel_option_overwrite(&data.email);
      let bio = diesel_option_overwrite(&data.bio);
-     let preferred_username = diesel_option_overwrite(&data.preferred_username);
+     let display_name = diesel_option_overwrite(&data.display_name);
      let matrix_user_id = diesel_option_overwrite(&data.matrix_user_id);
  
      if let Some(Some(bio)) = &bio {
        }
      }
  
-     if let Some(Some(preferred_username)) = &preferred_username {
-       if !is_valid_preferred_username(preferred_username.trim()) {
+     if let Some(Some(display_name)) = &display_name {
+       if !is_valid_display_name(display_name.trim()) {
          return Err(ApiError::err("invalid_username").into());
        }
      }
  
      let local_user_id = local_user_view.local_user.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_sort_type = data.default_sort_type;
 +    let password_encrypted = local_user_view.local_user.password_encrypted;
  
      let person_form = PersonForm {
        name: local_user_view.person.name,
        avatar,
        banner,
        inbox_url: None,
-       preferred_username,
+       display_name,
        published: None,
        updated: Some(naive_now()),
        banned: None,
        email,
        password_encrypted,
        show_nsfw: data.show_nsfw,
+       show_scores: data.show_scores,
        theme: data.theme.to_owned(),
        default_sort_type,
        default_listing_type,
    }
  }
  
 +#[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)]
  impl Perform for AddAdmin {
    type Response = AddAdminResponse;
index 53033a9205083b73ab285f0b4d5d79ae89436adb,21fa1c778e5fe0393c6ef57368cd436e77ff055a..6402096c9a0b94d16893fd69f167ef13f9914b2c
@@@ -39,37 -39,33 +39,41 @@@ pub struct GetCaptchaResponse 
  
  #[derive(Serialize)]
  pub struct CaptchaResponse {
-   pub png: String,         // A Base64 encoded png
-   pub wav: Option<String>, // A Base64 encoded wav audio
+   pub png: String, // A Base64 encoded png
+   pub wav: String, // A Base64 encoded wav audio
    pub uuid: String,
  }
  
  #[derive(Deserialize)]
  pub struct SaveUserSettings {
    pub show_nsfw: Option<bool>,
 -  pub show_avatars: Option<bool>,
+   pub show_scores: Option<bool>,
    pub theme: Option<String>,
    pub default_sort_type: Option<i16>,
    pub default_listing_type: Option<i16>,
    pub lang: Option<String>,
    pub avatar: Option<String>,
    pub banner: Option<String>,
-   pub preferred_username: Option<String>,
+   pub display_name: Option<String>,
    pub email: Option<String>,
    pub bio: Option<String>,
    pub matrix_user_id: Option<String>,
 +  pub show_avatars: Option<bool>,
+   pub new_password: Option<String>,
+   pub new_password_verify: Option<String>,
+   pub old_password: Option<String>,
    pub send_notifications_to_email: Option<bool>,
    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)]
  pub struct LoginResponse {
    pub jwt: String,