diff --git a/crates/core/database/src/util/bulk_permissions.rs b/crates/core/database/src/util/bulk_permissions.rs index 976b0d69..4a44bea2 100644 --- a/crates/core/database/src/util/bulk_permissions.rs +++ b/crates/core/database/src/util/bulk_permissions.rs @@ -280,14 +280,30 @@ async fn calculate_members_permissions<'a>( continue; } - // Get the user's server permissions - let mut permission = calculate_server_permissions(&query.server, user, member); + // Get the server default permission, apply channel default override + let mut permission = PermissionValue::from(query.server.default_permissions); if let Some(defaults) = channel_default_permissions { permission.apply(defaults.into()); } - // Get the applicable role overrides + // Apply server role overrides + let mut server_roles = query.server + .roles + .iter() + .filter(|(id, _)| member.roles.contains(id)) + .map(|(_, role)| { + let v: Override = role.permissions.into(); + (role.rank, v) + }) + .collect::>(); + + server_roles.sort_by(|a, b| b.0.cmp(&a.0)); + for (_, role_override) in server_roles { + permission.apply(role_override); + } + + // Get the applicable channel role overrides let mut roles = channel_role_permissions .iter() .filter(|(id, _)| member.roles.contains(id)) @@ -306,6 +322,10 @@ async fn calculate_members_permissions<'a>( permission.apply(role_override) } + if member.in_timeout() { + permission.restrict(*ALLOW_IN_TIMEOUT); + } + resp.insert(user.id.clone(), permission); } diff --git a/crates/core/permissions/src/impl.rs b/crates/core/permissions/src/impl.rs index 064fee3e..f73d0a08 100644 --- a/crates/core/permissions/src/impl.rs +++ b/crates/core/permissions/src/impl.rs @@ -122,13 +122,26 @@ pub async fn calculate_channel_permissions(query: &mut P) -> if query.are_we_server_owner().await { ChannelPermission::GrantAllSafe.into() } else if query.are_we_a_member().await { - let mut permissions = calculate_server_permissions(query).await; + let mut permissions = PermissionValue::from(query.get_default_server_permissions().await); permissions.apply(query.get_default_channel_permissions().await); + for role_override in query.get_our_server_role_overrides().await { + permissions.apply(role_override); + } + for role_override in query.get_our_channel_role_overrides().await { permissions.apply(role_override); } + if !query.do_we_have_publish_overwrites().await { + permissions.revoke(ChannelPermission::Speak as u64); + permissions.revoke(ChannelPermission::Video as u64); + } + + if !query.do_we_have_receive_overwrites().await { + permissions.revoke(ChannelPermission::Listen as u64); + } + if query.are_we_timed_out().await { permissions.restrict(*ALLOW_IN_TIMEOUT); } diff --git a/crates/core/permissions/src/test.rs b/crates/core/permissions/src/test.rs index f9225b0c..a09c7eb8 100644 --- a/crates/core/permissions/src/test.rs +++ b/crates/core/permissions/src/test.rs @@ -407,3 +407,114 @@ async fn validate_timed_out_member() { } } } + +#[tokio::test] +async fn validate_channel_default_below_server_roles() { + /// Scenario where: + /// - Server default allows ViewChannel. + /// - Channel default override denies SendMessage. + /// - Server role override allows SendMessage. + /// - We don't have channel role overrides. + /// Since default permissions should be below role permissions, + /// our server role override (allowing SendMessage) should take precedence + /// over the channel default permission (denying SendMessage). + struct Scenario {} + let mut query = Scenario {}; + + let perms = calculate_channel_permissions(&mut query).await; + let value: u64 = perms.into(); + assert_eq!( + value, + ChannelPermission::ViewChannel as u64 | ChannelPermission::SendMessage as u64 + ); + + #[async_trait] + impl PermissionQuery for Scenario { + async fn are_we_privileged(&mut self) -> bool { + false + } + + async fn are_we_a_bot(&mut self) -> bool { + unreachable!() + } + + async fn are_the_users_same(&mut self) -> bool { + unreachable!() + } + + async fn user_relationship(&mut self) -> RelationshipStatus { + unreachable!() + } + + async fn user_is_bot(&mut self) -> bool { + unreachable!() + } + + async fn have_mutual_connection(&mut self) -> bool { + unreachable!() + } + + async fn are_we_server_owner(&mut self) -> bool { + false + } + + async fn are_we_a_member(&mut self) -> bool { + true + } + + async fn get_default_server_permissions(&mut self) -> u64 { + ChannelPermission::ViewChannel as u64 + } + + async fn get_our_server_role_overrides(&mut self) -> Vec { + vec![Override { + allow: ChannelPermission::SendMessage as u64, + deny: 0, + }] + } + + async fn are_we_timed_out(&mut self) -> bool { + false + } + + async fn do_we_have_publish_overwrites(&mut self) -> bool { + true + } + + async fn do_we_have_receive_overwrites(&mut self) -> bool { + true + } + + async fn get_channel_type(&mut self) -> ChannelType { + ChannelType::ServerChannel + } + + async fn get_default_channel_permissions(&mut self) -> Override { + Override { + allow: 0, + deny: ChannelPermission::SendMessage as u64, + } + } + + async fn get_our_channel_role_overrides(&mut self) -> Vec { + vec![] + } + + async fn do_we_own_the_channel(&mut self) -> bool { + unreachable!() + } + + async fn are_we_part_of_the_channel(&mut self) -> bool { + unreachable!() + } + + async fn set_recipient_as_user(&mut self) { + unreachable!() + } + + async fn set_server_from_channel(&mut self) { + // no-op + } + } +} +