// NAC资产一键上链系统 - 认证API处理器 use actix_web::{web, HttpResponse}; use serde::{Deserialize, Serialize}; use jsonwebtoken::{encode, EncodingKey, Header}; use bcrypt::{hash, verify, DEFAULT_COST}; use crate::database::DbPool; use crate::error::Result; use crate::models::User; use crate::middleware::Claims; use crate::response::ApiResponse; /// 注册请求 #[derive(Debug, Deserialize)] pub struct RegisterRequest { pub username: String, pub password: String, pub email: String, pub full_name: String, } /// 登录请求 #[derive(Debug, Deserialize)] pub struct LoginRequest { pub username: String, pub password: String, } /// 登录响应 #[derive(Debug, Serialize)] pub struct LoginResponse { pub token: String, pub user: UserInfo, } /// 用户信息 #[derive(Debug, Serialize)] pub struct UserInfo { pub id: String, pub username: String, pub email: String, pub full_name: String, pub role: String, } /// 注册 pub async fn register( pool: web::Data, req: web::Json, ) -> Result { log::info!("用户注册:username = {}", req.username); // 检查用户名是否已存在 if User::find_by_username(&pool, &req.username).await.is_ok() { return Ok(HttpResponse::BadRequest().json(ApiResponse::<()>::error("用户名已存在"))); } // 检查邮箱是否已存在 if User::find_by_email(&pool, &req.email).await.is_ok() { return Ok(HttpResponse::BadRequest().json(ApiResponse::<()>::error("邮箱已存在"))); } // 哈希密码 let password_hash = hash(&req.password, DEFAULT_COST) .map_err(|e| crate::error::OnboardingError::Internal(format!("密码哈希失败: {}", e)))?; // 创建用户 let user = User::create( &pool, &req.username, &password_hash, &req.email, &req.full_name, ).await?; log::info!("用户注册成功:user_id = {}", user.id); Ok(HttpResponse::Ok().json(ApiResponse::success(UserInfo { id: user.id, username: user.username, email: user.email, full_name: user.full_name, role: user.role, }))) } /// 登录 pub async fn login( pool: web::Data, req: web::Json, ) -> Result { log::info!("用户登录:username = {}", req.username); // 查找用户 let user = User::find_by_username(&pool, &req.username).await?; // 验证密码 let valid = verify(&req.password, &user.password_hash) .map_err(|e| crate::error::OnboardingError::Internal(format!("密码验证失败: {}", e)))?; if !valid { return Ok(HttpResponse::Unauthorized().json(ApiResponse::<()>::error("用户名或密码错误"))); } // 生成JWT token let jwt_secret = std::env::var("JWT_SECRET").unwrap_or_else(|_| "nac-secret-key".to_string()); let claims = Claims { sub: user.id.clone(), username: user.username.clone(), role: user.role.clone(), exp: (chrono::Utc::now() + chrono::Duration::days(7)).timestamp() as usize, }; let token = encode( &Header::default(), &claims, &EncodingKey::from_secret(jwt_secret.as_bytes()), ).map_err(|e| crate::error::OnboardingError::Internal(format!("Token生成失败: {}", e)))?; log::info!("用户登录成功:user_id = {}", user.id); Ok(HttpResponse::Ok().json(ApiResponse::success(LoginResponse { token, user: UserInfo { id: user.id, username: user.username, email: user.email, full_name: user.full_name, role: user.role, }, }))) } /// 获取当前用户信息 pub async fn me( pool: web::Data, claims: web::ReqData, ) -> Result { let user = User::find_by_id(&pool, &claims.sub).await?; Ok(HttpResponse::Ok().json(ApiResponse::success(UserInfo { id: user.id, username: user.username, email: user.email, full_name: user.full_name, role: user.role, }))) }