Files
backend/internal/service/profile_service.go
lafay 801f1b1397 refactor: Implement dependency injection for handlers and services
- Refactored AuthHandler, UserHandler, TextureHandler, ProfileHandler, CaptchaHandler, and YggdrasilHandler to use dependency injection.
- Removed direct instantiation of services and repositories within handlers, replacing them with constructor injection.
- Updated the container to initialize service instances and provide them to handlers.
- Enhanced code structure for better testability and adherence to Go best practices.
2025-12-02 19:47:04 +08:00

235 lines
5.8 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"
"go.uber.org/zap"
"gorm.io/gorm"
)
// profileServiceImpl ProfileService的实现
type profileServiceImpl struct {
profileRepo repository.ProfileRepository
userRepo repository.UserRepository
logger *zap.Logger
}
// NewProfileService 创建ProfileService实例
func NewProfileService(
profileRepo repository.ProfileRepository,
userRepo repository.UserRepository,
logger *zap.Logger,
) ProfileService {
return &profileServiceImpl{
profileRepo: profileRepo,
userRepo: userRepo,
logger: logger,
}
}
func (s *profileServiceImpl) Create(userID int64, name string) (*model.Profile, error) {
// 验证用户存在
user, err := s.userRepo.FindByID(userID)
if err != nil || user == nil {
return nil, errors.New("用户不存在")
}
if user.Status != 1 {
return nil, errors.New("用户状态异常")
}
// 检查角色名是否已存在
existingName, err := s.profileRepo.FindByName(name)
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fmt.Errorf("查询角色名失败: %w", err)
}
if existingName != nil {
return nil, errors.New("角色名已被使用")
}
// 生成UUID和RSA密钥
profileUUID := uuid.New().String()
privateKey, err := generateRSAPrivateKeyInternal()
if err != nil {
return nil, fmt.Errorf("生成RSA密钥失败: %w", err)
}
// 创建档案
profile := &model.Profile{
UUID: profileUUID,
UserID: userID,
Name: name,
RSAPrivateKey: privateKey,
IsActive: true,
}
if err := s.profileRepo.Create(profile); err != nil {
return nil, fmt.Errorf("创建档案失败: %w", err)
}
// 设置活跃状态
if err := s.profileRepo.SetActive(profileUUID, userID); err != nil {
return nil, fmt.Errorf("设置活跃状态失败: %w", err)
}
return profile, nil
}
func (s *profileServiceImpl) GetByUUID(uuid string) (*model.Profile, error) {
profile, err := s.profileRepo.FindByUUID(uuid)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, ErrProfileNotFound
}
return nil, fmt.Errorf("查询档案失败: %w", err)
}
return profile, nil
}
func (s *profileServiceImpl) GetByUserID(userID int64) ([]*model.Profile, error) {
profiles, err := s.profileRepo.FindByUserID(userID)
if err != nil {
return nil, fmt.Errorf("查询档案列表失败: %w", err)
}
return profiles, nil
}
func (s *profileServiceImpl) Update(uuid string, userID int64, name *string, skinID, capeID *int64) (*model.Profile, error) {
// 获取档案并验证权限
profile, err := s.profileRepo.FindByUUID(uuid)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, ErrProfileNotFound
}
return nil, fmt.Errorf("查询档案失败: %w", err)
}
if profile.UserID != userID {
return nil, ErrProfileNoPermission
}
// 检查角色名是否重复
if name != nil && *name != profile.Name {
existingName, err := s.profileRepo.FindByName(*name)
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fmt.Errorf("查询角色名失败: %w", err)
}
if existingName != nil {
return nil, errors.New("角色名已被使用")
}
profile.Name = *name
}
// 更新皮肤和披风
if skinID != nil {
profile.SkinID = skinID
}
if capeID != nil {
profile.CapeID = capeID
}
if err := s.profileRepo.Update(profile); err != nil {
return nil, fmt.Errorf("更新档案失败: %w", err)
}
return s.profileRepo.FindByUUID(uuid)
}
func (s *profileServiceImpl) Delete(uuid string, userID int64) error {
// 获取档案并验证权限
profile, err := s.profileRepo.FindByUUID(uuid)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return ErrProfileNotFound
}
return fmt.Errorf("查询档案失败: %w", err)
}
if profile.UserID != userID {
return ErrProfileNoPermission
}
if err := s.profileRepo.Delete(uuid); err != nil {
return fmt.Errorf("删除档案失败: %w", err)
}
return nil
}
func (s *profileServiceImpl) SetActive(uuid string, userID int64) error {
// 获取档案并验证权限
profile, err := s.profileRepo.FindByUUID(uuid)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return ErrProfileNotFound
}
return fmt.Errorf("查询档案失败: %w", err)
}
if profile.UserID != userID {
return ErrProfileNoPermission
}
if err := s.profileRepo.SetActive(uuid, userID); err != nil {
return fmt.Errorf("设置活跃状态失败: %w", err)
}
if err := s.profileRepo.UpdateLastUsedAt(uuid); err != nil {
return fmt.Errorf("更新使用时间失败: %w", err)
}
return nil
}
func (s *profileServiceImpl) CheckLimit(userID int64, maxProfiles int) error {
count, err := s.profileRepo.CountByUserID(userID)
if err != nil {
return fmt.Errorf("查询档案数量失败: %w", err)
}
if int(count) >= maxProfiles {
return fmt.Errorf("已达到档案数量上限(%d个", maxProfiles)
}
return nil
}
func (s *profileServiceImpl) GetByNames(names []string) ([]*model.Profile, error) {
profiles, err := s.profileRepo.GetByNames(names)
if err != nil {
return nil, fmt.Errorf("查找失败: %w", err)
}
return profiles, nil
}
func (s *profileServiceImpl) GetByProfileName(name string) (*model.Profile, error) {
profile, err := s.profileRepo.FindByName(name)
if err != nil {
return nil, errors.New("用户角色未创建")
}
return profile, nil
}
// generateRSAPrivateKeyInternal 生成RSA-2048私钥PEM格式
func generateRSAPrivateKeyInternal() (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
}