feat: 添加种子数据初始化功能,重构多个处理程序以简化错误响应和用户验证

This commit is contained in:
lan
2025-12-02 10:33:19 +08:00
parent bdd2be5dc5
commit 10fdcd916b
30 changed files with 1291 additions and 1778 deletions

View File

@@ -7,18 +7,18 @@ import (
// AuditLog 审计日志模型
type AuditLog struct {
ID int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
UserID *int64 `gorm:"column:user_id;type:bigint;index" json:"user_id,omitempty"`
Action string `gorm:"column:action;type:varchar(100);not null;index" json:"action"`
ResourceType string `gorm:"column:resource_type;type:varchar(50);not null;index:idx_audit_logs_resource" json:"resource_type"`
ResourceID string `gorm:"column:resource_id;type:varchar(50);index:idx_audit_logs_resource" json:"resource_id,omitempty"`
UserID *int64 `gorm:"column:user_id;type:bigint;index:idx_audit_logs_user_created,priority:1" json:"user_id,omitempty"`
Action string `gorm:"column:action;type:varchar(100);not null;index:idx_audit_logs_action" json:"action"`
ResourceType string `gorm:"column:resource_type;type:varchar(50);not null;index:idx_audit_logs_resource,priority:1" json:"resource_type"`
ResourceID string `gorm:"column:resource_id;type:varchar(50);index:idx_audit_logs_resource,priority:2" json:"resource_id,omitempty"`
OldValues string `gorm:"column:old_values;type:jsonb" json:"old_values,omitempty"` // JSONB 格式
NewValues string `gorm:"column:new_values;type:jsonb" json:"new_values,omitempty"` // JSONB 格式
IPAddress string `gorm:"column:ip_address;type:inet;not null" json:"ip_address"`
IPAddress string `gorm:"column:ip_address;type:inet;not null;index:idx_audit_logs_ip" json:"ip_address"`
UserAgent string `gorm:"column:user_agent;type:text" json:"user_agent,omitempty"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp;not null;default:CURRENT_TIMESTAMP;index:idx_audit_logs_created_at,sort:desc" json:"created_at"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp;not null;default:CURRENT_TIMESTAMP;index:idx_audit_logs_user_created,priority:2,sort:desc;index:idx_audit_logs_created_at,sort:desc" json:"created_at"`
// 关联
User *User `gorm:"foreignKey:UserID" json:"user,omitempty"`
User *User `gorm:"foreignKey:UserID;constraint:OnDelete:SET NULL" json:"user,omitempty"`
}
// TableName 指定表名
@@ -29,13 +29,13 @@ func (AuditLog) TableName() string {
// CasbinRule Casbin 权限规则模型
type CasbinRule struct {
ID int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
PType string `gorm:"column:ptype;type:varchar(100);not null;index;uniqueIndex:uk_casbin_rule" json:"ptype"`
V0 string `gorm:"column:v0;type:varchar(100);not null;default:'';index;uniqueIndex:uk_casbin_rule" json:"v0"`
V1 string `gorm:"column:v1;type:varchar(100);not null;default:'';index;uniqueIndex:uk_casbin_rule" json:"v1"`
V2 string `gorm:"column:v2;type:varchar(100);not null;default:'';uniqueIndex:uk_casbin_rule" json:"v2"`
V3 string `gorm:"column:v3;type:varchar(100);not null;default:'';uniqueIndex:uk_casbin_rule" json:"v3"`
V4 string `gorm:"column:v4;type:varchar(100);not null;default:'';uniqueIndex:uk_casbin_rule" json:"v4"`
V5 string `gorm:"column:v5;type:varchar(100);not null;default:'';uniqueIndex:uk_casbin_rule" json:"v5"`
PType string `gorm:"column:ptype;type:varchar(100);not null;index:idx_casbin_ptype;uniqueIndex:uk_casbin_rule,priority:1" json:"ptype"`
V0 string `gorm:"column:v0;type:varchar(100);not null;default:'';index:idx_casbin_v0;uniqueIndex:uk_casbin_rule,priority:2" json:"v0"`
V1 string `gorm:"column:v1;type:varchar(100);not null;default:'';index:idx_casbin_v1;uniqueIndex:uk_casbin_rule,priority:3" json:"v1"`
V2 string `gorm:"column:v2;type:varchar(100);not null;default:'';uniqueIndex:uk_casbin_rule,priority:4" json:"v2"`
V3 string `gorm:"column:v3;type:varchar(100);not null;default:'';uniqueIndex:uk_casbin_rule,priority:5" json:"v3"`
V4 string `gorm:"column:v4;type:varchar(100);not null;default:'';uniqueIndex:uk_casbin_rule,priority:6" json:"v4"`
V5 string `gorm:"column:v5;type:varchar(100);not null;default:'';uniqueIndex:uk_casbin_rule,priority:7" json:"v5"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp;not null;default:CURRENT_TIMESTAMP" json:"created_at"`
}

View File

@@ -7,20 +7,20 @@ import (
// Profile Minecraft 档案模型
type Profile struct {
UUID string `gorm:"column:uuid;type:varchar(36);primaryKey" json:"uuid"`
UserID int64 `gorm:"column:user_id;not null;index" json:"user_id"`
Name string `gorm:"column:name;type:varchar(16);not null;uniqueIndex" json:"name"` // Minecraft 角色名
SkinID *int64 `gorm:"column:skin_id;type:bigint" json:"skin_id,omitempty"`
CapeID *int64 `gorm:"column:cape_id;type:bigint" json:"cape_id,omitempty"`
UserID int64 `gorm:"column:user_id;not null;index:idx_profiles_user_created,priority:1;index:idx_profiles_user_active,priority:1" json:"user_id"`
Name string `gorm:"column:name;type:varchar(16);not null;uniqueIndex:idx_profiles_name" json:"name"` // Minecraft 角色名
SkinID *int64 `gorm:"column:skin_id;type:bigint;index:idx_profiles_skin_id" json:"skin_id,omitempty"`
CapeID *int64 `gorm:"column:cape_id;type:bigint;index:idx_profiles_cape_id" json:"cape_id,omitempty"`
RSAPrivateKey string `gorm:"column:rsa_private_key;type:text;not null" json:"-"` // RSA 私钥不返回给前端
IsActive bool `gorm:"column:is_active;not null;default:true;index" json:"is_active"`
LastUsedAt *time.Time `gorm:"column:last_used_at;type:timestamp" json:"last_used_at,omitempty"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp;not null;default:CURRENT_TIMESTAMP" json:"created_at"`
IsActive bool `gorm:"column:is_active;not null;default:true;index:idx_profiles_user_active,priority:2" json:"is_active"`
LastUsedAt *time.Time `gorm:"column:last_used_at;type:timestamp;index:idx_profiles_last_used,sort:desc" json:"last_used_at,omitempty"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp;not null;default:CURRENT_TIMESTAMP;index:idx_profiles_user_created,priority:2,sort:desc" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp;not null;default:CURRENT_TIMESTAMP" json:"updated_at"`
// 关联
User *User `gorm:"foreignKey:UserID" json:"user,omitempty"`
Skin *Texture `gorm:"foreignKey:SkinID" json:"skin,omitempty"`
Cape *Texture `gorm:"foreignKey:CapeID" json:"cape,omitempty"`
User *User `gorm:"foreignKey:UserID;constraint:OnDelete:CASCADE" json:"user,omitempty"`
Skin *Texture `gorm:"foreignKey:SkinID;constraint:OnDelete:SET NULL" json:"skin,omitempty"`
Cape *Texture `gorm:"foreignKey:CapeID;constraint:OnDelete:SET NULL" json:"cape,omitempty"`
}
// TableName 指定表名

View File

@@ -15,23 +15,23 @@ const (
// Texture 材质模型
type Texture struct {
ID int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
UploaderID int64 `gorm:"column:uploader_id;not null;index" json:"uploader_id"`
UploaderID int64 `gorm:"column:uploader_id;not null;index:idx_textures_uploader_status,priority:1;index:idx_textures_uploader_created,priority:1" json:"uploader_id"`
Name string `gorm:"column:name;type:varchar(100);not null;default:''" json:"name"`
Description string `gorm:"column:description;type:text" json:"description,omitempty"`
Type TextureType `gorm:"column:type;type:varchar(50);not null" json:"type"` // SKIN, CAPE
Type TextureType `gorm:"column:type;type:varchar(50);not null;index:idx_textures_public_type_status,priority:2" json:"type"` // SKIN, CAPE
URL string `gorm:"column:url;type:varchar(255);not null" json:"url"`
Hash string `gorm:"column:hash;type:varchar(64);not null;uniqueIndex" json:"hash"` // SHA-256
Hash string `gorm:"column:hash;type:varchar(64);not null;uniqueIndex:idx_textures_hash" json:"hash"` // SHA-256
Size int `gorm:"column:size;type:integer;not null;default:0" json:"size"`
IsPublic bool `gorm:"column:is_public;not null;default:false;index:idx_textures_public_type_status" json:"is_public"`
IsPublic bool `gorm:"column:is_public;not null;default:false;index:idx_textures_public_type_status,priority:1" json:"is_public"`
DownloadCount int `gorm:"column:download_count;type:integer;not null;default:0;index:idx_textures_download_count,sort:desc" json:"download_count"`
FavoriteCount int `gorm:"column:favorite_count;type:integer;not null;default:0;index:idx_textures_favorite_count,sort:desc" json:"favorite_count"`
IsSlim bool `gorm:"column:is_slim;not null;default:false" json:"is_slim"` // Alex(细) or Steve(粗)
Status int16 `gorm:"column:status;type:smallint;not null;default:1;index:idx_textures_public_type_status" json:"status"` // 1:正常, 0:审核中, -1:已删除
CreatedAt time.Time `gorm:"column:created_at;type:timestamp;not null;default:CURRENT_TIMESTAMP" json:"created_at"`
Status int16 `gorm:"column:status;type:smallint;not null;default:1;index:idx_textures_public_type_status,priority:3;index:idx_textures_uploader_status,priority:2" json:"status"` // 1:正常, 0:审核中, -1:已删除
CreatedAt time.Time `gorm:"column:created_at;type:timestamp;not null;default:CURRENT_TIMESTAMP;index:idx_textures_uploader_created,priority:2,sort:desc;index:idx_textures_created_at,sort:desc" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp;not null;default:CURRENT_TIMESTAMP" json:"updated_at"`
// 关联
Uploader *User `gorm:"foreignKey:UploaderID" json:"uploader,omitempty"`
Uploader *User `gorm:"foreignKey:UploaderID;constraint:OnDelete:CASCADE" json:"uploader,omitempty"`
}
// TableName 指定表名
@@ -42,13 +42,13 @@ func (Texture) TableName() string {
// UserTextureFavorite 用户材质收藏
type UserTextureFavorite struct {
ID int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
UserID int64 `gorm:"column:user_id;not null;index;uniqueIndex:uk_user_texture" json:"user_id"`
TextureID int64 `gorm:"column:texture_id;not null;index;uniqueIndex:uk_user_texture" json:"texture_id"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp;not null;default:CURRENT_TIMESTAMP;index" json:"created_at"`
UserID int64 `gorm:"column:user_id;not null;uniqueIndex:uk_user_texture,priority:1;index:idx_favorites_user_created,priority:1" json:"user_id"`
TextureID int64 `gorm:"column:texture_id;not null;uniqueIndex:uk_user_texture,priority:2;index:idx_favorites_texture_id" json:"texture_id"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp;not null;default:CURRENT_TIMESTAMP;index:idx_favorites_user_created,priority:2,sort:desc;index:idx_favorites_created_at,sort:desc" json:"created_at"`
// 关联
User *User `gorm:"foreignKey:UserID" json:"user,omitempty"`
Texture *Texture `gorm:"foreignKey:TextureID" json:"texture,omitempty"`
User *User `gorm:"foreignKey:UserID;constraint:OnDelete:CASCADE" json:"user,omitempty"`
Texture *Texture `gorm:"foreignKey:TextureID;constraint:OnDelete:CASCADE" json:"texture,omitempty"`
}
// TableName 指定表名
@@ -59,15 +59,15 @@ func (UserTextureFavorite) TableName() string {
// TextureDownloadLog 材质下载记录
type TextureDownloadLog struct {
ID int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
TextureID int64 `gorm:"column:texture_id;not null;index" json:"texture_id"`
UserID *int64 `gorm:"column:user_id;type:bigint;index" json:"user_id,omitempty"`
IPAddress string `gorm:"column:ip_address;type:inet;not null;index" json:"ip_address"`
TextureID int64 `gorm:"column:texture_id;not null;index:idx_download_logs_texture_created,priority:1" json:"texture_id"`
UserID *int64 `gorm:"column:user_id;type:bigint;index:idx_download_logs_user_id" json:"user_id,omitempty"`
IPAddress string `gorm:"column:ip_address;type:inet;not null;index:idx_download_logs_ip" json:"ip_address"`
UserAgent string `gorm:"column:user_agent;type:text" json:"user_agent,omitempty"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp;not null;default:CURRENT_TIMESTAMP;index:idx_download_logs_created_at,sort:desc" json:"created_at"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp;not null;default:CURRENT_TIMESTAMP;index:idx_download_logs_texture_created,priority:2,sort:desc;index:idx_download_logs_created_at,sort:desc" json:"created_at"`
// 关联
Texture *Texture `gorm:"foreignKey:TextureID" json:"texture,omitempty"`
User *User `gorm:"foreignKey:UserID" json:"user,omitempty"`
Texture *Texture `gorm:"foreignKey:TextureID;constraint:OnDelete:CASCADE" json:"texture,omitempty"`
User *User `gorm:"foreignKey:UserID;constraint:OnDelete:SET NULL" json:"user,omitempty"`
}
// TableName 指定表名

View File

@@ -2,13 +2,19 @@ package model
import "time"
// Token Yggdrasil 认证令牌模型
type Token struct {
AccessToken string `json:"_id"`
UserID int64 `json:"user_id"`
ClientToken string `json:"client_token"`
ProfileId string `json:"profile_id"`
Usable bool `json:"usable"`
IssueDate time.Time `json:"issue_date"`
AccessToken string `gorm:"column:access_token;type:varchar(64);primaryKey" json:"access_token"`
UserID int64 `gorm:"column:user_id;not null;index:idx_tokens_user_id" json:"user_id"`
ClientToken string `gorm:"column:client_token;type:varchar(64);not null;index:idx_tokens_client_token" json:"client_token"`
ProfileId string `gorm:"column:profile_id;type:varchar(36);not null;index:idx_tokens_profile_id" json:"profile_id"`
Usable bool `gorm:"column:usable;not null;default:true;index:idx_tokens_usable" json:"usable"`
IssueDate time.Time `gorm:"column:issue_date;type:timestamp;not null;default:CURRENT_TIMESTAMP;index:idx_tokens_issue_date,sort:desc" json:"issue_date"`
// 关联
User *User `gorm:"foreignKey:UserID;constraint:OnDelete:CASCADE" json:"user,omitempty"`
Profile *Profile `gorm:"foreignKey:ProfileId;references:UUID;constraint:OnDelete:CASCADE" json:"profile,omitempty"`
}
func (Token) TableName() string { return "token" }
// TableName 指定表名
func (Token) TableName() string { return "tokens" }

View File

@@ -9,16 +9,16 @@ import (
// User 用户模型
type User struct {
ID int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
Username string `gorm:"column:username;type:varchar(255);not null;uniqueIndex" json:"username"`
Username string `gorm:"column:username;type:varchar(255);not null;uniqueIndex:idx_user_username_status,priority:1" json:"username"`
Password string `gorm:"column:password;type:varchar(255);not null" json:"-"` // 密码不返回给前端
Email string `gorm:"column:email;type:varchar(255);not null;uniqueIndex" json:"email"`
Email string `gorm:"column:email;type:varchar(255);not null;uniqueIndex:idx_user_email_status,priority:1" json:"email"`
Avatar string `gorm:"column:avatar;type:varchar(255);not null;default:''" json:"avatar"`
Points int `gorm:"column:points;type:integer;not null;default:0" json:"points"`
Role string `gorm:"column:role;type:varchar(50);not null;default:'user'" json:"role"`
Status int16 `gorm:"column:status;type:smallint;not null;default:1" json:"status"` // 1:正常, 0:禁用, -1:删除
Properties *datatypes.JSON `gorm:"column:properties;type:jsonb" json:"properties,omitempty"` // JSON数据存储为PostgreSQL的JSONB类型
LastLoginAt *time.Time `gorm:"column:last_login_at;type:timestamp" json:"last_login_at,omitempty"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp;not null;default:CURRENT_TIMESTAMP" json:"created_at"`
Points int `gorm:"column:points;type:integer;not null;default:0;index:idx_user_points,sort:desc" json:"points"`
Role string `gorm:"column:role;type:varchar(50);not null;default:'user';index:idx_user_role_status,priority:1" json:"role"`
Status int16 `gorm:"column:status;type:smallint;not null;default:1;index:idx_user_username_status,priority:2;index:idx_user_email_status,priority:2;index:idx_user_role_status,priority:2" json:"status"` // 1:正常, 0:禁用, -1:删除
Properties *datatypes.JSON `gorm:"column:properties;type:jsonb" json:"properties,omitempty"` // JSON数据存储为PostgreSQL的JSONB类型
LastLoginAt *time.Time `gorm:"column:last_login_at;type:timestamp;index:idx_user_last_login,sort:desc" json:"last_login_at,omitempty"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp;not null;default:CURRENT_TIMESTAMP;index:idx_user_created_at,sort:desc" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp;not null;default:CURRENT_TIMESTAMP" json:"updated_at"`
}
@@ -30,20 +30,20 @@ func (User) TableName() string {
// UserPointLog 用户积分变更记录
type UserPointLog struct {
ID int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
UserID int64 `gorm:"column:user_id;not null;index" json:"user_id"`
ChangeType string `gorm:"column:change_type;type:varchar(50);not null" json:"change_type"` // EARN, SPEND, ADMIN_ADJUST
UserID int64 `gorm:"column:user_id;not null;index:idx_point_logs_user_created,priority:1" json:"user_id"`
ChangeType string `gorm:"column:change_type;type:varchar(50);not null;index:idx_point_logs_change_type" json:"change_type"` // EARN, SPEND, ADMIN_ADJUST
Amount int `gorm:"column:amount;type:integer;not null" json:"amount"`
BalanceBefore int `gorm:"column:balance_before;type:integer;not null" json:"balance_before"`
BalanceAfter int `gorm:"column:balance_after;type:integer;not null" json:"balance_after"`
Reason string `gorm:"column:reason;type:varchar(255);not null" json:"reason"`
ReferenceType string `gorm:"column:reference_type;type:varchar(50)" json:"reference_type,omitempty"`
ReferenceID *int64 `gorm:"column:reference_id;type:bigint" json:"reference_id,omitempty"`
OperatorID *int64 `gorm:"column:operator_id;type:bigint" json:"operator_id,omitempty"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp;not null;default:CURRENT_TIMESTAMP;index:idx_point_logs_created_at,sort:desc" json:"created_at"`
OperatorID *int64 `gorm:"column:operator_id;type:bigint;index" json:"operator_id,omitempty"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp;not null;default:CURRENT_TIMESTAMP;index:idx_point_logs_user_created,priority:2,sort:desc;index:idx_point_logs_created_at,sort:desc" json:"created_at"`
// 关联
User *User `gorm:"foreignKey:UserID" json:"user,omitempty"`
Operator *User `gorm:"foreignKey:OperatorID" json:"operator,omitempty"`
User *User `gorm:"foreignKey:UserID;constraint:OnDelete:CASCADE" json:"user,omitempty"`
Operator *User `gorm:"foreignKey:OperatorID;constraint:OnDelete:SET NULL" json:"operator,omitempty"`
}
// TableName 指定表名
@@ -54,16 +54,16 @@ func (UserPointLog) TableName() string {
// UserLoginLog 用户登录日志
type UserLoginLog struct {
ID int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
UserID int64 `gorm:"column:user_id;not null;index" json:"user_id"`
IPAddress string `gorm:"column:ip_address;type:inet;not null;index" json:"ip_address"`
UserID int64 `gorm:"column:user_id;not null;index:idx_login_logs_user_created,priority:1" json:"user_id"`
IPAddress string `gorm:"column:ip_address;type:inet;not null;index:idx_login_logs_ip" json:"ip_address"`
UserAgent string `gorm:"column:user_agent;type:text" json:"user_agent,omitempty"`
LoginMethod string `gorm:"column:login_method;type:varchar(50);not null;default:'PASSWORD'" json:"login_method"`
IsSuccess bool `gorm:"column:is_success;not null;index" json:"is_success"`
IsSuccess bool `gorm:"column:is_success;not null;index:idx_login_logs_success" json:"is_success"`
FailureReason string `gorm:"column:failure_reason;type:varchar(255)" json:"failure_reason,omitempty"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp;not null;default:CURRENT_TIMESTAMP;index:idx_login_logs_created_at,sort:desc" json:"created_at"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp;not null;default:CURRENT_TIMESTAMP;index:idx_login_logs_user_created,priority:2,sort:desc;index:idx_login_logs_created_at,sort:desc" json:"created_at"`
// 关联
User *User `gorm:"foreignKey:UserID" json:"user,omitempty"`
User *User `gorm:"foreignKey:UserID;constraint:OnDelete:CASCADE" json:"user,omitempty"`
}
// TableName 指定表名

View File

@@ -1,10 +1,12 @@
package model
import (
"crypto/rand"
"fmt"
"math/big"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
"math/rand"
"time"
)
// 定义随机字符集
@@ -13,36 +15,47 @@ const passwordChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234
// Yggdrasil ygg密码与用户id绑定
type Yggdrasil struct {
ID int64 `gorm:"column:id;primaryKey;not null" json:"id"`
Password string `gorm:"column:password;not null" json:"password"`
Password string `gorm:"column:password;type:varchar(255);not null" json:"-"` // 加密后的密码,不返回给前端
// 关联 - Yggdrasil的ID引用User的ID但不自动创建外键约束避免循环依赖
User *User `gorm:"foreignKey:ID;references:ID;constraint:OnDelete:CASCADE,OnUpdate:CASCADE" json:"user,omitempty"`
}
func (Yggdrasil) TableName() string { return "Yggdrasil" }
func (Yggdrasil) TableName() string { return "yggdrasil" }
// AfterCreate User创建后自动同步生成GeneratePassword记录
// AfterCreate User创建后自动同步生成Yggdrasil密码记录
func (u *User) AfterCreate(tx *gorm.DB) error {
randomPwd := GenerateRandomPassword(16)
// 生成随机明文密码
plainPassword := GenerateRandomPassword(16)
// 创建GeneratePassword记录
gp := Yggdrasil{
ID: u.ID, // 关联User的ID
Password: randomPwd, // 16位随机密码
// 使用 bcrypt 加密密码
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(plainPassword), bcrypt.DefaultCost)
if err != nil {
return fmt.Errorf("密码加密失败: %w", err)
}
if err := tx.Create(&gp).Error; err != nil {
// 若同步失败,可记录日志或回滚事务(根据业务需求处理)
return fmt.Errorf("同步生成密码失败: %w", err)
// 创建Yggdrasil记录存储加密后的密码
ygg := Yggdrasil{
ID: u.ID,
Password: string(hashedPassword),
}
if err := tx.Create(&ygg).Error; err != nil {
return fmt.Errorf("同步生成Yggdrasil密码失败: %w", err)
}
return nil
}
// GenerateRandomPassword 生成指定长度的随机字符串
// GenerateRandomPassword 生成指定长度的安全随机字符串
func GenerateRandomPassword(length int) string {
rand.Seed(time.Now().UnixNano()) // 初始化随机数种子
b := make([]byte, length)
for i := range b {
b[i] = passwordChars[rand.Intn(len(passwordChars))]
num, err := rand.Int(rand.Reader, big.NewInt(int64(len(passwordChars))))
if err != nil {
// 如果安全随机数生成失败,使用固定值(极端情况下的降级处理)
b[i] = passwordChars[0]
continue
}
b[i] = passwordChars[num.Int64()]
}
return string(b)
}