Put locale in compliance portal URLs
Path-segment locales make each language crawlable with self canonical and hreflang, while identity.locale persists an explicit choice without client storage or cookie banners. Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
@@ -62,8 +62,18 @@ type (
|
||||
UpdateIdentityRequest struct {
|
||||
FullName string `json:"fullName"`
|
||||
}
|
||||
|
||||
UpdateLocaleRequest struct {
|
||||
Locale string `json:"locale"`
|
||||
}
|
||||
)
|
||||
|
||||
// Short URL locale tags accepted for Identity.locale (must stay in sync with
|
||||
// the compliance-portal URL_LOCALES list).
|
||||
var supportedIdentityLocales = []string{
|
||||
"en", "fr", "de", "es", "id", "it", "ja", "ko", "pl", "pt", "tr", "uk", "zh",
|
||||
}
|
||||
|
||||
const (
|
||||
TokenTypeEmailConfirmation = "email_confirmation"
|
||||
)
|
||||
@@ -88,6 +98,20 @@ func (req UpdateIdentityRequest) Validate() error {
|
||||
return v.Error()
|
||||
}
|
||||
|
||||
func (req UpdateLocaleRequest) Validate() error {
|
||||
v := validator.New()
|
||||
|
||||
v.Check(
|
||||
req.Locale,
|
||||
"locale",
|
||||
validator.NotEmpty(),
|
||||
validator.MaxLen(8),
|
||||
validator.OneOfSlice(supportedIdentityLocales),
|
||||
)
|
||||
|
||||
return v.Error()
|
||||
}
|
||||
|
||||
func (s AccountService) ChangeEmail(ctx context.Context, identityID gid.GID, req *ChangeEmailRequest) error {
|
||||
if err := req.Validate(); err != nil {
|
||||
return fmt.Errorf("invalid request: %w", err)
|
||||
@@ -402,6 +426,42 @@ func (s AccountService) UpdateIdentity(ctx context.Context, identityID gid.GID,
|
||||
return identity, nil
|
||||
}
|
||||
|
||||
func (s AccountService) UpdateLocale(ctx context.Context, identityID gid.GID, req *UpdateLocaleRequest) (*coredata.Identity, error) {
|
||||
if err := req.Validate(); err != nil {
|
||||
return nil, fmt.Errorf("invalid request: %w", err)
|
||||
}
|
||||
|
||||
identity := &coredata.Identity{}
|
||||
|
||||
err := s.pg.WithTx(
|
||||
ctx,
|
||||
func(ctx context.Context, tx pg.Tx) error {
|
||||
err := identity.LoadByID(ctx, tx, identityID)
|
||||
if err != nil {
|
||||
if err == coredata.ErrResourceNotFound {
|
||||
return NewIdentityNotFoundError(identityID)
|
||||
}
|
||||
|
||||
return fmt.Errorf("cannot load identity: %w", err)
|
||||
}
|
||||
|
||||
identity.Locale = &req.Locale
|
||||
identity.UpdatedAt = time.Now()
|
||||
|
||||
if err := identity.Update(ctx, tx); err != nil {
|
||||
return fmt.Errorf("cannot update identity locale: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return identity, nil
|
||||
}
|
||||
|
||||
func (s AccountService) ListPersonalAPIKeys(
|
||||
ctx context.Context,
|
||||
identityID gid.GID,
|
||||
|
||||
Reference in New Issue
Block a user