# 用户模型 **本文引用的文件** - [internal/model/user.go](file://internal/model/user.go) - [internal/repository/user_repository.go](file://internal/repository/user_repository.go) - [internal/service/user_service.go](file://internal/service/user_service.go) - [pkg/auth/password.go](file://pkg/auth/password.go) - [pkg/database/postgres.go](file://pkg/database/postgres.go) - [internal/model/profile.go](file://internal/model/profile.go) - [internal/model/system_config.go](file://internal/model/system_config.go) - [internal/service/serialize_service.go](file://internal/service/serialize_service.go) - [internal/service/user_service_test.go](file://internal/service/user_service_test.go) - [internal/repository/user_repository_test.go](file://internal/repository/user_repository_test.go) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖分析](#依赖分析) 7. [性能考虑](#性能考虑) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 简介 本文件聚焦于用户模型 User 的字段定义、数据类型、GORM 标签与业务含义,以及与 UserPointLog、UserLoginLog 的关联关系。同时提供用户状态流转图、积分系统使用模式、属性扩展(Properties JSONB)的实践建议,并给出数据验证规则、唯一性约束与索引优化建议,最后结合代码路径说明如何安全地处理密码存储与敏感信息脱敏。 ## 项目结构 围绕用户模型的关键文件分布如下: - 模型层:用户、积分日志、登录日志、档案等 - 仓储层:用户 CRUD、积分更新、登录日志创建等 - 服务层:注册、登录、修改密码、更换邮箱等业务流程 - 安全层:密码哈希与校验 - 数据库层:PostgreSQL 连接与配置 ```mermaid graph TB subgraph "模型层" M_User["User
internal/model/user.go"] M_PointLog["UserPointLog
internal/model/user.go"] M_LoginLog["UserLoginLog
internal/model/user.go"] M_Profile["Profile
internal/model/profile.go"] end subgraph "仓储层" R_UserRepo["UserRepository
internal/repository/user_repository.go"] end subgraph "服务层" S_UserSvc["UserService
internal/service/user_service.go"] S_Serialize["SerializeService
internal/service/serialize_service.go"] end subgraph "安全层" A_Password["Password Hash/Check
pkg/auth/password.go"] end subgraph "数据库层" D_Postgres["PostgreSQL连接
pkg/database/postgres.go"] end S_UserSvc --> R_UserRepo R_UserRepo --> D_Postgres S_UserSvc --> A_Password S_Serialize --> M_User M_User --> M_PointLog M_User --> M_LoginLog M_Profile --> M_User ``` 图表来源 - [internal/model/user.go](file://internal/model/user.go#L1-L70) - [internal/repository/user_repository.go](file://internal/repository/user_repository.go#L1-L137) - [internal/service/user_service.go](file://internal/service/user_service.go#L1-L249) - [pkg/auth/password.go](file://pkg/auth/password.go#L1-L21) - [pkg/database/postgres.go](file://pkg/database/postgres.go#L1-L74) - [internal/model/profile.go](file://internal/model/profile.go#L1-L64) - [internal/service/serialize_service.go](file://internal/service/serialize_service.go#L86-L97) 章节来源 - [internal/model/user.go](file://internal/model/user.go#L1-L70) - [internal/repository/user_repository.go](file://internal/repository/user_repository.go#L1-L137) - [internal/service/user_service.go](file://internal/service/user_service.go#L1-L249) - [pkg/auth/password.go](file://pkg/auth/password.go#L1-L21) - [pkg/database/postgres.go](file://pkg/database/postgres.go#L1-L74) - [internal/model/profile.go](file://internal/model/profile.go#L1-L64) - [internal/service/serialize_service.go](file://internal/service/serialize_service.go#L86-L97) ## 核心组件 本节对 User 结构体及其关键字段进行逐项解析,涵盖字段类型、GORM 标签、默认值、业务语义与约束。 - 字段与类型 - ID:整型自增主键,用于唯一标识用户 - Username:字符串,长度限制与唯一索引约束 - Password:字符串,存储哈希后的密码,JSON 中不返回 - Email:字符串,长度限制与唯一索引约束 - Avatar:字符串,头像 URL,默认空串 - Points:整型,积分余额,默认 0 - Role:字符串,角色,默认 "user" - Status:短整型,状态枚举,默认 1(正常),0(禁用),-1(删除) - Properties:字符串,映射 PostgreSQL 的 JSONB 类型,用于扩展属性 - LastLoginAt:时间戳,最近登录时间 - CreatedAt/UpdatedAt:时间戳,默认 CURRENT_TIMESTAMP - 约束与索引 - Username、Email 唯一索引 - UserPointLog、UserLoginLog 的 UserID、IP 地址、is_success 等字段建立索引 - Properties 以 JSONB 存储,便于灵活扩展 - 业务含义 - 注册时默认 Role 为 "user",Status 为 1(正常),Points 为 0 - 登录成功后更新 LastLoginAt - 删除采用软删除,将 Status 设为 -1 章节来源 - [internal/model/user.go](file://internal/model/user.go#L1-L26) - [internal/model/user.go](file://internal/model/user.go#L28-L70) - [internal/service/user_service.go](file://internal/service/user_service.go#L12-L67) - [internal/service/user_service.go](file://internal/service/user_service.go#L111-L121) - [internal/repository/user_repository.go](file://internal/repository/user_repository.go#L71-L75) ## 架构总览 用户模型在系统中的交互流程如下: ```mermaid sequenceDiagram participant Client as "客户端" participant Handler as "处理器/控制器" participant Service as "UserService" participant Repo as "UserRepository" participant DB as "数据库(PostgreSQL)" participant Auth as "Password(哈希/校验)" Client->>Handler : "注册/登录请求" Handler->>Service : "调用业务方法" Service->>Auth : "注册时哈希密码" Auth-->>Service : "返回哈希值" Service->>Repo : "创建用户/保存用户" Repo->>DB : "执行SQL" DB-->>Repo : "返回结果" Repo-->>Service : "返回用户对象" Service-->>Handler : "返回用户与令牌" Handler-->>Client : "响应(不含敏感字段)" ``` 图表来源 - [internal/service/user_service.go](file://internal/service/user_service.go#L12-L67) - [pkg/auth/password.go](file://pkg/auth/password.go#L1-L21) - [internal/repository/user_repository.go](file://internal/repository/user_repository.go#L11-L15) - [pkg/database/postgres.go](file://pkg/database/postgres.go#L1-L74) ## 详细组件分析 ### User 结构体与字段详解 - ID - 类型:整型自增主键 - 用途:全局唯一标识 - GORM 标签:主键、自增 - Username - 类型:字符串,长度限制,唯一索引 - 用途:登录凭据之一 - 约束:唯一性 - Password - 类型:字符串,存储 bcrypt 哈希 - 用途:登录凭据 - 安全:JSON 中不返回 - Email - 类型:字符串,长度限制,唯一索引 - 用途:找回密码、通知等 - 约束:唯一性 - Avatar - 类型:字符串,URL - 默认:空串 - Points - 类型:整型 - 默认:0 - 用途:积分系统余额 - Role - 类型:字符串 - 默认:"user" - Status - 类型:短整型 - 默认:1(正常) - 取值:1 正常;0 禁用;-1 删除(软删) - Properties - 类型:字符串,映射 PostgreSQL 的 JSONB - 用途:扩展属性,如权限、配置等 - LastLoginAt - 类型:时间戳 - 用途:记录最近登录时间 - CreatedAt/UpdatedAt - 类型:时间戳,默认 CURRENT_TIMESTAMP 章节来源 - [internal/model/user.go](file://internal/model/user.go#L1-L26) ### User 与 UserPointLog 的关联 - 外键关系 - UserPointLog.UserID 引用 User.ID - UserPointLog.OperatorID 可选,指向操作者用户 - 级联行为 - 代码中未显式声明级联删除/更新,遵循 GORM 默认行为 - 由于 User 采用软删除(Status=-1),建议在业务层避免直接删除用户,防止破坏积分日志的完整性 - 日志字段 - ChangeType:变更类型(如 EARN、SPEND、ADMIN_ADJUST) - Amount/BalanceBefore/BalanceAfter:金额与前后余额 - Reason/ReferenceType/ReferenceID:原因与关联对象类型/ID - OperatorID:可选,记录管理员操作者 ```mermaid classDiagram class User { +int64 ID +string Username +string Email +string Avatar +int Points +string Role +int16 Status +string Properties +time.Time LastLoginAt +time.Time CreatedAt +time.Time UpdatedAt } class UserPointLog { +int64 ID +int64 UserID +string ChangeType +int Amount +int BalanceBefore +int BalanceAfter +string Reason +string ReferenceType +*int64 ReferenceID +*int64 OperatorID +time.Time CreatedAt } class UserLoginLog { +int64 ID +int64 UserID +string IPAddress +string UserAgent +string LoginMethod +bool IsSuccess +string FailureReason +time.Time CreatedAt } User "1" <-- "many" UserPointLog : "外键UserID" User "1" <-- "many" UserLoginLog : "外键UserID" User "1" <-- "many" UserPointLog : "外键OperatorID(可选)" ``` 图表来源 - [internal/model/user.go](file://internal/model/user.go#L28-L70) 章节来源 - [internal/model/user.go](file://internal/model/user.go#L28-L70) - [internal/repository/user_repository.go](file://internal/repository/user_repository.go#L89-L124) ### User 与 UserLoginLog 的关联 - 外键关系 - UserLoginLog.UserID 引用 User.ID - 日志字段 - IPAddress:inet 类型,记录登录 IP - UserAgent:文本 - LoginMethod:默认 PASSWORD - IsSuccess/FailureReason:登录成功与否及原因 - 索引 - UserID、IPAddress、IsSuccess 建有索引,CreatedAt 建有复合索引并按降序排序 章节来源 - [internal/model/user.go](file://internal/model/user.go#L52-L70) - [internal/repository/user_repository.go](file://internal/repository/user_repository.go#L77-L87) ### 用户状态流转图 - 正常(1):可登录、可消费积分 - 禁用(0):禁止登录,不影响积分 - 删除(-1):软删除,查询时默认过滤该状态 ```mermaid stateDiagram-v2 [*] --> 正常 正常 --> 禁用 : "管理员操作" 正常 --> 删除 : "软删除" 禁用 --> 正常 : "恢复" 禁用 --> 删除 : "软删除" 删除 --> 正常 : "不可恢复" 删除 --> 禁用 : "不可恢复" ``` 图表来源 - [internal/model/user.go](file://internal/model/user.go#L14-L16) - [internal/repository/user_repository.go](file://internal/repository/user_repository.go#L71-L75) ### 积分系统(Points)使用模式 - 初始化:注册时 Points 默认 0 - 更新:通过 UpdateUserPoints 在事务中完成,先读取当前余额,计算新余额,再写入并创建日志 - 校验:若新余额小于 0,则回滚并返回错误 - 日志:记录变更类型、金额、前后余额、原因、关联对象与操作者 ```mermaid flowchart TD Start(["开始"]) --> ReadUser["读取用户当前积分"] ReadUser --> Calc["计算新余额 = 当前 + 变更金额"] Calc --> Check{"新余额 >= 0 ?"} Check --> |否| Rollback["回滚事务并返回错误"] Check --> |是| Update["更新用户积分"] Update --> Log["创建积分日志"] Log --> End(["结束"]) Rollback --> End ``` 图表来源 - [internal/repository/user_repository.go](file://internal/repository/user_repository.go#L89-L124) 章节来源 - [internal/repository/user_repository.go](file://internal/repository/user_repository.go#L89-L124) - [internal/service/user_service.go](file://internal/service/user_service.go#L12-L67) ### 属性扩展(Properties JSONB)使用模式 - 存储:Properties 为字符串,映射 PostgreSQL 的 JSONB 类型 - 用途:存放扩展字段,如权限、配置等 - 序列化:在序列化时可直接返回 Properties,但需注意敏感信息脱敏 - 示例路径:序列化用户时将 Properties 原样返回,供上层处理 章节来源 - [internal/model/user.go](file://internal/model/user.go#L16-L17) - [internal/service/serialize_service.go](file://internal/service/serialize_service.go#L86-L97) ### 数据验证规则、唯一性约束与索引优化建议 - 验证规则 - 用户名非空,长度范围(建议在服务层补充) - 邮箱非空且包含 @ 符号(建议在服务层补充) - 密码非空(建议在服务层补充) - 唯一性约束 - Username、Email 唯一索引 - 索引优化建议 - User:Username、Email 唯一索引(已具备) - UserPointLog:UserID、CreatedAt(降序)、ReferenceType/ReferenceID(可选) - UserLoginLog:UserID、IPAddress、IsSuccess、CreatedAt(降序) - 状态查询 - 查询用户时默认排除 Status=-1(软删除) 章节来源 - [internal/model/user.go](file://internal/model/user.go#L9-L21) - [internal/model/user.go](file://internal/model/user.go#L31-L41) - [internal/model/user.go](file://internal/model/user.go#L55-L61) - [internal/repository/user_repository.go](file://internal/repository/user_repository.go#L18-L29) - [internal/repository/user_repository.go](file://internal/repository/user_repository.go#L31-L43) - [internal/repository/user_repository.go](file://internal/repository/user_repository.go#L45-L57) - [internal/service/user_service_test.go](file://internal/service/user_service_test.go#L109-L164) - [internal/repository/user_repository_test.go](file://internal/repository/user_repository_test.go#L1-L69) ### 密码存储与敏感信息脱敏 - 密码存储 - 注册时使用 bcrypt 哈希存储 - 登录时使用 bcrypt 校验 - User.Password 在 JSON 响应中不返回 - 敏感信息脱敏 - Password 字段在 JSON 中标记为不输出 - Properties 作为 JSONB 返回,需在上层进行脱敏处理(例如移除敏感键或替换为占位符) - 头像 URL、邮箱等字段在返回前可根据需要进行脱敏策略 章节来源 - [pkg/auth/password.go](file://pkg/auth/password.go#L1-L21) - [internal/service/user_service.go](file://internal/service/user_service.go#L12-L67) - [internal/service/user_service.go](file://internal/service/user_service.go#L141-L164) - [internal/model/user.go](file://internal/model/user.go#L10-L12) - [internal/service/serialize_service.go](file://internal/service/serialize_service.go#L86-L97) ## 依赖分析 - 组件耦合 - UserService 依赖 UserRepository、JWT 服务与 Password 工具 - UserRepository 依赖数据库连接 - User 模型与 UserPointLog、UserLoginLog 通过外键关联 - 外键与级联 - 未显式声明级联,遵循 GORM 默认行为 - 建议在业务层避免直接物理删除用户,以保持积分与登录日志的完整性 - 外部依赖 - PostgreSQL 驱动与连接池配置 - bcrypt 密码哈希 ```mermaid graph LR S_UserSvc["UserService"] --> R_UserRepo["UserRepository"] S_UserSvc --> A_Password["Password"] R_UserRepo --> D_Postgres["PostgreSQL"] M_User["User"] --> M_PointLog["UserPointLog"] M_User --> M_LoginLog["UserLoginLog"] ``` 图表来源 - [internal/service/user_service.go](file://internal/service/user_service.go#L1-L249) - [internal/repository/user_repository.go](file://internal/repository/user_repository.go#L1-L137) - [pkg/auth/password.go](file://pkg/auth/password.go#L1-L21) - [pkg/database/postgres.go](file://pkg/database/postgres.go#L1-L74) - [internal/model/user.go](file://internal/model/user.go#L1-L70) 章节来源 - [internal/service/user_service.go](file://internal/service/user_service.go#L1-L249) - [internal/repository/user_repository.go](file://internal/repository/user_repository.go#L1-L137) - [pkg/auth/password.go](file://pkg/auth/password.go#L1-L21) - [pkg/database/postgres.go](file://pkg/database/postgres.go#L1-L74) - [internal/model/user.go](file://internal/model/user.go#L1-L70) ## 性能考虑 - 索引设计 - User:Username、Email 唯一索引 - UserPointLog:UserID、CreatedAt(降序)、ReferenceType/ReferenceID(可选) - UserLoginLog:UserID、IPAddress、IsSuccess、CreatedAt(降序) - 查询过滤 - 查询用户时默认排除软删除(Status!=-1),减少扫描 - 事务与并发 - 积分更新使用事务,保证一致性 - 缓存与限流 - 登录失败与成功日志可配合缓存与限流策略,降低暴力破解风险 [本节为通用指导,无需列出具体文件来源] ## 故障排查指南 - 登录失败 - 检查用户是否存在与状态是否为 1 - 校验密码哈希是否正确 - 记录失败日志以便审计 - 积分不足 - 确认余额计算逻辑与事务一致性 - 检查日志是否正确记录 - 软删除影响 - 查询用户时默认排除 Status=-1 - 若出现“用户不存在”,确认是否被软删除 章节来源 - [internal/service/user_service.go](file://internal/service/user_service.go#L70-L121) - [internal/repository/user_repository.go](file://internal/repository/user_repository.go#L71-L75) - [internal/repository/user_repository.go](file://internal/repository/user_repository.go#L89-L124) - [internal/repository/user_repository_test.go](file://internal/repository/user_repository_test.go#L1-L69) ## 结论 User 模型通过明确的字段定义、GORM 标签与业务约束,支撑了注册、登录、积分与日志等核心功能。通过软删除与事务化的积分更新,确保了数据一致性与可审计性。建议在服务层补充输入验证与脱敏策略,并根据业务增长持续优化索引与查询路径。 [本节为总结性内容,无需列出具体文件来源] ## 附录 - 相关模型与配置 - Profile 模型与 User 的关联 - SystemConfig 模型(系统配置) - 序列化与脱敏 - SerializeUser 返回 Properties,需在上层进行脱敏处理 章节来源 - [internal/model/profile.go](file://internal/model/profile.go#L1-L64) - [internal/model/system_config.go](file://internal/model/system_config.go#L1-L42) - [internal/service/serialize_service.go](file://internal/service/serialize_service.go#L86-L97)