feat(web): Router, Login/Logout, Übersicht, CSRF-geschützter Download, Anleitungen und /healthz
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NBHF4R9EAejDJUMdwr6C68
This commit is contained in:
parent
bb2bc223b9
commit
eb89d78ce2
8 changed files with 1618 additions and 0 deletions
97
internal/web/guides.go
Normal file
97
internal/web/guides.go
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
package web
|
||||
|
||||
import "strings"
|
||||
|
||||
// Guide ist eine Kurzanleitung für eine Plattform.
|
||||
type Guide struct {
|
||||
Platform string
|
||||
Client string
|
||||
Steps []string
|
||||
Suggested bool
|
||||
}
|
||||
|
||||
// baseGuides ist die feste Reihenfolge aller Anleitungen.
|
||||
var baseGuides = []Guide{
|
||||
{
|
||||
Platform: "Windows",
|
||||
Client: "OpenVPN Community Client",
|
||||
Steps: []string{
|
||||
"Laden Sie den OpenVPN Community Client von openvpn.net herunter und installieren Sie ihn.",
|
||||
"Laden Sie hier im Portal Ihre .ovpn-Datei herunter.",
|
||||
"Klicken Sie mit der rechten Maustaste auf das OpenVPN-Symbol im Infobereich und wählen Sie „Datei importieren“.",
|
||||
"Wählen Sie die heruntergeladene .ovpn-Datei aus.",
|
||||
"Klicken Sie erneut auf das Symbol und wählen Sie „Verbinden“.",
|
||||
},
|
||||
},
|
||||
{
|
||||
Platform: "macOS",
|
||||
Client: "Tunnelblick oder Viscosity",
|
||||
Steps: []string{
|
||||
"Installieren Sie Tunnelblick (kostenfrei) oder Viscosity.",
|
||||
"Laden Sie hier im Portal Ihre Konfiguration herunter — für Viscosity das Viscosity-Paket, für Tunnelblick die .ovpn-Datei.",
|
||||
"Öffnen Sie die heruntergeladene Datei per Doppelklick; die Konfiguration wird importiert.",
|
||||
"Starten Sie die Verbindung über das Symbol in der Menüleiste.",
|
||||
},
|
||||
},
|
||||
{
|
||||
Platform: "iOS / iPadOS",
|
||||
Client: "OpenVPN Connect",
|
||||
Steps: []string{
|
||||
"Installieren Sie „OpenVPN Connect“ aus dem App Store.",
|
||||
"Laden Sie hier im Portal Ihre .ovpn-Datei herunter.",
|
||||
"Öffnen Sie die Datei aus der Dateien-App heraus und wählen Sie „Teilen“ und dann „OpenVPN Connect“.",
|
||||
"Bestätigen Sie den Import mit „Add“ und erlauben Sie die VPN-Konfiguration.",
|
||||
},
|
||||
},
|
||||
{
|
||||
Platform: "Android",
|
||||
Client: "OpenVPN Connect",
|
||||
Steps: []string{
|
||||
"Installieren Sie „OpenVPN Connect“ aus dem Google Play Store.",
|
||||
"Laden Sie hier im Portal Ihre .ovpn-Datei herunter.",
|
||||
"Öffnen Sie OpenVPN Connect, wählen Sie „Import“, dann „File“ und dann die heruntergeladene Datei.",
|
||||
"Bestätigen Sie den Import und erlauben Sie die VPN-Verbindung.",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// detectPlatform rät die Plattform aus dem User-Agent.
|
||||
// Das Ergebnis ist ausdrücklich nur ein Vorschlag, nie ein Filter.
|
||||
// iOS wird vor macOS geprüft, weil iPad-User-Agents „Mac OS X“ enthalten können.
|
||||
func detectPlatform(userAgent string) string {
|
||||
ua := strings.ToLower(userAgent)
|
||||
switch {
|
||||
case strings.Contains(ua, "iphone"), strings.Contains(ua, "ipad"), strings.Contains(ua, "ipod"):
|
||||
return "iOS / iPadOS"
|
||||
case strings.Contains(ua, "android"):
|
||||
return "Android"
|
||||
case strings.Contains(ua, "windows"):
|
||||
return "Windows"
|
||||
case strings.Contains(ua, "mac os x"), strings.Contains(ua, "macintosh"):
|
||||
return "macOS"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// Guides liefert alle Anleitungen; die erkannte Plattform steht vorn und ist
|
||||
// als Vorschlag markiert. Es wird niemals etwas ausgeblendet — die
|
||||
// User-Agent-Erkennung ist zu unzuverlässig, um Inhalte zu verstecken.
|
||||
func Guides(userAgent string) []Guide {
|
||||
detected := detectPlatform(userAgent)
|
||||
out := make([]Guide, 0, len(baseGuides))
|
||||
if detected != "" {
|
||||
for _, g := range baseGuides {
|
||||
if g.Platform == detected {
|
||||
g.Suggested = true
|
||||
out = append(out, g)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, g := range baseGuides {
|
||||
if g.Platform != detected {
|
||||
out = append(out, g)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue