Files
backend/internal/service/profile_service.go

210 lines
5.4 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 service
import (
"carrotskin/internal/model"
"carrotskin/internal/repository"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
"github.com/google/uuid"
"github.com/jackc/pgx/v5"
"gorm.io/gorm"
)
// CreateProfile 创建档案
func CreateProfile(db *gorm.DB, userID int64, name string) (*model.Profile, error) {
// 验证用户存在
user, err := EnsureUserExists(userID)
if err != nil {
return nil, err
}
if user.Status != 1 {
return nil, fmt.Errorf("用户状态异常")
}
// 检查角色名是否已存在
existingName, err := repository.FindProfileByName(name)
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return nil, WrapError(err, "查询角色名失败")
}
if existingName != nil {
return nil, fmt.Errorf("角色名已被使用")
}
// 生成UUID和RSA密钥
profileUUID := uuid.New().String()
privateKey, err := generateRSAPrivateKey()
if err != nil {
return nil, WrapError(err, "生成RSA密钥失败")
}
// 创建档案
profile := &model.Profile{
UUID: profileUUID,
UserID: userID,
Name: name,
RSAPrivateKey: privateKey,
IsActive: true,
}
if err := repository.CreateProfile(profile); err != nil {
return nil, WrapError(err, "创建档案失败")
}
// 设置活跃状态
if err := repository.SetActiveProfile(profileUUID, userID); err != nil {
return nil, WrapError(err, "设置活跃状态失败")
}
return profile, nil
}
// GetProfileByUUID 获取档案详情
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, ErrProfileNotFound
}
return nil, WrapError(err, "查询档案失败")
}
return profile, nil
}
// GetUserProfiles 获取用户的所有档案
func GetUserProfiles(db *gorm.DB, userID int64) ([]*model.Profile, error) {
profiles, err := repository.FindProfilesByUserID(userID)
if err != nil {
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) {
// 获取档案并验证权限
profile, err := GetProfileWithPermissionCheck(uuid, userID)
if err != nil {
return nil, err
}
// 检查角色名是否重复
if name != nil && *name != profile.Name {
existingName, err := repository.FindProfileByName(*name)
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return nil, WrapError(err, "查询角色名失败")
}
if existingName != nil {
return nil, fmt.Errorf("角色名已被使用")
}
profile.Name = *name
}
// 更新皮肤和披风
if skinID != nil {
profile.SkinID = skinID
}
if capeID != nil {
profile.CapeID = capeID
}
if err := repository.UpdateProfile(profile); err != nil {
return nil, WrapError(err, "更新档案失败")
}
return repository.FindProfileByUUID(uuid)
}
// DeleteProfile 删除档案
func DeleteProfile(db *gorm.DB, uuid string, userID int64) error {
if _, err := GetProfileWithPermissionCheck(uuid, userID); err != nil {
return err
}
if err := repository.DeleteProfile(uuid); err != nil {
return WrapError(err, "删除档案失败")
}
return nil
}
// SetActiveProfile 设置活跃档案
func SetActiveProfile(db *gorm.DB, uuid string, userID int64) error {
if _, err := GetProfileWithPermissionCheck(uuid, userID); err != nil {
return err
}
if err := repository.SetActiveProfile(uuid, userID); err != nil {
return WrapError(err, "设置活跃状态失败")
}
if err := repository.UpdateProfileLastUsedAt(uuid); err != nil {
return WrapError(err, "更新使用时间失败")
}
return nil
}
// CheckProfileLimit 检查用户档案数量限制
func CheckProfileLimit(db *gorm.DB, userID int64, maxProfiles int) error {
count, err := repository.CountProfilesByUserID(userID)
if err != nil {
return WrapError(err, "查询档案数量失败")
}
if int(count) >= maxProfiles {
return fmt.Errorf("已达到档案数量上限(%d个", maxProfiles)
}
return nil
}
// generateRSAPrivateKey 生成RSA-2048私钥PEM格式
func generateRSAPrivateKey() (string, error) {
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return "", err
}
privateKeyBytes := x509.MarshalPKCS1PrivateKey(privateKey)
privateKeyPEM := pem.EncodeToMemory(&pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: privateKeyBytes,
})
return string(privateKeyPEM), nil
}
func ValidateProfileByUserID(db *gorm.DB, userId int64, UUID string) (bool, error) {
if userId == 0 || UUID == "" {
return false, errors.New("用户ID或配置文件ID不能为空")
}
profile, err := repository.FindProfileByUUID(UUID)
if err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return false, errors.New("配置文件不存在")
}
return false, WrapError(err, "验证配置文件失败")
}
return profile.UserID == userId, nil
}
func GetProfilesDataByNames(db *gorm.DB, names []string) ([]*model.Profile, error) {
profiles, err := repository.GetProfilesByNames(names)
if err != nil {
return nil, WrapError(err, "查找失败")
}
return profiles, nil
}
func GetProfileKeyPair(db *gorm.DB, profileId string) (*model.KeyPair, error) {
keyPair, err := repository.GetProfileKeyPair(profileId)
if err != nil {
return nil, WrapError(err, "查找失败")
}
return keyPair, nil
}