feat: comprehensive project improvements
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
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
- 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
This commit is contained in:
@@ -1,19 +1,34 @@
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
#[derive(Clone)]
|
||||
#[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 {
|
||||
rooms: HashMap<String, RoomInfo>,
|
||||
pub rooms: HashMap<String, RoomInfo>,
|
||||
}
|
||||
|
||||
impl RoomManager {
|
||||
pub fn new() -> Self {
|
||||
Self { rooms: HashMap::new() }
|
||||
Self {
|
||||
rooms: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_room(&mut self, room: RoomInfo) {
|
||||
@@ -35,4 +50,112 @@ impl RoomManager {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user