feat: 统一前后端日志和错误处理
This commit is contained in:
@@ -1,57 +1,32 @@
|
||||
use actix_web::{web, get, put, HttpResponse, Responder};
|
||||
use actix_web::{web, get, put, HttpResponse};
|
||||
use sqlx::postgres::PgPool;
|
||||
use tracing::error;
|
||||
use chrono::{DateTime, Utc};
|
||||
|
||||
use crate::db;
|
||||
use crate::models::{Claims, ErrorResponse, UpdatePaymentRequest};
|
||||
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>,
|
||||
) -> impl Responder {
|
||||
) -> Result<HttpResponse, AppError> {
|
||||
let target_user_id = path.into_inner();
|
||||
tracing::info!("管理员获取用户信息, 目标用户ID: {}", target_user_id);
|
||||
|
||||
// 验证当前用户是否为管理员
|
||||
let current_user = match db::get_user_by_id(pool.get_ref(), claims.user_id).await {
|
||||
Ok(user) => user,
|
||||
Err(e) => {
|
||||
error!("获取当前用户信息失败: {}", e);
|
||||
return HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": false,
|
||||
"errcode": 500,
|
||||
"errmsg": "获取用户信息失败"
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
let current_user = db::get_user_by_id(pool.get_ref(), claims.user_id).await?;
|
||||
if !current_user.is_admin {
|
||||
return HttpResponse::Forbidden().json(serde_json::json!({
|
||||
"success": false,
|
||||
"errcode": 403,
|
||||
"errmsg": "无权限执行此操作"
|
||||
}));
|
||||
return Err(AppError::Forbidden("无权限执行此操作".to_string()));
|
||||
}
|
||||
|
||||
// 获取目标用户信息
|
||||
match db::get_user_by_id(pool.get_ref(), target_user_id).await {
|
||||
Ok(user) => HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": true,
|
||||
"data": user
|
||||
})),
|
||||
Err(e) => {
|
||||
error!("获取目标用户信息失败: {}", e);
|
||||
let errcode = if e.starts_with("未找到") { 404 } else { 500 };
|
||||
HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": false,
|
||||
"errcode": errcode,
|
||||
"errmsg": e
|
||||
}))
|
||||
}
|
||||
}
|
||||
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")]
|
||||
@@ -60,29 +35,14 @@ pub async fn admin_update_user_payment(
|
||||
pool: web::Data<PgPool>,
|
||||
claims: web::ReqData<Claims>,
|
||||
body: web::Json<UpdatePaymentRequest>,
|
||||
) -> impl Responder {
|
||||
) -> Result<HttpResponse, AppError> {
|
||||
let target_user_id = path.into_inner();
|
||||
tracing::info!("管理员更新用户付费状态, 目标用户ID: {}", target_user_id);
|
||||
|
||||
// 验证当前用户是否为管理员
|
||||
let current_user = match db::get_user_by_id(pool.get_ref(), claims.user_id).await {
|
||||
Ok(user) => user,
|
||||
Err(e) => {
|
||||
error!("获取当前用户信息失败: {}", e);
|
||||
return HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": false,
|
||||
"errcode": 500,
|
||||
"errmsg": "获取用户信息失败"
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
let current_user = db::get_user_by_id(pool.get_ref(), claims.user_id).await?;
|
||||
if !current_user.is_admin {
|
||||
return HttpResponse::Forbidden().json(serde_json::json!({
|
||||
"success": false,
|
||||
"errcode": 403,
|
||||
"errmsg": "无权限执行此操作"
|
||||
}));
|
||||
return Err(AppError::Forbidden("无权限执行此操作".to_string()));
|
||||
}
|
||||
|
||||
// 解析 paid_expires_at
|
||||
@@ -90,29 +50,16 @@ pub async fn admin_update_user_payment(
|
||||
Some(date_str) => match DateTime::parse_from_rfc3339(date_str) {
|
||||
Ok(dt) => Some(dt.with_timezone(&Utc)),
|
||||
Err(e) => {
|
||||
return HttpResponse::BadRequest().json(serde_json::json!({
|
||||
"success": false,
|
||||
"errcode": 400,
|
||||
"errmsg": format!("日期格式错误: {}", e)
|
||||
}));
|
||||
return Err(AppError::BadRequest(format!("日期格式错误: {}", e)));
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
|
||||
// 更新用户付费状态
|
||||
match db::update_user_payment_status(pool.get_ref(), target_user_id, body.is_paid, paid_expires_at).await {
|
||||
Ok(_) => HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": true,
|
||||
"message": "用户付费状态已更新"
|
||||
})),
|
||||
Err(e) => {
|
||||
error!("更新用户付费状态失败: {}", e);
|
||||
HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": false,
|
||||
"errcode": 500,
|
||||
"errmsg": e
|
||||
}))
|
||||
}
|
||||
}
|
||||
db::update_user_payment_status(pool.get_ref(), target_user_id, body.is_paid, paid_expires_at).await?;
|
||||
Ok(HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": true,
|
||||
"message": "用户付费状态已更新"
|
||||
})))
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
use actix_web::{web, delete, get, post, HttpResponse, Responder};
|
||||
use actix_web::{web, delete, get, post, HttpResponse};
|
||||
use sqlx::postgres::PgPool;
|
||||
use tracing::{debug, error, info};
|
||||
use tracing::{debug, info};
|
||||
|
||||
use crate::db;
|
||||
use crate::error::AppError;
|
||||
use crate::models::Claims;
|
||||
|
||||
// GET /api/favorites - 获取收藏列表
|
||||
@@ -11,31 +12,21 @@ pub async fn get_favorites(
|
||||
query: web::Query<serde_json::Value>,
|
||||
pool: web::Data<PgPool>,
|
||||
claims: web::ReqData<Claims>,
|
||||
) -> impl Responder {
|
||||
) -> Result<HttpResponse, AppError> {
|
||||
let page = query.get("page").and_then(|v| v.as_i64()).unwrap_or(1).max(1) as i32;
|
||||
let limit = query.get("limit").and_then(|v| v.as_i64()).unwrap_or(10).clamp(1, 100) as i32;
|
||||
|
||||
debug!("获取收藏列表, 页码: {}, 每页条数: {}", page, limit);
|
||||
|
||||
match db::get_favorites_list(pool.get_ref(), claims.user_id, page, limit).await {
|
||||
Ok(response) => {
|
||||
HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": true,
|
||||
"data": response.list,
|
||||
"page": page,
|
||||
"limit": limit,
|
||||
"total": response.total
|
||||
}))
|
||||
}
|
||||
Err(error_msg) => {
|
||||
error!("获取收藏列表失败: {}", error_msg);
|
||||
HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": false,
|
||||
"errcode": 500,
|
||||
"errmsg": error_msg
|
||||
}))
|
||||
}
|
||||
}
|
||||
let response = db::get_favorites_list(pool.get_ref(), claims.user_id, page, limit).await?;
|
||||
|
||||
Ok(HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": true,
|
||||
"data": response.list,
|
||||
"page": page,
|
||||
"limit": limit,
|
||||
"total": response.total
|
||||
})))
|
||||
}
|
||||
|
||||
// POST /api/favorites/{id} - 添加收藏
|
||||
@@ -44,25 +35,16 @@ pub async fn add_favorite(
|
||||
path: web::Path<i32>,
|
||||
pool: web::Data<PgPool>,
|
||||
claims: web::ReqData<Claims>,
|
||||
) -> impl Responder {
|
||||
) -> Result<HttpResponse, AppError> {
|
||||
let weather_id = path.into_inner();
|
||||
info!("添加收藏, weather_id: {}", weather_id);
|
||||
|
||||
match db::set_weather_favorite(pool.get_ref(), weather_id, claims.user_id, true).await {
|
||||
Ok(_) => HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": true,
|
||||
"message": format!("已添加收藏")
|
||||
})),
|
||||
Err(error_msg) => {
|
||||
error!("添加收藏失败: {}", error_msg);
|
||||
let errcode = if error_msg.starts_with("未找到") { 404 } else { 500 };
|
||||
HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": false,
|
||||
"errcode": errcode,
|
||||
"errmsg": error_msg
|
||||
}))
|
||||
}
|
||||
}
|
||||
db::set_weather_favorite(pool.get_ref(), weather_id, claims.user_id, true).await?;
|
||||
|
||||
Ok(HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": true,
|
||||
"message": "已添加收藏"
|
||||
})))
|
||||
}
|
||||
|
||||
// DELETE /api/favorites/{id} - 取消收藏
|
||||
@@ -71,23 +53,14 @@ pub async fn remove_favorite(
|
||||
path: web::Path<i32>,
|
||||
pool: web::Data<PgPool>,
|
||||
claims: web::ReqData<Claims>,
|
||||
) -> impl Responder {
|
||||
) -> Result<HttpResponse, AppError> {
|
||||
let weather_id = path.into_inner();
|
||||
info!("取消收藏, weather_id: {}", weather_id);
|
||||
|
||||
match db::set_weather_favorite(pool.get_ref(), weather_id, claims.user_id, false).await {
|
||||
Ok(_) => HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": true,
|
||||
"message": format!("已取消收藏")
|
||||
})),
|
||||
Err(error_msg) => {
|
||||
error!("取消收藏失败: {}", error_msg);
|
||||
let errcode = if error_msg.starts_with("未找到") { 404 } else { 500 };
|
||||
HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": false,
|
||||
"errcode": errcode,
|
||||
"errmsg": error_msg
|
||||
}))
|
||||
}
|
||||
}
|
||||
db::set_weather_favorite(pool.get_ref(), weather_id, claims.user_id, false).await?;
|
||||
|
||||
Ok(HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": true,
|
||||
"message": "已取消收藏"
|
||||
})))
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
// handlers/payment.rs — 支付相关处理器
|
||||
use actix_web::{get, post, web, HttpResponse, Responder};
|
||||
use actix_web::{get, post, web, HttpResponse};
|
||||
use chrono::Utc;
|
||||
use sqlx::postgres::PgPool;
|
||||
use tracing::error;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::db;
|
||||
use crate::error::AppError;
|
||||
use crate::models::{Claims, CreateOrderRequest, MockConfirmRequest};
|
||||
|
||||
struct PackageInfo {
|
||||
@@ -45,24 +45,20 @@ pub async fn create_order(
|
||||
pool: web::Data<PgPool>,
|
||||
claims: web::ReqData<Claims>,
|
||||
body: web::Json<CreateOrderRequest>,
|
||||
) -> impl Responder {
|
||||
) -> Result<HttpResponse, AppError> {
|
||||
let user_id = claims.user_id;
|
||||
|
||||
let pkg = match get_package_info(&body.package_type) {
|
||||
Some(p) => p,
|
||||
None => {
|
||||
return HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": false,
|
||||
"errcode": 400,
|
||||
"errmsg": "无效的套餐类型"
|
||||
}));
|
||||
return Err(AppError::BadRequest("无效的套餐类型".to_string()));
|
||||
}
|
||||
};
|
||||
|
||||
let order_no = Uuid::new_v4().to_string();
|
||||
let expires_at = pkg.days.map(|d| Utc::now() + chrono::Duration::days(d));
|
||||
|
||||
match db::create_payment_order(
|
||||
db::create_payment_order(
|
||||
pool.get_ref(),
|
||||
user_id,
|
||||
&order_no,
|
||||
@@ -70,28 +66,19 @@ pub async fn create_order(
|
||||
pkg.amount,
|
||||
expires_at,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(_) => HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": true,
|
||||
"data": {
|
||||
"order_id": order_no,
|
||||
"package_type": body.package_type,
|
||||
"amount": pkg.amount,
|
||||
"display_amount": pkg.display_amount,
|
||||
"display_name": pkg.display_name,
|
||||
"expires_at": expires_at,
|
||||
}
|
||||
})),
|
||||
Err(e) => {
|
||||
error!("创建订单失败: {}", e);
|
||||
HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": false,
|
||||
"errcode": 500,
|
||||
"errmsg": "创建订单失败,请重试"
|
||||
}))
|
||||
.await?;
|
||||
|
||||
Ok(HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": true,
|
||||
"data": {
|
||||
"order_id": order_no,
|
||||
"package_type": body.package_type,
|
||||
"amount": pkg.amount,
|
||||
"display_amount": pkg.display_amount,
|
||||
"display_name": pkg.display_name,
|
||||
"expires_at": expires_at,
|
||||
}
|
||||
}
|
||||
})))
|
||||
}
|
||||
|
||||
/// POST /api/payment/mock-confirm
|
||||
@@ -100,26 +87,18 @@ pub async fn mock_confirm(
|
||||
pool: web::Data<PgPool>,
|
||||
claims: web::ReqData<Claims>,
|
||||
body: web::Json<MockConfirmRequest>,
|
||||
) -> impl Responder {
|
||||
) -> Result<HttpResponse, AppError> {
|
||||
let user_id = claims.user_id;
|
||||
|
||||
match db::confirm_payment_order(pool.get_ref(), &body.order_id, user_id).await {
|
||||
Ok(expires_at) => HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": true,
|
||||
"data": {
|
||||
"is_paid_active": true,
|
||||
"paid_expires_at": expires_at,
|
||||
}
|
||||
})),
|
||||
Err(e) => {
|
||||
error!("确认支付失败: {}", e);
|
||||
HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": false,
|
||||
"errcode": 400,
|
||||
"errmsg": "支付确认失败,请重试"
|
||||
}))
|
||||
let expires_at = db::confirm_payment_order(pool.get_ref(), &body.order_id, user_id).await?;
|
||||
|
||||
Ok(HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": true,
|
||||
"data": {
|
||||
"is_paid_active": true,
|
||||
"paid_expires_at": expires_at,
|
||||
}
|
||||
}
|
||||
})))
|
||||
}
|
||||
|
||||
/// GET /api/user/quota
|
||||
@@ -127,34 +106,23 @@ pub async fn mock_confirm(
|
||||
pub async fn get_user_quota(
|
||||
pool: web::Data<PgPool>,
|
||||
claims: web::ReqData<Claims>,
|
||||
) -> impl Responder {
|
||||
) -> Result<HttpResponse, AppError> {
|
||||
let user_id = claims.user_id;
|
||||
|
||||
match db::get_user_quota(pool.get_ref(), user_id).await {
|
||||
Ok((used, is_paid_active, paid_expires_at)) => {
|
||||
let limit: i64 = std::env::var("FREE_USER_DATA_LIMIT")
|
||||
.ok()
|
||||
.and_then(|v| v.parse().ok())
|
||||
.unwrap_or(20);
|
||||
let (used, is_paid_active, paid_expires_at) = db::get_user_quota(pool.get_ref(), user_id).await?;
|
||||
let limit: i64 = std::env::var("FREE_USER_DATA_LIMIT")
|
||||
.ok()
|
||||
.and_then(|v| v.parse().ok())
|
||||
.unwrap_or(20);
|
||||
|
||||
HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": true,
|
||||
"data": {
|
||||
"used": used,
|
||||
"limit": limit,
|
||||
"unlimited": is_paid_active,
|
||||
"is_paid_active": is_paid_active,
|
||||
"paid_expires_at": paid_expires_at,
|
||||
}
|
||||
}))
|
||||
Ok(HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": true,
|
||||
"data": {
|
||||
"used": used,
|
||||
"limit": limit,
|
||||
"unlimited": is_paid_active,
|
||||
"is_paid_active": is_paid_active,
|
||||
"paid_expires_at": paid_expires_at,
|
||||
}
|
||||
Err(e) => {
|
||||
error!("获取配额信息失败: {}", e);
|
||||
HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": false,
|
||||
"errcode": 500,
|
||||
"errmsg": "获取配额信息失败"
|
||||
}))
|
||||
}
|
||||
}
|
||||
})))
|
||||
}
|
||||
@@ -1,47 +1,37 @@
|
||||
use actix_web::{web, get, put, HttpResponse, Responder};
|
||||
use actix_web::{web, get, put, HttpResponse};
|
||||
use sqlx::postgres::PgPool;
|
||||
use tracing::error;
|
||||
use tracing::info;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::db;
|
||||
use crate::models::{Claims, ErrorResponse};
|
||||
use crate::error::AppError;
|
||||
use crate::models::Claims;
|
||||
|
||||
#[get("/api/user/profile")]
|
||||
pub async fn get_current_user_profile(
|
||||
pool: web::Data<PgPool>,
|
||||
claims: web::ReqData<Claims>,
|
||||
) -> impl Responder {
|
||||
) -> Result<HttpResponse, AppError> {
|
||||
let user_id = claims.user_id;
|
||||
tracing::info!("获取当前用户信息, 用户ID: {}", user_id);
|
||||
info!("获取当前用户信息, 用户ID: {}", user_id);
|
||||
|
||||
match db::get_user_by_id(pool.get_ref(), user_id).await {
|
||||
Ok(user) => {
|
||||
let is_paid_active = user.is_paid &&
|
||||
(user.paid_expires_at.is_none() || user.paid_expires_at.unwrap() > chrono::Utc::now());
|
||||
|
||||
HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": true,
|
||||
"data": {
|
||||
"id": user.id,
|
||||
"name": user.name,
|
||||
"nickname": user.nickname,
|
||||
"avatarUrl": user.avatar_url,
|
||||
"is_paid": user.is_paid,
|
||||
"is_paid_active": is_paid_active,
|
||||
"is_admin": user.is_admin,
|
||||
"paid_expires_at": user.paid_expires_at
|
||||
}
|
||||
}))
|
||||
let user = db::get_user_by_id(pool.get_ref(), user_id).await?;
|
||||
let is_paid_active = user.is_paid &&
|
||||
(user.paid_expires_at.is_none() || user.paid_expires_at.unwrap() > chrono::Utc::now());
|
||||
|
||||
Ok(HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": true,
|
||||
"data": {
|
||||
"id": user.id,
|
||||
"name": user.name,
|
||||
"nickname": user.nickname,
|
||||
"avatarUrl": user.avatar_url,
|
||||
"is_paid": user.is_paid,
|
||||
"is_paid_active": is_paid_active,
|
||||
"is_admin": user.is_admin,
|
||||
"paid_expires_at": user.paid_expires_at
|
||||
}
|
||||
Err(e) => {
|
||||
error!("获取用户信息失败: {}", e);
|
||||
HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": false,
|
||||
"errcode": 500,
|
||||
"errmsg": e
|
||||
}))
|
||||
}
|
||||
}
|
||||
})))
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
@@ -55,23 +45,12 @@ pub async fn save_user_profile(
|
||||
pool: web::Data<PgPool>,
|
||||
claims: web::ReqData<Claims>,
|
||||
body: web::Json<SaveUserProfileRequest>,
|
||||
) -> impl Responder {
|
||||
) -> Result<HttpResponse, AppError> {
|
||||
let user_id = claims.user_id;
|
||||
tracing::info!("保存用户信息, 用户ID: {}", user_id);
|
||||
info!("保存用户信息, 用户ID: {}", user_id);
|
||||
|
||||
match db::update_user_profile(pool.get_ref(), user_id, &body.nickname, &body.avatar_url).await {
|
||||
Ok(_) => {
|
||||
HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": true
|
||||
}))
|
||||
}
|
||||
Err(e) => {
|
||||
error!("保存用户信息失败: {}", e);
|
||||
HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": false,
|
||||
"errcode": 500,
|
||||
"errmsg": e
|
||||
}))
|
||||
}
|
||||
}
|
||||
db::update_user_profile(pool.get_ref(), user_id, &body.nickname, &body.avatar_url).await?;
|
||||
Ok(HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": true
|
||||
})))
|
||||
}
|
||||
|
||||
@@ -1,45 +1,35 @@
|
||||
use actix_web::{web, delete, get, post, HttpResponse, Responder};
|
||||
use actix_web::{web, delete, get, post, HttpResponse};
|
||||
use sqlx::postgres::PgPool;
|
||||
use tracing::{debug, error, info};
|
||||
use tracing::{debug, info};
|
||||
|
||||
use crate::auth;
|
||||
use crate::db;
|
||||
use crate::error::AppError;
|
||||
use crate::handlers::TEMPLATES_DIR;
|
||||
use crate::models::{AppState, Claims, ErrorResponse};
|
||||
use crate::models::{AppState, Claims};
|
||||
|
||||
#[post("/api/post-weather-data")]
|
||||
pub async fn post_weather_data(
|
||||
data: web::Json<crate::models::WeatherData>,
|
||||
pool: web::Data<PgPool>,
|
||||
claims: web::ReqData<Claims>,
|
||||
) -> impl Responder {
|
||||
) -> Result<HttpResponse, AppError> {
|
||||
info!("Received weather data, preparing to insert into DB...");
|
||||
|
||||
let user_id = claims.user_id;
|
||||
|
||||
// 调用 db.rs 中的函数来处理数据库逻辑
|
||||
match db::insert_weather_data(pool.get_ref(), &data, user_id).await {
|
||||
Ok(inserted_id) => {
|
||||
info!(
|
||||
"Successfully inserted weather data with id: {}",
|
||||
inserted_id
|
||||
);
|
||||
HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": true,
|
||||
"message": "Weather data inserted successfully",
|
||||
"inserted_id": inserted_id,
|
||||
"received_assignment": data.assignment_number
|
||||
}))
|
||||
}
|
||||
Err(error_msg) => {
|
||||
error!("Database operation failed: {}", error_msg);
|
||||
HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": false,
|
||||
"errcode": 500,
|
||||
"errmsg": error_msg
|
||||
}))
|
||||
}
|
||||
}
|
||||
let inserted_id = db::insert_weather_data(pool.get_ref(), &data, user_id).await?;
|
||||
info!(
|
||||
"Successfully inserted weather data with id: {}",
|
||||
inserted_id
|
||||
);
|
||||
Ok(HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": true,
|
||||
"message": "Weather data inserted successfully",
|
||||
"inserted_id": inserted_id,
|
||||
"received_assignment": data.assignment_number
|
||||
})))
|
||||
}
|
||||
|
||||
#[post("/api/generate-temp-token/{resource_id}")]
|
||||
@@ -48,45 +38,23 @@ pub async fn generate_temp_token_handler(
|
||||
pool: web::Data<PgPool>,
|
||||
claims: web::ReqData<Claims>,
|
||||
app_state: web::Data<AppState>,
|
||||
) -> impl Responder {
|
||||
) -> Result<HttpResponse, AppError> {
|
||||
let resource_id = path.into_inner();
|
||||
let openid: &String = &claims.openid;
|
||||
|
||||
match db::get_weather_details(pool.get_ref(), resource_id).await {
|
||||
Ok(weather_data) => {
|
||||
if weather_data.openid != *openid {
|
||||
return HttpResponse::Forbidden().json(ErrorResponse {
|
||||
error: "无权限为该资源生成临时token".to_string(),
|
||||
errcode: Some(403),
|
||||
errmsg: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
return HttpResponse::BadRequest().json(ErrorResponse {
|
||||
error: format!("资源不存在: {}", e),
|
||||
errcode: Some(404),
|
||||
errmsg: None,
|
||||
});
|
||||
}
|
||||
let weather_data = db::get_weather_details(pool.get_ref(), resource_id).await?;
|
||||
if weather_data.openid != *openid {
|
||||
return Err(AppError::Forbidden("无权限为该资源生成临时token".to_string()));
|
||||
}
|
||||
|
||||
let temp_token = match auth::generate_temp_token(openid, resource_id, &app_state.jwt_secret, 10) {
|
||||
Ok(token) => token,
|
||||
Err(e) => {
|
||||
return HttpResponse::InternalServerError().json(ErrorResponse {
|
||||
error: format!("生成临时token失败: {}", e),
|
||||
errcode: Some(500),
|
||||
errmsg: None,
|
||||
});
|
||||
}
|
||||
};
|
||||
let temp_token = auth::generate_temp_token(openid, resource_id, &app_state.jwt_secret, 10)
|
||||
.map_err(|e| AppError::Internal(format!("生成临时token失败: {}", e)))?;
|
||||
|
||||
HttpResponse::Ok().json(serde_json::json!({
|
||||
Ok(HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": true,
|
||||
"temp_token": temp_token,
|
||||
"expire_minutes": 10,
|
||||
}))
|
||||
})))
|
||||
}
|
||||
|
||||
#[get("/weather/details")]
|
||||
@@ -95,22 +63,14 @@ pub async fn get_weather_details(
|
||||
claims: Option<web::ReqData<Claims>>,
|
||||
query: web::Query<serde_json::Value>,
|
||||
app_state: web::Data<AppState>,
|
||||
) -> impl Responder {
|
||||
) -> Result<HttpResponse, AppError> {
|
||||
let mut is_temp_token = false;
|
||||
|
||||
let (openid, weather_id) =
|
||||
if let Some(temp_token) = query.get("temp_token").and_then(|v| v.as_str()) {
|
||||
is_temp_token = true;
|
||||
let temp_claims = match auth::verify_temp_token(temp_token, &app_state.jwt_secret) {
|
||||
Ok(c) => c,
|
||||
Err(e) => {
|
||||
return HttpResponse::Unauthorized().json(ErrorResponse {
|
||||
error: format!("临时token无效: {}", e),
|
||||
errcode: Some(401),
|
||||
errmsg: None,
|
||||
});
|
||||
}
|
||||
};
|
||||
let temp_claims = auth::verify_temp_token(temp_token, &app_state.jwt_secret)
|
||||
.map_err(|e| AppError::Unauthorized(format!("临时token无效: {}", e)))?;
|
||||
(temp_claims.openid, temp_claims.resource_id)
|
||||
} else if let Some(claims) = claims {
|
||||
let weather_id = match query.get("id") {
|
||||
@@ -120,57 +80,24 @@ pub async fn get_weather_details(
|
||||
}
|
||||
Some(v) if v.is_number() => v.as_f64().unwrap() as i32,
|
||||
_ => {
|
||||
return HttpResponse::BadRequest().json(ErrorResponse {
|
||||
error: "缺少资源ID参数(id)".to_string(),
|
||||
errcode: Some(400),
|
||||
errmsg: None,
|
||||
});
|
||||
return Err(AppError::BadRequest("缺少资源ID参数(id)".to_string()));
|
||||
}
|
||||
};
|
||||
(claims.openid.clone(), weather_id)
|
||||
} else {
|
||||
return HttpResponse::Unauthorized().json(ErrorResponse {
|
||||
error: "缺少token(需提供JWT或临时token)".to_string(),
|
||||
errcode: Some(401),
|
||||
errmsg: None,
|
||||
});
|
||||
return Err(AppError::Unauthorized("缺少token(需提供JWT或临时token)".to_string()));
|
||||
};
|
||||
|
||||
let weather_data = match db::get_weather_details(pool.get_ref(), weather_id).await {
|
||||
Ok(data) => {
|
||||
if data.openid != openid {
|
||||
return HttpResponse::Forbidden().json(ErrorResponse {
|
||||
error: "无权限访问该数据".to_string(),
|
||||
errcode: Some(403),
|
||||
errmsg: None,
|
||||
});
|
||||
}
|
||||
data
|
||||
}
|
||||
Err(error_msg) => {
|
||||
error!("获取天气数据详情失败: {}", error_msg);
|
||||
let errcode = if error_msg.starts_with("未找到") {
|
||||
404
|
||||
} else {
|
||||
500
|
||||
};
|
||||
return HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": false,
|
||||
"errcode": errcode,
|
||||
"errmsg": error_msg
|
||||
}));
|
||||
}
|
||||
};
|
||||
let weather_data = db::get_weather_details(pool.get_ref(), weather_id).await?;
|
||||
if weather_data.openid != openid {
|
||||
return Err(AppError::Forbidden("无权限访问该数据".to_string()));
|
||||
}
|
||||
|
||||
if is_temp_token {
|
||||
let index_html = match TEMPLATES_DIR.get_file("index.html") {
|
||||
Some(file) => file.contents_utf8().unwrap_or_default(),
|
||||
None => {
|
||||
return HttpResponse::InternalServerError().json(ErrorResponse {
|
||||
error: "无法找到模板文件".to_string(),
|
||||
errcode: Some(500),
|
||||
errmsg: None,
|
||||
});
|
||||
return Err(AppError::Internal("无法找到模板文件".to_string()));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -191,14 +118,14 @@ pub async fn get_weather_details(
|
||||
"",
|
||||
);
|
||||
|
||||
HttpResponse::Ok()
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("text/html; charset=utf-8")
|
||||
.body(rendered_html)
|
||||
.body(rendered_html))
|
||||
} else {
|
||||
HttpResponse::Ok().json(serde_json::json!({
|
||||
Ok(HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": true,
|
||||
"data": weather_data
|
||||
}))
|
||||
})))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,7 +134,7 @@ pub async fn get_weather_brief(
|
||||
query: web::Query<serde_json::Value>,
|
||||
pool: web::Data<PgPool>,
|
||||
claims: web::ReqData<Claims>,
|
||||
) -> impl Responder {
|
||||
) -> Result<HttpResponse, AppError> {
|
||||
let page = match query.get("page") {
|
||||
Some(v) => {
|
||||
let raw = if let Some(num) = v.as_i64() {
|
||||
@@ -238,29 +165,18 @@ pub async fn get_weather_brief(
|
||||
|
||||
debug!("获取天气数据列表, 页码: {}, 每页条数: {}", page, limit);
|
||||
|
||||
match db::get_weather_list(pool.get_ref(), claims.user_id, page, limit).await {
|
||||
Ok(response) => {
|
||||
debug!(
|
||||
"获取到的天气列表: {:?}, 总条数: {}",
|
||||
response.list, response.total
|
||||
);
|
||||
HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": true,
|
||||
"data": response.list,
|
||||
"page": page,
|
||||
"limit": limit,
|
||||
"total": response.total
|
||||
}))
|
||||
}
|
||||
Err(error_msg) => {
|
||||
error!("获取天气数据列表失败: {}", error_msg);
|
||||
HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": false,
|
||||
"errcode": 500,
|
||||
"errmsg": error_msg
|
||||
}))
|
||||
}
|
||||
}
|
||||
let response = db::get_weather_list(pool.get_ref(), claims.user_id, page, limit).await?;
|
||||
debug!(
|
||||
"获取到的天气列表: {:?}, 总条数: {}",
|
||||
response.list, response.total
|
||||
);
|
||||
Ok(HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": true,
|
||||
"data": response.list,
|
||||
"page": page,
|
||||
"limit": limit,
|
||||
"total": response.total
|
||||
})))
|
||||
}
|
||||
|
||||
#[delete("/weather/delete/{id}")]
|
||||
@@ -268,27 +184,13 @@ pub async fn delete_weather(
|
||||
path: web::Path<i32>,
|
||||
pool: web::Data<PgPool>,
|
||||
claims: web::ReqData<Claims>,
|
||||
) -> impl Responder {
|
||||
) -> Result<HttpResponse, AppError> {
|
||||
let weather_id = path.into_inner();
|
||||
info!("删除天气数据, ID: {}", weather_id);
|
||||
|
||||
match db::delete_weather_data(pool.get_ref(), weather_id, claims.user_id).await {
|
||||
Ok(_) => HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": true,
|
||||
"message": format!("天气数据 {} 已成功删除", weather_id)
|
||||
})),
|
||||
Err(error_msg) => {
|
||||
error!("删除天气数据失败: {}", error_msg);
|
||||
let errcode = if error_msg.starts_with("未找到") {
|
||||
404
|
||||
} else {
|
||||
500
|
||||
};
|
||||
HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": false,
|
||||
"errcode": errcode,
|
||||
"errmsg": error_msg
|
||||
}))
|
||||
}
|
||||
}
|
||||
db::delete_weather_data(pool.get_ref(), weather_id, claims.user_id).await?;
|
||||
Ok(HttpResponse::Ok().json(serde_json::json!({
|
||||
"success": true,
|
||||
"message": format!("天气数据 {} 已成功删除", weather_id)
|
||||
})))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user