easyremote/crates/server/src/handlers/sessions.rs
2026-01-04 18:15:07 +08:00

142 lines
4.7 KiB
Rust

//! 会话处理器
use axum::{
extract::{Path, Query, State},
http::StatusCode,
response::IntoResponse,
Json,
};
use std::sync::Arc;
use crate::models::{ApiResponse, HistoryResponse, PaginatedResponse, PaginationParams, SessionResponse};
use crate::services::{
device::DeviceRepository,
session::{HistoryRepository, SessionRepository},
AppState,
};
use super::{api_error, AuthUser};
/// 获取活跃会话列表
pub async fn list_sessions(
State(state): State<Arc<AppState>>,
user: AuthUser,
) -> impl IntoResponse {
let session_repo = SessionRepository::new(&state.db);
let device_repo = DeviceRepository::new(&state.db);
// 获取用户的设备
let devices = match device_repo.find_by_user(&user.user_id).await {
Ok(devices) => devices,
Err(e) => return api_error(StatusCode::INTERNAL_SERVER_ERROR, e.to_string()),
};
let device_ids: Vec<&str> = devices.iter().map(|d| d.device_id.as_str()).collect();
// 获取活跃会话
match session_repo.find_active().await {
Ok(sessions) => {
// 过滤出与用户设备相关的会话
let filtered: Vec<SessionResponse> = sessions
.into_iter()
.filter(|s| {
device_ids.contains(&s.controller_device_id.as_str())
|| device_ids.contains(&s.controlled_device_id.as_str())
})
.map(Into::into)
.collect();
(StatusCode::OK, Json(ApiResponse::ok(filtered))).into_response()
}
Err(e) => api_error(StatusCode::INTERNAL_SERVER_ERROR, e.to_string()),
}
}
/// 获取控制历史记录
pub async fn get_history(
State(state): State<Arc<AppState>>,
user: AuthUser,
Query(params): Query<PaginationParams>,
) -> impl IntoResponse {
let repo = HistoryRepository::new(&state.db);
match repo.find_by_user(&user.user_id, params.offset(), params.limit()).await {
Ok((history, total)) => {
let items: Vec<HistoryResponse> = history.into_iter().map(Into::into).collect();
let total_pages = ((total as f64) / (params.limit() as f64)).ceil() as u32;
let response = PaginatedResponse {
items,
total,
page: params.page.unwrap_or(1),
limit: params.limit(),
total_pages,
};
(StatusCode::OK, Json(ApiResponse::ok(response))).into_response()
}
Err(e) => api_error(StatusCode::INTERNAL_SERVER_ERROR, e.to_string()),
}
}
/// 获取单个会话
pub async fn get_session(
State(state): State<Arc<AppState>>,
Path(session_id): Path<String>,
_user: AuthUser,
) -> impl IntoResponse {
let repo = SessionRepository::new(&state.db);
match repo.find_by_id(&session_id).await {
Ok(session) => {
let response: SessionResponse = session.into();
(StatusCode::OK, Json(ApiResponse::ok(response))).into_response()
}
Err(_) => api_error(StatusCode::NOT_FOUND, "会话不存在"),
}
}
/// 结束会话
pub async fn end_session(
State(state): State<Arc<AppState>>,
Path(session_id): Path<String>,
user: AuthUser,
) -> impl IntoResponse {
let session_repo = SessionRepository::new(&state.db);
let device_repo = DeviceRepository::new(&state.db);
// 获取会话
let session = match session_repo.find_by_id(&session_id).await {
Ok(session) => session,
Err(_) => return api_error(StatusCode::NOT_FOUND, "会话不存在"),
};
// 验证用户有权结束会话
let user_devices = match device_repo.find_by_user(&user.user_id).await {
Ok(devices) => devices,
Err(e) => return api_error(StatusCode::INTERNAL_SERVER_ERROR, e.to_string()),
};
let device_ids: Vec<&str> = user_devices.iter().map(|d| d.device_id.as_str()).collect();
let is_owner = device_ids.contains(&session.controller_device_id.as_str())
|| device_ids.contains(&session.controlled_device_id.as_str());
if !is_owner && user.role != "admin" {
return api_error(StatusCode::FORBIDDEN, "无权结束此会话");
}
// 发送断开连接消息
let message = serde_json::json!({
"type": "session_end",
"session_id": session_id,
});
state.send_to_device(&session.controller_device_id, &message.to_string()).await;
state.send_to_device(&session.controlled_device_id, &message.to_string()).await;
// 更新会话状态
match session_repo.end_session(&session_id).await {
Ok(_) => (StatusCode::OK, Json(ApiResponse::ok("会话已结束"))).into_response(),
Err(e) => api_error(StatusCode::INTERNAL_SERVER_ERROR, e.to_string()),
}
}