From 85814d9c295e995299d15a3e588f9a4ac27aceb7 Mon Sep 17 00:00:00 2001 From: Val Lorentz Date: Sat, 29 Mar 2025 21:17:09 +0100 Subject: [PATCH] Automatically attach preclients to an existing session of the account, if any --- sable_ircd/src/client.rs | 5 ++- sable_ircd/src/server/update_handler.rs | 35 +++++++++++++++++++ .../src/policy/standard_user_policy.rs | 4 +++ sable_network/src/policy/user_policy.rs | 6 ++++ 4 files changed, 49 insertions(+), 1 deletion(-) diff --git a/sable_ircd/src/client.rs b/sable_ircd/src/client.rs index ffee7450..5ad18f0d 100644 --- a/sable_ircd/src/client.rs +++ b/sable_ircd/src/client.rs @@ -253,14 +253,17 @@ impl PreClient { pub fn can_register(&self) -> bool { let can_register_new = self.can_register_new_user(); let can_attach = self.can_attach_to_user().is_some(); + let is_negotiating_caps = + self.progress_flags.load(Ordering::Relaxed) & ProgressFlag::CapNegotiation as u32 != 0; tracing::trace!( ?self, can_register_new, can_attach, + is_negotiating_caps, "PreClient::can_register" ); - can_register_new || can_attach + (can_register_new || can_attach) && !is_negotiating_caps } /// Determine whether this connection is ready to register as a new user diff --git a/sable_ircd/src/server/update_handler.rs b/sable_ircd/src/server/update_handler.rs index a0ac7c79..37c9543d 100644 --- a/sable_ircd/src/server/update_handler.rs +++ b/sable_ircd/src/server/update_handler.rs @@ -4,6 +4,7 @@ use sable_network::prelude::state::{HistoricMessageSourceId, HistoricMessageTarg use super::*; use crate::errors::HandleResult; use crate::monitor::MonitoredItem; +use sable_network::network::update::UserAwayChange; impl ClientServer { pub(super) fn handle_history_update(&self, update: NetworkHistoryUpdate) -> HandleResult { @@ -169,6 +170,40 @@ impl ClientServer { connection.send(message::Notice::new(&self.node.name().to_string(), &user, "The network is currently running in debug mode. Do not send any sensitive information such as passwords.")); + + if let Some(&away_reason) = user.away_reason() { + let fake_log_entry = NetworkHistoryUpdate { + timestamp: 0, // XXX + event: EventId::new(Snowflake::from_parts(self.node().id(), 0, 0)), // XXX + change: NetworkStateChange::UserAwayChange(UserAwayChange { + user: user.historic_id(), + old_reason: None, + new_reason: Some(away_reason), + }), + users_to_notify: vec![], + }; + + // Set away status if user has away-notify capability + // FIXME: suffers from https://github.com/Libera-Chat/sable/issues/155 + self.send_now(&fake_log_entry, &connection, &fake_log_entry)?; + } + + for membership in user.channels() { + let fake_join = update::ChannelJoin { + membership: membership.id(), + user: user.historic_id(), + }; + + let fake_log_entry = NetworkHistoryUpdate { + timestamp: 0, // XXX + event: EventId::new(Snowflake::from_parts(self.node().id(), 0, 0)), // XXX + change: NetworkStateChange::ChannelJoin(fake_join), + users_to_notify: vec![], + }; + + // Send join + topic + names + self.send_now(&fake_log_entry, &connection, &fake_log_entry)?; + } } Ok(()) } diff --git a/sable_network/src/policy/standard_user_policy.rs b/sable_network/src/policy/standard_user_policy.rs index 09f033b0..34785b28 100644 --- a/sable_network/src/policy/standard_user_policy.rs +++ b/sable_network/src/policy/standard_user_policy.rs @@ -52,4 +52,8 @@ impl UserPolicyService for StandardUserPolicy { Err(PermissionError::User(Invisible)) } + + fn auto_attach_session(&self, _user: &wrapper::User) -> bool { + true + } } diff --git a/sable_network/src/policy/user_policy.rs b/sable_network/src/policy/user_policy.rs index bd76243f..eaa17bdc 100644 --- a/sable_network/src/policy/user_policy.rs +++ b/sable_network/src/policy/user_policy.rs @@ -5,9 +5,15 @@ use super::*; pub trait UserPolicyService { /// Determine whether a given user can set a given user mode on themselves fn can_set_umode(&self, user: &wrapper::User, mode: UserModeFlag) -> PermissionResult; + /// Determine whether a given user can unset a given user mode on themselves fn can_unset_umode(&self, user: &wrapper::User, mode: UserModeFlag) -> PermissionResult; + /// Determine whether one user can discover another without knowing their nick /// (eg. with `WHO *`) fn can_list_user(&self, touser: &User, user: &User) -> PermissionResult; + + /// Determine whether a new connection of the given `user` will join an existing + /// session if there is any + fn auto_attach_session(&self, user: &wrapper::User) -> bool; }