fix: deactivate accounts that should be deactivated

next
Timo Kösters 2021-05-30 21:55:43 +02:00
parent bff68e595b
commit 88cf043f94
No known key found for this signature in database
GPG Key ID: 24DA7517711A2BA4
5 changed files with 91 additions and 44 deletions

View File

@ -179,12 +179,11 @@ pub async fn register_route(
let password = if is_guest { let password = if is_guest {
None None
} else { } else {
body.password.clone() body.password.as_deref()
} };
.unwrap_or_default();
// Create user // Create user
db.users.create(&user_id, &password)?; db.users.create(&user_id, password)?;
// Initial data // Initial data
db.account_data.update( 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()) let conduit_user = UserId::parse_with_server_name("conduit", db.globals.server_name())
.expect("@conduit:server_name is valid"); .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()); let room_id = RoomId::new(db.globals.server_name());
@ -547,7 +546,8 @@ pub async fn change_password_route(
return Err(Error::Uiaa(uiaainfo)); 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 { if body.logout_devices {
// Logout all devices except the current one // Logout all devices except the current one

View File

@ -38,7 +38,11 @@ pub async fn create_content_route(
); );
db.media.create( db.media.create(
mxc.clone(), 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.content_type.as_deref(),
&body.file, &body.file,
)?; )?;
@ -64,7 +68,7 @@ pub async fn get_content_route(
let mxc = format!("mxc://{}/{}", body.server_name, body.media_id); let mxc = format!("mxc://{}/{}", body.server_name, body.media_id);
if let Some(FileMeta { if let Some(FileMeta {
filename, content_disposition,
content_type, content_type,
file, file,
}) = db.media.get(&mxc)? }) = db.media.get(&mxc)?
@ -72,7 +76,7 @@ pub async fn get_content_route(
Ok(get_content::Response { Ok(get_content::Response {
file, file,
content_type, content_type,
content_disposition: filename, content_disposition,
} }
.into()) .into())
} else if &*body.server_name != db.globals.server_name() && body.allow_remote { } else if &*body.server_name != db.globals.server_name() && body.allow_remote {

View File

@ -11,7 +11,7 @@ pub mod transaction_ids;
pub mod uiaa; pub mod uiaa;
pub mod users; pub mod users;
use crate::{Error, Result}; use crate::{utils, Error, Result};
use directories::ProjectDirs; use directories::ProjectDirs;
use futures::StreamExt; use futures::StreamExt;
use log::{error, info}; use log::{error, info};
@ -246,6 +246,25 @@ impl Database {
info!("Migration: 0 -> 1 finished"); 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 // This data is probably outdated
db.rooms.edus.presenceid_presence.clear()?; db.rooms.edus.presenceid_presence.clear()?;

View File

@ -4,14 +4,14 @@ use crate::{utils, Error, Result};
use std::mem; use std::mem;
pub struct FileMeta { pub struct FileMeta {
pub filename: Option<String>, pub content_disposition: Option<String>,
pub content_type: Option<String>, pub content_type: Option<String>,
pub file: Vec<u8>, pub file: Vec<u8>,
} }
#[derive(Clone)] #[derive(Clone)]
pub struct Media { 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 { impl Media {
@ -19,7 +19,7 @@ impl Media {
pub fn create( pub fn create(
&self, &self,
mxc: String, mxc: String,
filename: &Option<&str>, content_disposition: &Option<&str>,
content_type: &Option<&str>, content_type: &Option<&str>,
file: &[u8], file: &[u8],
) -> Result<()> { ) -> 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()); // 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.extend_from_slice(&0_u32.to_be_bytes()); // Height = 0 if it's not a thumbnail
key.push(0xff); 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.push(0xff);
key.extend_from_slice( key.extend_from_slice(
content_type content_type
@ -46,7 +51,7 @@ impl Media {
pub fn upload_thumbnail( pub fn upload_thumbnail(
&self, &self,
mxc: String, mxc: String,
filename: &Option<String>, content_disposition: &Option<String>,
content_type: &Option<String>, content_type: &Option<String>,
width: u32, width: u32,
height: u32, height: u32,
@ -57,7 +62,12 @@ impl Media {
key.extend_from_slice(&width.to_be_bytes()); key.extend_from_slice(&width.to_be_bytes());
key.extend_from_slice(&height.to_be_bytes()); key.extend_from_slice(&height.to_be_bytes());
key.push(0xff); 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.push(0xff);
key.extend_from_slice( key.extend_from_slice(
content_type content_type
@ -92,20 +102,24 @@ impl Media {
}) })
.transpose()?; .transpose()?;
let filename_bytes = parts let content_disposition_bytes = parts
.next() .next()
.ok_or_else(|| Error::bad_database("Media ID in db is invalid."))?; .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 None
} else { } else {
Some(utils::string_from_bytes(filename_bytes).map_err(|_| { Some(
Error::bad_database("Filename in mediaid_file is invalid unicode.") utils::string_from_bytes(content_disposition_bytes).map_err(|_| {
})?) Error::bad_database(
"Content Disposition in mediaid_file is invalid unicode.",
)
})?,
)
}; };
Ok(Some(FileMeta { Ok(Some(FileMeta {
filename, content_disposition,
content_type, content_type,
file: file.to_vec(), file: file.to_vec(),
})) }))
@ -169,21 +183,22 @@ impl Media {
}) })
.transpose()?; .transpose()?;
let filename_bytes = parts let content_disposition_bytes = parts
.next() .next()
.ok_or_else(|| Error::bad_database("Media ID in db is invalid."))?; .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 None
} else { } else {
Some( Some(
utils::string_from_bytes(filename_bytes) utils::string_from_bytes(content_disposition_bytes).map_err(|_| {
.map_err(|_| Error::bad_database("Filename in db is invalid."))?, Error::bad_database("Content Disposition in db is invalid.")
})?,
) )
}; };
Ok(Some(FileMeta { Ok(Some(FileMeta {
filename, content_disposition,
content_type, content_type,
file: file.to_vec(), file: file.to_vec(),
})) }))
@ -202,16 +217,20 @@ impl Media {
}) })
.transpose()?; .transpose()?;
let filename_bytes = parts let content_disposition_bytes = parts
.next() .next()
.ok_or_else(|| Error::bad_database("Media ID in db is invalid."))?; .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 None
} else { } else {
Some(utils::string_from_bytes(filename_bytes).map_err(|_| { Some(
Error::bad_database("Filename in mediaid_file is invalid unicode.") 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) { if let Ok(image) = image::load_from_memory(&file) {
@ -219,7 +238,7 @@ impl Media {
let original_height = image.height(); let original_height = image.height();
if width > original_width || height > original_height { if width > original_width || height > original_height {
return Ok(Some(FileMeta { return Ok(Some(FileMeta {
filename, content_disposition,
content_type, content_type,
file: file.to_vec(), file: file.to_vec(),
})); }));
@ -286,14 +305,14 @@ impl Media {
self.mediaid_file.insert(thumbnail_key, &*thumbnail_bytes)?; self.mediaid_file.insert(thumbnail_key, &*thumbnail_bytes)?;
Ok(Some(FileMeta { Ok(Some(FileMeta {
filename, content_disposition,
content_type, content_type,
file: thumbnail_bytes.to_vec(), file: thumbnail_bytes.to_vec(),
})) }))
} else { } else {
// Couldn't parse file to generate thumbnail, send original // Couldn't parse file to generate thumbnail, send original
Ok(Some(FileMeta { Ok(Some(FileMeta {
filename, content_disposition,
content_type, content_type,
file: file.to_vec(), file: file.to_vec(),
})) }))

View File

@ -49,7 +49,7 @@ impl Users {
} }
/// Create a new user account on this homeserver. /// 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)?; self.set_password(user_id, password)?;
Ok(()) Ok(())
} }
@ -110,7 +110,8 @@ impl Users {
} }
/// Hash and set the user's password to the Argon2 hash /// Hash and set the user's password to the Argon2 hash
pub fn set_password(&self, user_id: &UserId, password: &str) -> Result<()> { 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) { if let Ok(hash) = utils::calculate_hash(&password) {
self.userid_password.insert(user_id.to_string(), &*hash)?; self.userid_password.insert(user_id.to_string(), &*hash)?;
Ok(()) Ok(())
@ -120,6 +121,10 @@ impl Users {
"Password does not meet the requirements.", "Password does not meet the requirements.",
)) ))
} }
} else {
self.userid_password.insert(user_id.to_string(), "")?;
Ok(())
}
} }
/// Returns the displayname of a user on this homeserver. /// Returns the displayname of a user on this homeserver.