profile_service.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. package service
  2. import (
  3. "context"
  4. "net/http"
  5. "cmr-backend/internal/apperr"
  6. "cmr-backend/internal/store/postgres"
  7. )
  8. type ProfileService struct {
  9. store *postgres.Store
  10. }
  11. type ProfileResult struct {
  12. User struct {
  13. ID string `json:"id"`
  14. PublicID string `json:"publicId"`
  15. Status string `json:"status"`
  16. Nickname *string `json:"nickname,omitempty"`
  17. AvatarURL *string `json:"avatarUrl,omitempty"`
  18. } `json:"user"`
  19. Bindings struct {
  20. HasMobile bool `json:"hasMobile"`
  21. HasWechatMini bool `json:"hasWechatMini"`
  22. HasWechatUnion bool `json:"hasWechatUnion"`
  23. Items []ProfileBindingItem `json:"items"`
  24. } `json:"bindings"`
  25. RecentSessions []EntrySessionSummary `json:"recentSessions"`
  26. }
  27. type ProfileBindingItem struct {
  28. IdentityType string `json:"identityType"`
  29. Provider string `json:"provider"`
  30. Status string `json:"status"`
  31. CountryCode *string `json:"countryCode,omitempty"`
  32. Mobile *string `json:"mobile,omitempty"`
  33. MaskedLabel string `json:"maskedLabel"`
  34. }
  35. func NewProfileService(store *postgres.Store) *ProfileService {
  36. return &ProfileService{store: store}
  37. }
  38. func (s *ProfileService) GetProfile(ctx context.Context, userID string) (*ProfileResult, error) {
  39. if userID == "" {
  40. return nil, apperr.New(http.StatusUnauthorized, "unauthorized", "user is required")
  41. }
  42. user, err := s.store.GetUserByID(ctx, s.store.Pool(), userID)
  43. if err != nil {
  44. return nil, err
  45. }
  46. if user == nil {
  47. return nil, apperr.New(http.StatusNotFound, "user_not_found", "user not found")
  48. }
  49. identities, err := s.store.ListIdentitiesByUserID(ctx, userID)
  50. if err != nil {
  51. return nil, err
  52. }
  53. sessions, err := s.store.ListSessionsByUserID(ctx, userID, 5)
  54. if err != nil {
  55. return nil, err
  56. }
  57. result := &ProfileResult{}
  58. result.User.ID = user.ID
  59. result.User.PublicID = user.PublicID
  60. result.User.Status = user.Status
  61. result.User.Nickname = user.Nickname
  62. result.User.AvatarURL = user.AvatarURL
  63. for _, identity := range identities {
  64. item := ProfileBindingItem{
  65. IdentityType: identity.IdentityType,
  66. Provider: identity.Provider,
  67. Status: identity.Status,
  68. CountryCode: identity.CountryCode,
  69. Mobile: identity.Mobile,
  70. MaskedLabel: maskIdentity(identity),
  71. }
  72. result.Bindings.Items = append(result.Bindings.Items, item)
  73. switch identity.Provider {
  74. case "mobile":
  75. result.Bindings.HasMobile = true
  76. case "wechat_mini":
  77. result.Bindings.HasWechatMini = true
  78. case "wechat_unionid":
  79. result.Bindings.HasWechatUnion = true
  80. }
  81. }
  82. for i := range sessions {
  83. result.RecentSessions = append(result.RecentSessions, buildEntrySessionSummary(&sessions[i]))
  84. }
  85. return result, nil
  86. }
  87. func maskIdentity(identity postgres.LoginIdentity) string {
  88. if identity.Provider == "mobile" && identity.Mobile != nil {
  89. value := *identity.Mobile
  90. if len(value) >= 7 {
  91. return value[:3] + "****" + value[len(value)-4:]
  92. }
  93. return value
  94. }
  95. if identity.Provider == "wechat_mini" {
  96. return "WeChat Mini bound"
  97. }
  98. if identity.Provider == "wechat_unionid" {
  99. return "WeChat Union bound"
  100. }
  101. return identity.Provider
  102. }