624 lines
23 KiB
Go
624 lines
23 KiB
Go
// Package grpc 将 user-service 认证、用户和短号用例适配成 protobuf gRPC 服务。
|
||
package grpc
|
||
|
||
import (
|
||
userv1 "hyapp.local/api/proto/user/v1"
|
||
authdomain "hyapp/services/user-service/internal/domain/auth"
|
||
hostdomain "hyapp/services/user-service/internal/domain/host"
|
||
invitedomain "hyapp/services/user-service/internal/domain/invite"
|
||
mictimedomain "hyapp/services/user-service/internal/domain/mictime"
|
||
userdomain "hyapp/services/user-service/internal/domain/user"
|
||
authservice "hyapp/services/user-service/internal/service/auth"
|
||
userservice "hyapp/services/user-service/internal/service/user"
|
||
)
|
||
|
||
// toProtoApp 把 App 注册表事实转换为 protobuf 投影。
|
||
func toProtoApp(app userdomain.App) *userv1.App {
|
||
return &userv1.App{
|
||
AppId: app.AppID,
|
||
AppCode: app.AppCode,
|
||
AppName: app.AppName,
|
||
PackageName: app.PackageName,
|
||
Platform: app.Platform,
|
||
Status: app.Status,
|
||
CreatedAtMs: app.CreatedAtMs,
|
||
UpdatedAtMs: app.UpdatedAtMs,
|
||
}
|
||
}
|
||
|
||
// toProtoToken 把领域令牌转换为 protobuf 响应。
|
||
func toProtoToken(token authdomain.Token) *userv1.AuthToken {
|
||
// Token 中包含 refresh token 原文,只能出现在登录/刷新响应路径。
|
||
return &userv1.AuthToken{
|
||
AppCode: token.AppCode,
|
||
UserId: token.UserID,
|
||
DisplayUserId: token.DisplayUserID,
|
||
DefaultDisplayUserId: token.DefaultDisplayUserID,
|
||
DisplayUserIdKind: token.DisplayUserIDKind,
|
||
DisplayUserIdExpiresAtMs: token.DisplayUserIDExpiresAtMs,
|
||
ProfileCompleted: token.ProfileCompleted,
|
||
OnboardingStatus: token.OnboardingStatus,
|
||
SessionId: token.SessionID,
|
||
AccessToken: token.AccessToken,
|
||
RefreshToken: token.RefreshToken,
|
||
ExpiresInSec: token.ExpiresInSec,
|
||
TokenType: token.TokenType,
|
||
}
|
||
}
|
||
|
||
func toProtoRegisterRiskConfig(config authdomain.RegisterRiskConfig) *userv1.RegisterRiskConfig {
|
||
return &userv1.RegisterRiskConfig{
|
||
AppCode: config.AppCode,
|
||
MaxAccountsPerDevice: config.MaxAccountsPerDevice,
|
||
UpdatedAtMs: config.UpdatedAtMs,
|
||
UpdatedByAdminId: config.UpdatedByAdminID,
|
||
}
|
||
}
|
||
|
||
// toProtoUser 把领域用户转换为 protobuf 用户投影。
|
||
func toProtoUser(user userdomain.User) *userv1.User {
|
||
// User proto 只暴露用户主状态和当前展示短号,不包含密码、三方身份或房间状态。
|
||
return &userv1.User{
|
||
AppCode: user.AppCode,
|
||
UserId: user.UserID,
|
||
Status: toProtoStatus(user.Status),
|
||
CreatedAtMs: user.CreatedAtMs,
|
||
UpdatedAtMs: user.UpdatedAtMs,
|
||
DisplayUserId: user.CurrentDisplayUserID,
|
||
DefaultDisplayUserId: user.DefaultDisplayUserID,
|
||
DisplayUserIdKind: string(user.CurrentDisplayUserIDKind),
|
||
DisplayUserIdExpiresAtMs: user.CurrentDisplayUserIDExpiresAtMs,
|
||
Username: user.Username,
|
||
Gender: user.Gender,
|
||
Country: user.Country,
|
||
Avatar: user.Avatar,
|
||
ProfileBgImg: user.ProfileBgImg,
|
||
ContactInfo: user.ContactInfo,
|
||
WithdrawUsdtTrc20Address: user.WithdrawUSDTTRC20Address,
|
||
Birth: user.BirthDate,
|
||
Language: user.Language,
|
||
CountryId: user.CountryID,
|
||
CountryName: user.CountryName,
|
||
CountryDisplayName: user.CountryDisplayName,
|
||
RegionId: user.RegionID,
|
||
RegionCode: user.RegionCode,
|
||
RegionName: user.RegionName,
|
||
ProfileCompleted: user.ProfileCompleted,
|
||
ProfileCompletedAtMs: user.ProfileCompletedAtMs,
|
||
OnboardingStatus: string(user.OnboardingStatus),
|
||
IsoNumeric: user.ISONumeric,
|
||
PhoneCountryCode: user.PhoneCountryCode,
|
||
CountryEnabled: user.CountryEnabled,
|
||
Invite: toProtoInviteOverview(user.InviteOverview),
|
||
PrettyId: user.PrettyID,
|
||
PrettyDisplayUserId: user.PrettyDisplayUserID,
|
||
}
|
||
}
|
||
|
||
func toProtoBusinessUserLookupItem(item userdomain.BusinessUserLookupItem) *userv1.BusinessUserLookupItem {
|
||
return &userv1.BusinessUserLookupItem{
|
||
UserId: item.UserID,
|
||
DisplayUserId: item.DisplayUserID,
|
||
Username: item.Username,
|
||
Avatar: item.Avatar,
|
||
Status: toProtoStatus(item.Status),
|
||
RegionId: item.RegionID,
|
||
RegionCode: item.RegionCode,
|
||
RegionName: item.RegionName,
|
||
}
|
||
}
|
||
|
||
func toProtoManagerUserBlock(block userservice.ManagerUserBlock) *userv1.ManagerUserBlock {
|
||
// 经理封禁记录是 H5 弹窗的列表数据;这里仅暴露可展示和可操作的稳定字段。
|
||
return &userv1.ManagerUserBlock{
|
||
BlockId: block.BlockID,
|
||
ManagerUserId: block.ManagerUserID,
|
||
TargetUserId: block.TargetUserID,
|
||
TargetDisplayUserId: block.TargetDisplayUserID,
|
||
TargetUsername: block.TargetUsername,
|
||
TargetAvatar: block.TargetAvatar,
|
||
Country: block.Country,
|
||
BlockedUntilMs: block.BlockedUntilMS,
|
||
Status: block.Status,
|
||
Reason: block.Reason,
|
||
CreatedAtMs: block.CreatedAtMS,
|
||
UpdatedAtMs: block.UpdatedAtMS,
|
||
}
|
||
}
|
||
|
||
func toProtoInviteOverview(overview invitedomain.Overview) *userv1.InviteOverview {
|
||
if overview.MyInviteCode == "" && !overview.InviteEnabled && overview.InviteCount == 0 && overview.ValidInviteCount == 0 && overview.ValidInviteThresholdCoin == 0 {
|
||
return nil
|
||
}
|
||
return &userv1.InviteOverview{
|
||
MyInviteCode: overview.MyInviteCode,
|
||
InviteEnabled: overview.InviteEnabled,
|
||
InviteCount: overview.InviteCount,
|
||
ValidInviteCount: overview.ValidInviteCount,
|
||
ValidInviteThresholdCoin: overview.ValidInviteThresholdCoin,
|
||
}
|
||
}
|
||
|
||
func toProtoInviteBinding(binding invitedomain.Binding) *userv1.InviteBinding {
|
||
if !binding.Bound && binding.InviteCode == "" && binding.InviterUserID == 0 {
|
||
return nil
|
||
}
|
||
return &userv1.InviteBinding{
|
||
Bound: binding.Bound,
|
||
InviteCode: binding.InviteCode,
|
||
InviterUserId: binding.InviterUserID,
|
||
}
|
||
}
|
||
|
||
func toProtoInviteAttribution(attribution invitedomain.Attribution) *userv1.InviteAttribution {
|
||
return &userv1.InviteAttribution{
|
||
Found: attribution.Found,
|
||
AppCode: attribution.AppCode,
|
||
InvitedUserId: attribution.InvitedUserID,
|
||
InviterUserId: attribution.InviterUserID,
|
||
InviteCode: attribution.InviteCode,
|
||
BoundAtMs: attribution.BoundAtMS,
|
||
ValidityStatus: attribution.ValidityStatus,
|
||
AccumulatedRechargeCoinAmount: attribution.AccumulatedRechargeCoinAmount,
|
||
RequiredRechargeCoinAmount: attribution.RequiredRechargeCoinAmount,
|
||
ValidAtMs: attribution.ValidAtMS,
|
||
}
|
||
}
|
||
|
||
func toProtoMicLifetimeStats(stats mictimedomain.LifetimeStats) *userv1.UserMicLifetimeStats {
|
||
return &userv1.UserMicLifetimeStats{
|
||
AppCode: stats.AppCode,
|
||
UserId: stats.UserID,
|
||
SeatOccupiedMs: stats.SeatOccupiedMs,
|
||
MicOnlineMs: stats.MicOnlineMs,
|
||
SessionCount: stats.SessionCount,
|
||
FirstMicAtMs: stats.FirstMicAtMs,
|
||
LastMicAtMs: stats.LastMicAtMs,
|
||
UpdatedAtMs: stats.UpdatedAtMs,
|
||
}
|
||
}
|
||
|
||
func toProtoProfileStats(stats userdomain.ProfileStats) *userv1.UserProfileStats {
|
||
return &userv1.UserProfileStats{
|
||
AppCode: stats.AppCode,
|
||
UserId: stats.UserID,
|
||
VisitorsCount: stats.VisitorsCount,
|
||
FollowingCount: stats.FollowingCount,
|
||
FriendsCount: stats.FriendsCount,
|
||
UpdatedAtMs: stats.UpdatedAtMs,
|
||
}
|
||
}
|
||
|
||
func toProtoProfileVisitRecord(record userdomain.ProfileVisitRecord) *userv1.ProfileVisitRecord {
|
||
return &userv1.ProfileVisitRecord{
|
||
VisitorUserId: record.VisitorUserID,
|
||
TargetUserId: record.TargetUserID,
|
||
VisitCount: record.VisitCount,
|
||
LastVisitedAtMs: record.LastVisitedAtMs,
|
||
}
|
||
}
|
||
|
||
func toProtoFollowRecord(record userdomain.FollowRecord) *userv1.FollowRecord {
|
||
return &userv1.FollowRecord{
|
||
FollowerUserId: record.FollowerUserID,
|
||
FolloweeUserId: record.FolloweeUserID,
|
||
FollowedAtMs: record.FollowedAtMs,
|
||
}
|
||
}
|
||
|
||
func toProtoFriendRecord(record userdomain.FriendRecord) *userv1.FriendRecord {
|
||
return &userv1.FriendRecord{
|
||
UserId: record.UserID,
|
||
FriendUserId: record.FriendUserID,
|
||
FriendedAtMs: record.FriendedAtMs,
|
||
}
|
||
}
|
||
|
||
func toProtoFriendApplication(application userdomain.FriendApplication) *userv1.FriendApplication {
|
||
return &userv1.FriendApplication{
|
||
RequesterUserId: application.RequesterUserID,
|
||
TargetUserId: application.TargetUserID,
|
||
Status: application.Status,
|
||
CreatedAtMs: application.CreatedAtMs,
|
||
UpdatedAtMs: application.UpdatedAtMs,
|
||
}
|
||
}
|
||
|
||
func toProtoUserReport(report userdomain.Report) *userv1.UserReport {
|
||
return &userv1.UserReport{
|
||
ReportId: report.ReportID,
|
||
ReporterUserId: report.ReporterUserID,
|
||
TargetType: report.TargetType,
|
||
UserId: report.UserID,
|
||
RoomId: report.RoomID,
|
||
ReportType: report.ReportType,
|
||
Reason: report.Reason,
|
||
ImageUrls: append([]string{}, report.ImageURLs...),
|
||
Status: report.Status,
|
||
CreatedAtMs: report.CreatedAtMs,
|
||
}
|
||
}
|
||
|
||
// toProtoCountry 把国家领域对象转换为管理 RPC 响应。
|
||
func toProtoCountry(country userdomain.Country) *userv1.Country {
|
||
return &userv1.Country{
|
||
AppCode: country.AppCode,
|
||
CountryId: country.CountryID,
|
||
CountryName: country.CountryName,
|
||
CountryCode: country.CountryCode,
|
||
CountryDisplayName: country.CountryDisplayName,
|
||
SortOrder: country.SortOrder,
|
||
CreatedAtMs: country.CreatedAtMs,
|
||
UpdatedAtMs: country.UpdatedAtMs,
|
||
IsoAlpha3: country.ISOAlpha3,
|
||
IsoNumeric: country.ISONumeric,
|
||
PhoneCountryCode: country.PhoneCountryCode,
|
||
Enabled: country.Enabled,
|
||
Flag: country.Flag,
|
||
}
|
||
}
|
||
|
||
// toProtoRegion 把区域领域对象转换为管理 RPC 响应。
|
||
func toProtoRegion(region userdomain.Region) *userv1.Region {
|
||
return &userv1.Region{
|
||
AppCode: region.AppCode,
|
||
RegionId: region.RegionID,
|
||
RegionCode: region.RegionCode,
|
||
Name: region.Name,
|
||
Status: region.Status,
|
||
Countries: append([]string{}, region.Countries...),
|
||
SortOrder: region.SortOrder,
|
||
CreatedAtMs: region.CreatedAtMs,
|
||
UpdatedAtMs: region.UpdatedAtMs,
|
||
}
|
||
}
|
||
|
||
// toProtoIdentity 把短号领域投影转换为 protobuf 响应。
|
||
func toProtoIdentity(identity userdomain.Identity) *userv1.UserIdentity {
|
||
// Identity proto 用于短号解析和修改结果,字段语义与领域 Identity 保持一致。
|
||
// PrettyId/PrettyDisplayUserId 只表示当前 active 靓号,没有靓号时为空,不回填默认短号。
|
||
return &userv1.UserIdentity{
|
||
AppCode: identity.AppCode,
|
||
UserId: identity.UserID,
|
||
DisplayUserId: identity.DisplayUserID,
|
||
Status: string(identity.Status),
|
||
DefaultDisplayUserId: identity.DefaultDisplayUserID,
|
||
DisplayUserIdKind: string(identity.DisplayUserIDKind),
|
||
DisplayUserIdExpiresAtMs: identity.DisplayUserIDExpiresAtMs,
|
||
PrettyId: identity.PrettyID,
|
||
PrettyDisplayUserId: identity.PrettyDisplayUserID,
|
||
}
|
||
}
|
||
|
||
func toProtoPrettyDisplayIDPool(pool userdomain.PrettyDisplayIDPool) *userv1.PrettyDisplayIDPool {
|
||
// 池配置是后台和 App 可申请列表共用的展示信息,等级轨道和区间必须原样透出。
|
||
return &userv1.PrettyDisplayIDPool{
|
||
AppCode: pool.AppCode,
|
||
PoolId: pool.PoolID,
|
||
Name: pool.Name,
|
||
LevelTrack: pool.LevelTrack,
|
||
MinLevel: pool.MinLevel,
|
||
MaxLevel: pool.MaxLevel,
|
||
RuleType: pool.RuleType,
|
||
RuleConfigJson: pool.RuleConfigJSON,
|
||
Status: pool.Status,
|
||
SortOrder: pool.SortOrder,
|
||
CreatedByAdminId: pool.CreatedByAdminID,
|
||
UpdatedByAdminId: pool.UpdatedByAdminID,
|
||
CreatedAtMs: pool.CreatedAtMs,
|
||
UpdatedAtMs: pool.UpdatedAtMs,
|
||
}
|
||
}
|
||
|
||
func toProtoPrettyDisplayID(item userdomain.PrettyDisplayID) *userv1.PrettyDisplayID {
|
||
// 后台发放号码没有 pool_id,Pool 会是零值;前端以 source 判断是否展示池信息。
|
||
return &userv1.PrettyDisplayID{
|
||
AppCode: item.AppCode,
|
||
PrettyId: item.PrettyID,
|
||
PoolId: item.PoolID,
|
||
Source: item.Source,
|
||
DisplayUserId: item.DisplayUserID,
|
||
Status: item.Status,
|
||
AssignedUserId: item.AssignedUserID,
|
||
AssignedLeaseId: item.AssignedLeaseID,
|
||
AssignedAtMs: item.AssignedAtMs,
|
||
ReleasedAtMs: item.ReleasedAtMs,
|
||
ReleaseReason: item.ReleaseReason,
|
||
GeneratedBatchId: item.GeneratedBatchID,
|
||
CreatedByAdminId: item.CreatedByAdminID,
|
||
CreatedAtMs: item.CreatedAtMs,
|
||
UpdatedAtMs: item.UpdatedAtMs,
|
||
Pool: toProtoPrettyDisplayIDPool(item.Pool),
|
||
}
|
||
}
|
||
|
||
func toProtoPrettyDisplayIDBatch(batch userdomain.PrettyDisplayIDGenerationBatch) *userv1.PrettyDisplayIDGenerationBatch {
|
||
// 批次响应保留 requested/generated/skipped 三个计数,后台可以直接解释生成不足是否来自冲突。
|
||
return &userv1.PrettyDisplayIDGenerationBatch{
|
||
AppCode: batch.AppCode,
|
||
BatchId: batch.BatchID,
|
||
PoolId: batch.PoolID,
|
||
RuleType: batch.RuleType,
|
||
RuleConfigJson: batch.RuleConfigJSON,
|
||
RequestedCount: batch.RequestedCount,
|
||
GeneratedCount: batch.GeneratedCount,
|
||
SkippedConflictCount: batch.SkippedConflictCount,
|
||
Status: batch.Status,
|
||
OperatorAdminId: batch.OperatorAdminID,
|
||
RequestId: batch.RequestID,
|
||
CreatedAtMs: batch.CreatedAtMs,
|
||
UpdatedAtMs: batch.UpdatedAtMs,
|
||
}
|
||
}
|
||
|
||
// toProtoStatus 固定未知状态的安全默认值。
|
||
func toProtoStatus(status userdomain.Status) userv1.UserStatus {
|
||
// 状态枚举转换集中在这里,未知状态使用 UNSPECIFIED 安全兜底。
|
||
switch status {
|
||
case userdomain.StatusActive:
|
||
return userv1.UserStatus_USER_STATUS_ACTIVE
|
||
case userdomain.StatusDisabled:
|
||
return userv1.UserStatus_USER_STATUS_DISABLED
|
||
case userdomain.StatusBanned:
|
||
return userv1.UserStatus_USER_STATUS_BANNED
|
||
default:
|
||
return userv1.UserStatus_USER_STATUS_UNSPECIFIED
|
||
}
|
||
}
|
||
|
||
func fromProtoStatus(status userv1.UserStatus) userdomain.Status {
|
||
switch status {
|
||
case userv1.UserStatus_USER_STATUS_ACTIVE:
|
||
return userdomain.StatusActive
|
||
case userv1.UserStatus_USER_STATUS_DISABLED:
|
||
return userdomain.StatusDisabled
|
||
case userv1.UserStatus_USER_STATUS_BANNED:
|
||
return userdomain.StatusBanned
|
||
default:
|
||
return ""
|
||
}
|
||
}
|
||
|
||
// authMeta 提取认证链路审计所需的 gateway 透传字段。
|
||
func authMeta(meta *userv1.RequestMeta) authservice.Meta {
|
||
if meta == nil {
|
||
// meta 可选,缺失时审计字段为空但不能让 RPC panic。
|
||
return authservice.Meta{}
|
||
}
|
||
|
||
// 只提取认证审计需要的字段,device_id 在各 RPC 中单独传入。
|
||
return authservice.Meta{
|
||
AppCode: meta.GetAppCode(),
|
||
RequestID: meta.GetRequestId(),
|
||
ClientIP: meta.GetClientIp(),
|
||
UserAgent: meta.GetUserAgent(),
|
||
CountryByIP: meta.GetCountryByIp(),
|
||
Platform: meta.GetPlatform(),
|
||
Language: meta.GetLanguage(),
|
||
Timezone: meta.GetTimezone(),
|
||
}
|
||
}
|
||
|
||
// toProtoHostProfile 把 host profile 事实转换为内部 gRPC 投影。
|
||
func toProtoHostProfile(profile hostdomain.HostProfile) *userv1.HostProfile {
|
||
if profile.UserID == 0 {
|
||
return nil
|
||
}
|
||
return &userv1.HostProfile{
|
||
UserId: profile.UserID,
|
||
Status: profile.Status,
|
||
RegionId: profile.RegionID,
|
||
CurrentAgencyId: profile.CurrentAgencyID,
|
||
CurrentMembershipId: profile.CurrentMembershipID,
|
||
CurrentAgencyOwnerUserId: profile.CurrentAgencyOwnerUserID,
|
||
Source: profile.Source,
|
||
FirstBecameHostAtMs: profile.FirstBecameHostAtMs,
|
||
CreatedAtMs: profile.CreatedAtMs,
|
||
UpdatedAtMs: profile.UpdatedAtMs,
|
||
}
|
||
}
|
||
|
||
// toProtoAgency 把 Agency 事实转换为内部 gRPC 投影。
|
||
func toProtoAgency(agency hostdomain.Agency) *userv1.Agency {
|
||
if agency.AgencyID == 0 {
|
||
return nil
|
||
}
|
||
return &userv1.Agency{
|
||
AgencyId: agency.AgencyID,
|
||
OwnerUserId: agency.OwnerUserID,
|
||
RegionId: agency.RegionID,
|
||
ParentBdUserId: agency.ParentBDUserID,
|
||
Name: agency.Name,
|
||
Status: agency.Status,
|
||
JoinEnabled: agency.JoinEnabled,
|
||
MaxHosts: agency.MaxHosts,
|
||
CreatedByUserId: agency.CreatedByUserID,
|
||
CreatedAtMs: agency.CreatedAtMs,
|
||
UpdatedAtMs: agency.UpdatedAtMs,
|
||
Avatar: agency.Avatar,
|
||
HostCount: agency.ActiveHostCount,
|
||
}
|
||
}
|
||
|
||
// toProtoBDProfile 把 BD profile 事实转换为内部 gRPC 投影。
|
||
func toProtoBDProfile(profile hostdomain.BDProfile) *userv1.BDProfile {
|
||
if profile.UserID == 0 {
|
||
return nil
|
||
}
|
||
return &userv1.BDProfile{
|
||
UserId: profile.UserID,
|
||
Role: profile.Role,
|
||
RegionId: profile.RegionID,
|
||
ParentLeaderUserId: profile.ParentLeaderUserID,
|
||
Status: profile.Status,
|
||
CreatedByUserId: profile.CreatedByUserID,
|
||
CreatedAtMs: profile.CreatedAtMs,
|
||
UpdatedAtMs: profile.UpdatedAtMs,
|
||
}
|
||
}
|
||
|
||
// toProtoCoinSellerProfile 把币商身份事实转换为内部 gRPC 投影。
|
||
func toProtoCoinSellerProfile(profile hostdomain.CoinSellerProfile) *userv1.CoinSellerProfile {
|
||
if profile.UserID == 0 {
|
||
return nil
|
||
}
|
||
return &userv1.CoinSellerProfile{
|
||
UserId: profile.UserID,
|
||
Status: profile.Status,
|
||
MerchantAssetType: profile.MerchantAssetType,
|
||
CanManageSubCoinSellers: profile.CanManageSubCoinSellers,
|
||
CreatedByUserId: profile.CreatedByUserID,
|
||
CreatedAtMs: profile.CreatedAtMs,
|
||
UpdatedAtMs: profile.UpdatedAtMs,
|
||
}
|
||
}
|
||
|
||
// toProtoCoinSellerListItem 把区域币商列表项转换为 App 读取投影。
|
||
func toProtoCoinSellerListItem(item hostdomain.CoinSellerListItem) *userv1.CoinSellerListItem {
|
||
if item.UserID == 0 {
|
||
return nil
|
||
}
|
||
return &userv1.CoinSellerListItem{
|
||
UserId: item.UserID,
|
||
DisplayUserId: item.DisplayUserID,
|
||
Username: item.Username,
|
||
Avatar: item.Avatar,
|
||
CountryId: item.CountryID,
|
||
CountryCode: item.CountryCode,
|
||
CountryName: item.CountryName,
|
||
CountryDisplayName: item.CountryDisplayName,
|
||
RegionId: item.RegionID,
|
||
RegionCode: item.RegionCode,
|
||
RegionName: item.RegionName,
|
||
Status: item.Status,
|
||
MerchantAssetType: item.MerchantAssetType,
|
||
ContactInfo: item.ContactInfo,
|
||
CanManageSubCoinSellers: item.CanManageSubCoinSellers,
|
||
UpdatedAtMs: item.UpdatedAtMs,
|
||
}
|
||
}
|
||
|
||
// toProtoCoinSellerSubRelation 把父子币商关系事实转换为内部 gRPC 投影。
|
||
func toProtoCoinSellerSubRelation(relation hostdomain.CoinSellerSubRelation) *userv1.CoinSellerSubRelation {
|
||
if relation.RelationID == 0 {
|
||
return nil
|
||
}
|
||
return &userv1.CoinSellerSubRelation{
|
||
RelationId: relation.RelationID,
|
||
ParentUserId: relation.ParentUserID,
|
||
ChildUserId: relation.ChildUserID,
|
||
Status: relation.Status,
|
||
CreatedByUserId: relation.CreatedByUserID,
|
||
CreatedAtMs: relation.CreatedAtMs,
|
||
UpdatedAtMs: relation.UpdatedAtMs,
|
||
}
|
||
}
|
||
|
||
// toProtoCoinSellerSubApplication 把子币商审核申请转换为内部 gRPC 投影。
|
||
func toProtoCoinSellerSubApplication(application hostdomain.CoinSellerSubApplication) *userv1.CoinSellerSubApplication {
|
||
if application.ApplicationID == 0 {
|
||
return nil
|
||
}
|
||
return &userv1.CoinSellerSubApplication{
|
||
ApplicationId: application.ApplicationID,
|
||
CommandId: application.CommandID,
|
||
ParentUserId: application.ParentUserID,
|
||
TargetUserId: application.TargetUserID,
|
||
Status: application.Status,
|
||
RelationId: application.RelationID,
|
||
ReviewedByAdminId: application.ReviewedByAdminID,
|
||
ReviewReason: application.ReviewReason,
|
||
ReviewedAtMs: application.ReviewedAtMs,
|
||
CreatedAtMs: application.CreatedAtMs,
|
||
UpdatedAtMs: application.UpdatedAtMs,
|
||
}
|
||
}
|
||
|
||
// toProtoUserRoleSummary 把 host domain 入口显隐摘要转换为 gRPC 投影。
|
||
func toProtoUserRoleSummary(summary hostdomain.UserRoleSummary) *userv1.UserRoleSummary {
|
||
if summary.UserID == 0 {
|
||
return nil
|
||
}
|
||
return &userv1.UserRoleSummary{
|
||
UserId: summary.UserID,
|
||
IsHost: summary.IsHost,
|
||
IsAgency: summary.IsAgency,
|
||
IsManager: summary.IsManager,
|
||
IsBd: summary.IsBD,
|
||
IsBdLeader: summary.IsBDLeader,
|
||
IsCoinSeller: summary.IsCoinSeller,
|
||
HostStatus: summary.HostStatus,
|
||
AgencyId: summary.AgencyID,
|
||
BdId: summary.BDID,
|
||
BdStatus: summary.BDStatus,
|
||
CoinSellerStatus: summary.CoinSellerStatus,
|
||
PendingRoleInvitations: summary.PendingRoleInvitations,
|
||
}
|
||
}
|
||
|
||
// toProtoAgencyMembership 把 Agency membership 事实转换为内部 gRPC 投影。
|
||
func toProtoAgencyMembership(membership hostdomain.AgencyMembership) *userv1.AgencyMembership {
|
||
if membership.MembershipID == 0 {
|
||
return nil
|
||
}
|
||
return &userv1.AgencyMembership{
|
||
MembershipId: membership.MembershipID,
|
||
AgencyId: membership.AgencyID,
|
||
HostUserId: membership.HostUserID,
|
||
RegionId: membership.RegionID,
|
||
MembershipType: membership.MembershipType,
|
||
Status: membership.Status,
|
||
JoinedAtMs: membership.JoinedAtMs,
|
||
EndedAtMs: membership.EndedAtMs,
|
||
EndedByUserId: membership.EndedByUserID,
|
||
EndedReason: membership.EndedReason,
|
||
CreatedAtMs: membership.CreatedAtMs,
|
||
UpdatedAtMs: membership.UpdatedAtMs,
|
||
}
|
||
}
|
||
|
||
// toProtoAgencyApplication 把 Agency application 事实转换为内部 gRPC 投影。
|
||
func toProtoAgencyApplication(application hostdomain.AgencyApplication) *userv1.AgencyApplication {
|
||
if application.ApplicationID == 0 {
|
||
return nil
|
||
}
|
||
return &userv1.AgencyApplication{
|
||
ApplicationId: application.ApplicationID,
|
||
CommandId: application.CommandID,
|
||
ApplicantUserId: application.ApplicantUserID,
|
||
AgencyId: application.AgencyID,
|
||
RegionId: application.RegionID,
|
||
Status: application.Status,
|
||
ReviewedByUserId: application.ReviewedByUserID,
|
||
ReviewReason: application.ReviewReason,
|
||
ReviewedAtMs: application.ReviewedAtMs,
|
||
CreatedAtMs: application.CreatedAtMs,
|
||
UpdatedAtMs: application.UpdatedAtMs,
|
||
}
|
||
}
|
||
|
||
// toProtoRoleInvitation 把角色邀请事实转换为内部 gRPC 投影。
|
||
func toProtoRoleInvitation(invitation hostdomain.RoleInvitation) *userv1.RoleInvitation {
|
||
if invitation.InvitationID == 0 {
|
||
return nil
|
||
}
|
||
return &userv1.RoleInvitation{
|
||
InvitationId: invitation.InvitationID,
|
||
CommandId: invitation.CommandID,
|
||
InvitationType: invitation.InvitationType,
|
||
Status: invitation.Status,
|
||
InviterUserId: invitation.InviterUserID,
|
||
InviterBdUserId: invitation.InviterBDUserID,
|
||
TargetUserId: invitation.TargetUserID,
|
||
RegionId: invitation.RegionID,
|
||
AgencyName: invitation.AgencyName,
|
||
ParentBdUserId: invitation.ParentBDUserID,
|
||
ParentLeaderUserId: invitation.ParentLeaderUserID,
|
||
ProcessedByUserId: invitation.ProcessedByUserID,
|
||
ProcessReason: invitation.ProcessReason,
|
||
ProcessedAtMs: invitation.ProcessedAtMs,
|
||
CreatedAtMs: invitation.CreatedAtMs,
|
||
UpdatedAtMs: invitation.UpdatedAtMs,
|
||
}
|
||
}
|