feat: Enhance dependency injection and service integration

- 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.
This commit is contained in:
lan
2025-12-02 22:52:33 +08:00
parent 792e96b238
commit 034e02e93a
54 changed files with 2305 additions and 2708 deletions

View File

@@ -4,7 +4,6 @@ import (
"bytes"
"carrotskin/internal/container"
"carrotskin/internal/model"
"carrotskin/internal/service"
"carrotskin/pkg/utils"
"io"
"net/http"
@@ -189,9 +188,9 @@ func (h *YggdrasilHandler) Authenticate(c *gin.Context) {
var UUID string
if emailRegex.MatchString(request.Identifier) {
userId, err = service.GetUserIDByEmail(h.container.DB, request.Identifier)
userId, err = h.container.YggdrasilService.GetUserIDByEmail(c.Request.Context(), request.Identifier)
} else {
profile, err = service.GetProfileByProfileName(h.container.DB, request.Identifier)
profile, err = h.container.ProfileRepo.FindByName(request.Identifier)
if err != nil {
h.logger.Error("用户名不存在", zap.String("identifier", request.Identifier), zap.Error(err))
c.JSON(http.StatusForbidden, gin.H{"error": err.Error()})
@@ -207,27 +206,27 @@ func (h *YggdrasilHandler) Authenticate(c *gin.Context) {
return
}
if err := service.VerifyPassword(h.container.DB, request.Password, userId); err != nil {
if err := h.container.YggdrasilService.VerifyPassword(c.Request.Context(), request.Password, userId); err != nil {
h.logger.Warn("认证失败: 密码错误", zap.Error(err))
c.JSON(http.StatusForbidden, gin.H{"error": ErrWrongPassword})
return
}
selectedProfile, availableProfiles, accessToken, clientToken, err := h.container.TokenService.Create(userId, UUID, request.ClientToken)
selectedProfile, availableProfiles, accessToken, clientToken, err := h.container.TokenService.Create(c.Request.Context(), userId, UUID, request.ClientToken)
if err != nil {
h.logger.Error("生成令牌失败", zap.Error(err), zap.Int64("userId", userId))
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
user, err := h.container.UserService.GetByID(userId)
user, err := h.container.UserService.GetByID(c.Request.Context(), userId)
if err != nil {
h.logger.Error("获取用户信息失败", zap.Error(err), zap.Int64("userId", userId))
}
availableProfilesData := make([]map[string]interface{}, 0, len(availableProfiles))
for _, p := range availableProfiles {
availableProfilesData = append(availableProfilesData, service.SerializeProfile(h.container.DB, h.logger, h.container.Redis, *p))
availableProfilesData = append(availableProfilesData, h.container.YggdrasilService.SerializeProfile(c.Request.Context(), *p))
}
response := AuthenticateResponse{
@@ -237,11 +236,11 @@ func (h *YggdrasilHandler) Authenticate(c *gin.Context) {
}
if selectedProfile != nil {
response.SelectedProfile = service.SerializeProfile(h.container.DB, h.logger, h.container.Redis, *selectedProfile)
response.SelectedProfile = h.container.YggdrasilService.SerializeProfile(c.Request.Context(), *selectedProfile)
}
if request.RequestUser && user != nil {
response.User = service.SerializeUser(h.logger, user, UUID)
response.User = h.container.YggdrasilService.SerializeUser(c.Request.Context(), user, UUID)
}
h.logger.Info("用户认证成功", zap.Int64("userId", userId))
@@ -257,7 +256,7 @@ func (h *YggdrasilHandler) ValidToken(c *gin.Context) {
return
}
if h.container.TokenService.Validate(request.AccessToken, request.ClientToken) {
if h.container.TokenService.Validate(c.Request.Context(), request.AccessToken, request.ClientToken) {
h.logger.Info("令牌验证成功", zap.String("accessToken", request.AccessToken))
c.JSON(http.StatusNoContent, gin.H{"valid": true})
} else {
@@ -275,17 +274,17 @@ func (h *YggdrasilHandler) RefreshToken(c *gin.Context) {
return
}
UUID, err := h.container.TokenService.GetUUIDByAccessToken(request.AccessToken)
UUID, err := h.container.TokenService.GetUUIDByAccessToken(c.Request.Context(), request.AccessToken)
if err != nil {
h.logger.Warn("刷新令牌失败: 无效的访问令牌", zap.String("token", request.AccessToken), zap.Error(err))
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
userID, _ := h.container.TokenService.GetUserIDByAccessToken(request.AccessToken)
userID, _ := h.container.TokenService.GetUserIDByAccessToken(c.Request.Context(), request.AccessToken)
UUID = utils.FormatUUID(UUID)
profile, err := h.container.ProfileService.GetByUUID(UUID)
profile, err := h.container.ProfileService.GetByUUID(c.Request.Context(), UUID)
if err != nil {
h.logger.Error("刷新令牌失败: 无法获取用户信息", zap.Error(err))
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
@@ -322,15 +321,15 @@ func (h *YggdrasilHandler) RefreshToken(c *gin.Context) {
return
}
profileData = service.SerializeProfile(h.container.DB, h.logger, h.container.Redis, *profile)
profileData = h.container.YggdrasilService.SerializeProfile(c.Request.Context(), *profile)
}
user, _ := h.container.UserService.GetByID(userID)
user, _ := h.container.UserService.GetByID(c.Request.Context(), userID)
if request.RequestUser && user != nil {
userData = service.SerializeUser(h.logger, user, UUID)
userData = h.container.YggdrasilService.SerializeUser(c.Request.Context(), user, UUID)
}
newAccessToken, newClientToken, err := h.container.TokenService.Refresh(
newAccessToken, newClientToken, err := h.container.TokenService.Refresh(c.Request.Context(),
request.AccessToken,
request.ClientToken,
profileID,
@@ -359,7 +358,7 @@ func (h *YggdrasilHandler) InvalidToken(c *gin.Context) {
return
}
h.container.TokenService.Invalidate(request.AccessToken)
h.container.TokenService.Invalidate(c.Request.Context(), request.AccessToken)
h.logger.Info("令牌已失效", zap.String("token", request.AccessToken))
c.JSON(http.StatusNoContent, gin.H{})
}
@@ -379,20 +378,20 @@ func (h *YggdrasilHandler) SignOut(c *gin.Context) {
return
}
user, err := h.container.UserService.GetByEmail(request.Email)
user, err := h.container.UserService.GetByEmail(c.Request.Context(), request.Email)
if err != nil || user == nil {
h.logger.Warn("登出失败: 用户不存在", zap.String("email", request.Email), zap.Error(err))
c.JSON(http.StatusBadRequest, gin.H{"error": "用户不存在"})
return
}
if err := service.VerifyPassword(h.container.DB, request.Password, user.ID); err != nil {
if err := h.container.YggdrasilService.VerifyPassword(c.Request.Context(), request.Password, user.ID); err != nil {
h.logger.Warn("登出失败: 密码错误", zap.Int64("userId", user.ID))
c.JSON(http.StatusBadRequest, gin.H{"error": ErrWrongPassword})
return
}
h.container.TokenService.InvalidateUserTokens(user.ID)
h.container.TokenService.InvalidateUserTokens(c.Request.Context(), user.ID)
h.logger.Info("用户登出成功", zap.Int64("userId", user.ID))
c.JSON(http.StatusNoContent, gin.H{"valid": true})
}
@@ -402,7 +401,7 @@ func (h *YggdrasilHandler) GetProfileByUUID(c *gin.Context) {
uuid := utils.FormatUUID(c.Param("uuid"))
h.logger.Info("获取配置文件请求", zap.String("uuid", uuid))
profile, err := h.container.ProfileService.GetByUUID(uuid)
profile, err := h.container.ProfileService.GetByUUID(c.Request.Context(), uuid)
if err != nil {
h.logger.Error("获取配置文件失败", zap.Error(err), zap.String("uuid", uuid))
standardResponse(c, http.StatusInternalServerError, nil, err.Error())
@@ -410,7 +409,7 @@ func (h *YggdrasilHandler) GetProfileByUUID(c *gin.Context) {
}
h.logger.Info("成功获取配置文件", zap.String("uuid", uuid), zap.String("name", profile.Name))
c.JSON(http.StatusOK, service.SerializeProfile(h.container.DB, h.logger, h.container.Redis, *profile))
c.JSON(http.StatusOK, h.container.YggdrasilService.SerializeProfile(c.Request.Context(), *profile))
}
// JoinServer 加入服务器
@@ -430,7 +429,7 @@ func (h *YggdrasilHandler) JoinServer(c *gin.Context) {
zap.String("ip", clientIP),
)
if err := service.JoinServer(h.container.DB, h.logger, h.container.Redis, request.ServerID, request.AccessToken, request.SelectedProfile, clientIP); err != nil {
if err := h.container.YggdrasilService.JoinServer(c.Request.Context(), request.ServerID, request.AccessToken, request.SelectedProfile, clientIP); err != nil {
h.logger.Error("加入服务器失败",
zap.Error(err),
zap.String("serverId", request.ServerID),
@@ -473,7 +472,7 @@ func (h *YggdrasilHandler) HasJoinedServer(c *gin.Context) {
zap.String("ip", clientIP),
)
if err := service.HasJoinedServer(h.logger, h.container.Redis, serverID, username, clientIP); err != nil {
if err := h.container.YggdrasilService.HasJoinedServer(c.Request.Context(), serverID, username, clientIP); err != nil {
h.logger.Warn("会话验证失败",
zap.Error(err),
zap.String("serverId", serverID),
@@ -484,7 +483,7 @@ func (h *YggdrasilHandler) HasJoinedServer(c *gin.Context) {
return
}
profile, err := h.container.ProfileService.GetByUUID(username)
profile, err := h.container.ProfileService.GetByUUID(c.Request.Context(), username)
if err != nil {
h.logger.Error("获取用户配置文件失败", zap.Error(err), zap.String("username", username))
standardResponse(c, http.StatusNoContent, nil, ErrProfileNotFound)
@@ -496,7 +495,7 @@ func (h *YggdrasilHandler) HasJoinedServer(c *gin.Context) {
zap.String("username", username),
zap.String("uuid", profile.UUID),
)
c.JSON(200, service.SerializeProfile(h.container.DB, h.logger, h.container.Redis, *profile))
c.JSON(200, h.container.YggdrasilService.SerializeProfile(c.Request.Context(), *profile))
}
// GetProfilesByName 批量获取配置文件
@@ -511,7 +510,7 @@ func (h *YggdrasilHandler) GetProfilesByName(c *gin.Context) {
h.logger.Info("接收到批量获取配置文件请求", zap.Int("count", len(names)))
profiles, err := h.container.ProfileService.GetByNames(names)
profiles, err := h.container.ProfileService.GetByNames(c.Request.Context(), names)
if err != nil {
h.logger.Error("获取配置文件失败", zap.Error(err))
}
@@ -535,7 +534,7 @@ func (h *YggdrasilHandler) GetMetaData(c *gin.Context) {
}
skinDomains := []string{".hitwh.games", ".littlelan.cn"}
signature, err := service.GetPublicKeyFromRedisFunc(h.logger, h.container.Redis)
signature, err := h.container.YggdrasilService.GetPublicKey(c.Request.Context())
if err != nil {
h.logger.Error("获取公钥失败", zap.Error(err))
standardResponse(c, http.StatusInternalServerError, nil, ErrInternalServer)
@@ -573,7 +572,7 @@ func (h *YggdrasilHandler) GetPlayerCertificates(c *gin.Context) {
return
}
uuid, err := h.container.TokenService.GetUUIDByAccessToken(tokenID)
uuid, err := h.container.TokenService.GetUUIDByAccessToken(c.Request.Context(), tokenID)
if uuid == "" {
h.logger.Error("获取玩家UUID失败", zap.Error(err))
standardResponse(c, http.StatusInternalServerError, nil, ErrInternalServer)
@@ -582,7 +581,7 @@ func (h *YggdrasilHandler) GetPlayerCertificates(c *gin.Context) {
uuid = utils.FormatUUID(uuid)
certificate, err := service.GeneratePlayerCertificate(h.container.DB, h.logger, h.container.Redis, uuid)
certificate, err := h.container.YggdrasilService.GeneratePlayerCertificate(c.Request.Context(), uuid)
if err != nil {
h.logger.Error("生成玩家证书失败", zap.Error(err))
standardResponse(c, http.StatusInternalServerError, nil, ErrInternalServer)