195 lines
6.6 KiB
Go
195 lines
6.6 KiB
Go
package handlers
|
|
|
|
import (
|
|
"errors"
|
|
"net/url"
|
|
"strings"
|
|
)
|
|
|
|
// LoginRequest POST /api/auth/login JSON body
|
|
type LoginRequest struct {
|
|
Account string `json:"account"`
|
|
Password string `json:"password"`
|
|
ClientID string `json:"clientId"`
|
|
ClientName string `json:"clientName"`
|
|
TurnstileToken string `json:"turnstileToken"`
|
|
}
|
|
|
|
// VerifyRequest POST /api/auth/verify
|
|
type VerifyRequest struct {
|
|
Token string `json:"token"`
|
|
}
|
|
|
|
// RegisterRequest POST /api/auth/register
|
|
type RegisterRequest struct {
|
|
Account string `json:"account"`
|
|
Password string `json:"password"`
|
|
Username string `json:"username"`
|
|
Email string `json:"email"`
|
|
InviteCode string `json:"inviteCode"`
|
|
TurnstileToken string `json:"turnstileToken"`
|
|
}
|
|
|
|
// VerifyEmailRequest POST /api/auth/verify-email
|
|
type VerifyEmailRequest struct {
|
|
Account string `json:"account"`
|
|
Code string `json:"code"`
|
|
}
|
|
|
|
// UpdateProfileRequest PUT /api/auth/profile
|
|
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"`
|
|
}
|
|
|
|
// ForgotPasswordRequest POST /api/auth/forgot-password
|
|
type ForgotPasswordRequest struct {
|
|
Account string `json:"account"`
|
|
Email string `json:"email"`
|
|
}
|
|
|
|
// ResetPasswordRequest POST /api/auth/reset-password
|
|
type ResetPasswordRequest struct {
|
|
Account string `json:"account"`
|
|
Code string `json:"code"`
|
|
NewPassword string `json:"newPassword"`
|
|
}
|
|
|
|
// SecondaryEmailRequest POST /api/auth/secondary-email/request
|
|
type SecondaryEmailRequest struct {
|
|
Email string `json:"email"`
|
|
}
|
|
|
|
// VerifySecondaryEmailRequest POST /api/auth/secondary-email/verify
|
|
type VerifySecondaryEmailRequest struct {
|
|
Email string `json:"email"`
|
|
Code string `json:"code"`
|
|
}
|
|
|
|
// UpdateCheckInConfigRequest PUT /api/admin/check-in/config
|
|
type UpdateCheckInConfigRequest struct {
|
|
RewardCoins int `json:"rewardCoins"`
|
|
}
|
|
|
|
// UpdateRegistrationPolicyRequest PUT /api/admin/registration
|
|
type UpdateRegistrationPolicyRequest struct {
|
|
RequireInviteCode bool `json:"requireInviteCode"`
|
|
ForbiddenAccounts string `json:"forbiddenAccounts"`
|
|
InviteRegisterRewardCoins *int `json:"inviteRegisterRewardCoins"` // nil 表示不修改此项
|
|
}
|
|
|
|
// CreateInviteRequest POST /api/admin/registration/invites
|
|
type CreateInviteRequest struct {
|
|
Note string `json:"note"`
|
|
MaxUses int `json:"maxUses"`
|
|
ExpiresAt string `json:"expiresAt"`
|
|
}
|
|
|
|
// CreateUserRequest POST /api/admin/users
|
|
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
|
|
|
|
// UpdateUserRequest PUT /api/admin/users/:account
|
|
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"`
|
|
}
|
|
|
|
// OAuthBindURLRequest POST /api/auth/oauth/:provider/bind
|
|
type OAuthBindURLRequest struct {
|
|
ReturnTo string `json:"returnTo"`
|
|
}
|
|
|
|
// PutAdminOAuthRequest PUT /api/admin/oauth
|
|
type PutAdminOAuthRequest struct {
|
|
GitHubEnabled bool `json:"githubEnabled"`
|
|
GiteaEnabled bool `json:"giteaEnabled"`
|
|
GoogleEnabled bool `json:"googleEnabled"`
|
|
MicrosoftEnabled bool `json:"microsoftEnabled"`
|
|
LinuxdoEnabled bool `json:"linuxdoEnabled"`
|
|
GitHubClientID string `json:"githubClientId"`
|
|
GitHubClientSecret string `json:"githubClientSecret"`
|
|
GiteaBaseURL string `json:"giteaBaseUrl"`
|
|
GiteaClientID string `json:"giteaClientId"`
|
|
GiteaClientSecret string `json:"giteaClientSecret"`
|
|
GoogleClientID string `json:"googleClientId"`
|
|
GoogleClientSecret string `json:"googleClientSecret"`
|
|
MicrosoftClientID string `json:"microsoftClientId"`
|
|
MicrosoftClientSecret string `json:"microsoftClientSecret"`
|
|
MicrosoftTenant string `json:"microsoftTenant"`
|
|
LinuxdoConnectBaseURL string `json:"linuxdoConnectBaseUrl"`
|
|
LinuxdoClientID string `json:"linuxdoClientId"`
|
|
LinuxdoClientSecret string `json:"linuxdoClientSecret"`
|
|
GitHubLogoURL string `json:"githubLogoUrl"`
|
|
GiteaLogoURL string `json:"giteaLogoUrl"`
|
|
GoogleLogoURL string `json:"googleLogoUrl"`
|
|
MicrosoftLogoURL string `json:"microsoftLogoUrl"`
|
|
LinuxdoLogoURL string `json:"linuxdoLogoUrl"`
|
|
AllowedReturnPrefixes []string `json:"allowedReturnPrefixes"`
|
|
AllowOAuthSignUpWhenInviteRequired bool `json:"allowOAuthSignUpWhenInviteRequired"`
|
|
}
|
|
|
|
// PutAdminTurnstileRequest PUT /api/admin/turnstile
|
|
type PutAdminTurnstileRequest struct {
|
|
Enabled bool `json:"enabled"`
|
|
SiteKey string `json:"siteKey"`
|
|
SecretKey string `json:"secretKey"`
|
|
}
|
|
|
|
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
|
|
}
|