diff --git a/server-api/src/auth.rs b/server-api/src/auth.rs index afdf428..ba1f371 100644 --- a/server-api/src/auth.rs +++ b/server-api/src/auth.rs @@ -27,6 +27,17 @@ fn valid_user(secret: &str, row: &Option<(VarChar, VarChar, BigInt, Integer, UBi } } +fn valid_perms(user_opt: &Option<(VarChar, VarChar, BigInt, Integer, UBigInt)>, path: &str) -> bool { + use crate::perms; + if let Some(user) = user_opt { + if let Some(p) = perms::get_perm_mask(path) { + return (p & user.4) == p; + } + return true; // no perms required + } + return false; +} + pub async fn wall_entry(path: &str, pool: &Pool, params: &serde_json::Value) -> Result { // Start by Checking if the api key is in our keystore if routes::is_open(path) { @@ -34,14 +45,20 @@ pub async fn wall_entry(path: &str, pool: &Pool, params: &serde_json::Value) -> } else { match (params.get("id"), params.get("secret")) { + /* + * If we apparantly have user data then check for validity in credentials + */ + (Some(id_v), Some(secret_v)) => { + /* unwrapping because i couldn't care less about poorly formatted request data */ let id = id_v.as_u64().unwrap(); let secret = secret_v.as_str().unwrap(); let conn = pool.get_conn().await?; let db_tup: (Conn, Option<(VarChar, VarChar, BigInt, Integer, UBigInt)>) = conn.first_exec( "SELECT secret, name, joindate, status, permissions FROM members WHERE id = :id", mysql_async::params!{"id" => id}).await?; - if valid_user(secret, &db_tup.1) { + let user_data = &db_tup.1; + if valid_user(secret, user_data) && valid_perms(user_data, path) { Ok(AuthReason::Good) } else { diff --git a/server-api/src/perms.rs b/server-api/src/perms.rs index da29ec6..f34932e 100644 --- a/server-api/src/perms.rs +++ b/server-api/src/perms.rs @@ -8,6 +8,7 @@ pub const CREATE_TMP_INVITES:u64 = 4; pub const CREATE_PERM_INVITES:u64 = 8; // to make perma invites you need both flags + pub const OWNER: u64 = 1 << 63; pub const ADMIN: u64 = 1 << 62; // can make other admins but can't really touch the owner @@ -19,3 +20,21 @@ pub const DELETE_CHANNEL:u64 = 128; pub const OWNER_PERMS: u64 = std::u64::MAX; pub const GENERAL_NEW: u64 = JOIN_VOICE | SEND_MESSAGES | ALLOW_PFP | CHANGE_NICK; pub const ADMIN_PERMS: u64 = !(std::u64::MAX & OWNER); // filter the only perm admins don't get + +pub fn get_perm_mask(path: &str) -> Option { + use crate::routes::{ + INVITE_CREATE, + CHANNELS_LIST, CHANNELS_CREATE, CHANNELS_DELETE, + MESSAGE_SEND, + SERVER_META, + }; + match path { + INVITE_CREATE => Some(CREATE_TMP_INVITES), + CHANNELS_LIST => None, + CHANNELS_CREATE => Some(CREATE_CHANNEL), + CHANNELS_DELETE => Some(DELETE_CHANNEL), + MESSAGE_SEND => Some(SEND_MESSAGES), + SERVER_META => None, + _ => Some(0) + } +}