Files
eifeldc/bot-sdk/src/room.rs
root cacd2b04a7
Some checks failed
CI / Rust Format (push) Has been cancelled
CI / Clippy (push) Has been cancelled
CI / Test Server (push) Has been cancelled
CI / Frontend Check (push) Has been cancelled
CI / Tauri Client Check (push) Has been cancelled
CI / Docker Build (push) Has been cancelled
CI / Build Tauri (Linux) (push) Has been cancelled
feat: comprehensive project improvements
- Fix 14 Clippy warnings across server and bot-sdk
- Add 67 unit tests (32 bot-sdk, 34 server, 1 doctest)
- Add Prometheus metrics endpoint (/api/metrics)
- Add structured JSON logging (EIFELDC_LOG_FORMAT=json)
- Add release workflow (Docker push + GitHub Release + Tauri builds)
- Add rate limiting middleware (EIFELDC_RATE_LIMIT)
- Add CORS restriction (EIFELDC_CORS_ORIGINS)
- Add session token expiry (EIFELDC_SESSION_TTL)
- Add input validation (username/password/homeserver length limits)
- Add upload size limit (EIFELDC_MAX_UPLOAD_MB)
- Upgrade Tauri client from v1 to v2
- Add session store with SQLite persistence
- Add proper error types and cleanup across all crates
- Format all code with cargo fmt
- Update CI pipeline with fmt, clippy, test, frontend, and Tauri checks
- Add README with full API reference and setup guide
2026-04-29 13:08:01 +02:00

162 lines
4.0 KiB
Rust

use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::Mutex;
#[derive(Clone, Debug)]
pub struct RoomInfo {
pub room_id: String,
pub name: String,
pub is_encrypted: bool,
}
impl RoomInfo {
pub fn new(room_id: String, name: String, is_encrypted: bool) -> Self {
Self {
room_id,
name,
is_encrypted,
}
}
}
#[derive(Default)]
pub struct RoomManager {
pub rooms: HashMap<String, RoomInfo>,
}
impl RoomManager {
pub fn new() -> Self {
Self {
rooms: HashMap::new(),
}
}
pub fn add_room(&mut self, room: RoomInfo) {
self.rooms.insert(room.room_id.clone(), room);
}
pub fn remove_room(&mut self, room_id: &str) {
self.rooms.remove(room_id);
}
pub fn get_room(&self, room_id: &str) -> Option<&RoomInfo> {
self.rooms.get(room_id)
}
pub fn list_rooms(&self) -> Vec<&RoomInfo> {
self.rooms.values().collect()
}
pub fn room_count(&self) -> usize {
self.rooms.len()
}
}
pub type SharedRoomManager = Arc<Mutex<RoomManager>>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_creates_empty_manager() {
let mgr = RoomManager::new();
assert_eq!(mgr.room_count(), 0);
}
#[test]
fn default_creates_empty_manager() {
let mgr = RoomManager::default();
assert_eq!(mgr.room_count(), 0);
}
#[test]
fn add_room_inserts_room() {
let mut mgr = RoomManager::new();
mgr.add_room(RoomInfo::new(
"!room1:server".into(),
"Room One".into(),
false,
));
assert_eq!(mgr.room_count(), 1);
}
#[test]
fn add_multiple_rooms() {
let mut mgr = RoomManager::new();
mgr.add_room(RoomInfo::new("!r1:server".into(), "A".into(), false));
mgr.add_room(RoomInfo::new("!r2:server".into(), "B".into(), true));
assert_eq!(mgr.room_count(), 2);
}
#[test]
fn get_room_returns_correct_room() {
let mut mgr = RoomManager::new();
mgr.add_room(RoomInfo::new(
"!room1:server".into(),
"Room One".into(),
false,
));
let room = mgr.get_room("!room1:server").unwrap();
assert_eq!(room.name, "Room One");
assert!(!room.is_encrypted);
}
#[test]
fn get_room_returns_none_for_missing() {
let mgr = RoomManager::new();
assert!(mgr.get_room("!nonexistent:server").is_none());
}
#[test]
fn remove_room_deletes_room() {
let mut mgr = RoomManager::new();
mgr.add_room(RoomInfo::new(
"!room1:server".into(),
"Room One".into(),
false,
));
assert_eq!(mgr.room_count(), 1);
mgr.remove_room("!room1:server");
assert_eq!(mgr.room_count(), 0);
}
#[test]
fn remove_nonexistent_room_is_noop() {
let mut mgr = RoomManager::new();
mgr.add_room(RoomInfo::new(
"!room1:server".into(),
"Room One".into(),
false,
));
mgr.remove_room("!nonexistent:server");
assert_eq!(mgr.room_count(), 1);
}
#[test]
fn add_room_overwrites_existing() {
let mut mgr = RoomManager::new();
mgr.add_room(RoomInfo::new(
"!room1:server".into(),
"Old Name".into(),
false,
));
mgr.add_room(RoomInfo::new(
"!room1:server".into(),
"New Name".into(),
true,
));
assert_eq!(mgr.room_count(), 1);
assert_eq!(mgr.get_room("!room1:server").unwrap().name, "New Name");
assert!(mgr.get_room("!room1:server").unwrap().is_encrypted);
}
#[test]
fn list_rooms_returns_all() {
let mut mgr = RoomManager::new();
mgr.add_room(RoomInfo::new("!r1:server".into(), "A".into(), false));
mgr.add_room(RoomInfo::new("!r2:server".into(), "B".into(), true));
assert_eq!(mgr.list_rooms().len(), 2);
}
}