- Updated main.go to initialize email service and include it in the dependency injection container. - Refactored handlers to utilize context in service method calls, improving consistency and error handling. - Introduced new service options for upload, security, and captcha services, enhancing modularity and testability. - Removed unused repository implementations to streamline the codebase. This commit continues the effort to improve the architecture by ensuring all services are properly injected and utilized across the application.
981 lines
24 KiB
Go
981 lines
24 KiB
Go
package service
|
||
|
||
import (
|
||
"carrotskin/internal/model"
|
||
"carrotskin/pkg/database"
|
||
"errors"
|
||
"time"
|
||
)
|
||
|
||
// ============================================================================
|
||
// Repository Mocks
|
||
// ============================================================================
|
||
|
||
// MockUserRepository 模拟UserRepository
|
||
type MockUserRepository struct {
|
||
users map[int64]*model.User
|
||
// 用于模拟错误的标志
|
||
FailCreate bool
|
||
FailFindByID bool
|
||
FailFindByUsername bool
|
||
FailFindByEmail bool
|
||
FailUpdate bool
|
||
}
|
||
|
||
func NewMockUserRepository() *MockUserRepository {
|
||
return &MockUserRepository{
|
||
users: make(map[int64]*model.User),
|
||
}
|
||
}
|
||
|
||
func (m *MockUserRepository) Create(user *model.User) error {
|
||
if m.FailCreate {
|
||
return errors.New("mock create error")
|
||
}
|
||
if user.ID == 0 {
|
||
user.ID = int64(len(m.users) + 1)
|
||
}
|
||
m.users[user.ID] = user
|
||
return nil
|
||
}
|
||
|
||
func (m *MockUserRepository) FindByID(id int64) (*model.User, error) {
|
||
if m.FailFindByID {
|
||
return nil, errors.New("mock find error")
|
||
}
|
||
if user, ok := m.users[id]; ok {
|
||
return user, nil
|
||
}
|
||
return nil, nil
|
||
}
|
||
|
||
func (m *MockUserRepository) FindByUsername(username string) (*model.User, error) {
|
||
if m.FailFindByUsername {
|
||
return nil, errors.New("mock find by username error")
|
||
}
|
||
for _, user := range m.users {
|
||
if user.Username == username {
|
||
return user, nil
|
||
}
|
||
}
|
||
return nil, nil
|
||
}
|
||
|
||
func (m *MockUserRepository) FindByEmail(email string) (*model.User, error) {
|
||
if m.FailFindByEmail {
|
||
return nil, errors.New("mock find by email error")
|
||
}
|
||
for _, user := range m.users {
|
||
if user.Email == email {
|
||
return user, nil
|
||
}
|
||
}
|
||
return nil, nil
|
||
}
|
||
|
||
func (m *MockUserRepository) Update(user *model.User) error {
|
||
if m.FailUpdate {
|
||
return errors.New("mock update error")
|
||
}
|
||
m.users[user.ID] = user
|
||
return nil
|
||
}
|
||
|
||
func (m *MockUserRepository) UpdateFields(id int64, fields map[string]interface{}) error {
|
||
if m.FailUpdate {
|
||
return errors.New("mock update fields error")
|
||
}
|
||
_, ok := m.users[id]
|
||
if !ok {
|
||
return errors.New("user not found")
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func (m *MockUserRepository) Delete(id int64) error {
|
||
delete(m.users, id)
|
||
return nil
|
||
}
|
||
|
||
func (m *MockUserRepository) CreateLoginLog(log *model.UserLoginLog) error {
|
||
return nil
|
||
}
|
||
|
||
func (m *MockUserRepository) CreatePointLog(log *model.UserPointLog) error {
|
||
return nil
|
||
}
|
||
|
||
func (m *MockUserRepository) UpdatePoints(userID int64, amount int, changeType, reason string) error {
|
||
return nil
|
||
}
|
||
|
||
// MockProfileRepository 模拟ProfileRepository
|
||
type MockProfileRepository struct {
|
||
profiles map[string]*model.Profile
|
||
userProfiles map[int64][]*model.Profile
|
||
nextID int64
|
||
FailCreate bool
|
||
FailFind bool
|
||
FailUpdate bool
|
||
FailDelete bool
|
||
}
|
||
|
||
func NewMockProfileRepository() *MockProfileRepository {
|
||
return &MockProfileRepository{
|
||
profiles: make(map[string]*model.Profile),
|
||
userProfiles: make(map[int64][]*model.Profile),
|
||
nextID: 1,
|
||
}
|
||
}
|
||
|
||
func (m *MockProfileRepository) Create(profile *model.Profile) error {
|
||
if m.FailCreate {
|
||
return errors.New("mock create error")
|
||
}
|
||
m.profiles[profile.UUID] = profile
|
||
m.userProfiles[profile.UserID] = append(m.userProfiles[profile.UserID], profile)
|
||
return nil
|
||
}
|
||
|
||
func (m *MockProfileRepository) FindByUUID(uuid string) (*model.Profile, error) {
|
||
if m.FailFind {
|
||
return nil, errors.New("mock find error")
|
||
}
|
||
if profile, ok := m.profiles[uuid]; ok {
|
||
return profile, nil
|
||
}
|
||
return nil, errors.New("profile not found")
|
||
}
|
||
|
||
func (m *MockProfileRepository) FindByName(name string) (*model.Profile, error) {
|
||
if m.FailFind {
|
||
return nil, errors.New("mock find error")
|
||
}
|
||
for _, profile := range m.profiles {
|
||
if profile.Name == name {
|
||
return profile, nil
|
||
}
|
||
}
|
||
return nil, nil
|
||
}
|
||
|
||
func (m *MockProfileRepository) FindByUserID(userID int64) ([]*model.Profile, error) {
|
||
if m.FailFind {
|
||
return nil, errors.New("mock find error")
|
||
}
|
||
return m.userProfiles[userID], nil
|
||
}
|
||
|
||
func (m *MockProfileRepository) Update(profile *model.Profile) error {
|
||
if m.FailUpdate {
|
||
return errors.New("mock update error")
|
||
}
|
||
m.profiles[profile.UUID] = profile
|
||
return nil
|
||
}
|
||
|
||
func (m *MockProfileRepository) UpdateFields(uuid string, updates map[string]interface{}) error {
|
||
if m.FailUpdate {
|
||
return errors.New("mock update error")
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func (m *MockProfileRepository) Delete(uuid string) error {
|
||
if m.FailDelete {
|
||
return errors.New("mock delete error")
|
||
}
|
||
delete(m.profiles, uuid)
|
||
return nil
|
||
}
|
||
|
||
func (m *MockProfileRepository) CountByUserID(userID int64) (int64, error) {
|
||
return int64(len(m.userProfiles[userID])), nil
|
||
}
|
||
|
||
func (m *MockProfileRepository) SetActive(uuid string, userID int64) error {
|
||
return nil
|
||
}
|
||
|
||
func (m *MockProfileRepository) UpdateLastUsedAt(uuid string) error {
|
||
return nil
|
||
}
|
||
|
||
func (m *MockProfileRepository) GetByNames(names []string) ([]*model.Profile, error) {
|
||
var result []*model.Profile
|
||
for _, name := range names {
|
||
for _, profile := range m.profiles {
|
||
if profile.Name == name {
|
||
result = append(result, profile)
|
||
}
|
||
}
|
||
}
|
||
return result, nil
|
||
}
|
||
|
||
func (m *MockProfileRepository) GetKeyPair(profileId string) (*model.KeyPair, error) {
|
||
return nil, nil
|
||
}
|
||
|
||
func (m *MockProfileRepository) UpdateKeyPair(profileId string, keyPair *model.KeyPair) error {
|
||
return nil
|
||
}
|
||
|
||
// MockTextureRepository 模拟TextureRepository
|
||
type MockTextureRepository struct {
|
||
textures map[int64]*model.Texture
|
||
favorites map[int64]map[int64]bool // userID -> textureID -> favorited
|
||
nextID int64
|
||
FailCreate bool
|
||
FailFind bool
|
||
FailUpdate bool
|
||
FailDelete bool
|
||
}
|
||
|
||
func NewMockTextureRepository() *MockTextureRepository {
|
||
return &MockTextureRepository{
|
||
textures: make(map[int64]*model.Texture),
|
||
favorites: make(map[int64]map[int64]bool),
|
||
nextID: 1,
|
||
}
|
||
}
|
||
|
||
func (m *MockTextureRepository) Create(texture *model.Texture) error {
|
||
if m.FailCreate {
|
||
return errors.New("mock create error")
|
||
}
|
||
if texture.ID == 0 {
|
||
texture.ID = m.nextID
|
||
m.nextID++
|
||
}
|
||
m.textures[texture.ID] = texture
|
||
return nil
|
||
}
|
||
|
||
func (m *MockTextureRepository) FindByID(id int64) (*model.Texture, error) {
|
||
if m.FailFind {
|
||
return nil, errors.New("mock find error")
|
||
}
|
||
if texture, ok := m.textures[id]; ok {
|
||
return texture, nil
|
||
}
|
||
return nil, errors.New("texture not found")
|
||
}
|
||
|
||
func (m *MockTextureRepository) FindByHash(hash string) (*model.Texture, error) {
|
||
if m.FailFind {
|
||
return nil, errors.New("mock find error")
|
||
}
|
||
for _, texture := range m.textures {
|
||
if texture.Hash == hash {
|
||
return texture, nil
|
||
}
|
||
}
|
||
return nil, nil
|
||
}
|
||
|
||
func (m *MockTextureRepository) FindByUploaderID(uploaderID int64, page, pageSize int) ([]*model.Texture, int64, error) {
|
||
if m.FailFind {
|
||
return nil, 0, errors.New("mock find error")
|
||
}
|
||
var result []*model.Texture
|
||
for _, texture := range m.textures {
|
||
if texture.UploaderID == uploaderID {
|
||
result = append(result, texture)
|
||
}
|
||
}
|
||
return result, int64(len(result)), nil
|
||
}
|
||
|
||
func (m *MockTextureRepository) Search(keyword string, textureType model.TextureType, publicOnly bool, page, pageSize int) ([]*model.Texture, int64, error) {
|
||
if m.FailFind {
|
||
return nil, 0, errors.New("mock find error")
|
||
}
|
||
var result []*model.Texture
|
||
for _, texture := range m.textures {
|
||
if publicOnly && !texture.IsPublic {
|
||
continue
|
||
}
|
||
result = append(result, texture)
|
||
}
|
||
return result, int64(len(result)), nil
|
||
}
|
||
|
||
func (m *MockTextureRepository) Update(texture *model.Texture) error {
|
||
if m.FailUpdate {
|
||
return errors.New("mock update error")
|
||
}
|
||
m.textures[texture.ID] = texture
|
||
return nil
|
||
}
|
||
|
||
func (m *MockTextureRepository) UpdateFields(id int64, fields map[string]interface{}) error {
|
||
if m.FailUpdate {
|
||
return errors.New("mock update error")
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func (m *MockTextureRepository) Delete(id int64) error {
|
||
if m.FailDelete {
|
||
return errors.New("mock delete error")
|
||
}
|
||
delete(m.textures, id)
|
||
return nil
|
||
}
|
||
|
||
func (m *MockTextureRepository) IncrementDownloadCount(id int64) error {
|
||
if texture, ok := m.textures[id]; ok {
|
||
texture.DownloadCount++
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func (m *MockTextureRepository) IncrementFavoriteCount(id int64) error {
|
||
if texture, ok := m.textures[id]; ok {
|
||
texture.FavoriteCount++
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func (m *MockTextureRepository) DecrementFavoriteCount(id int64) error {
|
||
if texture, ok := m.textures[id]; ok && texture.FavoriteCount > 0 {
|
||
texture.FavoriteCount--
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func (m *MockTextureRepository) CreateDownloadLog(log *model.TextureDownloadLog) error {
|
||
return nil
|
||
}
|
||
|
||
func (m *MockTextureRepository) IsFavorited(userID, textureID int64) (bool, error) {
|
||
if userFavs, ok := m.favorites[userID]; ok {
|
||
return userFavs[textureID], nil
|
||
}
|
||
return false, nil
|
||
}
|
||
|
||
func (m *MockTextureRepository) AddFavorite(userID, textureID int64) error {
|
||
if m.favorites[userID] == nil {
|
||
m.favorites[userID] = make(map[int64]bool)
|
||
}
|
||
m.favorites[userID][textureID] = true
|
||
return nil
|
||
}
|
||
|
||
func (m *MockTextureRepository) RemoveFavorite(userID, textureID int64) error {
|
||
if userFavs, ok := m.favorites[userID]; ok {
|
||
delete(userFavs, textureID)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func (m *MockTextureRepository) GetUserFavorites(userID int64, page, pageSize int) ([]*model.Texture, int64, error) {
|
||
var result []*model.Texture
|
||
if userFavs, ok := m.favorites[userID]; ok {
|
||
for textureID := range userFavs {
|
||
if texture, exists := m.textures[textureID]; exists {
|
||
result = append(result, texture)
|
||
}
|
||
}
|
||
}
|
||
return result, int64(len(result)), nil
|
||
}
|
||
|
||
func (m *MockTextureRepository) CountByUploaderID(uploaderID int64) (int64, error) {
|
||
var count int64
|
||
for _, texture := range m.textures {
|
||
if texture.UploaderID == uploaderID {
|
||
count++
|
||
}
|
||
}
|
||
return count, nil
|
||
}
|
||
|
||
// MockTokenRepository 模拟TokenRepository
|
||
type MockTokenRepository struct {
|
||
tokens map[string]*model.Token
|
||
userTokens map[int64][]*model.Token
|
||
FailCreate bool
|
||
FailFind bool
|
||
FailDelete bool
|
||
}
|
||
|
||
func NewMockTokenRepository() *MockTokenRepository {
|
||
return &MockTokenRepository{
|
||
tokens: make(map[string]*model.Token),
|
||
userTokens: make(map[int64][]*model.Token),
|
||
}
|
||
}
|
||
|
||
func (m *MockTokenRepository) Create(token *model.Token) error {
|
||
if m.FailCreate {
|
||
return errors.New("mock create error")
|
||
}
|
||
m.tokens[token.AccessToken] = token
|
||
m.userTokens[token.UserID] = append(m.userTokens[token.UserID], token)
|
||
return nil
|
||
}
|
||
|
||
func (m *MockTokenRepository) FindByAccessToken(accessToken string) (*model.Token, error) {
|
||
if m.FailFind {
|
||
return nil, errors.New("mock find error")
|
||
}
|
||
if token, ok := m.tokens[accessToken]; ok {
|
||
return token, nil
|
||
}
|
||
return nil, errors.New("token not found")
|
||
}
|
||
|
||
func (m *MockTokenRepository) GetByUserID(userId int64) ([]*model.Token, error) {
|
||
if m.FailFind {
|
||
return nil, errors.New("mock find error")
|
||
}
|
||
return m.userTokens[userId], nil
|
||
}
|
||
|
||
func (m *MockTokenRepository) GetUUIDByAccessToken(accessToken string) (string, error) {
|
||
if m.FailFind {
|
||
return "", errors.New("mock find error")
|
||
}
|
||
if token, ok := m.tokens[accessToken]; ok {
|
||
return token.ProfileId, nil
|
||
}
|
||
return "", errors.New("token not found")
|
||
}
|
||
|
||
func (m *MockTokenRepository) GetUserIDByAccessToken(accessToken string) (int64, error) {
|
||
if m.FailFind {
|
||
return 0, errors.New("mock find error")
|
||
}
|
||
if token, ok := m.tokens[accessToken]; ok {
|
||
return token.UserID, nil
|
||
}
|
||
return 0, errors.New("token not found")
|
||
}
|
||
|
||
func (m *MockTokenRepository) DeleteByAccessToken(accessToken string) error {
|
||
if m.FailDelete {
|
||
return errors.New("mock delete error")
|
||
}
|
||
delete(m.tokens, accessToken)
|
||
return nil
|
||
}
|
||
|
||
func (m *MockTokenRepository) DeleteByUserID(userId int64) error {
|
||
if m.FailDelete {
|
||
return errors.New("mock delete error")
|
||
}
|
||
for _, token := range m.userTokens[userId] {
|
||
delete(m.tokens, token.AccessToken)
|
||
}
|
||
m.userTokens[userId] = nil
|
||
return nil
|
||
}
|
||
|
||
func (m *MockTokenRepository) BatchDelete(accessTokens []string) (int64, error) {
|
||
if m.FailDelete {
|
||
return 0, errors.New("mock delete error")
|
||
}
|
||
var count int64
|
||
for _, accessToken := range accessTokens {
|
||
if _, ok := m.tokens[accessToken]; ok {
|
||
delete(m.tokens, accessToken)
|
||
count++
|
||
}
|
||
}
|
||
return count, nil
|
||
}
|
||
|
||
// MockSystemConfigRepository 模拟SystemConfigRepository
|
||
type MockSystemConfigRepository struct {
|
||
configs map[string]*model.SystemConfig
|
||
}
|
||
|
||
func NewMockSystemConfigRepository() *MockSystemConfigRepository {
|
||
return &MockSystemConfigRepository{
|
||
configs: make(map[string]*model.SystemConfig),
|
||
}
|
||
}
|
||
|
||
func (m *MockSystemConfigRepository) GetByKey(key string) (*model.SystemConfig, error) {
|
||
if config, ok := m.configs[key]; ok {
|
||
return config, nil
|
||
}
|
||
return nil, nil
|
||
}
|
||
|
||
func (m *MockSystemConfigRepository) GetPublic() ([]model.SystemConfig, error) {
|
||
var result []model.SystemConfig
|
||
for _, v := range m.configs {
|
||
result = append(result, *v)
|
||
}
|
||
return result, nil
|
||
}
|
||
|
||
func (m *MockSystemConfigRepository) GetAll() ([]model.SystemConfig, error) {
|
||
var result []model.SystemConfig
|
||
for _, v := range m.configs {
|
||
result = append(result, *v)
|
||
}
|
||
return result, nil
|
||
}
|
||
|
||
func (m *MockSystemConfigRepository) Update(config *model.SystemConfig) error {
|
||
m.configs[config.Key] = config
|
||
return nil
|
||
}
|
||
|
||
func (m *MockSystemConfigRepository) UpdateValue(key, value string) error {
|
||
if config, ok := m.configs[key]; ok {
|
||
config.Value = value
|
||
return nil
|
||
}
|
||
return errors.New("config not found")
|
||
}
|
||
|
||
// ============================================================================
|
||
// Service Mocks
|
||
// ============================================================================
|
||
|
||
// MockUserService 模拟UserService
|
||
type MockUserService struct {
|
||
users map[int64]*model.User
|
||
maxProfilesPerUser int
|
||
maxTexturesPerUser int
|
||
FailRegister bool
|
||
FailLogin bool
|
||
FailGetByID bool
|
||
FailUpdate bool
|
||
}
|
||
|
||
func NewMockUserService() *MockUserService {
|
||
return &MockUserService{
|
||
users: make(map[int64]*model.User),
|
||
maxProfilesPerUser: 5,
|
||
maxTexturesPerUser: 50,
|
||
}
|
||
}
|
||
|
||
func (m *MockUserService) Register(username, password, email, avatar string) (*model.User, string, error) {
|
||
if m.FailRegister {
|
||
return nil, "", errors.New("mock register error")
|
||
}
|
||
user := &model.User{
|
||
ID: int64(len(m.users) + 1),
|
||
Username: username,
|
||
Email: email,
|
||
Avatar: avatar,
|
||
Status: 1,
|
||
}
|
||
m.users[user.ID] = user
|
||
return user, "mock-token", nil
|
||
}
|
||
|
||
func (m *MockUserService) Login(usernameOrEmail, password, ipAddress, userAgent string) (*model.User, string, error) {
|
||
if m.FailLogin {
|
||
return nil, "", errors.New("mock login error")
|
||
}
|
||
for _, user := range m.users {
|
||
if user.Username == usernameOrEmail || user.Email == usernameOrEmail {
|
||
return user, "mock-token", nil
|
||
}
|
||
}
|
||
return nil, "", errors.New("user not found")
|
||
}
|
||
|
||
func (m *MockUserService) GetByID(id int64) (*model.User, error) {
|
||
if m.FailGetByID {
|
||
return nil, errors.New("mock get by id error")
|
||
}
|
||
if user, ok := m.users[id]; ok {
|
||
return user, nil
|
||
}
|
||
return nil, nil
|
||
}
|
||
|
||
func (m *MockUserService) GetByEmail(email string) (*model.User, error) {
|
||
for _, user := range m.users {
|
||
if user.Email == email {
|
||
return user, nil
|
||
}
|
||
}
|
||
return nil, nil
|
||
}
|
||
|
||
func (m *MockUserService) UpdateInfo(user *model.User) error {
|
||
if m.FailUpdate {
|
||
return errors.New("mock update error")
|
||
}
|
||
m.users[user.ID] = user
|
||
return nil
|
||
}
|
||
|
||
func (m *MockUserService) UpdateAvatar(userID int64, avatarURL string) error {
|
||
if m.FailUpdate {
|
||
return errors.New("mock update error")
|
||
}
|
||
if user, ok := m.users[userID]; ok {
|
||
user.Avatar = avatarURL
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func (m *MockUserService) ChangePassword(userID int64, oldPassword, newPassword string) error {
|
||
return nil
|
||
}
|
||
|
||
func (m *MockUserService) ResetPassword(email, newPassword string) error {
|
||
return nil
|
||
}
|
||
|
||
func (m *MockUserService) ChangeEmail(userID int64, newEmail string) error {
|
||
if user, ok := m.users[userID]; ok {
|
||
user.Email = newEmail
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func (m *MockUserService) ValidateAvatarURL(avatarURL string) error {
|
||
return nil
|
||
}
|
||
|
||
func (m *MockUserService) GetMaxProfilesPerUser() int {
|
||
return m.maxProfilesPerUser
|
||
}
|
||
|
||
func (m *MockUserService) GetMaxTexturesPerUser() int {
|
||
return m.maxTexturesPerUser
|
||
}
|
||
|
||
// MockProfileService 模拟ProfileService
|
||
type MockProfileService struct {
|
||
profiles map[string]*model.Profile
|
||
FailCreate bool
|
||
FailGet bool
|
||
FailUpdate bool
|
||
FailDelete bool
|
||
}
|
||
|
||
func NewMockProfileService() *MockProfileService {
|
||
return &MockProfileService{
|
||
profiles: make(map[string]*model.Profile),
|
||
}
|
||
}
|
||
|
||
func (m *MockProfileService) Create(userID int64, name string) (*model.Profile, error) {
|
||
if m.FailCreate {
|
||
return nil, errors.New("mock create error")
|
||
}
|
||
profile := &model.Profile{
|
||
UUID: "mock-uuid-" + name,
|
||
UserID: userID,
|
||
Name: name,
|
||
}
|
||
m.profiles[profile.UUID] = profile
|
||
return profile, nil
|
||
}
|
||
|
||
func (m *MockProfileService) GetByUUID(uuid string) (*model.Profile, error) {
|
||
if m.FailGet {
|
||
return nil, errors.New("mock get error")
|
||
}
|
||
if profile, ok := m.profiles[uuid]; ok {
|
||
return profile, nil
|
||
}
|
||
return nil, errors.New("profile not found")
|
||
}
|
||
|
||
func (m *MockProfileService) GetByUserID(userID int64) ([]*model.Profile, error) {
|
||
if m.FailGet {
|
||
return nil, errors.New("mock get error")
|
||
}
|
||
var result []*model.Profile
|
||
for _, profile := range m.profiles {
|
||
if profile.UserID == userID {
|
||
result = append(result, profile)
|
||
}
|
||
}
|
||
return result, nil
|
||
}
|
||
|
||
func (m *MockProfileService) Update(uuid string, userID int64, name *string, skinID, capeID *int64) (*model.Profile, error) {
|
||
if m.FailUpdate {
|
||
return nil, errors.New("mock update error")
|
||
}
|
||
if profile, ok := m.profiles[uuid]; ok {
|
||
if name != nil {
|
||
profile.Name = *name
|
||
}
|
||
if skinID != nil {
|
||
profile.SkinID = skinID
|
||
}
|
||
if capeID != nil {
|
||
profile.CapeID = capeID
|
||
}
|
||
return profile, nil
|
||
}
|
||
return nil, errors.New("profile not found")
|
||
}
|
||
|
||
func (m *MockProfileService) Delete(uuid string, userID int64) error {
|
||
if m.FailDelete {
|
||
return errors.New("mock delete error")
|
||
}
|
||
delete(m.profiles, uuid)
|
||
return nil
|
||
}
|
||
|
||
func (m *MockProfileService) SetActive(uuid string, userID int64) error {
|
||
return nil
|
||
}
|
||
|
||
func (m *MockProfileService) CheckLimit(userID int64, maxProfiles int) error {
|
||
count := 0
|
||
for _, profile := range m.profiles {
|
||
if profile.UserID == userID {
|
||
count++
|
||
}
|
||
}
|
||
if count >= maxProfiles {
|
||
return errors.New("达到档案数量上限")
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func (m *MockProfileService) GetByNames(names []string) ([]*model.Profile, error) {
|
||
var result []*model.Profile
|
||
for _, name := range names {
|
||
for _, profile := range m.profiles {
|
||
if profile.Name == name {
|
||
result = append(result, profile)
|
||
}
|
||
}
|
||
}
|
||
return result, nil
|
||
}
|
||
|
||
func (m *MockProfileService) GetByProfileName(name string) (*model.Profile, error) {
|
||
for _, profile := range m.profiles {
|
||
if profile.Name == name {
|
||
return profile, nil
|
||
}
|
||
}
|
||
return nil, errors.New("profile not found")
|
||
}
|
||
|
||
// MockTextureService 模拟TextureService
|
||
type MockTextureService struct {
|
||
textures map[int64]*model.Texture
|
||
nextID int64
|
||
FailCreate bool
|
||
FailGet bool
|
||
FailUpdate bool
|
||
FailDelete bool
|
||
}
|
||
|
||
func NewMockTextureService() *MockTextureService {
|
||
return &MockTextureService{
|
||
textures: make(map[int64]*model.Texture),
|
||
nextID: 1,
|
||
}
|
||
}
|
||
|
||
func (m *MockTextureService) Create(uploaderID int64, name, description, textureType, url, hash string, size int, isPublic, isSlim bool) (*model.Texture, error) {
|
||
if m.FailCreate {
|
||
return nil, errors.New("mock create error")
|
||
}
|
||
texture := &model.Texture{
|
||
ID: m.nextID,
|
||
UploaderID: uploaderID,
|
||
Name: name,
|
||
Description: description,
|
||
URL: url,
|
||
Hash: hash,
|
||
Size: size,
|
||
IsPublic: isPublic,
|
||
IsSlim: isSlim,
|
||
}
|
||
m.textures[texture.ID] = texture
|
||
m.nextID++
|
||
return texture, nil
|
||
}
|
||
|
||
func (m *MockTextureService) GetByID(id int64) (*model.Texture, error) {
|
||
if m.FailGet {
|
||
return nil, errors.New("mock get error")
|
||
}
|
||
if texture, ok := m.textures[id]; ok {
|
||
return texture, nil
|
||
}
|
||
return nil, errors.New("texture not found")
|
||
}
|
||
|
||
func (m *MockTextureService) GetByUserID(uploaderID int64, page, pageSize int) ([]*model.Texture, int64, error) {
|
||
if m.FailGet {
|
||
return nil, 0, errors.New("mock get error")
|
||
}
|
||
var result []*model.Texture
|
||
for _, texture := range m.textures {
|
||
if texture.UploaderID == uploaderID {
|
||
result = append(result, texture)
|
||
}
|
||
}
|
||
return result, int64(len(result)), nil
|
||
}
|
||
|
||
func (m *MockTextureService) Search(keyword string, textureType model.TextureType, publicOnly bool, page, pageSize int) ([]*model.Texture, int64, error) {
|
||
if m.FailGet {
|
||
return nil, 0, errors.New("mock get error")
|
||
}
|
||
var result []*model.Texture
|
||
for _, texture := range m.textures {
|
||
if publicOnly && !texture.IsPublic {
|
||
continue
|
||
}
|
||
result = append(result, texture)
|
||
}
|
||
return result, int64(len(result)), nil
|
||
}
|
||
|
||
func (m *MockTextureService) Update(textureID, uploaderID int64, name, description string, isPublic *bool) (*model.Texture, error) {
|
||
if m.FailUpdate {
|
||
return nil, errors.New("mock update error")
|
||
}
|
||
if texture, ok := m.textures[textureID]; ok {
|
||
if name != "" {
|
||
texture.Name = name
|
||
}
|
||
if description != "" {
|
||
texture.Description = description
|
||
}
|
||
if isPublic != nil {
|
||
texture.IsPublic = *isPublic
|
||
}
|
||
return texture, nil
|
||
}
|
||
return nil, errors.New("texture not found")
|
||
}
|
||
|
||
func (m *MockTextureService) Delete(textureID, uploaderID int64) error {
|
||
if m.FailDelete {
|
||
return errors.New("mock delete error")
|
||
}
|
||
delete(m.textures, textureID)
|
||
return nil
|
||
}
|
||
|
||
func (m *MockTextureService) ToggleFavorite(userID, textureID int64) (bool, error) {
|
||
return true, nil
|
||
}
|
||
|
||
func (m *MockTextureService) GetUserFavorites(userID int64, page, pageSize int) ([]*model.Texture, int64, error) {
|
||
return nil, 0, nil
|
||
}
|
||
|
||
func (m *MockTextureService) CheckUploadLimit(uploaderID int64, maxTextures int) error {
|
||
count := 0
|
||
for _, texture := range m.textures {
|
||
if texture.UploaderID == uploaderID {
|
||
count++
|
||
}
|
||
}
|
||
if count >= maxTextures {
|
||
return errors.New("达到材质数量上限")
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// MockTokenService 模拟TokenService
|
||
type MockTokenService struct {
|
||
tokens map[string]*model.Token
|
||
FailCreate bool
|
||
FailValidate bool
|
||
FailRefresh bool
|
||
}
|
||
|
||
func NewMockTokenService() *MockTokenService {
|
||
return &MockTokenService{
|
||
tokens: make(map[string]*model.Token),
|
||
}
|
||
}
|
||
|
||
func (m *MockTokenService) Create(userID int64, uuid, clientToken string) (*model.Profile, []*model.Profile, string, string, error) {
|
||
if m.FailCreate {
|
||
return nil, nil, "", "", errors.New("mock create error")
|
||
}
|
||
accessToken := "mock-access-token"
|
||
if clientToken == "" {
|
||
clientToken = "mock-client-token"
|
||
}
|
||
token := &model.Token{
|
||
AccessToken: accessToken,
|
||
ClientToken: clientToken,
|
||
UserID: userID,
|
||
ProfileId: uuid,
|
||
Usable: true,
|
||
}
|
||
m.tokens[accessToken] = token
|
||
return nil, nil, accessToken, clientToken, nil
|
||
}
|
||
|
||
func (m *MockTokenService) Validate(accessToken, clientToken string) bool {
|
||
if m.FailValidate {
|
||
return false
|
||
}
|
||
if token, ok := m.tokens[accessToken]; ok {
|
||
if clientToken == "" || token.ClientToken == clientToken {
|
||
return token.Usable
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
func (m *MockTokenService) Refresh(accessToken, clientToken, selectedProfileID string) (string, string, error) {
|
||
if m.FailRefresh {
|
||
return "", "", errors.New("mock refresh error")
|
||
}
|
||
return "new-access-token", clientToken, nil
|
||
}
|
||
|
||
func (m *MockTokenService) Invalidate(accessToken string) {
|
||
delete(m.tokens, accessToken)
|
||
}
|
||
|
||
func (m *MockTokenService) InvalidateUserTokens(userID int64) {
|
||
for key, token := range m.tokens {
|
||
if token.UserID == userID {
|
||
delete(m.tokens, key)
|
||
}
|
||
}
|
||
}
|
||
|
||
func (m *MockTokenService) GetUUIDByAccessToken(accessToken string) (string, error) {
|
||
if token, ok := m.tokens[accessToken]; ok {
|
||
return token.ProfileId, nil
|
||
}
|
||
return "", errors.New("token not found")
|
||
}
|
||
|
||
func (m *MockTokenService) GetUserIDByAccessToken(accessToken string) (int64, error) {
|
||
if token, ok := m.tokens[accessToken]; ok {
|
||
return token.UserID, nil
|
||
}
|
||
return 0, errors.New("token not found")
|
||
}
|
||
|
||
// ============================================================================
|
||
// CacheManager Mock - uses database.CacheManager with nil redis
|
||
// ============================================================================
|
||
|
||
// NewMockCacheManager 创建一个禁用的 CacheManager 用于测试
|
||
// 通过设置 Enabled = false,缓存操作会被跳过,测试不依赖 Redis
|
||
func NewMockCacheManager() *database.CacheManager {
|
||
return database.NewCacheManager(nil, database.CacheConfig{
|
||
Prefix: "test:",
|
||
Expiration: 5 * time.Minute,
|
||
Enabled: false, // 禁用缓存,测试不依赖 Redis
|
||
})
|
||
}
|