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 }