1 use actix_web::web::Data;
2 use base64::{engine::general_purpose::STANDARD_NO_PAD as base64, Engine};
4 use lemmy_api_common::{context::LemmyContext, utils::local_site_to_slur_regex};
5 use lemmy_db_schema::source::local_site::LocalSite;
7 error::{LemmyError, LemmyErrorExt, LemmyErrorType},
8 utils::slurs::check_slurs,
19 mod private_message_report;
22 #[async_trait::async_trait(?Send)]
24 type Response: serde::ser::Serialize + Send + Clone + Sync;
26 async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError>;
29 /// Converts the captcha to a base64 encoded wav audio file
30 pub(crate) fn captcha_as_wav_base64(captcha: &Captcha) -> Result<String, LemmyError> {
31 let letters = captcha.as_wav();
33 // Decode each wav file, concatenate the samples
34 let mut concat_samples: Vec<i16> = Vec::new();
35 let mut any_header: Option<wav::Header> = None;
36 for letter in letters {
37 let mut cursor = Cursor::new(letter.unwrap_or_default());
38 let (header, samples) = wav::read(&mut cursor)?;
39 any_header = Some(header);
40 if let Some(samples16) = samples.as_sixteen() {
41 concat_samples.extend(samples16);
43 return Err(LemmyErrorType::CouldntCreateAudioCaptcha)?;
47 // Encode the concatenated result as a wav file
48 let mut output_buffer = Cursor::new(vec![]);
49 let header = match any_header {
50 Some(header) => header,
51 None => return Err(LemmyErrorType::CouldntCreateAudioCaptcha)?,
55 &wav::BitDepth::Sixteen(concat_samples),
58 .with_lemmy_type(LemmyErrorType::CouldntCreateAudioCaptcha)?;
60 Ok(base64.encode(output_buffer.into_inner()))
63 /// Check size of report and remove whitespace
64 pub(crate) fn check_report_reason(reason: &str, local_site: &LocalSite) -> Result<(), LemmyError> {
65 let slur_regex = &local_site_to_slur_regex(local_site);
67 check_slurs(reason, slur_regex)?;
68 if reason.is_empty() {
69 return Err(LemmyErrorType::ReportReasonRequired)?;
71 if reason.chars().count() > 1000 {
72 return Err(LemmyErrorType::ReportTooLong)?;
79 use lemmy_api_common::utils::check_validator_time;
80 use lemmy_db_schema::{
83 local_user::{LocalUser, LocalUserInsertForm},
84 person::{Person, PersonInsertForm},
88 utils::build_db_pool_for_tests,
90 use lemmy_utils::{claims::Claims, settings::SETTINGS};
91 use serial_test::serial;
95 async fn test_should_not_validate_user_token_after_password_change() {
96 let pool = &build_db_pool_for_tests().await;
97 let pool = &mut pool.into();
98 let secret = Secret::init(pool).await.unwrap();
99 let settings = &SETTINGS.to_owned();
101 let inserted_instance = Instance::read_or_create(pool, "my_domain.tld".to_string())
105 let new_person = PersonInsertForm::builder()
106 .name("Gerry9812".into())
107 .public_key("pubkey".to_string())
108 .instance_id(inserted_instance.id)
111 let inserted_person = Person::create(pool, &new_person).await.unwrap();
113 let local_user_form = LocalUserInsertForm::builder()
114 .person_id(inserted_person.id)
115 .password_encrypted("123456".to_string())
118 let inserted_local_user = LocalUser::create(pool, &local_user_form).await.unwrap();
120 let jwt = Claims::jwt(
121 inserted_local_user.id.0,
126 let claims = Claims::decode(&jwt, &secret.jwt_secret).unwrap().claims;
127 let check = check_validator_time(&inserted_local_user.validator_time, &claims);
128 assert!(check.is_ok());
130 // The check should fail, since the validator time is now newer than the jwt issue time
131 let updated_local_user =
132 LocalUser::update_password(pool, inserted_local_user.id, "password111")
135 let check_after = check_validator_time(&updated_local_user.validator_time, &claims);
136 assert!(check_after.is_err());
138 let num_deleted = Person::delete(pool, inserted_person.id).await.unwrap();
139 assert_eq!(1, num_deleted);