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

@@ -9,6 +9,7 @@ import (
"encoding/pem"
"errors"
"fmt"
"github.com/google/uuid"
"github.com/jackc/pgx/v5"
"gorm.io/gorm"
@@ -16,53 +17,47 @@ import (
// CreateProfile 创建档案
func CreateProfile(db *gorm.DB, userID int64, name string) (*model.Profile, error) {
// 1. 验证用户存在
user, err := repository.FindUserByID(userID)
// 验证用户存在
user, err := EnsureUserExists(userID)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fmt.Errorf("用户不存在")
}
return nil, fmt.Errorf("查询用户失败: %w", err)
return nil, err
}
if user.Status != 1 {
return nil, fmt.Errorf("用户状态异常")
}
// 2. 检查角色名是否已存在
// 检查角色名是否已存在
existingName, err := repository.FindProfileByName(name)
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fmt.Errorf("查询角色名失败: %w", err)
return nil, WrapError(err, "查询角色名失败")
}
if existingName != nil {
return nil, fmt.Errorf("角色名已被使用")
}
// 3. 生成UUID
// 生成UUID和RSA密钥
profileUUID := uuid.New().String()
// 4. 生成RSA密钥对
privateKey, err := generateRSAPrivateKey()
if err != nil {
return nil, fmt.Errorf("生成RSA密钥失败: %w", err)
return nil, WrapError(err, "生成RSA密钥失败")
}
// 5. 创建档案
// 创建档案
profile := &model.Profile{
UUID: profileUUID,
UserID: userID,
Name: name,
RSAPrivateKey: privateKey,
IsActive: true, // 新创建的档案默认为活跃状态
IsActive: true,
}
if err := repository.CreateProfile(profile); err != nil {
return nil, fmt.Errorf("创建档案失败: %w", err)
return nil, WrapError(err, "创建档案失败")
}
// 6. 将用户的其他档案设置为非活跃
// 设置活跃状态
if err := repository.SetActiveProfile(profileUUID, userID); err != nil {
return nil, fmt.Errorf("设置活跃状态失败: %w", err)
return nil, WrapError(err, "设置活跃状态失败")
}
return profile, nil
@@ -73,9 +68,9 @@ func GetProfileByUUID(db *gorm.DB, uuid string) (*model.Profile, error) {
profile, err := repository.FindProfileByUUID(uuid)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fmt.Errorf("档案不存在")
return nil, ErrProfileNotFound
}
return nil, fmt.Errorf("查询档案失败: %w", err)
return nil, WrapError(err, "查询档案失败")
}
return profile, nil
}
@@ -84,32 +79,24 @@ func GetProfileByUUID(db *gorm.DB, uuid string) (*model.Profile, error) {
func GetUserProfiles(db *gorm.DB, userID int64) ([]*model.Profile, error) {
profiles, err := repository.FindProfilesByUserID(userID)
if err != nil {
return nil, fmt.Errorf("查询档案列表失败: %w", err)
return nil, WrapError(err, "查询档案列表失败")
}
return profiles, nil
}
// UpdateProfile 更新档案
func UpdateProfile(db *gorm.DB, uuid string, userID int64, name *string, skinID, capeID *int64) (*model.Profile, error) {
// 1. 查询档案
profile, err := repository.FindProfileByUUID(uuid)
// 获取档案并验证权限
profile, err := GetProfileWithPermissionCheck(uuid, userID)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fmt.Errorf("档案不存在")
}
return nil, fmt.Errorf("查询档案失败: %w", err)
return nil, err
}
// 2. 验证权限
if profile.UserID != userID {
return nil, fmt.Errorf("无权操作此档案")
}
// 3. 检查角色名是否重复
// 检查角色名是否重复
if name != nil && *name != profile.Name {
existingName, err := repository.FindProfileByName(*name)
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fmt.Errorf("查询角色名失败: %w", err)
return nil, WrapError(err, "查询角色名失败")
}
if existingName != nil {
return nil, fmt.Errorf("角色名已被使用")
@@ -117,7 +104,7 @@ func UpdateProfile(db *gorm.DB, uuid string, userID int64, name *string, skinID,
profile.Name = *name
}
// 4. 更新皮肤和披风
// 更新皮肤和披风
if skinID != nil {
profile.SkinID = skinID
}
@@ -125,63 +112,37 @@ func UpdateProfile(db *gorm.DB, uuid string, userID int64, name *string, skinID,
profile.CapeID = capeID
}
// 5. 保存更新
if err := repository.UpdateProfile(profile); err != nil {
return nil, fmt.Errorf("更新档案失败: %w", err)
return nil, WrapError(err, "更新档案失败")
}
// 6. 重新加载关联数据
return repository.FindProfileByUUID(uuid)
}
// DeleteProfile 删除档案
func DeleteProfile(db *gorm.DB, uuid string, userID int64) error {
// 1. 查询档案
profile, err := repository.FindProfileByUUID(uuid)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return fmt.Errorf("档案不存在")
}
return fmt.Errorf("查询档案失败: %w", err)
if _, err := GetProfileWithPermissionCheck(uuid, userID); err != nil {
return err
}
// 2. 验证权限
if profile.UserID != userID {
return fmt.Errorf("无权操作此档案")
}
// 3. 删除档案
if err := repository.DeleteProfile(uuid); err != nil {
return fmt.Errorf("删除档案失败: %w", err)
return WrapError(err, "删除档案失败")
}
return nil
}
// SetActiveProfile 设置活跃档案
func SetActiveProfile(db *gorm.DB, uuid string, userID int64) error {
// 1. 查询档案
profile, err := repository.FindProfileByUUID(uuid)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return fmt.Errorf("档案不存在")
}
return fmt.Errorf("查询档案失败: %w", err)
if _, err := GetProfileWithPermissionCheck(uuid, userID); err != nil {
return err
}
// 2. 验证权限
if profile.UserID != userID {
return fmt.Errorf("无权操作此档案")
}
// 3. 设置活跃状态
if err := repository.SetActiveProfile(uuid, userID); err != nil {
return fmt.Errorf("设置活跃状态失败: %w", err)
return WrapError(err, "设置活跃状态失败")
}
// 4. 更新最后使用时间
if err := repository.UpdateProfileLastUsedAt(uuid); err != nil {
return fmt.Errorf("更新使用时间失败: %w", err)
return WrapError(err, "更新使用时间失败")
}
return nil
@@ -191,25 +152,22 @@ func SetActiveProfile(db *gorm.DB, uuid string, userID int64) error {
func CheckProfileLimit(db *gorm.DB, userID int64, maxProfiles int) error {
count, err := repository.CountProfilesByUserID(userID)
if err != nil {
return fmt.Errorf("查询档案数量失败: %w", err)
return WrapError(err, "查询档案数量失败")
}
if int(count) >= maxProfiles {
return fmt.Errorf("已达到档案数量上限(%d个", maxProfiles)
}
return nil
}
// generateRSAPrivateKey 生成RSA-2048私钥PEM格式
func generateRSAPrivateKey() (string, error) {
// 生成2048位RSA密钥对
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return "", err
}
// 将私钥编码为PEM格式
privateKeyBytes := x509.MarshalPKCS1PrivateKey(privateKey)
privateKeyPEM := pem.EncodeToMemory(&pem.Block{
Type: "RSA PRIVATE KEY",
@@ -229,7 +187,7 @@ func ValidateProfileByUserID(db *gorm.DB, userId int64, UUID string) (bool, erro
if errors.Is(err, pgx.ErrNoRows) {
return false, errors.New("配置文件不存在")
}
return false, fmt.Errorf("验证配置文件失败: %w", err)
return false, WrapError(err, "验证配置文件失败")
}
return profile.UserID == userId, nil
}
@@ -237,16 +195,15 @@ func ValidateProfileByUserID(db *gorm.DB, userId int64, UUID string) (bool, erro
func GetProfilesDataByNames(db *gorm.DB, names []string) ([]*model.Profile, error) {
profiles, err := repository.GetProfilesByNames(names)
if err != nil {
return nil, fmt.Errorf("查找失败: %w", err)
return nil, WrapError(err, "查找失败")
}
return profiles, nil
}
// GetProfileKeyPair 从 PostgreSQL 获取密钥对GORM 实现,无手动 SQL
func GetProfileKeyPair(db *gorm.DB, profileId string) (*model.KeyPair, error) {
keyPair, err := repository.GetProfileKeyPair(profileId)
if err != nil {
return nil, fmt.Errorf("查找失败: %w", err)
return nil, WrapError(err, "查找失败")
}
return keyPair, nil
}