Add backend foundation and config-driven workbench
This commit is contained in:
119
backend/internal/service/profile_service.go
Normal file
119
backend/internal/service/profile_service.go
Normal file
@@ -0,0 +1,119 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"cmr-backend/internal/apperr"
|
||||
"cmr-backend/internal/store/postgres"
|
||||
)
|
||||
|
||||
type ProfileService struct {
|
||||
store *postgres.Store
|
||||
}
|
||||
|
||||
type ProfileResult struct {
|
||||
User struct {
|
||||
ID string `json:"id"`
|
||||
PublicID string `json:"publicId"`
|
||||
Status string `json:"status"`
|
||||
Nickname *string `json:"nickname,omitempty"`
|
||||
AvatarURL *string `json:"avatarUrl,omitempty"`
|
||||
} `json:"user"`
|
||||
Bindings struct {
|
||||
HasMobile bool `json:"hasMobile"`
|
||||
HasWechatMini bool `json:"hasWechatMini"`
|
||||
HasWechatUnion bool `json:"hasWechatUnion"`
|
||||
Items []ProfileBindingItem `json:"items"`
|
||||
} `json:"bindings"`
|
||||
RecentSessions []EntrySessionSummary `json:"recentSessions"`
|
||||
}
|
||||
|
||||
type ProfileBindingItem struct {
|
||||
IdentityType string `json:"identityType"`
|
||||
Provider string `json:"provider"`
|
||||
Status string `json:"status"`
|
||||
CountryCode *string `json:"countryCode,omitempty"`
|
||||
Mobile *string `json:"mobile,omitempty"`
|
||||
MaskedLabel string `json:"maskedLabel"`
|
||||
}
|
||||
|
||||
func NewProfileService(store *postgres.Store) *ProfileService {
|
||||
return &ProfileService{store: store}
|
||||
}
|
||||
|
||||
func (s *ProfileService) GetProfile(ctx context.Context, userID string) (*ProfileResult, error) {
|
||||
if userID == "" {
|
||||
return nil, apperr.New(http.StatusUnauthorized, "unauthorized", "user is required")
|
||||
}
|
||||
|
||||
user, err := s.store.GetUserByID(ctx, s.store.Pool(), userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if user == nil {
|
||||
return nil, apperr.New(http.StatusNotFound, "user_not_found", "user not found")
|
||||
}
|
||||
|
||||
identities, err := s.store.ListIdentitiesByUserID(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sessions, err := s.store.ListSessionsByUserID(ctx, userID, 5)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := &ProfileResult{}
|
||||
result.User.ID = user.ID
|
||||
result.User.PublicID = user.PublicID
|
||||
result.User.Status = user.Status
|
||||
result.User.Nickname = user.Nickname
|
||||
result.User.AvatarURL = user.AvatarURL
|
||||
|
||||
for _, identity := range identities {
|
||||
item := ProfileBindingItem{
|
||||
IdentityType: identity.IdentityType,
|
||||
Provider: identity.Provider,
|
||||
Status: identity.Status,
|
||||
CountryCode: identity.CountryCode,
|
||||
Mobile: identity.Mobile,
|
||||
MaskedLabel: maskIdentity(identity),
|
||||
}
|
||||
result.Bindings.Items = append(result.Bindings.Items, item)
|
||||
|
||||
switch identity.Provider {
|
||||
case "mobile":
|
||||
result.Bindings.HasMobile = true
|
||||
case "wechat_mini":
|
||||
result.Bindings.HasWechatMini = true
|
||||
case "wechat_unionid":
|
||||
result.Bindings.HasWechatUnion = true
|
||||
}
|
||||
}
|
||||
|
||||
for i := range sessions {
|
||||
result.RecentSessions = append(result.RecentSessions, buildEntrySessionSummary(&sessions[i]))
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func maskIdentity(identity postgres.LoginIdentity) string {
|
||||
if identity.Provider == "mobile" && identity.Mobile != nil {
|
||||
value := *identity.Mobile
|
||||
if len(value) >= 7 {
|
||||
return value[:3] + "****" + value[len(value)-4:]
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
if identity.Provider == "wechat_mini" {
|
||||
return "WeChat Mini bound"
|
||||
}
|
||||
if identity.Provider == "wechat_unionid" {
|
||||
return "WeChat Union bound"
|
||||
}
|
||||
return identity.Provider
|
||||
}
|
||||
Reference in New Issue
Block a user