228 lines
8.3 KiB
Go
228 lines
8.3 KiB
Go
// Package user 定义 user-service 的用户主数据、展示短号和临时靓号领域模型。
|
||
package user
|
||
|
||
import "regexp"
|
||
|
||
// Status 是用户主状态,业务服务只应该依赖这里的稳定语义。
|
||
type Status string
|
||
|
||
const (
|
||
// StatusActive 表示用户可以正常登录和参与业务。
|
||
StatusActive Status = "active"
|
||
// StatusDisabled 表示用户被平台禁用。
|
||
StatusDisabled Status = "disabled"
|
||
// StatusBanned 表示用户被封禁。
|
||
StatusBanned Status = "banned"
|
||
)
|
||
|
||
// DisplayUserIDStatus 表达短号历史记录状态。
|
||
type DisplayUserIDStatus string
|
||
|
||
const (
|
||
// DisplayUserIDStatusActive 表示当前可被普通业务解析的短号归属。
|
||
DisplayUserIDStatusActive DisplayUserIDStatus = "active"
|
||
// DisplayUserIDStatusHeld 表示默认短号仍归用户所有,但被临时靓号覆盖。
|
||
DisplayUserIDStatusHeld DisplayUserIDStatus = "held"
|
||
// DisplayUserIDStatusExpired 表示临时靓号租约已经到期。
|
||
DisplayUserIDStatusExpired DisplayUserIDStatus = "expired"
|
||
// DisplayUserIDStatusReleased 表示短号曾经属于用户,但已经释放。
|
||
DisplayUserIDStatusReleased DisplayUserIDStatus = "released"
|
||
// DisplayUserIDStatusReserved 表示短号被系统预留,不能被普通用户占用。
|
||
DisplayUserIDStatusReserved DisplayUserIDStatus = "reserved"
|
||
// DisplayUserIDStatusBlocked 表示短号被运营阻断,不能分配。
|
||
DisplayUserIDStatusBlocked DisplayUserIDStatus = "blocked"
|
||
)
|
||
|
||
// DisplayUserIDKind 表达当前展示号来源。
|
||
type DisplayUserIDKind string
|
||
|
||
const (
|
||
// DisplayUserIDKindDefault 表示当前展示号来自用户永久默认短号。
|
||
DisplayUserIDKindDefault DisplayUserIDKind = "default"
|
||
// DisplayUserIDKindPretty 表示当前展示号来自有效临时靓号租约。
|
||
DisplayUserIDKindPretty DisplayUserIDKind = "pretty"
|
||
)
|
||
|
||
// PrettyLeaseStatus 表达临时靓号租约生命周期。
|
||
type PrettyLeaseStatus string
|
||
|
||
const (
|
||
// PrettyLeaseStatusActive 表示租约当前覆盖用户展示号。
|
||
PrettyLeaseStatusActive PrettyLeaseStatus = "active"
|
||
// PrettyLeaseStatusExpired 表示租约已按到期流程恢复默认短号。
|
||
PrettyLeaseStatusExpired PrettyLeaseStatus = "expired"
|
||
// PrettyLeaseStatusCancelled 表示租约被业务主动取消。
|
||
PrettyLeaseStatusCancelled PrettyLeaseStatus = "cancelled"
|
||
// PrettyLeaseStatusRefunded 表示租约被退款终止。
|
||
PrettyLeaseStatusRefunded PrettyLeaseStatus = "refunded"
|
||
)
|
||
|
||
// displayUserIDPattern 限制短号为 6 到 11 位非 0 开头数字。
|
||
var displayUserIDPattern = regexp.MustCompile(`^[1-9][0-9]{5,10}$`)
|
||
|
||
// User 是 user-service 的主数据实体。
|
||
// 首版只保留全局身份和状态,不包含资料、关系链或房间内临时态。
|
||
type User struct {
|
||
// UserID 是系统内部不可变用户 ID。
|
||
UserID int64
|
||
// DefaultDisplayUserID 是用户永久默认短号。
|
||
DefaultDisplayUserID string
|
||
// CurrentDisplayUserID 是当前对外展示短号,可能被有效靓号覆盖。
|
||
CurrentDisplayUserID string
|
||
// CurrentDisplayUserIDKind 表示当前展示号来源。
|
||
CurrentDisplayUserIDKind DisplayUserIDKind
|
||
// CurrentDisplayUserIDExpiresAtMs 是当前靓号过期时间,默认短号为 0。
|
||
CurrentDisplayUserIDExpiresAtMs int64
|
||
// Status 控制登录和业务可用性。
|
||
Status Status
|
||
// CreatedAtMs 是用户创建时间。
|
||
CreatedAtMs int64
|
||
// UpdatedAtMs 是用户主记录更新时间。
|
||
UpdatedAtMs int64
|
||
}
|
||
|
||
// Identity 是 user_id 与当前 active display_user_id 的绑定投影。
|
||
type Identity struct {
|
||
// UserID 是短号归属用户。
|
||
UserID int64
|
||
// DisplayUserID 是当前 active 短号。
|
||
DisplayUserID string
|
||
// DefaultDisplayUserID 是永久默认短号。
|
||
DefaultDisplayUserID string
|
||
// DisplayUserIDKind 表示 DisplayUserID 来源。
|
||
DisplayUserIDKind DisplayUserIDKind
|
||
// DisplayUserIDExpiresAtMs 是 active 靓号过期时间。
|
||
DisplayUserIDExpiresAtMs int64
|
||
// Status 是短号记录状态。
|
||
Status DisplayUserIDStatus
|
||
}
|
||
|
||
// DisplayUserIDChangeCommand 描述短号变更的事务输入。
|
||
type DisplayUserIDChangeCommand struct {
|
||
// UserID 是要修改默认短号的用户。
|
||
UserID int64
|
||
// NewDisplayUserID 是新的默认短号。
|
||
NewDisplayUserID string
|
||
// Reason 是审计原因。
|
||
Reason string
|
||
// OperatorUserID 是操作者,用户自助修改时等于 UserID。
|
||
OperatorUserID int64
|
||
// RequestID 是入口请求 ID,写入变更日志。
|
||
RequestID string
|
||
// ChangedAtMs 是本次变更时间。
|
||
ChangedAtMs int64
|
||
// CooldownMs 是默认短号修改冷却期。
|
||
CooldownMs int64
|
||
}
|
||
|
||
// PrettyDisplayUserIDLease 是临时靓号覆盖关系的事实记录。
|
||
type PrettyDisplayUserIDLease struct {
|
||
// LeaseID 是临时靓号租约主键。
|
||
LeaseID string
|
||
// DisplayUserID 是租约覆盖的靓号。
|
||
DisplayUserID string
|
||
// UserID 是租约所属用户。
|
||
UserID int64
|
||
// Status 是租约生命周期状态。
|
||
Status PrettyLeaseStatus
|
||
// StartsAtMs 是租约开始时间。
|
||
StartsAtMs int64
|
||
// ExpiresAtMs 是租约过期时间。
|
||
ExpiresAtMs int64
|
||
// PaymentReceiptID 是外部支付回执。
|
||
PaymentReceiptID string
|
||
// Source 标识租约来源,例如 payment。
|
||
Source string
|
||
// CreatedAtMs 是租约创建时间。
|
||
CreatedAtMs int64
|
||
// UpdatedAtMs 是租约更新时间。
|
||
UpdatedAtMs int64
|
||
}
|
||
|
||
// PrettyDisplayUserIDCommand 描述申请临时靓号的事务输入。
|
||
type PrettyDisplayUserIDCommand struct {
|
||
// LeaseID 是本次申请生成的租约 ID。
|
||
LeaseID string
|
||
// UserID 是申请用户。
|
||
UserID int64
|
||
// PrettyDisplayID 是申请覆盖的靓号。
|
||
PrettyDisplayID string
|
||
// LeaseDurationMs 是租期长度。
|
||
LeaseDurationMs int64
|
||
// PaymentReceiptID 是已完成支付的账务回执。
|
||
PaymentReceiptID string
|
||
// Source 是申请来源。
|
||
Source string
|
||
// RequestID 是入口请求 ID。
|
||
RequestID string
|
||
// OperatorUserID 是操作者。
|
||
OperatorUserID int64
|
||
// NowMs 是事务时间。
|
||
NowMs int64
|
||
}
|
||
|
||
// ExpirePrettyDisplayUserIDCommand 描述靓号过期恢复的事务输入。
|
||
type ExpirePrettyDisplayUserIDCommand struct {
|
||
// UserID 是需要恢复默认短号的用户。
|
||
UserID int64
|
||
// LeaseID 可选;传入时必须匹配当前 active lease。
|
||
LeaseID string
|
||
// RequestID 是触发过期的请求或任务 ID。
|
||
RequestID string
|
||
// NowMs 是过期事务时间。
|
||
NowMs int64
|
||
}
|
||
|
||
// CanLogin 判断用户状态是否允许签发新会话。
|
||
func (u User) CanLogin() bool {
|
||
// 只有 active 用户允许签发新 session,disabled/banned 都必须阻断登录。
|
||
return u.Status == StatusActive
|
||
}
|
||
|
||
// DisplayUserIDExpired 判断当前展示号快照是否已经因为靓号到期而失效。
|
||
func (u User) DisplayUserIDExpired(nowMs int64) bool {
|
||
// 只有 pretty 展示号有过期语义,默认短号永不过期。
|
||
return u.CurrentDisplayUserIDKind == DisplayUserIDKindPretty && u.CurrentDisplayUserIDExpiresAtMs > 0 && u.CurrentDisplayUserIDExpiresAtMs <= nowMs
|
||
}
|
||
|
||
// EffectiveIdentity 把用户当前展示号快照转换成对外身份投影。
|
||
func (u User) EffectiveIdentity() Identity {
|
||
// Identity 是对外短号投影,不暴露 users 表内部状态之外的资料字段。
|
||
return Identity{
|
||
UserID: u.UserID,
|
||
DisplayUserID: u.CurrentDisplayUserID,
|
||
DefaultDisplayUserID: u.DefaultDisplayUserID,
|
||
DisplayUserIDKind: u.CurrentDisplayUserIDKind,
|
||
DisplayUserIDExpiresAtMs: u.CurrentDisplayUserIDExpiresAtMs,
|
||
Status: DisplayUserIDStatusActive,
|
||
}
|
||
}
|
||
|
||
// NormalizeDisplayUserIDState 补齐老测试数据或迁移窗口中的默认短号字段。
|
||
func (u User) NormalizeDisplayUserIDState() User {
|
||
if u.DefaultDisplayUserID == "" {
|
||
// 兼容旧测试或迁移窗口中只有 current_display_user_id 的用户。
|
||
u.DefaultDisplayUserID = u.CurrentDisplayUserID
|
||
}
|
||
if u.CurrentDisplayUserID == "" {
|
||
// 当前展示号缺失时回退到默认短号,避免返回空短号。
|
||
u.CurrentDisplayUserID = u.DefaultDisplayUserID
|
||
}
|
||
if u.CurrentDisplayUserIDKind == "" {
|
||
// 未写 kind 的老数据按默认短号处理。
|
||
u.CurrentDisplayUserIDKind = DisplayUserIDKindDefault
|
||
}
|
||
if u.CurrentDisplayUserIDKind == DisplayUserIDKindDefault {
|
||
// 默认短号没有过期时间,清理脏数据中的 expires_at。
|
||
u.CurrentDisplayUserIDExpiresAtMs = 0
|
||
}
|
||
|
||
return u
|
||
}
|
||
|
||
// ValidDisplayUserID 校验短号格式。
|
||
func ValidDisplayUserID(value string) bool {
|
||
// 格式校验只判断形态,唯一性和可用性由 repository 事务决定。
|
||
return displayUserIDPattern.MatchString(value)
|
||
}
|