feat(auth): 用户账户 - 完善个人资料与登录日志 (#752)

Co-authored-by: wuligao <1247662379@qq.com>
This commit is contained in:
ddcat666
2026-10-13 05:31:30 +08:00
committed by GitHub
parent e70fe1b9c9
commit 4c1d2b4012
83 changed files with 5836 additions and 328 deletions

View File

@@ -10,6 +10,9 @@ type User struct {
EmailVerifiedAt *time.Time `json:"emailVerifiedAt,omitempty"`
PhoneVerifiedAt *time.Time `json:"phoneVerifiedAt,omitempty"`
DisplayName string `json:"displayName" gorm:"size:80"`
AvatarMode string `json:"avatarMode" gorm:"size:16"`
AvatarPreset string `json:"avatarPreset,omitempty" gorm:"size:16"`
AvatarVersion string `json:"-" gorm:"size:36"`
Role UserRole `json:"role" gorm:"index;size:24"`
Status UserStatus `json:"status" gorm:"index;size:24"`
PasswordHash string `json:"-"`
@@ -19,12 +22,13 @@ type User struct {
}
type AuthSession struct {
ID string `json:"id" gorm:"primaryKey;size:36"`
UserID string `json:"userId" gorm:"index;size:36"`
TokenHash string `json:"-"`
ExpiresAt time.Time `json:"expiresAt" gorm:"index"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
ReauthenticatedAt *time.Time `json:"-"`
ID string `json:"id" gorm:"primaryKey;size:36"`
UserID string `json:"userId" gorm:"index;size:36"`
TokenHash string `json:"-"`
ExpiresAt time.Time `json:"expiresAt" gorm:"index"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
type UserIdentity struct {
@@ -39,15 +43,17 @@ type UserIdentity struct {
}
type OAuthState struct {
ID string `json:"id" gorm:"primaryKey;size:36"`
Provider string `json:"provider" gorm:"index;size:32"`
StateHash string `json:"-" gorm:"uniqueIndex;size:64"`
CodeVerifier string `json:"-" gorm:"size:160"`
NextPath string `json:"nextPath"`
AcceptedTerms bool `json:"acceptedTerms" gorm:"not null;default:false"`
ExpiresAt time.Time `json:"expiresAt" gorm:"index"`
UsedAt *time.Time `json:"usedAt" gorm:"index"`
CreatedAt time.Time `json:"createdAt"`
ReauthUserID string `json:"-" gorm:"size:36"`
ReauthSessionID string `json:"-" gorm:"size:36"`
ID string `json:"id" gorm:"primaryKey;size:36"`
Provider string `json:"provider" gorm:"index;size:32"`
StateHash string `json:"-" gorm:"uniqueIndex;size:64"`
CodeVerifier string `json:"-" gorm:"size:160"`
NextPath string `json:"nextPath"`
AcceptedTerms bool `json:"acceptedTerms" gorm:"not null;default:false"`
ExpiresAt time.Time `json:"expiresAt" gorm:"index"`
UsedAt *time.Time `json:"usedAt" gorm:"index"`
CreatedAt time.Time `json:"createdAt"`
}
type EmailVerificationCode struct {

View File

@@ -0,0 +1,22 @@
package model
import "time"
// LoginLog 保存事件时的用户快照,不随账号改名或会话清理改写历史。
type LoginLog struct {
ID string `json:"id" gorm:"primaryKey;size:36"`
UserID *string `json:"userId" gorm:"index;size:36"`
Username string `json:"username" gorm:"size:80"`
DisplayName string `json:"displayName" gorm:"size:80"`
Account string `json:"account" gorm:"size:160"`
Event string `json:"event" gorm:"index;size:16"`
Method string `json:"method" gorm:"index;size:24"`
Source string `json:"source" gorm:"size:24"`
Result string `json:"result" gorm:"index;size:16"`
IP string `json:"ip" gorm:"index;size:64"`
UserAgent string `json:"userAgent" gorm:"size:512"`
SessionRef string `json:"sessionRef" gorm:"index;size:64"`
Reason string `json:"reason" gorm:"size:64"`
Message string `json:"message" gorm:"size:500"`
CreatedAt time.Time `json:"createdAt" gorm:"index"`
}

View File

@@ -43,21 +43,23 @@ type SMSRecord struct {
// Verification tickets are immutable, short-lived and purpose/target bound.
// Only code HMACs and the hash of the high-entropy client ticket are persisted.
type AuthVerification struct {
ID string `gorm:"primaryKey;size:36"`
TokenHash string `gorm:"size:64"`
Purpose string `gorm:"size:24"`
Method string `gorm:"size:24"`
UserID string `gorm:"size:36"`
Email string `gorm:"size:160"`
Phone string `gorm:"size:24"`
EmailHash string `gorm:"size:64"`
PhoneHash string `gorm:"size:64"`
PolicyHash string `gorm:"size:64"`
Ready bool
Attempts int
ExpiresAt time.Time `gorm:"index"`
UsedAt *time.Time
CreatedAt time.Time
SessionID string `json:"-" gorm:"size:36"`
CredentialHash string `json:"-" gorm:"size:64"`
ID string `gorm:"primaryKey;size:36"`
TokenHash string `gorm:"size:64"`
Purpose string `gorm:"size:24"`
Method string `gorm:"size:24"`
UserID string `gorm:"size:36"`
Email string `gorm:"size:160"`
Phone string `gorm:"size:24"`
EmailHash string `gorm:"size:64"`
PhoneHash string `gorm:"size:64"`
PolicyHash string `gorm:"size:64"`
Ready bool
Attempts int
ExpiresAt time.Time `gorm:"index"`
UsedAt *time.Time
CreatedAt time.Time
}
// Fixed window quotas and per-recipient cooldowns are shared by all instances.

View File

@@ -0,0 +1,10 @@
package model
import "time"
// UserAvatar keeps the bounded image payload out of ordinary user queries.
type UserAvatar struct {
UserID string `gorm:"primaryKey;size:36" json:"userId"`
Data []byte `gorm:"not null" json:"-"`
UpdatedAt time.Time `json:"updatedAt"`
}