telegram bot user isolation, config store, user context channels

This commit is contained in:
2026-07-11 01:02:37 +01:00
parent 587958ffe0
commit 5848829a92
18 changed files with 1179 additions and 426 deletions
+13
View File
@@ -16,6 +16,7 @@ use tokio_util::sync::CancellationToken;
use core_api::remote::RemoteAccess;
use core_api::system_bus::SystemEventBus;
use core_api::user_channel::UserChannelApi;
use crate::approval::ApprovalManager;
use crate::chat_event_bus::ChatEventBus;
@@ -112,3 +113,15 @@ impl Skald {
pub fn location_manager(&self) -> &Arc<LocationManager> { &self.infra.location_manager }
pub fn remote(&self) -> &Arc<RwLock<Option<Arc<dyn RemoteAccess>>>> { &self.infra.remote }
}
// ── UserChannelApi ────────────────────────────────────────────────────────────
use super::user_context::UserContextHandle;
#[async_trait::async_trait]
impl UserChannelApi for Skald {
async fn resolve_user(&self, user_id: &str) -> Option<std::sync::Arc<dyn core_api::user_channel::UserChannelHandle>> {
let ctx = self.user_context(user_id).await?;
Some(std::sync::Arc::new(UserContextHandle::new(ctx)))
}
}
+4 -4
View File
@@ -45,14 +45,14 @@ pub(super) struct Runtime {
impl Runtime {
/// Wires the cross-cutting primitives. Infallible.
pub(super) fn bootstrap(pool: Arc<SqlitePool>) -> Self {
let config = Arc::new(GlobalConfigManager::new(Arc::clone(&pool)));
let system_bus = Arc::new(SystemEventBus::new());
info!("system event bus ready");
let config = Arc::new(GlobalConfigManager::new(Arc::clone(&pool), Arc::clone(&system_bus)));
let users = Arc::new(UserManager::new(Arc::clone(&pool)));
let sessions = Arc::new(SessionStore::new(Arc::clone(&users)));
let system_bus = Arc::new(SystemEventBus::new());
info!("system event bus ready");
let event_bus = Arc::new(ChatEventBus::new());
info!("chat event bus ready");
@@ -29,8 +29,11 @@ use sqlx::SqlitePool;
use tokio::sync::{broadcast, Mutex};
use tokio_util::sync::CancellationToken;
use core_api::approval::ApprovalApi;
use core_api::chat_hub::ChatHubApi;
use core_api::events::GlobalEvent;
use core_api::system_bus::SystemEventBus;
use core_api::user_channel::UserChannelHandle;
use crate::approval::ApprovalManager;
use crate::chat_event_bus::ChatEventBus;
@@ -257,3 +260,38 @@ impl UserContextRegistry {
Ok(ctx)
}
}
// ── UserChannelHandle impl ────────────────────────────────────────────────────
/// Concrete [`UserChannelHandle`] wrapping a live [`UserContext`].
///
/// Constructed by [`Skald`](super::Skald) when resolving a user for a channel
/// plugin. The concrete type stays private — callers receive
/// `Arc<dyn UserChannelHandle>`.
pub(super) struct UserContextHandle {
ctx: Arc<UserContext>,
}
impl UserContextHandle {
pub(super) fn new(ctx: Arc<UserContext>) -> Self {
Self { ctx }
}
}
impl UserChannelHandle for UserContextHandle {
fn user_id(&self) -> &str {
&self.ctx.user_id
}
fn chat_hub(&self) -> Arc<dyn ChatHubApi> {
Arc::clone(&self.ctx.chat_hub) as Arc<dyn ChatHubApi>
}
fn approval(&self) -> Arc<dyn ApprovalApi> {
Arc::clone(&self.ctx.approval) as Arc<dyn ApprovalApi>
}
fn subscribe(&self) -> broadcast::Receiver<GlobalEvent> {
self.ctx.global_tx.subscribe()
}
}