identity_repo.go 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. // IdentityRepo 登录身份仓储(t_identity,一人多登录方式,(type,identifier,appid) 唯一·v1.2)。
  2. //
  3. // 平台级访问(同 user_repo.go 包注释):不继承 scope.BaseRepo,裸 *gorm.DB。
  4. // 登录主链路的核心查询:按 (type, identifier, appid) 唯一定位 → 取 canonical_user_id → 再查 user。
  5. // v1.2:唯一键从 (type,identifier) 扩为 (type,identifier,appid)——非微信类型 appid 恒 "",
  6. // 微信类型 appid 必填(per-appid 唯一,P0-07 M5 实测同 appid 同 openid 重复=0)。
  7. package repository
  8. import (
  9. "context"
  10. "gorm.io/gorm"
  11. "yuansiwei/unified-backend/internal/identity/model"
  12. )
  13. // IdentityRepo 登录身份仓储。
  14. type IdentityRepo struct {
  15. db *gorm.DB
  16. }
  17. // NewIdentityRepo 构造登录身份仓储。
  18. //
  19. // 入参:db *gorm.DB:数据库句柄(必填)。
  20. // 出参:*IdentityRepo:就绪仓储。
  21. func NewIdentityRepo(db *gorm.DB) *IdentityRepo {
  22. return &IdentityRepo{db: db}
  23. }
  24. // GetByTypeIdentifierAppID 按 (type, identifier, appid) 唯一键取登录身份记录(v1.2)。
  25. //
  26. // 入参:
  27. // - ctx context.Context:请求上下文。
  28. // - typ string:身份类型(model.IdentityType* 之一:phone/email/wechat/username/legacy_academic/legacy_teaching)。
  29. // - identifier string:归一后的标识值(phone 11 位 / email 小写 / wechat open_id / username 原值)。
  30. // - appid string:来源 appid(v1.2 进唯一键;非微信类型恒 "",微信类型必填)。
  31. //
  32. // 出参:
  33. // - *model.Identity:身份记录(含 CanonicalUserID,供 Service 再查 user)。
  34. // - error:
  35. // - errors.ErrNotFound:该 (type, identifier, appid) 无身份记录(登录"账号不存在"路径之一,防枚举统一文案);
  36. // - errors.ErrDBError:DB 异常。
  37. //
  38. // 归一纪律(调用方责任):
  39. // - email 必须小写、phone 必须 11 位数字、wechat 必须 open_id 原值——Repository 不做归一,
  40. // 归一发生在 Service 入参处理(与旧系统数据归一规则一致,见 P0-02 盘点)。
  41. // - 非微信类型 appid 必须传 ""(对齐 DDL NOT NULL DEFAULT '');微信类型 appid 必须传实际值。
  42. //
  43. // 实现说明:用 model(&model.Identity{}) 显式指定实体(GORM 自动映射表名 t_identity,TableName() 已锁定),
  44. // Where 用 (type, identifier, appid) 三列联合条件 + First 取单条(UNIQUE 键保证最多 1 条,无需 Limit 但 First 自带取一)。
  45. func (r *IdentityRepo) GetByTypeIdentifierAppID(ctx context.Context, typ, identifier, appid string) (*model.Identity, error) {
  46. var it model.Identity
  47. if err := r.db.WithContext(ctx).
  48. Where("type = ? AND identifier = ? AND appid = ?", typ, identifier, appid).
  49. First(&it).Error; err != nil {
  50. return nil, mapGormErr(err)
  51. }
  52. return &it, nil
  53. }