package handlers import ( "errors" "net/url" "strings" ) type loginRequest struct { Account string `json:"account"` Password string `json:"password"` ClientID string `json:"clientId"` ClientName string `json:"clientName"` } type verifyRequest struct { Token string `json:"token"` } type registerRequest struct { Account string `json:"account"` Password string `json:"password"` Username string `json:"username"` Email string `json:"email"` InviteCode string `json:"inviteCode"` } type verifyEmailRequest struct { Account string `json:"account"` Code string `json:"code"` } type updateProfileRequest struct { Password *string `json:"password"` Username *string `json:"username"` Phone *string `json:"phone"` AvatarURL *string `json:"avatarUrl"` WebsiteURL *string `json:"websiteUrl"` Bio *string `json:"bio"` } type forgotPasswordRequest struct { Account string `json:"account"` Email string `json:"email"` } type resetPasswordRequest struct { Account string `json:"account"` Code string `json:"code"` NewPassword string `json:"newPassword"` } type secondaryEmailRequest struct { Email string `json:"email"` } type verifySecondaryEmailRequest struct { Email string `json:"email"` Code string `json:"code"` } type updateCheckInConfigRequest struct { RewardCoins int `json:"rewardCoins"` } type updateRegistrationPolicyRequest struct { RequireInviteCode bool `json:"requireInviteCode"` } type createInviteRequest struct { Note string `json:"note"` MaxUses int `json:"maxUses"` ExpiresAt string `json:"expiresAt"` } type createUserRequest struct { Account string `json:"account"` Password string `json:"password"` Username string `json:"username"` Email string `json:"email"` Level int `json:"level"` SproutCoins int `json:"sproutCoins"` SecondaryEmails []string `json:"secondaryEmails"` Phone string `json:"phone"` AvatarURL string `json:"avatarUrl"` WebsiteURL string `json:"websiteUrl"` Bio string `json:"bio"` } const maxBanReasonLen = 500 type updateUserRequest struct { Password *string `json:"password"` Username *string `json:"username"` Email *string `json:"email"` Level *int `json:"level"` SproutCoins *int `json:"sproutCoins"` SecondaryEmails *[]string `json:"secondaryEmails"` Phone *string `json:"phone"` AvatarURL *string `json:"avatarUrl"` WebsiteURL *string `json:"websiteUrl"` Bio *string `json:"bio"` Banned *bool `json:"banned"` BanReason *string `json:"banReason"` } const maxWebsiteURLLen = 2048 func normalizePublicWebsiteURL(raw string) (string, error) { s := strings.TrimSpace(raw) if s == "" { return "", nil } if len(s) > maxWebsiteURLLen { return "", errors.New("website url is too long") } lower := strings.ToLower(s) if strings.HasPrefix(lower, "javascript:") || strings.HasPrefix(lower, "data:") { return "", errors.New("invalid website url") } candidate := s if !strings.Contains(candidate, "://") { candidate = "https://" + candidate } u, err := url.Parse(candidate) if err != nil || u.Host == "" { return "", errors.New("invalid website url") } scheme := strings.ToLower(u.Scheme) if scheme != "http" && scheme != "https" { return "", errors.New("only http and https urls are allowed") } u.Scheme = scheme return u.String(), nil }