community_user_ban_view::CommunityUserBanView,
community_view::CommunityView,
};
- use lemmy_structs::{blocking, comment::*, community::*, post::*, site::*, user::*, websocket::*};
- use lemmy_utils::{claims::Claims, settings::Settings, ApiError, ConnectionId, LemmyError};
+ use lemmy_utils::{
+ claims::Claims,
+ settings::structs::Settings,
+ ApiError,
+ ConnectionId,
+ LemmyError,
+ };
use lemmy_websocket::{serialize_websocket_message, LemmyContext, UserOperation};
use serde::Deserialize;
-use std::process::Command;
+use std::{env, process::Command};
use url::Url;
pub mod comment;
Ok(base64)
}
+ /// Checks the password length
+ pub(crate) fn password_length_check(pass: &str) -> Result<(), LemmyError> {
+ if pass.len() > 60 {
+ Err(ApiError::err("invalid_password").into())
+ } else {
+ Ok(())
+ }
+ }
+
#[cfg(test)]
mod tests {
- use crate::captcha_espeak_wav_base64;
+ use crate::{captcha_espeak_wav_base64, get_user_from_jwt};
+ use lemmy_db_queries::{
+ establish_pooled_connection,
+ source::user::User,
+ Crud,
+ ListingType,
+ SortType,
+ };
+ use lemmy_db_schema::source::user::{UserForm, User_};
+ use lemmy_utils::claims::Claims;
+ use std::{
+ env::{current_dir, set_current_dir},
+ path::PathBuf,
+ };
+
+ #[actix_rt::test]
+ async fn test_should_not_validate_user_token_after_password_change() {
+ struct CwdGuard(PathBuf);
+ impl Drop for CwdGuard {
+ fn drop(&mut self) {
+ let _ = set_current_dir(&self.0);
+ }
+ }
+
+ let _dir_bkp = CwdGuard(current_dir().unwrap());
+
+ // so configs could be read
+ let _ = set_current_dir("../..");
+
+ let conn = establish_pooled_connection();
+
+ let new_user = UserForm {
+ name: "user_df342sgf".into(),
+ preferred_username: None,
+ password_encrypted: "nope".into(),
+ email: None,
+ matrix_user_id: None,
+ avatar: None,
+ banner: None,
+ admin: false,
+ banned: Some(false),
+ published: None,
+ updated: None,
+ show_nsfw: false,
+ theme: "browser".into(),
+ default_sort_type: SortType::Hot as i16,
+ default_listing_type: ListingType::Subscribed as i16,
+ lang: "browser".into(),
+ show_avatars: true,
+ send_notifications_to_email: false,
+ actor_id: None,
+ bio: None,
+ local: true,
+ private_key: None,
+ public_key: None,
+ last_refreshed_at: None,
+ inbox_url: None,
+ shared_inbox_url: None,
+ };
+
+ let inserted_user: User_ = User_::create(&conn.get().unwrap(), &new_user).unwrap();
+
+ let jwt_token = Claims::jwt(inserted_user.id, String::from("my-host.com")).unwrap();
+
+ get_user_from_jwt(&jwt_token, &conn)
+ .await
+ .expect("User should be decoded");
+
+ std::thread::sleep(std::time::Duration::from_secs(1));
+
+ User_::update_password(&conn.get().unwrap(), inserted_user.id, &"password111").unwrap();
+
+ let jwt_decode_res = get_user_from_jwt(&jwt_token, &conn).await;
+
+ jwt_decode_res.expect_err("JWT decode should fail after password change");
+ }
#[test]
fn test_espeak() {
conn
}
+pub fn establish_pooled_connection(
+) -> diesel::r2d2::Pool<diesel::r2d2::ConnectionManager<diesel::PgConnection>> {
+ use diesel::r2d2::{ConnectionManager, Pool};
+
+ // Set up the r2d2 connection pool
+ let db_url = match get_database_url_from_env() {
+ Ok(url) => url,
+ Err(e) => panic!(
+ "Failed to read database URL from env var LEMMY_DATABASE_URL: {}",
+ e
+ ),
+ };
+
+ let manager = ConnectionManager::<PgConnection>::new(&db_url);
+ let pool = Pool::builder()
+ .max_size(1)
+ .build(manager)
+ .unwrap_or_else(|_| panic!("Error connecting to {}", db_url));
+
+ let conn = pool.get().unwrap();
+
+ // Run the migrations from code
+ embedded_migrations::run(&conn).unwrap();
+
+ pool
+}
+
lazy_static! {
static ref EMAIL_REGEX: Regex =
- Regex::new(r"^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$").unwrap();
+ Regex::new(r"^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$")
+ .expect("compile email regex");
}
pub mod functions {
pub private_key: Option<String>,
pub public_key: Option<String>,
pub last_refreshed_at: chrono::NaiveDateTime,
- pub banner: Option<String>,
+ pub banner: Option<DbUrl>,
pub deleted: bool,
- pub inbox_url: Url,
- pub shared_inbox_url: Option<Url>,
+ pub inbox_url: DbUrl,
+ pub shared_inbox_url: Option<DbUrl>,
+ pub validator_time: chrono::NaiveDateTime,
}
/// A safe representation of user, without the sensitive info
pub bio: Option<String>,
pub local: bool,
pub last_refreshed_at: chrono::NaiveDateTime,
- pub banner: Option<String>,
+ pub banner: Option<DbUrl>,
pub deleted: bool,
+ pub validator_time: chrono::NaiveDateTime,
}
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]