diff --git a/src/admin/appservice/commands.rs b/src/admin/appservice/commands.rs index 878fbf6f..29b3c0e8 100644 --- a/src/admin/appservice/commands.rs +++ b/src/admin/appservice/commands.rs @@ -1,4 +1,5 @@ use futures::StreamExt; +use ruma::api::appservice::Registration; use tuwunel_core::{Err, Result, checked, err}; use crate::admin_command; @@ -16,18 +17,19 @@ pub(super) async fn appservice_register(&self) -> Result { let range = 1..checked!(body_len - 1)?; let appservice_config_body = body[range].join("\n"); - let parsed_config = serde_yaml::from_str(&appservice_config_body); - let registration = - parsed_config.map_err(|e| err!("Could not parse appservice config as YAML: {e}"))?; + let registration: Registration = serde_yaml::from_str(&appservice_config_body) + .map_err(|e| err!("Could not parse appservice config as YAML: {e}"))?; + + let id = registration.id.clone(); self.services .appservice - .register_appservice(®istration, &appservice_config_body) + .register_appservice(registration) .await .map_err(|e| err!("Failed to register appservice: {e}"))?; - self.write_str(&format!("Appservice registered with ID: {}", registration.id)) + self.write_str(&format!("Appservice registered with ID: {}", &id)) .await } diff --git a/src/service/appservice/mod.rs b/src/service/appservice/mod.rs index 20972fef..73443b8f 100644 --- a/src/service/appservice/mod.rs +++ b/src/service/appservice/mod.rs @@ -80,7 +80,10 @@ impl Service { self.registration_info .write() .await - .insert(id.clone(), reg.try_into()?) + .insert( + id.clone(), + RegistrationInfo::new(reg, self.services.globals.server_name())?, + ) .map_or(Ok(()), |_| Err!("Conflicting Appservice ID: {id:?}")) }) .await @@ -105,42 +108,36 @@ impl Service { Ok(()) } - /// Registers an appservice and returns the ID to the caller - pub async fn register_appservice( - &self, - registration: &Registration, - appservice_config_body: &str, - ) -> Result { - let appservice_user = UserId::parse_with_server_name( - ®istration.sender_localpart, - &self.services.config.server_name, - )?; + pub async fn register_appservice(&self, registration: Registration) -> Result { + let appservice_yaml = serde_yaml::to_string(®istration)?; - if !self.services.users.exists(&appservice_user).await { + let id = registration.id.clone(); + + let registration_info = + RegistrationInfo::new(registration, self.services.globals.server_name())?; + + let appservice_user = ®istration_info.sender; + + if !self.services.users.exists(appservice_user).await { self.services .users - .create(&appservice_user, None, None) + .create(appservice_user, None, None) .await?; } //TODO: Check for collisions between exclusive appservice namespaces + self.db + .id_appserviceregistrations + .insert(&id, appservice_yaml); + self.registration_info .write() .await - .insert(registration.id.clone(), registration.clone().try_into()?); - - self.db - .id_appserviceregistrations - .insert(®istration.id, appservice_config_body); + .insert(id, registration_info); Ok(()) } - /// Remove an appservice registration - /// - /// # Arguments - /// - /// * `service_name` - the registration ID of the appservice pub async fn unregister_appservice(&self, appservice_id: &str) -> Result { // removes the appservice registration info self.registration_info diff --git a/src/service/appservice/registration_info.rs b/src/service/appservice/registration_info.rs index 60c348dc..e78a17b5 100644 --- a/src/service/appservice/registration_info.rs +++ b/src/service/appservice/registration_info.rs @@ -1,4 +1,4 @@ -use ruma::{UserId, api::appservice::Registration}; +use ruma::{OwnedUserId, ServerName, UserId, api::appservice::Registration}; use tuwunel_core::Result; use super::NamespaceRegex; @@ -10,32 +10,35 @@ pub struct RegistrationInfo { pub users: NamespaceRegex, pub aliases: NamespaceRegex, pub rooms: NamespaceRegex, + pub sender: OwnedUserId, } impl RegistrationInfo { + pub fn new(registration: Registration, server_name: &ServerName) -> Result { + let sender = + OwnedUserId::parse(format!("@{}:{}", registration.sender_localpart, server_name))?; + + Ok(Self { + users: registration.namespaces.users.clone().try_into()?, + aliases: registration + .namespaces + .aliases + .clone() + .try_into()?, + rooms: registration.namespaces.rooms.clone().try_into()?, + registration, + sender, + }) + } + #[must_use] pub fn is_user_match(&self, user_id: &UserId) -> bool { - self.users.is_match(user_id.as_str()) - || self.registration.sender_localpart == user_id.localpart() + user_id == self.sender || self.users.is_match(user_id.as_str()) } #[inline] #[must_use] pub fn is_exclusive_user_match(&self, user_id: &UserId) -> bool { - self.users.is_exclusive_match(user_id.as_str()) - || self.registration.sender_localpart == user_id.localpart() - } -} - -impl TryFrom for RegistrationInfo { - type Error = regex::Error; - - fn try_from(value: Registration) -> Result { - Ok(Self { - users: value.namespaces.users.clone().try_into()?, - aliases: value.namespaces.aliases.clone().try_into()?, - rooms: value.namespaces.rooms.clone().try_into()?, - registration: value, - }) + user_id == self.sender || self.users.is_exclusive_match(user_id.as_str()) } }