topfans/backend/services/userService/provider/auth_provider.go
2026-05-26 13:23:04 +08:00

329 lines
8.1 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 provider
import (
"context"
"time"
appErrors "github.com/topfans/backend/pkg/errors"
"github.com/topfans/backend/pkg/logger"
pbCommon "github.com/topfans/backend/pkg/proto/common"
pb "github.com/topfans/backend/pkg/proto/user"
"github.com/topfans/backend/services/userService/service"
"go.uber.org/zap"
)
// AuthProvider 认证Provider实现
type AuthProvider struct {
authService service.AuthService
}
// getClientIP 从 context 中获取客户端 IP简化实现
func getClientIP(ctx context.Context) string {
// 在实际部署中,应从网关传递的 attachments 或 header 中获取
// 这里返回一个默认值让代码能编译通过
return "127.0.0.1"
}
// NewAuthProvider 创建认证Provider实例
func NewAuthProvider(authService service.AuthService) *AuthProvider {
return &AuthProvider{
authService: authService,
}
}
// Register 用户注册
func (p *AuthProvider) Register(ctx context.Context, req *pb.RegisterRequest) (*pb.RegisterResponse, error) {
// 记录请求日志
logger.Logger.Info("Received Register request",
zap.String("mobile", req.Mobile),
zap.Int64("star_id", req.StarId),
)
// 调用Service层
resp, err := p.authService.Register(ctx, req)
if err != nil {
logger.Logger.Error("Register failed",
zap.String("mobile", req.Mobile),
zap.Error(err),
)
// 如果响应为空,构建错误响应
if resp == nil {
resp = &pb.RegisterResponse{
Base: &pbCommon.BaseResponse{
Code: appErrors.ToStatusCode(err),
Message: err.Error(),
Timestamp: 0, // 时间戳将在Service层设置
},
}
}
return resp, err
}
logger.Logger.Info("Register successful",
zap.String("mobile", req.Mobile),
zap.Int64("user_id", resp.User.Id),
)
return resp, nil
}
// Login 用户登录
func (p *AuthProvider) Login(ctx context.Context, req *pb.LoginRequest) (*pb.LoginResponse, error) {
// 记录请求日志
logger.Logger.Info("Received Login request",
zap.String("mobile", req.Mobile),
)
// 调用Service层
resp, err := p.authService.Login(req)
if err != nil {
logger.Logger.Error("Login failed",
zap.String("mobile", req.Mobile),
zap.Error(err),
)
// 如果响应为空,构建错误响应
if resp == nil {
resp = &pb.LoginResponse{
Base: &pbCommon.BaseResponse{
Code: appErrors.ToStatusCode(err),
Message: err.Error(),
Timestamp: 0, // 时间戳将在Service层设置
},
}
}
return resp, err
}
logger.Logger.Info("Login successful",
zap.String("mobile", req.Mobile),
zap.Int64("user_id", resp.User.Id),
)
return resp, nil
}
// Logout 用户登出
func (p *AuthProvider) Logout(ctx context.Context, req *pb.LogoutRequest) (*pb.LogoutResponse, error) {
// 记录请求日志
logger.Logger.Info("Received Logout request")
// 从 attachments 获取用户信息(网关已验证 Token
userID, _, err := extractUserInfoFromDubboAttachments(ctx)
if err != nil {
logger.Logger.Error("Failed to extract user info from attachments",
zap.Error(err),
)
return &pb.LogoutResponse{
Base: &pbCommon.BaseResponse{
Code: pbCommon.StatusCode_STATUS_UNAUTHORIZED,
Message: err.Error(),
Timestamp: 0,
},
}, nil
}
logger.Logger.Info("Extracted user info from attachments",
zap.Int64("user_id", userID),
)
// 调用Service层传递 userID
resp, err := p.authService.Logout(userID)
if err != nil {
logger.Logger.Error("Logout failed",
zap.Int64("user_id", userID),
zap.Error(err),
)
// 如果响应为空,构建错误响应
if resp == nil {
resp = &pb.LogoutResponse{
Base: &pbCommon.BaseResponse{
Code: appErrors.ToStatusCode(err),
Message: err.Error(),
Timestamp: 0, // 时间戳将在Service层设置
},
}
}
return resp, err
}
logger.Logger.Info("Logout successful",
zap.Int64("user_id", userID),
)
return resp, nil
}
// RefreshToken 刷新Token
func (p *AuthProvider) RefreshToken(ctx context.Context, req *pb.RefreshTokenRequest) (*pb.RefreshTokenResponse, error) {
// 记录请求日志
logger.Logger.Info("Received RefreshToken request")
// 从 attachments 获取用户信息(网关已验证 Token
userID, starID, err := extractUserInfoFromDubboAttachments(ctx)
if err != nil {
logger.Logger.Error("Failed to extract user info from attachments",
zap.Error(err),
)
return &pb.RefreshTokenResponse{
Base: &pbCommon.BaseResponse{
Code: pbCommon.StatusCode_STATUS_UNAUTHORIZED,
Message: err.Error(),
Timestamp: 0,
},
}, nil
}
logger.Logger.Info("Extracted user info from attachments",
zap.Int64("user_id", userID),
zap.Int64("star_id", starID),
)
// 调用Service层传递 userID 和 starID
resp, err := p.authService.RefreshToken(userID, starID)
if err != nil {
logger.Logger.Error("RefreshToken failed",
zap.Int64("user_id", userID),
zap.Int64("star_id", starID),
zap.Error(err),
)
// 如果响应为空,构建错误响应
if resp == nil {
resp = &pb.RefreshTokenResponse{
Base: &pbCommon.BaseResponse{
Code: appErrors.ToStatusCode(err),
Message: err.Error(),
Timestamp: 0, // 时间戳将在Service层设置
},
}
}
return resp, err
}
logger.Logger.Info("RefreshToken successful",
zap.Int64("user_id", userID),
zap.Int64("star_id", starID),
)
return resp, nil
}
// ValidateToken 验证Token
func (p *AuthProvider) ValidateToken(ctx context.Context, req *pb.ValidateTokenRequest) (*pb.ValidateTokenResponse, error) {
// 记录请求日志
logger.Logger.Debug("Received ValidateToken request")
// 调用Service层
resp, err := p.authService.ValidateToken(req)
if err != nil {
logger.Logger.Error("ValidateToken failed",
zap.Error(err),
)
// 如果响应为空,构建错误响应
if resp == nil {
resp = &pb.ValidateTokenResponse{
Base: &pbCommon.BaseResponse{
Code: appErrors.ToStatusCode(err),
Message: err.Error(),
Timestamp: 0, // 时间戳将在Service层设置
},
}
}
return resp, err
}
logger.Logger.Debug("ValidateToken successful",
zap.Bool("is_valid", resp.IsValid),
zap.Int64("user_id", resp.UserId),
)
return resp, nil
}
// SendCode 发送验证码
func (p *AuthProvider) SendCode(ctx context.Context, req *pb.SendCodeRequest) (*pb.SendCodeResponse, error) {
logger.Logger.Info("Received SendCode request",
zap.String("mobile", req.Mobile),
zap.String("scene", req.Scene),
)
// 获取客户端IP从context或 attachments 获取)
ip := getClientIP(ctx)
expiresIn, err := service.SendVerificationCode(ctx, req.Mobile, ip)
if err != nil {
logger.Logger.Error("SendCode failed",
zap.String("mobile", req.Mobile),
zap.Error(err),
)
return &pb.SendCodeResponse{
Base: &pbCommon.BaseResponse{
Code: appErrors.ToStatusCode(err),
Message: err.Error(),
Timestamp: time.Now().UnixMilli(),
},
}, nil
}
logger.Logger.Info("SendCode successful",
zap.String("mobile", req.Mobile),
)
return &pb.SendCodeResponse{
Base: &pbCommon.BaseResponse{
Code: pbCommon.StatusCode_STATUS_OK,
Message: "发送成功",
Timestamp: time.Now().UnixMilli(),
},
ExpiresIn: int32(expiresIn),
}, nil
}
// VerifyCode 验证验证码
func (p *AuthProvider) VerifyCode(ctx context.Context, req *pb.VerifyCodeRequest) (*pb.VerifyCodeResponse, error) {
logger.Logger.Info("Received VerifyCode request",
zap.String("mobile", req.Mobile),
zap.String("scene", req.Scene),
)
token, err := service.VerifyCode(ctx, req.Mobile, req.Code)
if err != nil {
logger.Logger.Warn("VerifyCode failed",
zap.String("mobile", req.Mobile),
zap.Error(err),
)
return &pb.VerifyCodeResponse{
Base: &pbCommon.BaseResponse{
Code: appErrors.ToStatusCode(err),
Message: err.Error(),
Timestamp: time.Now().UnixMilli(),
},
Verified: false,
}, nil
}
logger.Logger.Info("VerifyCode successful",
zap.String("mobile", req.Mobile),
)
return &pb.VerifyCodeResponse{
Base: &pbCommon.BaseResponse{
Code: pbCommon.StatusCode_STATUS_OK,
Message: "验证成功",
Timestamp: time.Now().UnixMilli(),
},
Verified: true,
VerifyToken: token,
ExpiresIn: 300,
}, nil
}