fix: deactivate accounts that should be deactivated
This commit is contained in:
		
							parent
							
								
									bff68e595b
								
							
						
					
					
						commit
						88cf043f94
					
				
					 5 changed files with 91 additions and 44 deletions
				
			
		|  | @ -179,12 +179,11 @@ pub async fn register_route( | |||
|     let password = if is_guest { | ||||
|         None | ||||
|     } else { | ||||
|         body.password.clone() | ||||
|     } | ||||
|     .unwrap_or_default(); | ||||
|         body.password.as_deref() | ||||
|     }; | ||||
| 
 | ||||
|     // Create user
 | ||||
|     db.users.create(&user_id, &password)?; | ||||
|     db.users.create(&user_id, password)?; | ||||
| 
 | ||||
|     // Initial data
 | ||||
|     db.account_data.update( | ||||
|  | @ -233,7 +232,7 @@ pub async fn register_route( | |||
|         let conduit_user = UserId::parse_with_server_name("conduit", db.globals.server_name()) | ||||
|             .expect("@conduit:server_name is valid"); | ||||
| 
 | ||||
|         db.users.create(&conduit_user, "")?; | ||||
|         db.users.create(&conduit_user, None)?; | ||||
| 
 | ||||
|         let room_id = RoomId::new(db.globals.server_name()); | ||||
| 
 | ||||
|  | @ -547,7 +546,8 @@ pub async fn change_password_route( | |||
|         return Err(Error::Uiaa(uiaainfo)); | ||||
|     } | ||||
| 
 | ||||
|     db.users.set_password(&sender_user, &body.new_password)?; | ||||
|     db.users | ||||
|         .set_password(&sender_user, Some(&body.new_password))?; | ||||
| 
 | ||||
|     if body.logout_devices { | ||||
|         // Logout all devices except the current one
 | ||||
|  |  | |||
|  | @ -38,7 +38,11 @@ pub async fn create_content_route( | |||
|     ); | ||||
|     db.media.create( | ||||
|         mxc.clone(), | ||||
|         &body.filename.as_deref(), | ||||
|         &body | ||||
|             .filename | ||||
|             .as_ref() | ||||
|             .map(|filename| "inline; filename=".to_owned() + filename) | ||||
|             .as_deref(), | ||||
|         &body.content_type.as_deref(), | ||||
|         &body.file, | ||||
|     )?; | ||||
|  | @ -64,7 +68,7 @@ pub async fn get_content_route( | |||
|     let mxc = format!("mxc://{}/{}", body.server_name, body.media_id); | ||||
| 
 | ||||
|     if let Some(FileMeta { | ||||
|         filename, | ||||
|         content_disposition, | ||||
|         content_type, | ||||
|         file, | ||||
|     }) = db.media.get(&mxc)? | ||||
|  | @ -72,7 +76,7 @@ pub async fn get_content_route( | |||
|         Ok(get_content::Response { | ||||
|             file, | ||||
|             content_type, | ||||
|             content_disposition: filename, | ||||
|             content_disposition, | ||||
|         } | ||||
|         .into()) | ||||
|     } else if &*body.server_name != db.globals.server_name() && body.allow_remote { | ||||
|  |  | |||
|  | @ -11,7 +11,7 @@ pub mod transaction_ids; | |||
| pub mod uiaa; | ||||
| pub mod users; | ||||
| 
 | ||||
| use crate::{Error, Result}; | ||||
| use crate::{utils, Error, Result}; | ||||
| use directories::ProjectDirs; | ||||
| use futures::StreamExt; | ||||
| use log::{error, info}; | ||||
|  | @ -246,6 +246,25 @@ impl Database { | |||
|             info!("Migration: 0 -> 1 finished"); | ||||
|         } | ||||
| 
 | ||||
|         if db.globals.database_version()? < 2 { | ||||
|             // We accidentally inserted hashed versions of "" into the db instead of just ""
 | ||||
|             for userid_password in db.users.userid_password.iter() { | ||||
|                 let (userid, password) = userid_password?; | ||||
| 
 | ||||
|                 let password = utils::string_from_bytes(&password); | ||||
| 
 | ||||
|                 if password.map_or(false, |password| { | ||||
|                     argon2::verify_encoded(&password, b"").unwrap_or(false) | ||||
|                 }) { | ||||
|                     db.users.userid_password.insert(userid, b"")?; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             db.globals.bump_database_version(2)?; | ||||
| 
 | ||||
|             info!("Migration: 1 -> 2 finished"); | ||||
|         } | ||||
| 
 | ||||
|         // This data is probably outdated
 | ||||
|         db.rooms.edus.presenceid_presence.clear()?; | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,14 +4,14 @@ use crate::{utils, Error, Result}; | |||
| use std::mem; | ||||
| 
 | ||||
| pub struct FileMeta { | ||||
|     pub filename: Option<String>, | ||||
|     pub content_disposition: Option<String>, | ||||
|     pub content_type: Option<String>, | ||||
|     pub file: Vec<u8>, | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone)] | ||||
| pub struct Media { | ||||
|     pub(super) mediaid_file: sled::Tree, // MediaId = MXC + WidthHeight + Filename + ContentType
 | ||||
|     pub(super) mediaid_file: sled::Tree, // MediaId = MXC + WidthHeight + ContentDisposition + ContentType
 | ||||
| } | ||||
| 
 | ||||
| impl Media { | ||||
|  | @ -19,7 +19,7 @@ impl Media { | |||
|     pub fn create( | ||||
|         &self, | ||||
|         mxc: String, | ||||
|         filename: &Option<&str>, | ||||
|         content_disposition: &Option<&str>, | ||||
|         content_type: &Option<&str>, | ||||
|         file: &[u8], | ||||
|     ) -> Result<()> { | ||||
|  | @ -28,7 +28,12 @@ impl Media { | |||
|         key.extend_from_slice(&0_u32.to_be_bytes()); // Width = 0 if it's not a thumbnail
 | ||||
|         key.extend_from_slice(&0_u32.to_be_bytes()); // Height = 0 if it's not a thumbnail
 | ||||
|         key.push(0xff); | ||||
|         key.extend_from_slice(filename.as_ref().map(|f| f.as_bytes()).unwrap_or_default()); | ||||
|         key.extend_from_slice( | ||||
|             content_disposition | ||||
|                 .as_ref() | ||||
|                 .map(|f| f.as_bytes()) | ||||
|                 .unwrap_or_default(), | ||||
|         ); | ||||
|         key.push(0xff); | ||||
|         key.extend_from_slice( | ||||
|             content_type | ||||
|  | @ -46,7 +51,7 @@ impl Media { | |||
|     pub fn upload_thumbnail( | ||||
|         &self, | ||||
|         mxc: String, | ||||
|         filename: &Option<String>, | ||||
|         content_disposition: &Option<String>, | ||||
|         content_type: &Option<String>, | ||||
|         width: u32, | ||||
|         height: u32, | ||||
|  | @ -57,7 +62,12 @@ impl Media { | |||
|         key.extend_from_slice(&width.to_be_bytes()); | ||||
|         key.extend_from_slice(&height.to_be_bytes()); | ||||
|         key.push(0xff); | ||||
|         key.extend_from_slice(filename.as_ref().map(|f| f.as_bytes()).unwrap_or_default()); | ||||
|         key.extend_from_slice( | ||||
|             content_disposition | ||||
|                 .as_ref() | ||||
|                 .map(|f| f.as_bytes()) | ||||
|                 .unwrap_or_default(), | ||||
|         ); | ||||
|         key.push(0xff); | ||||
|         key.extend_from_slice( | ||||
|             content_type | ||||
|  | @ -92,20 +102,24 @@ impl Media { | |||
|                 }) | ||||
|                 .transpose()?; | ||||
| 
 | ||||
|             let filename_bytes = parts | ||||
|             let content_disposition_bytes = parts | ||||
|                 .next() | ||||
|                 .ok_or_else(|| Error::bad_database("Media ID in db is invalid."))?; | ||||
| 
 | ||||
|             let filename = if filename_bytes.is_empty() { | ||||
|             let content_disposition = if content_disposition_bytes.is_empty() { | ||||
|                 None | ||||
|             } else { | ||||
|                 Some(utils::string_from_bytes(filename_bytes).map_err(|_| { | ||||
|                     Error::bad_database("Filename in mediaid_file is invalid unicode.") | ||||
|                 })?) | ||||
|                 Some( | ||||
|                     utils::string_from_bytes(content_disposition_bytes).map_err(|_| { | ||||
|                         Error::bad_database( | ||||
|                             "Content Disposition in mediaid_file is invalid unicode.", | ||||
|                         ) | ||||
|                     })?, | ||||
|                 ) | ||||
|             }; | ||||
| 
 | ||||
|             Ok(Some(FileMeta { | ||||
|                 filename, | ||||
|                 content_disposition, | ||||
|                 content_type, | ||||
|                 file: file.to_vec(), | ||||
|             })) | ||||
|  | @ -169,21 +183,22 @@ impl Media { | |||
|                 }) | ||||
|                 .transpose()?; | ||||
| 
 | ||||
|             let filename_bytes = parts | ||||
|             let content_disposition_bytes = parts | ||||
|                 .next() | ||||
|                 .ok_or_else(|| Error::bad_database("Media ID in db is invalid."))?; | ||||
| 
 | ||||
|             let filename = if filename_bytes.is_empty() { | ||||
|             let content_disposition = if content_disposition_bytes.is_empty() { | ||||
|                 None | ||||
|             } else { | ||||
|                 Some( | ||||
|                     utils::string_from_bytes(filename_bytes) | ||||
|                         .map_err(|_| Error::bad_database("Filename in db is invalid."))?, | ||||
|                     utils::string_from_bytes(content_disposition_bytes).map_err(|_| { | ||||
|                         Error::bad_database("Content Disposition in db is invalid.") | ||||
|                     })?, | ||||
|                 ) | ||||
|             }; | ||||
| 
 | ||||
|             Ok(Some(FileMeta { | ||||
|                 filename, | ||||
|                 content_disposition, | ||||
|                 content_type, | ||||
|                 file: file.to_vec(), | ||||
|             })) | ||||
|  | @ -202,16 +217,20 @@ impl Media { | |||
|                 }) | ||||
|                 .transpose()?; | ||||
| 
 | ||||
|             let filename_bytes = parts | ||||
|             let content_disposition_bytes = parts | ||||
|                 .next() | ||||
|                 .ok_or_else(|| Error::bad_database("Media ID in db is invalid."))?; | ||||
| 
 | ||||
|             let filename = if filename_bytes.is_empty() { | ||||
|             let content_disposition = if content_disposition_bytes.is_empty() { | ||||
|                 None | ||||
|             } else { | ||||
|                 Some(utils::string_from_bytes(filename_bytes).map_err(|_| { | ||||
|                     Error::bad_database("Filename in mediaid_file is invalid unicode.") | ||||
|                 })?) | ||||
|                 Some( | ||||
|                     utils::string_from_bytes(content_disposition_bytes).map_err(|_| { | ||||
|                         Error::bad_database( | ||||
|                             "Content Disposition in mediaid_file is invalid unicode.", | ||||
|                         ) | ||||
|                     })?, | ||||
|                 ) | ||||
|             }; | ||||
| 
 | ||||
|             if let Ok(image) = image::load_from_memory(&file) { | ||||
|  | @ -219,7 +238,7 @@ impl Media { | |||
|                 let original_height = image.height(); | ||||
|                 if width > original_width || height > original_height { | ||||
|                     return Ok(Some(FileMeta { | ||||
|                         filename, | ||||
|                         content_disposition, | ||||
|                         content_type, | ||||
|                         file: file.to_vec(), | ||||
|                     })); | ||||
|  | @ -286,14 +305,14 @@ impl Media { | |||
|                 self.mediaid_file.insert(thumbnail_key, &*thumbnail_bytes)?; | ||||
| 
 | ||||
|                 Ok(Some(FileMeta { | ||||
|                     filename, | ||||
|                     content_disposition, | ||||
|                     content_type, | ||||
|                     file: thumbnail_bytes.to_vec(), | ||||
|                 })) | ||||
|             } else { | ||||
|                 // Couldn't parse file to generate thumbnail, send original
 | ||||
|                 Ok(Some(FileMeta { | ||||
|                     filename, | ||||
|                     content_disposition, | ||||
|                     content_type, | ||||
|                     file: file.to_vec(), | ||||
|                 })) | ||||
|  |  | |||
|  | @ -49,7 +49,7 @@ impl Users { | |||
|     } | ||||
| 
 | ||||
|     /// Create a new user account on this homeserver.
 | ||||
|     pub fn create(&self, user_id: &UserId, password: &str) -> Result<()> { | ||||
|     pub fn create(&self, user_id: &UserId, password: Option<&str>) -> Result<()> { | ||||
|         self.set_password(user_id, password)?; | ||||
|         Ok(()) | ||||
|     } | ||||
|  | @ -110,15 +110,20 @@ impl Users { | |||
|     } | ||||
| 
 | ||||
|     /// Hash and set the user's password to the Argon2 hash
 | ||||
|     pub fn set_password(&self, user_id: &UserId, password: &str) -> Result<()> { | ||||
|         if let Ok(hash) = utils::calculate_hash(&password) { | ||||
|             self.userid_password.insert(user_id.to_string(), &*hash)?; | ||||
|             Ok(()) | ||||
|     pub fn set_password(&self, user_id: &UserId, password: Option<&str>) -> Result<()> { | ||||
|         if let Some(password) = password { | ||||
|             if let Ok(hash) = utils::calculate_hash(&password) { | ||||
|                 self.userid_password.insert(user_id.to_string(), &*hash)?; | ||||
|                 Ok(()) | ||||
|             } else { | ||||
|                 Err(Error::BadRequest( | ||||
|                     ErrorKind::InvalidParam, | ||||
|                     "Password does not meet the requirements.", | ||||
|                 )) | ||||
|             } | ||||
|         } else { | ||||
|             Err(Error::BadRequest( | ||||
|                 ErrorKind::InvalidParam, | ||||
|                 "Password does not meet the requirements.", | ||||
|             )) | ||||
|             self.userid_password.insert(user_id.to_string(), "")?; | ||||
|             Ok(()) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue