13 KiB
13 KiB
档案API
**本文引用的文件** - [routes.go](file://internal/handler/routes.go) - [profile_handler.go](file://internal/handler/profile_handler.go) - [profile_service.go](file://internal/service/profile_service.go) - [profile_repository.go](file://internal/repository/profile_repository.go) - [common.go](file://internal/types/common.go) - [response.go](file://internal/model/response.go) - [profile.go](file://internal/model/profile.go) - [texture.go](file://internal/model/texture.go) - [texture_service.go](file://internal/service/texture_service.go) - [texture_repository.go](file://internal/repository/texture_repository.go) - [postgres.go](file://pkg/database/postgres.go)目录
简介
本文件面向开发者与集成方,系统化梳理“档案API”的设计与使用方法,覆盖以下能力:
- 档案的创建、查询、更新、删除与“活跃档案”设置
- 公开获取档案详情与需要认证的档案管理端点
- 档案与Minecraft用户UUID的关系、活跃档案的概念
- 档案列表的获取方式
- 完整的API使用示例,包括创建档案的请求体结构与获取档案详情的响应格式
- 档案与材质之间的关系
项目结构
档案API位于路由组 /api/v1/profile 下,采用“公开路由 + 认证路由”的分层设计:
- 公开路由:通过档案UUID获取档案详情
- 认证路由:需要携带JWT令牌,支持创建、查询列表、更新、删除、设置活跃档案
graph TB
subgraph "路由组 /api/v1/profile"
A["GET /:uuid<br/>公开:获取档案详情"]
subgraph "认证组"
B["POST /<br/>创建档案"]
C["GET /<br/>获取我的档案列表"]
D["PUT /:uuid<br/>更新档案"]
E["DELETE /:uuid<br/>删除档案"]
F["POST /:uuid/activate<br/>设置活跃档案"]
end
end
图表来源
章节来源
核心组件
- 路由注册:集中于路由文件,定义公开与认证端点
- 处理器:profile_handler 负责鉴权、参数解析、调用服务层并返回统一响应
- 服务层:profile_service 实现业务规则(如创建档案时生成UUID与RSA私钥、设置活跃状态、权限校验等)
- 仓储层:profile_repository 封装数据库操作(增删改查、统计、事务)
- 类型与模型:types 中定义请求/响应结构;model 中定义档案与材质模型及响应结构
- 数据库:通过GORM连接PostgreSQL,统一日志与连接池配置
章节来源
- routes.go
- profile_handler.go
- profile_service.go
- profile_repository.go
- common.go
- response.go
- profile.go
- texture.go
- postgres.go
架构总览
档案API遵循经典的三层架构:HTTP路由 -> 处理器 -> 服务 -> 仓储 -> 数据库。认证中间件确保仅持有有效令牌的用户可访问受保护端点。
graph TB
Client["客户端"] --> R["Gin 路由<br/>/api/v1/profile"]
R --> M["认证中间件"]
M --> H["处理器<br/>profile_handler"]
H --> S["服务层<br/>profile_service"]
S --> Repo["仓储层<br/>profile_repository"]
Repo --> DB["数据库<br/>PostgreSQL(GORM)"]
图表来源
详细组件分析
路由与端点
- 公开端点
- GET /api/v1/profile/:uuid:根据UUID获取档案详情
- 认证端点
- POST /api/v1/profile:创建档案
- GET /api/v1/profile:获取当前用户的所有档案列表
- PUT /api/v1/profile/:uuid:更新档案(可更新角色名、皮肤ID、披风ID)
- DELETE /api/v1/profile/:uuid:删除档案
- POST /api/v1/profile/:uuid/activate:设置活跃档案(同时将该用户其他档案设为非活跃)
章节来源
处理器与鉴权
- 认证中间件:所有认证端点均使用认证中间件,从上下文提取user_id
- 参数绑定:使用Gin的ShouldBindJSON进行请求体校验
- 统一响应:使用统一响应结构,错误码与消息标准化
章节来源
服务层业务规则
- 创建档案
- 校验用户存在且状态正常
- 校验角色名唯一
- 生成UUID与RSA私钥(PEM格式)
- 默认设置为活跃档案,并将该用户其他档案设为非活跃
- 更新档案
- 校验档案归属(仅档案所属用户可更新)
- 校验新角色名唯一
- 支持更新角色名、皮肤ID、披风ID
- 删除档案
- 校验档案归属
- 设置活跃档案
- 校验档案归属
- 使用事务将该用户其他档案设为非活跃,再将目标档案设为活跃
- 同步更新最后使用时间
- 档案数量限制
- 通过服务层检查当前用户档案数量是否超过上限
章节来源
仓储层与数据库
- 查询
- FindProfileByUUID:按UUID查询并预加载皮肤与披风
- FindProfilesByUserID:按用户ID查询并预加载皮肤与披风,按创建时间倒序
- FindProfileByName:按角色名查询
- 更新
- UpdateProfile、UpdateProfileFields
- 删除
- DeleteProfile(按UUID删除)
- 统计
- CountProfilesByUserID
- 活跃状态
- SetActiveProfile:事务内将该用户其他档案设为非活跃,再将目标档案设为活跃
- 最后使用时间
- UpdateProfileLastUsedAt
章节来源
模型与类型
- 档案模型
- 字段:UUID、用户ID、角色名、皮肤ID、披风ID、活跃状态、最后使用时间、创建/更新时间
- 关联:User、Skin(Texture)、Cape(Texture)
- 档案响应结构
- ProfileResponse:包含UUID、角色名、textures(皮肤/披风)、活跃状态、最后使用时间、创建时间
- ProfileTexturesData:包含SKIN与CAPE两个可选字段
- ProfileTexture:包含URL与可选metadata(如模型类型)
- 请求/响应类型
- CreateProfileRequest:name(必填,1-16字符)
- UpdateProfileRequest:name(可选)、skin_id(可选)、cape_id(可选)
- ProfileInfo:用于列表与详情的统一返回字段
章节来源
档案与材质的关系
- 档案可关联两种材质:皮肤(SkinID)与披风(CapeID)
- 材质模型包含类型(SKIN/CAPE)、URL、哈希、大小、公开状态等
- 服务层与仓储层均支持对材质的创建、查询、更新、删除、收藏等操作,但这些属于独立的材质API范畴
章节来源
API使用示例
-
创建档案
- 方法与路径:POST /api/v1/profile
- 认证:需要JWT
- 请求体结构(CreateProfileRequest)
- name:字符串,必填,长度1-16
- 成功响应:返回ProfileInfo(包含UUID、用户ID、角色名、皮肤ID、披风ID、活跃状态、最后使用时间、创建/更新时间)
- 常见错误:400(参数错误/达到档案数量上限)、401(未授权)、500(服务器错误)
-
获取我的档案列表
- 方法与路径:GET /api/v1/profile
- 认证:需要JWT
- 成功响应:数组,元素为ProfileInfo
-
获取档案详情
- 方法与路径:GET /api/v1/profile/{uuid}
- 认证:公开端点,无需JWT
- 成功响应:ProfileInfo
-
更新档案
- 方法与路径:PUT /api/v1/profile/{uuid}
- 认证:需要JWT
- 请求体结构(UpdateProfileRequest)
- name:字符串,可选,长度1-16
- skin_id:整数,可选
- cape_id:整数,可选
- 成功响应:ProfileInfo
-
删除档案
- 方法与路径:DELETE /api/v1/profile/{uuid}
- 认证:需要JWT
- 成功响应:{"message":"删除成功"}
-
设置活跃档案
- 方法与路径:POST /api/v1/profile/{uuid}/activate
- 认证:需要JWT
- 成功响应:{"message":"设置成功"}
章节来源
活跃档案概念
- 每个用户在同一时刻只能有一个“活跃档案”
- 当创建新档案或切换活跃档案时,系统会将该用户其他档案设为非活跃
- 设置活跃档案会同步更新最后使用时间
章节来源
档案列表获取方式
- 通过认证端点 GET /api/v1/profile 获取当前用户的所有档案
- 返回顺序按创建时间倒序
章节来源
档案与Minecraft用户UUID的关系
- 档案模型包含UUID字段,用于标识Minecraft角色
- 档案与用户通过user_id关联
- 公开端点通过UUID获取档案详情,不涉及用户身份
章节来源
依赖分析
- 路由到处理器:路由文件注册各端点,处理器负责鉴权与参数解析
- 处理器到服务:处理器调用服务层实现业务逻辑
- 服务到仓储:服务层封装业务规则并委托仓储层执行数据库操作
- 仓储到数据库:仓储层通过GORM访问PostgreSQL
graph LR
Routes["routes.go"] --> Handler["profile_handler.go"]
Handler --> Service["profile_service.go"]
Service --> Repo["profile_repository.go"]
Repo --> DB["postgres.go"]
图表来源
性能考虑
- 预加载策略:查询档案时预加载皮肤与披风,减少N+1查询风险
- 分页与排序:列表查询按创建时间倒序,避免全量扫描
- 事务一致性:设置活跃档案使用事务,保证原子性
- 连接池:数据库连接池配置合理,建议结合实际负载调整
章节来源
故障排查指南
- 未授权
- 现象:返回401
- 排查:确认JWT是否正确传递与有效
- 参数错误
- 现象:返回400
- 排查:检查请求体字段是否符合长度与类型要求
- 无权操作
- 现象:返回403
- 排查:确认操作的档案是否属于当前用户
- 资源不存在
- 现象:返回404
- 排查:确认UUID是否正确、档案是否被删除
- 达到上限
- 现象:返回400
- 排查:检查当前用户档案数量与系统限制
章节来源
结论
档案API以清晰的公开/认证分层设计,结合严格的鉴权与参数校验,提供了完整的Minecraft角色档案生命周期管理能力。通过服务层的业务规则与仓储层的事务保障,系统在一致性与扩展性方面具备良好基础。建议在生产环境中配合限流、缓存与监控进一步优化性能与稳定性。
附录
API端点一览
- 公开
- GET /api/v1/profile/:uuid
- 认证
- POST /api/v1/profile
- GET /api/v1/profile
- PUT /api/v1/profile/:uuid
- DELETE /api/v1/profile/:uuid
- POST /api/v1/profile/:uuid/activate
章节来源