diff --git a/Cargo.lock b/Cargo.lock index c9dabd2..56830c0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1144,15 +1144,15 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.21" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10e2fcbb64ecbe64c8e040a386c3104d384583af58b956d870aaaf229df6e66d" +checksum = "12295df4f294471248581bc09bef3c38a5e46f1e36d6a37353621a0c6c357e1f" [[package]] name = "ppv-lite86" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ca011bd0129ff4ae15cd04c4eef202cadf6c51c21e47aba319b4e0501db741" +checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" [[package]] name = "proc-macro-error" diff --git a/src/graphql.rs b/src/graphql.rs index 333c27d..1282d5e 100644 --- a/src/graphql.rs +++ b/src/graphql.rs @@ -114,6 +114,24 @@ fn id_to_uuid(id: &ID) -> Result { Uuid::from_str(&id) } +fn is_valid_user_name(username: &str) -> bool { + if !username.starts_with('@') { + return false; + } + + for c in username[1..].chars() { + if !( + c.is_ascii_alphabetic() && c.is_ascii_lowercase() || + c.is_ascii_digit() || + "_-.".contains(c) + ) { + return false; + } + } + + true +} + #[derive(Clone, Debug)] pub struct Context { #[cfg(feature = "sqlite")] @@ -338,8 +356,12 @@ pub struct Query; #[graphql_object(context = Context)] impl Query { async fn getUserID(context: &Context, username: String) -> FieldResult { + if !is_valid_user_name(&username) { + return Err(format!("{:?} is not a valid username", username).into()); + } + sqlx::query(format!( - r#"SELECT id FROM users WHERE user_name="{}""#, + "SELECT id FROM users WHERE user_name={:?}", username ).as_str()).fetch_one(&context.db).await? .try_get::("id") @@ -411,20 +433,24 @@ pub struct Mutation; impl Mutation { async fn createUser(context: &Context, new_user: NewUser) -> FieldResult { let user: User = new_user.clone().into(); + if !is_valid_user_name(&user.user_name) { + return Err(format!("{:?} is not a valid username", user.user_name).into()); + } + let uuid = id_to_uuid(&user.id)?.to_simple(); let user_preferences: UserPreferences = new_user.into(); if sqlx::query( - format!(r#"SELECT id FROM users WHERE user_name="{}""#, user.user_name).as_str() + format!("SELECT id FROM users WHERE user_name={:?}", user.user_name).as_str() ).fetch_all(&context.db).await?.len() > 0 { return Err("username is already in use".into()); } sqlx::query(format!( - r#"INSERT INTO users VALUES ("{}", "{}", {}, {}, {}, {})"#, + r#"INSERT INTO users VALUES ("{}", {:?}, {}, {}, {}, {})"#, uuid, user.user_name, - user.display_name.map(|x| format!(r#""{}""#, x)).unwrap_or("NULL".to_string()), + user.display_name.map(|x| format!("{:?}", x)).unwrap_or("NULL".to_string()), user.activated as u8, user.created.timestamp(), match user.last_online { @@ -435,7 +461,7 @@ impl Mutation { let privacy_preferences = user_preferences.privacy_preferences; sqlx::query(format!( - r#"INSERT INTO privacy_preferences VALUES ("{}", {}, "{}", "{}", {}, "{}", "{}", {}, {}, "{}", "{}")"#, + r#"INSERT INTO privacy_preferences VALUES ("{}", {}, {:?}, {:?}, {}, {:?}, {:?}, {}, {}, {:?}, {:?})"#, uuid, privacy_preferences.discovery as u8, format_array_for_sql(&privacy_preferences.discovery_user_limit), @@ -459,7 +485,7 @@ impl Mutation { let security_preferences = user_preferences.security_preferences; sqlx::query(format!( - r#"INSERT INTO security_preferences VALUES ("{}", "{}", "{}")"#, + r#"INSERT INTO security_preferences VALUES ("{}", {:?}, {:?})"#, uuid, format_array_for_sql(&security_preferences.account_tokens), security_preferences.password_hash, @@ -467,7 +493,7 @@ impl Mutation { let external_servers_preferences = user_preferences.external_servers_preferences; sqlx::query(format!( - r#"INSERT INTO external_servers_preferences VALUES ("{}", {}, "{}")"#, + r#"INSERT INTO external_servers_preferences VALUES ("{}", {}, {:?})"#, uuid, external_servers_preferences.external_servers as u8, format_array_for_sql(&external_servers_preferences.external_servers_limit), @@ -475,7 +501,7 @@ impl Mutation { let external_servers_privacy_preferences = external_servers_preferences.privacy_preferences; sqlx::query(format!( - r#"INSERT INTO external_servers_privacy_preferences VALUES ("{}", {}, "{}", "{}", {}, "{}", "{}", {}, {}, "{}", "{}")"#, + r#"INSERT INTO external_servers_privacy_preferences VALUES ("{}", {}, {:?}, {:?}, {}, {:?}, {:?}, {}, {}, {:?}, {:?})"#, uuid, external_servers_privacy_preferences.discovery as u8, format_array_for_sql(&external_servers_privacy_preferences.discovery_user_limit),