first commit
This commit is contained in:
57
src/domain/dto/auth.rs
Normal file
57
src/domain/dto/auth.rs
Normal 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
1
src/domain/dto/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod auth;
|
||||
1
src/domain/dto/user.rs
Normal file
1
src/domain/dto/user.rs
Normal file
@@ -0,0 +1 @@
|
||||
// 用户相关 DTO(预留)
|
||||
2
src/domain/entities/mod.rs
Normal file
2
src/domain/entities/mod.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
pub mod users;
|
||||
|
||||
41
src/domain/entities/users.rs
Normal file
41
src/domain/entities/users.rs
Normal 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
3
src/domain/mod.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
pub mod dto;
|
||||
pub mod vo;
|
||||
pub mod entities;
|
||||
50
src/domain/vo/auth.rs
Normal file
50
src/domain/vo/auth.rs
Normal 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
56
src/domain/vo/mod.rs
Normal 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
1
src/domain/vo/user.rs
Normal file
@@ -0,0 +1 @@
|
||||
// 用户相关 VO(预留)
|
||||
Reference in New Issue
Block a user