feat: 完成Rust User API完整开发
Some checks failed
Deploy to Production / Run Tests (push) Failing after 16m35s
Deploy to Production / Security Scan (push) Has been skipped
Deploy to Production / Build Docker Image (push) Has been skipped
Deploy to Production / Deploy to Staging (push) Has been skipped
Deploy to Production / Deploy to Production (push) Has been skipped
Deploy to Production / Notify Results (push) Successful in 31s

 新功能:
- SQLite数据库集成和持久化存储
- 数据库迁移系统和版本管理
- API分页功能和高效查询
- 用户搜索和过滤机制
- 完整的RBAC角色权限系统
- 结构化日志记录和系统监控
- API限流和多层安全防护
- Docker容器化和生产部署配置

🔒 安全特性:
- JWT认证和授权
- 限流和防暴力破解
- 安全头和CORS配置
- 输入验证和XSS防护
- 审计日志和安全监控

📊 监控和运维:
- Prometheus指标收集
- 健康检查和系统监控
- 自动化备份和恢复
- 完整的运维文档和脚本
- CI/CD流水线配置

🚀 部署支持:
- 多环境Docker配置
- 生产环境部署指南
- 性能优化和安全加固
- 故障排除和应急响应
- 自动化运维脚本

📚 文档完善:
- API使用文档
- 部署检查清单
- 运维操作手册
- 性能和安全指南
- 故障排除指南
This commit is contained in:
2025-08-07 16:03:32 +08:00
parent cf01d557b9
commit bb9d7a869d
45 changed files with 8433 additions and 85 deletions

View File

@@ -7,6 +7,7 @@ use chrono::{DateTime, Utc};
use crate::models::user::User;
use crate::models::pagination::PaginationParams;
use crate::models::search::UserSearchParams;
use crate::models::role::UserRole;
use crate::utils::errors::ApiError;
use crate::storage::{UserStore, MigrationManager};
@@ -50,14 +51,15 @@ impl DatabaseUserStore {
async fn create_user_impl(&self, user: User) -> Result<User, ApiError> {
let result = sqlx::query(
r#"
INSERT INTO users (id, username, email, password_hash, created_at, updated_at)
VALUES (?, ?, ?, ?, ?, ?)
INSERT INTO users (id, username, email, password_hash, role, created_at, updated_at)
VALUES (?, ?, ?, ?, ?, ?, ?)
"#,
)
.bind(user.id.to_string())
.bind(&user.username)
.bind(&user.email)
.bind(&user.password_hash)
.bind(user.role.as_str())
.bind(user.created_at.to_rfc3339())
.bind(user.updated_at.to_rfc3339())
.execute(&self.pool)
@@ -75,7 +77,7 @@ impl DatabaseUserStore {
/// 根据 ID 获取用户
async fn get_user_impl(&self, id: &Uuid) -> Result<Option<User>, ApiError> {
let result = sqlx::query(
"SELECT id, username, email, password_hash, created_at, updated_at FROM users WHERE id = ?"
"SELECT id, username, email, password_hash, role, created_at, updated_at FROM users WHERE id = ?"
)
.bind(id.to_string())
.fetch_optional(&self.pool)
@@ -83,12 +85,16 @@ impl DatabaseUserStore {
match result {
Ok(Some(row)) => {
let role_str: String = row.get("role");
let role = UserRole::from_str(&role_str).unwrap_or_default();
let user = User {
id: Uuid::parse_str(&row.get::<String, _>("id"))
.map_err(|e| ApiError::InternalError(format!("UUID 解析错误: {}", e)))?,
username: row.get("username"),
email: row.get("email"),
password_hash: row.get("password_hash"),
role,
created_at: DateTime::parse_from_rfc3339(&row.get::<String, _>("created_at"))
.map_err(|e| ApiError::InternalError(format!("时间解析错误: {}", e)))?
.with_timezone(&Utc),
@@ -106,7 +112,7 @@ impl DatabaseUserStore {
/// 根据用户名获取用户
async fn get_user_by_username_impl(&self, username: &str) -> Result<Option<User>, ApiError> {
let result = sqlx::query(
"SELECT id, username, email, password_hash, created_at, updated_at FROM users WHERE username = ?"
"SELECT id, username, email, password_hash, role, created_at, updated_at FROM users WHERE username = ?"
)
.bind(username)
.fetch_optional(&self.pool)
@@ -114,12 +120,16 @@ impl DatabaseUserStore {
match result {
Ok(Some(row)) => {
let role_str: String = row.get("role");
let role = UserRole::from_str(&role_str).unwrap_or_default();
let user = User {
id: Uuid::parse_str(&row.get::<String, _>("id"))
.map_err(|e| ApiError::InternalError(format!("UUID 解析错误: {}", e)))?,
username: row.get("username"),
email: row.get("email"),
password_hash: row.get("password_hash"),
role,
created_at: DateTime::parse_from_rfc3339(&row.get::<String, _>("created_at"))
.map_err(|e| ApiError::InternalError(format!("时间解析错误: {}", e)))?
.with_timezone(&Utc),
@@ -137,7 +147,7 @@ impl DatabaseUserStore {
/// 获取所有用户
async fn list_users_impl(&self) -> Result<Vec<User>, ApiError> {
let result = sqlx::query(
"SELECT id, username, email, password_hash, created_at, updated_at FROM users ORDER BY created_at DESC"
"SELECT id, username, email, password_hash, role, created_at, updated_at FROM users ORDER BY created_at DESC"
)
.fetch_all(&self.pool)
.await;
@@ -146,12 +156,16 @@ impl DatabaseUserStore {
Ok(rows) => {
let mut users = Vec::new();
for row in rows {
let role_str: String = row.get("role");
let role = UserRole::from_str(&role_str).unwrap_or_default();
let user = User {
id: Uuid::parse_str(&row.get::<String, _>("id"))
.map_err(|e| ApiError::InternalError(format!("UUID 解析错误: {}", e)))?,
username: row.get("username"),
email: row.get("email"),
password_hash: row.get("password_hash"),
role,
created_at: DateTime::parse_from_rfc3339(&row.get::<String, _>("created_at"))
.map_err(|e| ApiError::InternalError(format!("时间解析错误: {}", e)))?
.with_timezone(&Utc),
@@ -181,7 +195,7 @@ impl DatabaseUserStore {
// 然后获取分页数据
let result = sqlx::query(
"SELECT id, username, email, password_hash, created_at, updated_at
"SELECT id, username, email, password_hash, role, created_at, updated_at
FROM users
ORDER BY created_at DESC
LIMIT ? OFFSET ?"
@@ -195,12 +209,16 @@ impl DatabaseUserStore {
Ok(rows) => {
let mut users = Vec::new();
for row in rows {
let role_str: String = row.get("role");
let role = UserRole::from_str(&role_str).unwrap_or_default();
let user = User {
id: Uuid::parse_str(&row.get::<String, _>("id"))
.map_err(|e| ApiError::InternalError(format!("UUID 解析错误: {}", e)))?,
username: row.get("username"),
email: row.get("email"),
password_hash: row.get("password_hash"),
role,
created_at: DateTime::parse_from_rfc3339(&row.get::<String, _>("created_at"))
.map_err(|e| ApiError::InternalError(format!("时间解析错误: {}", e)))?
.with_timezone(&Utc),
@@ -292,7 +310,7 @@ impl DatabaseUserStore {
// 然后获取分页数据
let data_query = format!(
"SELECT id, username, email, password_hash, created_at, updated_at FROM users {} {} LIMIT ? OFFSET ?",
"SELECT id, username, email, password_hash, role, created_at, updated_at FROM users {} {} LIMIT ? OFFSET ?",
where_clause, order_clause
);
@@ -314,12 +332,16 @@ impl DatabaseUserStore {
Ok(rows) => {
let mut users = Vec::new();
for row in rows {
let role_str: String = row.get("role");
let role = UserRole::from_str(&role_str).unwrap_or_default();
let user = User {
id: Uuid::parse_str(&row.get::<String, _>("id"))
.map_err(|e| ApiError::InternalError(format!("UUID 解析错误: {}", e)))?,
username: row.get("username"),
email: row.get("email"),
password_hash: row.get("password_hash"),
role,
created_at: DateTime::parse_from_rfc3339(&row.get::<String, _>("created_at"))
.map_err(|e| ApiError::InternalError(format!("时间解析错误: {}", e)))?
.with_timezone(&Utc),
@@ -339,13 +361,14 @@ impl DatabaseUserStore {
async fn update_user_impl(&self, id: &Uuid, updated_user: User) -> Result<Option<User>, ApiError> {
let result = sqlx::query(
r#"
UPDATE users
SET username = ?, email = ?, updated_at = ?
UPDATE users
SET username = ?, email = ?, role = ?, updated_at = ?
WHERE id = ?
"#,
)
.bind(&updated_user.username)
.bind(&updated_user.email)
.bind(updated_user.role.as_str())
.bind(updated_user.updated_at.to_rfc3339())
.bind(id.to_string())
.execute(&self.pool)