2026-04-04 01:28:57 +08:00

108 lines
3.5 KiB
Go

package auth
import (
"context"
"strings"
gatewaypb "chatappgateway/api/proto"
"chatappgateway/internal/apperr"
)
// Client 定义用户服务 gRPC 客户端能力。
type Client interface {
Login(ctx context.Context, request *gatewaypb.LoginRequest) (*gatewaypb.LoginResponse, error)
}
// Service 负责登录参数校验、字段归一化和下游调用。
type Service struct {
client Client
}
// LoginRequest 描述 HTTP 层的登录入参。
type LoginRequest struct {
LoginType string `json:"login_type"`
Account string `json:"account"`
Password string `json:"password"`
CountryCode string `json:"country_code"`
VerifyCode string `json:"verify_code"`
Provider string `json:"provider"`
ProviderToken string `json:"provider_token"`
DeviceID string `json:"device_id"`
Platform string `json:"platform"`
AppVersion string `json:"app_version"`
}
// New 创建登录服务。
func New(client Client) *Service {
return &Service{client: client}
}
// Login 校验客户端请求并转成 gRPC 请求。
func (s *Service) Login(ctx context.Context, request LoginRequest) (*gatewaypb.LoginResponse, error) {
normalized, err := normalize(request)
if err != nil {
return nil, err
}
return s.client.Login(ctx, &gatewaypb.LoginRequest{
LoginType: normalized.LoginType,
Account: normalized.Account,
Password: normalized.Password,
CountryCode: normalized.CountryCode,
VerifyCode: normalized.VerifyCode,
Provider: normalized.Provider,
ProviderToken: normalized.ProviderToken,
DeviceId: normalized.DeviceID,
Platform: normalized.Platform,
AppVersion: normalized.AppVersion,
})
}
func normalize(request LoginRequest) (LoginRequest, error) {
normalized := LoginRequest{
LoginType: strings.ToLower(strings.TrimSpace(request.LoginType)),
Account: strings.TrimSpace(request.Account),
Password: request.Password,
CountryCode: strings.TrimSpace(request.CountryCode),
VerifyCode: strings.TrimSpace(request.VerifyCode),
Provider: strings.ToLower(strings.TrimSpace(request.Provider)),
ProviderToken: strings.TrimSpace(request.ProviderToken),
DeviceID: strings.TrimSpace(request.DeviceID),
Platform: strings.TrimSpace(request.Platform),
AppVersion: strings.TrimSpace(request.AppVersion),
}
switch normalized.LoginType {
case "":
return LoginRequest{}, apperr.New(400, "bad_request", "login_type is required")
case "password":
if normalized.Account == "" {
return LoginRequest{}, apperr.New(400, "bad_request", "account is required")
}
if strings.TrimSpace(normalized.Password) == "" {
return LoginRequest{}, apperr.New(400, "bad_request", "password is required")
}
case "sms_code":
if normalized.CountryCode == "" {
return LoginRequest{}, apperr.New(400, "bad_request", "country_code is required")
}
if normalized.Account == "" {
return LoginRequest{}, apperr.New(400, "bad_request", "account is required")
}
if normalized.VerifyCode == "" {
return LoginRequest{}, apperr.New(400, "bad_request", "verify_code is required")
}
case "oauth":
if normalized.Provider == "" {
return LoginRequest{}, apperr.New(400, "bad_request", "provider is required")
}
if normalized.ProviderToken == "" {
return LoginRequest{}, apperr.New(400, "bad_request", "provider_token is required")
}
default:
return LoginRequest{}, apperr.New(400, "bad_request", "login_type must be one of password, sms_code, oauth")
}
return normalized, nil
}