100 lines
3.5 KiB
Rust
100 lines
3.5 KiB
Rust
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<i32>,
|
|
pool: web::Data<PgPool>,
|
|
claims: web::ReqData<Claims>,
|
|
) -> Result<HttpResponse, AppError> {
|
|
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<i32>,
|
|
pool: web::Data<PgPool>,
|
|
claims: web::ReqData<Claims>,
|
|
body: web::Json<UpdatePaymentRequest>,
|
|
) -> Result<HttpResponse, AppError> {
|
|
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<String>,
|
|
pool: web::Data<PgPool>,
|
|
claims: web::ReqData<Claims>,
|
|
) -> Result<HttpResponse, AppError> {
|
|
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,
|
|
}
|
|
})))
|
|
}
|