use actix_web::{web, get, post, put, HttpResponse}; use sqlx::postgres::PgPool; use chrono::{DateTime, Utc}; use crate::db; use crate::error::AppError; use crate::models::{Claims, UpdatePaymentRequest}; #[get("/api/admin/users/{id}")] pub async fn admin_get_user( path: web::Path, pool: web::Data, claims: web::ReqData, ) -> Result { let target_user_id = path.into_inner(); tracing::info!("管理员获取用户信息, 目标用户ID: {}", target_user_id); // 验证当前用户是否为管理员 let current_user = db::get_user_by_id(pool.get_ref(), claims.user_id).await?; if !current_user.is_admin { return Err(AppError::Forbidden("无权限执行此操作".to_string())); } // 获取目标用户信息 let user = db::get_user_by_id(pool.get_ref(), target_user_id).await?; Ok(HttpResponse::Ok().json(serde_json::json!({ "success": true, "data": user }))) } #[put("/api/admin/users/{id}/payment")] pub async fn admin_update_user_payment( path: web::Path, pool: web::Data, claims: web::ReqData, body: web::Json, ) -> Result { let target_user_id = path.into_inner(); tracing::info!("管理员更新用户付费状态, 目标用户ID: {}", target_user_id); // 验证当前用户是否为管理员 let current_user = db::get_user_by_id(pool.get_ref(), claims.user_id).await?; if !current_user.is_admin { return Err(AppError::Forbidden("无权限执行此操作".to_string())); } // 解析 paid_expires_at let paid_expires_at = match &body.paid_expires_at { Some(date_str) => match DateTime::parse_from_rfc3339(date_str) { Ok(dt) => Some(dt.with_timezone(&Utc)), Err(e) => { return Err(AppError::BadRequest(format!("日期格式错误: {}", e))); } }, None => None, }; // 更新用户付费状态 db::update_user_payment_status(pool.get_ref(), target_user_id, body.is_paid, paid_expires_at).await?; // 审计日志 let _ = db::insert_payment_audit_log( pool.get_ref(), "ADMIN_MANUAL", target_user_id, "admin_revoke", Some(claims.user_id), Some(&format!("管理员手动更新付费状态: is_paid={}, expires_at={:?}", body.is_paid, body.paid_expires_at)), ).await; Ok(HttpResponse::Ok().json(serde_json::json!({ "success": true, "message": "用户付费状态已更新" }))) } /// POST /api/admin/orders/{order_no}/force-confirm /// 管理员强制确认指定订单(用于回调失败后的手动恢复) #[post("/api/admin/orders/{order_no}/force-confirm")] pub async fn admin_force_confirm_order( path: web::Path, pool: web::Data, claims: web::ReqData, ) -> Result { let order_no = path.into_inner(); tracing::info!("管理员强制确认订单: {}", order_no); // 验证当前用户是否为管理员 let current_user = db::get_user_by_id(pool.get_ref(), claims.user_id).await?; if !current_user.is_admin { return Err(AppError::Forbidden("无权限执行此操作".to_string())); } let new_expires = db::admin_force_confirm_order(pool.get_ref(), &order_no, claims.user_id).await?; Ok(HttpResponse::Ok().json(serde_json::json!({ "success": true, "message": "订单已确认", "data": { "new_expires_at": new_expires, } }))) }