Files
ds-galo/backend/internal/auth/identifiers.go

64 lines
1.8 KiB
Go
Raw Permalink 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 auth
import (
"strings"
"galo/internal/httpx"
)
// Identifier kinds for login and registration.
const (
IdentifierEmail = "email"
IdentifierPhone = "phone"
)
// NormalizePhone validates and canonicalises a phone number to E.164: a leading
// plus followed by 8–15 digits. It is the single normalisation point used by
// registration, identifier addition and login, so lookups compare canonical
// values only.
func NormalizePhone(raw string) (string, error) {
s := strings.TrimSpace(raw)
if s == "" {
return "", httpx.BadRequest("invalid_phone", "phone is required")
}
if !strings.HasPrefix(s, "+") {
return "", httpx.BadRequest("invalid_phone", "phone must be in E.164 format with a leading +")
}
digits := s[1:]
if len(digits) < 8 || len(digits) > 15 {
return "", httpx.BadRequest("invalid_phone", "phone must contain between 8 and 15 digits")
}
for _, r := range digits {
if r < '0' || r > '9' {
return "", httpx.BadRequest("invalid_phone", "phone may contain digits only after the leading +")
}
}
return s, nil
}
func validEmail(s string) bool {
i := strings.Index(s, "@")
return i > 0 && i < len(s)-1 && !strings.ContainsAny(s, " \t\r\n")
}
// NormalizeIdentifier classifies a login identifier as email (contains `@`) or
// phone, returning the canonical value for lookups.
func NormalizeIdentifier(raw string) (kind, value string, err error) {
s := strings.TrimSpace(raw)
if s == "" {
return "", "", httpx.BadRequest("invalid_identifier", "identifier is required")
}
if strings.Contains(s, "@") {
v := strings.ToLower(s)
if !validEmail(v) {
return "", "", httpx.BadRequest("invalid_identifier", "valid email is required")
}
return IdentifierEmail, v, nil
}
v, err := NormalizePhone(s)
if err != nil {
return "", "", err
}
return IdentifierPhone, v, nil
}