package identity import ( "context" "errors" "strings" "unicode" "unicode/utf8" ) var ErrInvalidDisplayName = errors.New("invalid display name") func ValidateDisplayName(name string) (string, error) { name = strings.TrimSpace(name) if !utf8.ValidString(name) || utf8.RuneCountInString(name) < 1 || utf8.RuneCountInString(name) > 80 { return "", ErrInvalidDisplayName } for _, r := range name { if unicode.IsControl(r) { return "", ErrInvalidDisplayName } } return name, nil } // The principal comes from authenticated middleware. Callers cannot select another account. func (r *Repository) UpdateDisplayName(ctx context.Context, principal Principal, name string) error { name, err := ValidateDisplayName(name) if err != nil { return err } if principal.Issuer == "" || principal.Subject == "" { return ErrAccessDenied } result, err := r.pool.Exec(ctx, `UPDATE user_account ua SET display_name=$3, updated_at=now() FROM tenant t WHERE ua.tenant_id=t.id AND t.status='active' AND ua.status='active' AND ua.oidc_issuer=$1 AND ua.oidc_subject=$2`, principal.Issuer, principal.Subject, name) if err != nil { return err } if result.RowsAffected() == 0 { return ErrAccountNotFound } return nil }