feat(spaces): add custom state event types and config for space permission cascading
Add four custom Matrix state event content types for space role management: space roles definitions, per-user role assignments, per-room role requirements, and per-space cascading override. Add server config options: space_permission_cascading (default false) as the server-wide toggle, and space_roles_cache_flush_threshold (default 1000) for cache management.
This commit is contained in:
parent
3bfd10efab
commit
95fa3b022a
4 changed files with 112 additions and 0 deletions
|
|
@ -470,6 +470,18 @@
|
|||
#
|
||||
#suspend_on_register = false
|
||||
|
||||
# Server-wide default for space permission cascading (power levels and
|
||||
# role-based access). Individual Spaces can override this via the
|
||||
# `com.continuwuity.space.cascading` state event or the admin command
|
||||
# `!admin space roles enable/disable <space>`.
|
||||
#
|
||||
#space_permission_cascading = false
|
||||
|
||||
# Maximum number of spaces to cache role data for. When exceeded the
|
||||
# cache is cleared and repopulated on demand.
|
||||
#
|
||||
#space_roles_cache_flush_threshold = 1000
|
||||
|
||||
# Enabling this setting opens registration to anyone without restrictions.
|
||||
# This makes your server vulnerable to abuse
|
||||
#
|
||||
|
|
|
|||
|
|
@ -603,6 +603,22 @@ pub struct Config {
|
|||
#[serde(default)]
|
||||
pub suspend_on_register: bool,
|
||||
|
||||
/// Server-wide default for space permission cascading (power levels and
|
||||
/// role-based access). Individual Spaces can override this via the
|
||||
/// `com.continuwuity.space.cascading` state event or the admin command
|
||||
/// `!admin space roles enable/disable <space>`.
|
||||
///
|
||||
/// default: false
|
||||
#[serde(default)]
|
||||
pub space_permission_cascading: bool,
|
||||
|
||||
/// Maximum number of spaces to cache role data for. When exceeded the
|
||||
/// cache is cleared and repopulated on demand.
|
||||
///
|
||||
/// default: 1000
|
||||
#[serde(default = "default_space_roles_cache_flush_threshold")]
|
||||
pub space_roles_cache_flush_threshold: u32,
|
||||
|
||||
/// Enabling this setting opens registration to anyone without restrictions.
|
||||
/// This makes your server vulnerable to abuse
|
||||
#[serde(default)]
|
||||
|
|
@ -2826,3 +2842,5 @@ fn default_ldap_search_filter() -> String { "(objectClass=*)".to_owned() }
|
|||
fn default_ldap_uid_attribute() -> String { String::from("uid") }
|
||||
|
||||
fn default_ldap_name_attribute() -> String { String::from("givenName") }
|
||||
|
||||
fn default_space_roles_cache_flush_threshold() -> u32 { 1000 }
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
pub mod event;
|
||||
pub mod pdu;
|
||||
pub mod space_roles;
|
||||
pub mod state_key;
|
||||
pub mod state_res;
|
||||
|
||||
|
|
|
|||
81
src/core/matrix/space_roles.rs
Normal file
81
src/core/matrix/space_roles.rs
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
use std::collections::BTreeMap;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub const SPACE_ROLES_EVENT_TYPE: &str = "com.continuwuity.space.roles";
|
||||
pub const SPACE_ROLE_MEMBER_EVENT_TYPE: &str = "com.continuwuity.space.role.member";
|
||||
pub const SPACE_ROLE_ROOM_EVENT_TYPE: &str = "com.continuwuity.space.role.room";
|
||||
pub const SPACE_CASCADING_EVENT_TYPE: &str = "com.continuwuity.space.cascading";
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
|
||||
pub struct SpaceRolesEventContent {
|
||||
pub roles: BTreeMap<String, RoleDefinition>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
|
||||
pub struct RoleDefinition {
|
||||
pub description: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub power_level: Option<i64>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
|
||||
pub struct SpaceRoleMemberEventContent {
|
||||
pub roles: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
|
||||
pub struct SpaceRoleRoomEventContent {
|
||||
pub required_roles: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
|
||||
pub struct SpaceCascadingEventContent {
|
||||
pub enabled: bool,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn space_roles_roundtrip() {
|
||||
let mut roles = BTreeMap::new();
|
||||
roles.insert("admin".to_owned(), RoleDefinition {
|
||||
description: "Space administrator".to_owned(),
|
||||
power_level: Some(100),
|
||||
});
|
||||
roles.insert("nsfw".to_owned(), RoleDefinition {
|
||||
description: "NSFW access".to_owned(),
|
||||
power_level: None,
|
||||
});
|
||||
let content = SpaceRolesEventContent { roles };
|
||||
let json = serde_json::to_string(&content).unwrap();
|
||||
let deserialized: SpaceRolesEventContent = serde_json::from_str(&json).unwrap();
|
||||
assert_eq!(deserialized.roles["admin"].power_level, Some(100));
|
||||
assert!(deserialized.roles["nsfw"].power_level.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn power_level_omitted_in_serialization_when_none() {
|
||||
let role = RoleDefinition {
|
||||
description: "Test".to_owned(),
|
||||
power_level: None,
|
||||
};
|
||||
let json = serde_json::to_string(&role).unwrap();
|
||||
assert!(!json.contains("power_level"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn negative_power_level() {
|
||||
let json = r#"{"description":"Restricted","power_level":-10}"#;
|
||||
let role: RoleDefinition = serde_json::from_str(json).unwrap();
|
||||
assert_eq!(role.power_level, Some(-10));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn missing_description_fails() {
|
||||
let json = r#"{"power_level":100}"#;
|
||||
serde_json::from_str::<RoleDefinition>(json).unwrap_err();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue