2026-04-27 02:29:42 +08:00

228 lines
8.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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 用户允许签发新 sessiondisabled/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)
}