first commit

This commit is contained in:
2026-02-13 15:57:29 +08:00
commit aacda0b66a
53 changed files with 10029 additions and 0 deletions

57
src/domain/dto/auth.rs Normal file
View File

@@ -0,0 +1,57 @@
use serde::Deserialize;
use std::fmt;
/// 注册请求
#[derive(Deserialize)]
pub struct RegisterRequest {
pub email: String,
pub password: String,
}
// 实现 Debug trait对密码进行脱敏
impl fmt::Debug for RegisterRequest {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "RegisterRequest {{ email: {}, password: *** }}", self.email)
}
}
/// 登录请求
#[derive(Deserialize)]
pub struct LoginRequest {
pub email: String,
pub password: String,
}
// 实现 Debug trait
impl fmt::Debug for LoginRequest {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "LoginRequest {{ email: {}, password: *** }}", self.email)
}
}
/// 删除用户请求
#[derive(Deserialize)]
pub struct DeleteUserRequest {
pub user_id: String,
pub password: String,
}
// 实现 Debug trait
impl fmt::Debug for DeleteUserRequest {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "DeleteUserRequest {{ user_id: {}, password: *** }}", self.user_id)
}
}
/// 刷新令牌请求
#[derive(Deserialize)]
pub struct RefreshRequest {
pub refresh_token: String,
}
// RefreshRequest 的 refresh_token 是敏感字段,需要脱敏
impl fmt::Debug for RefreshRequest {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "RefreshRequest {{ refresh_token: *** }}")
}
}

1
src/domain/dto/mod.rs Normal file
View File

@@ -0,0 +1 @@
pub mod auth;

1
src/domain/dto/user.rs Normal file
View File

@@ -0,0 +1 @@
// 用户相关 DTO预留

View File

@@ -0,0 +1,2 @@
pub mod users;

View File

@@ -0,0 +1,41 @@
use sea_orm::entity::prelude::*;
use sea_orm::Set;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
#[sea_orm(table_name = "users")]
pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub id: String,
#[sea_orm(unique)]
pub email: String,
pub password_hash: String,
pub created_at: DateTime,
pub updated_at: DateTime,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
#[async_trait::async_trait]
impl ActiveModelBehavior for ActiveModel {
/// 在保存前自动填充时间戳
async fn before_save<C>(self, _db: &C, insert: bool) -> Result<Self, DbErr>
where
C: ConnectionTrait,
{
let mut this = self;
let now = chrono::Utc::now().naive_utc();
if insert {
// 插入时:设置创建时间和更新时间
this.created_at = Set(now);
this.updated_at = Set(now);
} else {
// 更新时:只更新更新时间
this.updated_at = Set(now);
}
Ok(this)
}
}

3
src/domain/mod.rs Normal file
View File

@@ -0,0 +1,3 @@
pub mod dto;
pub mod vo;
pub mod entities;

50
src/domain/vo/auth.rs Normal file
View File

@@ -0,0 +1,50 @@
use serde::Serialize;
/// 注册结果
#[derive(Debug, Serialize)]
pub struct RegisterResult {
pub email: String,
pub created_at: String, // ISO 8601 格式
pub access_token: String,
pub refresh_token: String,
}
impl From<(crate::domain::entities::users::Model, String, String)> for RegisterResult {
fn from((user_model, access_token, refresh_token): (crate::domain::entities::users::Model, String, String)) -> Self {
Self {
email: user_model.email,
created_at: user_model.created_at.format("%Y-%m-%dT%H:%M:%S%.3fZ").to_string(),
access_token,
refresh_token,
}
}
}
/// 登录结果
#[derive(Debug, Serialize)]
pub struct LoginResult {
pub id: String,
pub email: String,
pub created_at: String, // ISO 8601 格式
pub access_token: String,
pub refresh_token: String,
}
impl From<(crate::domain::entities::users::Model, String, String)> for LoginResult {
fn from((user_model, access_token, refresh_token): (crate::domain::entities::users::Model, String, String)) -> Self {
Self {
id: user_model.id,
email: user_model.email,
created_at: user_model.created_at.format("%Y-%m-%dT%H:%M:%S%.3fZ").to_string(),
access_token,
refresh_token,
}
}
}
/// 刷新 Token 结果
#[derive(Debug, Serialize)]
pub struct RefreshResult {
pub access_token: String,
pub refresh_token: String,
}

56
src/domain/vo/mod.rs Normal file
View File

@@ -0,0 +1,56 @@
pub mod auth;
pub mod user;
/// 统一的 API 响应结构
use serde::Serialize;
use axum::http::StatusCode;
#[derive(Debug, Serialize)]
pub struct ApiResponse<T> {
/// HTTP 状态码
pub code: u16,
/// 响应消息
pub message: String,
/// 响应数据
pub data: Option<T>,
}
impl<T: Serialize> ApiResponse<T> {
/// 成功响应200
pub fn success(data: T) -> Self {
Self {
code: 200,
message: "Success".to_string(),
data: Some(data),
}
}
/// 成功响应(自定义消息)
pub fn success_with_message(data: T, message: &str) -> Self {
Self {
code: 200,
message: message.to_string(),
data: Some(data),
}
}
/// 错误响应
#[allow(dead_code)]
pub fn error(status_code: StatusCode, message: &str) -> ApiResponse<()> {
ApiResponse {
code: status_code.as_u16(),
message: message.to_string(),
data: None,
}
}
/// 错误响应(带数据)
#[allow(dead_code)]
pub fn error_with_data(status_code: StatusCode, message: &str, data: T) -> ApiResponse<T> {
ApiResponse {
code: status_code.as_u16(),
message: message.to_string(),
data: Some(data),
}
}
}

1
src/domain/vo/user.rs Normal file
View File

@@ -0,0 +1 @@
// 用户相关 VO预留