142 lines
4.7 KiB
Rust
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()),
|
|
}
|
|
}
|