Files
zxyszx 86773c64ca
Docker Release / Check web and api (push) Waiting to run
Docker Release / Resolve release tag (push) Blocked by required conditions
Docker Release / Build and publish all-in-one (push) Blocked by required conditions
Docker Release / Build and publish api (push) Blocked by required conditions
Docker Release / Build and publish web (push) Blocked by required conditions
Docker Release / Build and publish dovecot (push) Blocked by required conditions
Docker Release / Build and publish postfix (push) Blocked by required conditions
Docker Release / Build and publish rspamd (push) Blocked by required conditions
Docker Release / Create GitHub release (push) Blocked by required conditions
feat: unify email identity and administrator security
2026-08-05 02:55:36 +08:00

66 lines
1.5 KiB
Go

package app
import (
"context"
"encoding/json"
"errors"
"net"
"net/http"
"net/url"
"strings"
"time"
)
type turnstileVerifyResponse struct {
Success bool `json:"success"`
ErrorCodes []string `json:"error-codes"`
}
func (a *App) verifyTurnstile(ctx context.Context, token, remoteIP string) error {
if !a.config().TurnstileEnabled {
return nil
}
token = strings.TrimSpace(token)
secret := strings.TrimSpace(a.config().TurnstileSecretKey)
if secret == "" || token == "" {
return errors.New("turnstile verification required")
}
form := url.Values{}
form.Set("secret", secret)
form.Set("response", token)
if ip := normalizeRemoteIP(remoteIP); ip != "" {
form.Set("remoteip", ip)
}
verifyURL := strings.TrimSpace(a.turnstileURL)
if verifyURL == "" {
verifyURL = "https://challenges.cloudflare.com/turnstile/v0/siteverify"
}
req, err := http.NewRequestWithContext(ctx, http.MethodPost, verifyURL, strings.NewReader(form.Encode()))
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
client := &http.Client{Timeout: 8 * time.Second}
res, err := client.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
var out turnstileVerifyResponse
if err := json.NewDecoder(res.Body).Decode(&out); err != nil {
return err
}
if !out.Success {
return errors.New("turnstile verification failed")
}
return nil
}
func normalizeRemoteIP(value string) string {
host, _, err := net.SplitHostPort(strings.TrimSpace(value))
if err == nil {
return host
}
return strings.TrimSpace(value)
}