]> Untitled Git - lemmy.git/blob - crates/api/src/lib.rs
Dont upsert Instance row every apub fetch (#2771)
[lemmy.git] / crates / api / src / lib.rs
1 use actix_web::web::Data;
2 use captcha::Captcha;
3 use lemmy_api_common::{context::LemmyContext, utils::local_site_to_slur_regex};
4 use lemmy_db_schema::source::local_site::LocalSite;
5 use lemmy_utils::{error::LemmyError, utils::slurs::check_slurs, ConnectionId};
6
7 mod comment;
8 mod comment_report;
9 mod community;
10 mod local_user;
11 mod post;
12 mod post_report;
13 mod private_message;
14 mod private_message_report;
15 mod site;
16 mod websocket;
17
18 #[async_trait::async_trait(?Send)]
19 pub trait Perform {
20   type Response: serde::ser::Serialize + Send;
21
22   async fn perform(
23     &self,
24     context: &Data<LemmyContext>,
25     websocket_id: Option<ConnectionId>,
26   ) -> Result<Self::Response, LemmyError>;
27 }
28
29 /// Converts the captcha to a base64 encoded wav audio file
30 pub(crate) fn captcha_as_wav_base64(captcha: &Captcha) -> String {
31   let letters = captcha.as_wav();
32
33   let mut concat_letters: Vec<u8> = Vec::new();
34
35   for letter in letters {
36     let bytes = letter.unwrap_or_default();
37     concat_letters.extend(bytes);
38   }
39
40   // Convert to base64
41   base64::encode(concat_letters)
42 }
43
44 /// Check size of report and remove whitespace
45 pub(crate) fn check_report_reason(reason: &str, local_site: &LocalSite) -> Result<(), LemmyError> {
46   let slur_regex = &local_site_to_slur_regex(local_site);
47
48   check_slurs(reason, slur_regex)?;
49   if reason.is_empty() {
50     return Err(LemmyError::from_message("report_reason_required"));
51   }
52   if reason.chars().count() > 1000 {
53     return Err(LemmyError::from_message("report_too_long"));
54   }
55   Ok(())
56 }
57
58 #[cfg(test)]
59 mod tests {
60   use lemmy_api_common::utils::check_validator_time;
61   use lemmy_db_schema::{
62     source::{
63       instance::Instance,
64       local_user::{LocalUser, LocalUserInsertForm},
65       person::{Person, PersonInsertForm},
66       secret::Secret,
67     },
68     traits::Crud,
69     utils::build_db_pool_for_tests,
70   };
71   use lemmy_utils::{claims::Claims, settings::SETTINGS};
72   use serial_test::serial;
73
74   #[tokio::test]
75   #[serial]
76   async fn test_should_not_validate_user_token_after_password_change() {
77     let pool = &build_db_pool_for_tests().await;
78     let secret = Secret::init(pool).await.unwrap();
79     let settings = &SETTINGS.to_owned();
80
81     let inserted_instance = Instance::read_or_create(pool, "my_domain.tld".to_string())
82       .await
83       .unwrap();
84
85     let new_person = PersonInsertForm::builder()
86       .name("Gerry9812".into())
87       .public_key("pubkey".to_string())
88       .instance_id(inserted_instance.id)
89       .build();
90
91     let inserted_person = Person::create(pool, &new_person).await.unwrap();
92
93     let local_user_form = LocalUserInsertForm::builder()
94       .person_id(inserted_person.id)
95       .password_encrypted("123456".to_string())
96       .build();
97
98     let inserted_local_user = LocalUser::create(pool, &local_user_form).await.unwrap();
99
100     let jwt = Claims::jwt(
101       inserted_local_user.id.0,
102       &secret.jwt_secret,
103       &settings.hostname,
104     )
105     .unwrap();
106     let claims = Claims::decode(&jwt, &secret.jwt_secret).unwrap().claims;
107     let check = check_validator_time(&inserted_local_user.validator_time, &claims);
108     assert!(check.is_ok());
109
110     // The check should fail, since the validator time is now newer than the jwt issue time
111     let updated_local_user =
112       LocalUser::update_password(pool, inserted_local_user.id, "password111")
113         .await
114         .unwrap();
115     let check_after = check_validator_time(&updated_local_user.validator_time, &claims);
116     assert!(check_after.is_err());
117
118     let num_deleted = Person::delete(pool, inserted_person.id).await.unwrap();
119     assert_eq!(1, num_deleted);
120   }
121 }