feat: user service
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
package shared
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"galaxy/user/internal/domain/common"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
// NormalizeString trims surrounding Unicode whitespace from value.
|
||||
func NormalizeString(value string) string {
|
||||
return strings.TrimSpace(value)
|
||||
}
|
||||
|
||||
// ParseEmail trims value and validates it as one exact normalized e-mail
|
||||
// subject used by the auth-facing contract.
|
||||
func ParseEmail(value string) (common.Email, error) {
|
||||
email := common.Email(NormalizeString(value))
|
||||
if err := email.Validate(); err != nil {
|
||||
return "", InvalidRequest(err.Error())
|
||||
}
|
||||
|
||||
return email, nil
|
||||
}
|
||||
|
||||
// ParseUserID trims value and validates it as one stable user identifier.
|
||||
func ParseUserID(value string) (common.UserID, error) {
|
||||
userID := common.UserID(NormalizeString(value))
|
||||
if err := userID.Validate(); err != nil {
|
||||
return "", InvalidRequest(err.Error())
|
||||
}
|
||||
|
||||
return userID, nil
|
||||
}
|
||||
|
||||
// ParseRaceName trims value and validates it as one exact stored race name.
|
||||
func ParseRaceName(value string) (common.RaceName, error) {
|
||||
raceName := common.RaceName(NormalizeString(value))
|
||||
if err := raceName.Validate(); err != nil {
|
||||
return "", InvalidRequest(err.Error())
|
||||
}
|
||||
|
||||
return raceName, nil
|
||||
}
|
||||
|
||||
// ParseReasonCode trims value and validates it as one machine-readable reason
|
||||
// code.
|
||||
func ParseReasonCode(value string) (common.ReasonCode, error) {
|
||||
reasonCode := common.ReasonCode(NormalizeString(value))
|
||||
if err := reasonCode.Validate(); err != nil {
|
||||
return "", InvalidRequest(err.Error())
|
||||
}
|
||||
|
||||
return reasonCode, nil
|
||||
}
|
||||
|
||||
// ParseLanguageTag trims value and validates it against the current Stage 03
|
||||
// boundary and BCP 47 semantics, returning the canonical tag form.
|
||||
func ParseLanguageTag(value string) (common.LanguageTag, error) {
|
||||
languageTag := common.LanguageTag(NormalizeString(value))
|
||||
if err := languageTag.Validate(); err != nil {
|
||||
return "", InvalidRequest(err.Error())
|
||||
}
|
||||
|
||||
parsedTag, err := language.Parse(languageTag.String())
|
||||
if err != nil {
|
||||
return "", InvalidRequest("language tag must be a valid BCP 47 language tag")
|
||||
}
|
||||
|
||||
canonicalTag := common.LanguageTag(parsedTag.String())
|
||||
if err := canonicalTag.Validate(); err != nil {
|
||||
return "", InvalidRequest(err.Error())
|
||||
}
|
||||
|
||||
return canonicalTag, nil
|
||||
}
|
||||
|
||||
// ParseTimeZoneName trims value and validates it against the current Stage 03
|
||||
// boundary and IANA time-zone semantics.
|
||||
func ParseTimeZoneName(value string) (common.TimeZoneName, error) {
|
||||
timeZoneName := common.TimeZoneName(NormalizeString(value))
|
||||
if err := timeZoneName.Validate(); err != nil {
|
||||
return "", InvalidRequest(err.Error())
|
||||
}
|
||||
if _, err := time.LoadLocation(timeZoneName.String()); err != nil {
|
||||
return "", InvalidRequest("time zone name must be a valid IANA time zone name")
|
||||
}
|
||||
|
||||
return timeZoneName, nil
|
||||
}
|
||||
|
||||
// ParseRegistrationPreferredLanguage trims value, validates it as one create-
|
||||
// only BCP 47 registration language tag, and returns the canonical tag form.
|
||||
func ParseRegistrationPreferredLanguage(value string) (common.LanguageTag, error) {
|
||||
languageTag, err := ParseLanguageTag(value)
|
||||
if err != nil {
|
||||
return "", reframeFieldError("registration_context.preferred_language", "language tag", err)
|
||||
}
|
||||
|
||||
return languageTag, nil
|
||||
}
|
||||
|
||||
// ParseRegistrationTimeZoneName trims value and validates it as one create-
|
||||
// only IANA registration time-zone name.
|
||||
func ParseRegistrationTimeZoneName(value string) (common.TimeZoneName, error) {
|
||||
timeZoneName, err := ParseTimeZoneName(value)
|
||||
if err != nil {
|
||||
return "", reframeFieldError("registration_context.time_zone", "time zone name", err)
|
||||
}
|
||||
|
||||
return timeZoneName, nil
|
||||
}
|
||||
|
||||
func reframeFieldError(fieldName string, valueName string, err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
message := err.Error()
|
||||
prefix := valueName + " "
|
||||
if strings.HasPrefix(message, prefix) {
|
||||
message = fieldName + " " + strings.TrimPrefix(message, prefix)
|
||||
} else {
|
||||
message = fmt.Sprintf("%s: %s", fieldName, message)
|
||||
}
|
||||
|
||||
return InvalidRequest(message)
|
||||
}
|
||||
Reference in New Issue
Block a user