Files
backend/README.md
lan 4b4980820f
Some checks failed
SonarQube Analysis / sonarqube (push) Has been cancelled
Test / test (push) Has been cancelled
Test / lint (push) Has been cancelled
Test / build (push) Has been cancelled
chore: 初始化仓库,排除二进制文件和覆盖率文件
2025-11-28 23:30:49 +08:00

564 lines
18 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# CarrotSkin Backend
一个功能完善的Minecraft皮肤站后端系统采用单体架构设计基于Go语言和Gin框架开发。
## ✨ 核心功能
-**用户认证系统** - 注册、登录、JWT认证、积分系统
-**邮箱验证系统** - 注册验证、找回密码、更换邮箱基于Redis的验证码
-**材质管理系统** - 皮肤/披风上传、搜索、收藏、下载统计
-**角色档案系统** - Minecraft角色创建、管理、RSA密钥生成
-**文件存储** - MinIO/RustFS对象存储集成、预签名URL上传
-**缓存系统** - Redis缓存、验证码存储、频率限制
-**权限管理** - Casbin RBAC权限控制
-**数据审计** - 登录日志、操作审计、下载记录
## 项目结构
```
backend/
├── cmd/ # 应用程序入口
│ └── server/ # 主服务器入口
│ └── main.go # 服务初始化、路由注册
├── internal/ # 私有应用代码
│ ├── handler/ # HTTP处理器函数式
│ │ ├── routes.go # 路由注册
│ │ ├── auth_handler.go
│ │ ├── user_handler.go
│ │ └── ...
│ ├── service/ # 业务逻辑服务(函数式)
│ │ ├── common.go # 公共声明jsoniter等
│ │ ├── user_service.go
│ │ └── ...
│ ├── repository/ # 数据访问层(函数式)
│ │ ├── user_repository.go
│ │ └── ...
│ ├── model/ # 数据模型GORM
│ ├── middleware/ # 中间件
│ └── types/ # 类型定义
├── pkg/ # 公共库代码
│ ├── auth/ # 认证授权
│ │ └── manager.go # JWT服务管理器
│ ├── config/ # 配置管理
│ │ └── manager.go # 配置管理器
│ ├── database/ # 数据库连接
│ │ ├── manager.go # 数据库管理器AutoMigrate
│ │ └── postgres.go # PostgreSQL连接
│ ├── email/ # 邮件服务
│ │ └── manager.go # 邮件服务管理器
│ ├── logger/ # 日志系统
│ │ └── manager.go # 日志管理器
│ ├── redis/ # Redis客户端
│ │ └── manager.go # Redis管理器
│ ├── storage/ # 文件存储(RustFS/MinIO)
│ │ └── manager.go # 存储管理器
│ ├── utils/ # 工具函数
│ └── validator/ # 数据验证
├── docs/ # API定义和文档Swagger
├── configs/ # 配置文件
│ └── casbin/ # Casbin权限配置
├── go.mod # Go模块依赖
├── go.sum # Go模块校验
├── start.sh # Linux/Mac启动脚本
├── .env # 环境变量配置
└── README.md # 项目说明
```
## 技术栈
- **语言**: Go 1.23+
- **框架**: Gin Web Framework
- **数据库**: PostgreSQL 15+ (GORM ORM)
- **缓存**: Redis 6.0+
- **存储**: RustFS/MinIO (S3兼容对象存储)
- **权限**: Casbin RBAC
- **日志**: Zap (结构化日志)
- **配置**: 环境变量 (.env) + Viper
- **JSON**: jsoniter (高性能JSON序列化)
- **文档**: Swagger/OpenAPI 3.0
## 快速开始
### 环境要求
- Go 1.21或更高版本
- PostgreSQL 15或更高版本
- Redis 6.0或更高版本
- RustFS 或其他 S3 兼容对象存储服务
### 安装和运行
1. **克隆项目**
```bash
git clone <repository-url>
cd CarrotSkin/backend
```
2. **安装依赖**
```bash
go mod download
```
3. **配置环境**
```bash
# 复制环境变量文件
cp .env.example .env
# 编辑 .env 文件配置数据库、RustFS等服务连接信息
```
**注意**:项目完全依赖 `.env` 文件进行配置,不再使用 YAML 配置文件,便于 Docker 容器化部署。
4. **初始化数据库**
```bash
# 创建数据库
createdb carrotskin
# 或者使用PostgreSQL客户端
psql -h localhost -U postgres -c "CREATE DATABASE carrotskin;"
```
> 💡 **提示**: 项目使用 GORM 的 `AutoMigrate` 功能自动创建和更新数据库表结构无需手动执行SQL脚本。首次启动时会自动创建所有表。
5. **运行服务**
方式一:使用启动脚本(推荐)
```bash
# Linux/Mac
chmod +x start.sh
./start.sh
# Windows
start.bat
```
方式二:直接运行
```bash
# 设置环境变量(或使用.env文件
export DATABASE_HOST=localhost
export DATABASE_PORT=5432
# ... 其他环境变量
# 运行服务
go run cmd/server/main.go
```
> 💡 **提示**:
> - 启动脚本会自动加载 `.env` 文件中的环境变量
> - 首次启动时会自动执行数据库迁移AutoMigrate
> - 如果对象存储未配置,服务仍可启动(相关功能不可用)
服务启动后:
- **服务地址**: http://localhost:8080
- **Swagger文档**: http://localhost:8080/swagger/index.html
- **健康检查**: http://localhost:8080/health
## API接口
### 认证相关
- `POST /api/v1/auth/register` - 用户注册(需邮箱验证码)
- `POST /api/v1/auth/login` - 用户登录(支持用户名/邮箱)
- `POST /api/v1/auth/send-code` - 发送验证码(注册/重置密码/更换邮箱)
- `POST /api/v1/auth/reset-password` - 重置密码(需验证码)
### 用户相关(需认证)
- `GET /api/v1/user/profile` - 获取用户信息
- `PUT /api/v1/user/profile` - 更新用户信息(头像、密码)
- `POST /api/v1/user/avatar/upload-url` - 生成头像上传URL
- `PUT /api/v1/user/avatar` - 更新头像
- `POST /api/v1/user/change-email` - 更换邮箱(需验证码)
### 材质管理
公开接口:
- `GET /api/v1/texture` - 搜索材质
- `GET /api/v1/texture/:id` - 获取材质详情
认证接口:
- `POST /api/v1/texture/upload-url` - 生成材质上传URL
- `POST /api/v1/texture` - 创建材质记录
- `PUT /api/v1/texture/:id` - 更新材质
- `DELETE /api/v1/texture/:id` - 删除材质
- `POST /api/v1/texture/:id/favorite` - 切换收藏状态
- `GET /api/v1/texture/my` - 我的材质列表
- `GET /api/v1/texture/favorites` - 我的收藏列表
### 角色档案
公开接口:
- `GET /api/v1/profile/:uuid` - 获取档案详情
认证接口:
- `POST /api/v1/profile` - 创建角色档案UUID由后端生成
- `GET /api/v1/profile` - 我的档案列表
- `PUT /api/v1/profile/:uuid` - 更新档案
- `DELETE /api/v1/profile/:uuid` - 删除档案
- `POST /api/v1/profile/:uuid/activate` - 设置活跃档案
### 系统配置
- `GET /api/v1/system/config` - 获取系统配置
## 配置管理
### 环境变量配置
项目**完全依赖环境变量**进行配置,不使用 YAML 配置文件,便于容器化部署:
1. **配置来源**: 环境变量 或 `.env` 文件
2. **环境变量格式**: 使用下划线分隔,全大写,如 `DATABASE_HOST`
3. **容器部署**: 直接在容器运行时设置环境变量即可
**主要环境变量**:
```bash
# 数据库配置
DATABASE_HOST=localhost
DATABASE_PORT=5432
DATABASE_USERNAME=postgres
DATABASE_PASSWORD=your_password
DATABASE_NAME=carrotskin
# Redis配置
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=your_redis_password
REDIS_DATABASE=0
REDIS_POOL_SIZE=10
# RustFS对象存储配置 (S3兼容)
RUSTFS_ENDPOINT=127.0.0.1:9000
RUSTFS_ACCESS_KEY=your_access_key
RUSTFS_SECRET_KEY=your_secret_key
RUSTFS_USE_SSL=false
RUSTFS_BUCKET_TEXTURES=carrot-skin-textures
RUSTFS_BUCKET_AVATARS=carrot-skin-avatars
# JWT配置
JWT_SECRET=your-jwt-secret-key
JWT_EXPIRE_HOURS=168
# 邮件配置
EMAIL_ENABLED=true
EMAIL_SMTP_HOST=smtp.example.com
EMAIL_SMTP_PORT=587
EMAIL_USERNAME=noreply@example.com
EMAIL_PASSWORD=your_email_password
EMAIL_FROM_NAME=CarrotSkin
```
**动态配置(存储在数据库中)**:
- 积分系统配置(注册奖励、签到积分等)
- 用户限制配置(最大材质数、最大角色数等)
- 网站设置(站点名称、公告、维护模式等)
完整的环境变量列表请参考 `.env.example` 文件。
### 数据库自动迁移
项目使用 GORM 的 `AutoMigrate` 功能自动管理数据库表结构:
- **首次启动**: 自动创建所有表结构
- **模型更新**: 自动添加新字段、索引等
- **类型转换**: 自动处理字段类型变更如枚举类型转为varchar
- **外键管理**: 自动管理外键关系
**注意事项**:
- 生产环境建议先备份数据库再执行迁移
- 某些复杂变更(如删除字段)可能需要手动处理
- 枚举类型在PostgreSQL中存储为varchar避免类型兼容问题
## 架构设计
### 面向过程的函数式架构
项目采用**面向过程的函数式架构**,摒弃不必要的面向对象抽象,使用独立函数和单例管理器模式,代码更简洁、可维护性更强:
```
┌─────────────────────────────────────┐
│ Handler 层 (函数) │ ← 路由处理、参数验证、响应格式化
├─────────────────────────────────────┤
│ Service 层 (函数) │ ← 业务逻辑、权限检查、数据验证
├─────────────────────────────────────┤
│ Repository 层 (函数) │ ← 数据库操作、关联查询
├─────────────────────────────────────┤
│ Manager 层 (单例模式) │ ← 核心依赖管理(线程安全)
│ - database.MustGetDB() │
│ - logger.MustGetLogger() │
│ - auth.MustGetJWTService() │
│ - redis.MustGetClient() │
│ - email.MustGetService() │
│ - storage.MustGetClient() │
│ - config.MustGetConfig() │
├──────────────┬──────────────────────┤
│ PostgreSQL │ Redis │ RustFS │ ← 数据存储层
└──────────────┴──────────────────────┘
```
### 架构特点
1. **函数式设计**: 所有业务逻辑以独立函数形式实现,无结构体方法,降低耦合度
2. **管理器模式**: 使用 `sync.Once` 实现线程安全的单例管理器,统一管理核心依赖
3. **按需获取**: 通过管理器函数按需获取依赖,避免链式传递,代码更清晰
4. **自动迁移**: 使用 GORM AutoMigrate 自动管理数据库表结构
5. **高性能**: 使用 jsoniter 替代标准库 json提升序列化性能
### 核心模块
1. **认证模块** (`internal/handler/auth_handler.go`)
- JWT令牌生成和验证通过 `auth.MustGetJWTService()` 获取)
- bcrypt密码加密
- 邮箱验证码注册
- 密码重置功能
- 登录日志记录(支持用户名/邮箱登录)
2. **用户模块** (`internal/handler/user_handler.go`)
- 用户信息管理
- 头像上传预签名URL通过 `storage.MustGetClient()` 获取)
- 密码修改(需原密码验证)
- 邮箱更换(需验证码)
- 积分系统
3. **邮箱验证模块** (`internal/service/verification_service.go`)
- 验证码生成6位数字
- 验证码存储Redis10分钟有效期通过 `redis.MustGetClient()` 获取)
- 发送频率限制1分钟
- 邮件发送HTML格式通过 `email.MustGetService()` 获取)
4. **材质模块** (`internal/handler/texture_handler.go`)
- 材质上传预签名URL
- 材质搜索和收藏
- Hash去重
- 下载统计
5. **档案模块** (`internal/handler/profile_handler.go`)
- Minecraft角色管理
- RSA密钥生成RSA-2048
- 活跃状态管理
- 档案数量限制
6. **管理器模块** (`pkg/*/manager.go`)
- 数据库管理器:`database.MustGetDB()` - 线程安全的数据库连接
- 日志管理器:`logger.MustGetLogger()` - 结构化日志实例
- JWT管理器`auth.MustGetJWTService()` - JWT服务实例
- Redis管理器`redis.MustGetClient()` - Redis客户端
- 邮件管理器:`email.MustGetService()` - 邮件服务
- 存储管理器:`storage.MustGetClient()` - 对象存储客户端
- 配置管理器:`config.MustGetConfig()` - 应用配置
### 技术特性
- **架构优势**:
- 面向过程的函数式设计,代码简洁清晰
- 单例管理器模式,线程安全的依赖管理
- 按需获取依赖,避免链式传递
- 自动数据库迁移AutoMigrate
- **安全性**:
- bcrypt密码加密、JWT令牌认证
- 邮箱验证码(注册/重置密码/更换邮箱)
- Casbin RBAC权限控制
- 频率限制(防暴力破解)
- **性能**:
- jsoniter 高性能JSON序列化替代标准库
- PostgreSQL索引优化
- Redis缓存验证码、会话等
- 预签名URL减轻服务器压力
- 连接池管理
- **可靠性**:
- 事务保证数据一致性
- 完整的错误处理和日志记录
- 优雅关闭和资源清理
- 对象存储连接失败时服务仍可启动
- **可扩展**:
- 清晰的函数式架构
- 管理器模式统一管理依赖
- 环境变量配置(便于容器化)
- **审计**:
- 登录日志(成功/失败)
- 操作审计
- 下载记录
## 开发指南
### 代码结构
- `cmd/server/` - 应用入口,初始化服务
- `internal/handler/` - HTTP请求处理
- `internal/service/` - 业务逻辑实现
- `internal/repository/` - 数据库操作
- `internal/model/` - 数据模型定义
- `internal/types/` - 请求/响应类型定义
- `internal/middleware/` - 中间件JWT、CORS、日志等
- `pkg/` - 可复用的公共库
### 开发规范
1. **代码风格**: 遵循Go官方代码规范使用 `gofmt` 格式化
2. **架构模式**: 使用函数式设计,避免不必要的结构体和方法
3. **依赖管理**: 通过管理器函数获取依赖(如 `database.MustGetDB()`),避免链式传递
4. **错误处理**: 使用统一的错误响应格式 (`model.NewErrorResponse`)
5. **日志记录**: 使用 Zap 结构化日志,通过 `logger.MustGetLogger()` 获取实例
6. **JSON序列化**: 使用 jsoniter 替代标准库 json提升性能
7. **RESTful API**: 遵循 REST 设计原则合理使用HTTP方法
### 添加新功能
1.`internal/model/` 定义数据模型GORM会自动迁移
2.`internal/repository/` 实现数据访问函数(使用 `database.MustGetDB()` 获取数据库)
3.`internal/service/` 实现业务逻辑函数(按需使用管理器获取依赖)
4.`internal/handler/` 实现HTTP处理函数使用管理器获取logger、jwtService等
5.`internal/handler/routes.go` 注册路由
**示例**:
```go
// Repository层
func FindUserByID(id uint) (*model.User, error) {
db := database.MustGetDB()
var user model.User
err := db.First(&user, id).Error
return &user, err
}
// Service层
func GetUserProfile(userID uint) (*model.User, error) {
logger := logger.MustGetLogger()
user, err := repository.FindUserByID(userID)
if err != nil {
logger.Error("获取用户失败", zap.Error(err))
return nil, err
}
return user, nil
}
// Handler层
func GetUserProfile(c *gin.Context) {
logger := logger.MustGetLogger()
jwtService := auth.MustGetJWTService()
// ... 处理逻辑
}
```
## 部署
### 本地开发
```bash
# 安装依赖
go mod download
# 配置环境变量(创建.env文件或直接export
cp .env.example .env
# 编辑 .env 文件
# 启动服务
# 方式1: 使用启动脚本
./start.sh # Linux/Mac
start.bat # Windows
# 方式2: 直接运行
go run cmd/server/main.go
```
**首次启动**:
- 会自动执行数据库迁移AutoMigrate创建所有表结构
- 如果对象存储未配置,会记录警告但服务仍可启动
- 检查日志确认所有服务初始化成功
### 生产部署
```bash
# 构建二进制文件
go build -o carrotskin-server cmd/server/main.go
# 运行服务
./carrotskin-server
```
### Docker部署
```bash
# 构建镜像
docker build -t carrotskin-backend:latest .
# 启动服务
docker-compose up -d
```
## 故障排查
### 常见问题
1. **数据库连接失败**
- 检查 `.env` 中的数据库配置(`DATABASE_HOST`, `DATABASE_PORT`, `DATABASE_USERNAME`, `DATABASE_PASSWORD`, `DATABASE_NAME`
- 确认PostgreSQL服务已启动
- 验证数据库用户权限
- 确认数据库已创建:`createdb carrotskin``psql -c "CREATE DATABASE carrotskin;"`
- 检查数据库迁移日志,确认表结构创建成功
2. **Redis连接失败**
- 检查Redis服务是否运行`redis-cli ping`
- 验证 `.env` 中的Redis配置
- 确认Redis密码是否正确
- 检查防火墙规则
3. **RustFS/MinIO连接失败**
- 检查存储服务是否运行
- 验证访问密钥是否正确(`RUSTFS_ACCESS_KEY`, `RUSTFS_SECRET_KEY`
- 确认存储桶是否已创建(`RUSTFS_BUCKET_TEXTURES`, `RUSTFS_BUCKET_AVATARS`
- 检查网络连接和端口(`RUSTFS_ENDPOINT`
- **注意**: 如果对象存储连接失败,服务仍可启动,但上传功能不可用
4. **邮件发送失败**
- 检查 `EMAIL_ENABLED=true`
- 验证SMTP服务器地址和端口
- 确认邮箱用户名和密码正确
- 检查邮件服务商是否需要开启SMTP
- 查看日志获取详细错误信息
5. **验证码相关问题**
- 验证码过期10分钟有效期
- 发送过于频繁1分钟限制
- Redis存储失败检查Redis连接
- 邮件未收到(检查垃圾邮件)
6. **JWT验证失败**
- 检查 `JWT_SECRET` 是否配置
- 验证令牌是否过期默认168小时
- 确认请求头中包含 `Authorization: Bearer <token>`
- Token格式是否正确
### 调试技巧
1. **查看日志**
```bash
# 实时查看日志
tail -f logs/app.log
# 搜索错误日志
grep "ERROR" logs/app.log
```
2. **测试Redis连接**
```bash
redis-cli -h localhost -p 6379 -a your_password
> PING
> KEYS *
```
3. **测试数据库连接**
```bash
psql -h localhost -U postgres -d carrotskin
\dt # 查看所有表
```
4. **测试邮件配置**
- 使用Swagger文档测试 `/api/v1/auth/send-code` 接口
- 检查邮件服务商是否限制发送频率
### 开发调试
启用详细日志:
```bash
# 在 .env 中设置
LOG_LEVEL=debug
SERVER_MODE=debug
```