feat(vpn): VPN on-demand Tailscale + agent studioE5 standalone
- Agent studioE5 standalone en Go (console + systray) - VPN on-demand via tailscaled + tailscale up (authkey Headscale) - Resolver/serveur dans le tailnet studioe5 - Caddy on-demand TLS pour les instances - Nouveaux endpoints serveur /api/internal/send-to-node - Suppression des anciens binaires edubox-agent - Suivi dans SUIVI_VPN_ONDEMAND.md
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"fyne.io/systray"
|
||||
)
|
||||
|
||||
//go:embed icon.png
|
||||
var iconBytes []byte
|
||||
|
||||
const uiURL = "http://localhost:7070"
|
||||
|
||||
func runTray(appName string, shutdownCh chan struct{}) {
|
||||
systray.Run(func() { onTrayReady(appName, shutdownCh) }, func() { onTrayExit(shutdownCh) })
|
||||
}
|
||||
|
||||
func onTrayReady(appName string, shutdownCh chan struct{}) {
|
||||
systray.SetIcon(iconBytes)
|
||||
systray.SetTitle(appName)
|
||||
systray.SetTooltip(fmt.Sprintf("%s Agent - Cliquez pour ouvrir l'interface", appName))
|
||||
|
||||
mOpen := systray.AddMenuItem("Ouvrir l'interface", "Ouvrir l'interface web locale")
|
||||
mInstances := systray.AddMenuItem("Mes instances", "Afficher les instances")
|
||||
mSettings := systray.AddMenuItem("Paramètres", "Ouvrir les paramètres")
|
||||
systray.AddSeparator()
|
||||
mQuit := systray.AddMenuItem("Quitter", "Arrêter l'agent")
|
||||
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-mOpen.ClickedCh:
|
||||
openBrowser(uiURL)
|
||||
case <-mInstances.ClickedCh:
|
||||
openBrowser(uiURL + "#instances")
|
||||
case <-mSettings.ClickedCh:
|
||||
openBrowser(uiURL + "#settings")
|
||||
case <-mQuit.ClickedCh:
|
||||
close(shutdownCh)
|
||||
systray.Quit()
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func onTrayExit(shutdownCh chan struct{}) {
|
||||
log.Printf("Tray exit requested")
|
||||
// If the user did not already trigger shutdown via the menu, signal it now.
|
||||
select {
|
||||
case <-shutdownCh:
|
||||
default:
|
||||
close(shutdownCh)
|
||||
}
|
||||
// Give other goroutines a moment to clean up, then exit.
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func openBrowser(url string) {
|
||||
var cmd string
|
||||
var args []string
|
||||
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
cmd = "rundll32"
|
||||
args = []string{"url.dll,FileProtocolHandler", url}
|
||||
case "darwin":
|
||||
cmd = "open"
|
||||
args = []string{url}
|
||||
default:
|
||||
cmd = "xdg-open"
|
||||
args = []string{url}
|
||||
}
|
||||
|
||||
if err := exec.Command(cmd, args...).Start(); err != nil {
|
||||
log.Printf("Failed to open browser: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func normalizeName(name string) string {
|
||||
return strings.ReplaceAll(name, " ", "")
|
||||
}
|
||||
Reference in New Issue
Block a user