wireguard-gui/main.go

268 lines
5.5 KiB
Go
Raw Permalink Normal View History

2022-09-12 11:14:53 +02:00
package main
import (
"fmt"
"image/color"
2022-09-12 13:31:42 +02:00
"io/fs"
2022-09-12 11:14:53 +02:00
"log"
"os"
2022-09-12 13:31:42 +02:00
"os/exec"
"path/filepath"
2022-09-12 11:14:53 +02:00
"strings"
2022-09-12 13:31:42 +02:00
"time"
2022-09-13 11:54:20 +02:00
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/layout"
"fyne.io/fyne/v2/widget"
)
var (
directory string
configs []Config
application fyne.App
window fyne.Window
menu *container.AppTabs
2022-09-12 11:14:53 +02:00
)
2022-09-12 13:31:42 +02:00
type Config struct {
Name string
File string
}
2022-09-13 11:54:20 +02:00
type ButtonCallback func()
2022-09-12 14:00:24 +02:00
2022-09-12 11:14:53 +02:00
func main() {
2022-09-13 11:54:20 +02:00
application = app.New()
window = application.NewWindow("Wireguard GUI")
directory = "/etc/wireguard/"
menu = container.NewAppTabs()
err := initConfigs()
if err != nil {
log.Fatalln(err)
}
initMenu()
content := container.New(layout.NewVBoxLayout(), menu)
2022-09-12 13:31:42 +02:00
2022-09-13 11:54:20 +02:00
window.SetContent(content)
window.Resize(fyne.NewSize(900, 400))
window.ShowAndRun()
}
func initMenu() {
tabs := make([]fyne.Container, len(configs))
for i, config := range configs {
tabs[i] = *createTab(config)
}
for i, config := range configs {
menu.Append(
container.NewTabItem(
config.Name,
&tabs[i],
),
)
}
}
func initConfigs() error {
2022-09-12 13:31:42 +02:00
err := filepath.WalkDir(directory, func(path string, info fs.DirEntry, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil
}
basename := string(info.Name())
if !strings.HasSuffix(basename, ".conf") {
return nil
}
if strings.Contains(strings.ReplaceAll(path, directory, ""), "/") {
return nil
}
2022-09-12 11:14:53 +02:00
2022-09-12 13:31:42 +02:00
configs = append(configs, Config{
Name: strings.ReplaceAll(basename, ".conf", ""),
File: path,
})
2022-09-12 11:14:53 +02:00
2022-09-12 13:31:42 +02:00
return nil
})
2022-09-12 11:14:53 +02:00
2022-09-13 11:54:20 +02:00
return err
}
2022-09-12 13:31:42 +02:00
2023-12-27 19:09:45 +01:00
func toggleNotice(notice *widget.Label, isVisible bool) {
2022-09-13 11:54:20 +02:00
notice.Hidden = !isVisible
notice.Refresh()
}
2022-09-12 13:31:42 +02:00
2023-12-27 19:09:45 +01:00
func updateNotice(notice *widget.Label, text string, importance widget.Importance, isVisible, isFlash bool) {
2022-09-13 11:54:20 +02:00
notice.Text = text
2023-12-27 19:09:45 +01:00
notice.Importance = importance
2022-09-13 11:54:20 +02:00
notice.Hidden = !isVisible
notice.Refresh()
2022-09-12 13:31:42 +02:00
2022-09-13 11:54:20 +02:00
if isFlash {
go func() {
time.Sleep(2 * time.Second)
toggleNotice(notice, false)
}()
2022-09-12 13:31:42 +02:00
}
2022-09-13 11:54:20 +02:00
log.Println(text)
2022-09-12 13:31:42 +02:00
}
2023-12-27 19:09:45 +01:00
func wgUp(config Config, notice *widget.Label) {
updateNotice(notice, fmt.Sprintf("Interface is starting"), widget.WarningImportance, true, false)
2022-09-12 13:31:42 +02:00
exec.Command("wg-quick", "up", config.Name).Output()
2023-12-27 19:09:45 +01:00
updateNotice(notice, fmt.Sprintf("Interface is up"), widget.SuccessImportance, true, true)
2022-09-12 13:31:42 +02:00
}
2023-12-27 19:09:45 +01:00
func wgDown(config Config, notice *widget.Label) {
updateNotice(notice, fmt.Sprintf("Interface is stopping"), widget.WarningImportance, true, false)
2022-09-12 13:31:42 +02:00
exec.Command("wg-quick", "down", config.Name).Output()
2023-12-27 19:09:45 +01:00
updateNotice(notice, fmt.Sprintf("Interface is down"), widget.SuccessImportance, true, true)
2022-09-12 13:31:42 +02:00
go func() {
time.Sleep(2 * time.Second)
notice.Hidden = true
notice.Refresh()
}()
}
2023-12-27 19:09:45 +01:00
func wgRestart(config Config, notice *widget.Label) {
2022-09-13 12:01:33 +02:00
wgDown(config, notice)
wgUp(config, notice)
2022-09-12 13:31:42 +02:00
}
2022-09-13 11:54:20 +02:00
func lintConfiguration(configuration string) string {
configuration = strings.TrimSpace(configuration)
configuration = fmt.Sprintf("%s\n", configuration)
return configuration
}
func updateTextareaConfiguration(textarea *widget.Entry, content string) {
textarea.SetText(content)
textarea.OnChanged(content)
}
func updateConfigFile(config Config, content string) error {
return os.WriteFile(config.File, []byte(content), 600)
}
func createTextarea() *widget.Entry {
textarea := widget.NewMultiLineEntry()
2022-09-13 14:30:58 +02:00
textarea.TextStyle.Monospace = true
2022-09-13 11:54:20 +02:00
textarea.OnChanged = func(text string) {
textarea.SetMinRowsVisible(strings.Count(text, "\n"))
textarea.Refresh()
}
return textarea
}
2023-12-27 19:09:45 +01:00
func createColoredButton(label string, importance widget.Importance, callback ButtonCallback) *fyne.Container {
button := widget.NewButton(label, callback)
button.Importance = importance
return container.NewMax(button)
2022-09-13 11:54:20 +02:00
}
2023-12-27 19:09:45 +01:00
func createNotice() *widget.Label {
notice := widget.NewLabel("")
2022-09-12 13:31:42 +02:00
notice.TextStyle.Bold = true
2023-12-27 19:09:45 +01:00
notice.Importance = widget.LowImportance
2022-09-12 13:31:42 +02:00
2022-09-13 11:54:20 +02:00
return notice
}
2022-09-12 13:31:42 +02:00
2022-09-13 11:54:20 +02:00
func createMargin() *canvas.Text {
text := canvas.NewText("", color.Transparent)
text.TextSize = 5
return text
}
2022-09-12 13:31:42 +02:00
2022-09-13 11:54:20 +02:00
func createTab(config Config) *fyne.Container {
data, err := os.ReadFile(config.File)
2022-09-12 13:31:42 +02:00
if err != nil {
log.Fatalln(err)
}
2022-09-13 11:54:20 +02:00
notice := createNotice()
2023-12-27 19:09:45 +01:00
buttonStart := createColoredButton("Start", widget.SuccessImportance, func() {
2022-09-13 12:01:33 +02:00
wgUp(config, notice)
2022-09-12 13:31:42 +02:00
})
2023-12-27 19:09:45 +01:00
buttonStop := createColoredButton("Stop", widget.DangerImportance, func() {
2022-09-13 12:01:33 +02:00
wgDown(config, notice)
2022-09-12 13:31:42 +02:00
})
2023-12-27 19:09:45 +01:00
buttonRestart := createColoredButton("Restart", widget.WarningImportance, func() {
2022-09-13 12:01:33 +02:00
wgRestart(config, notice)
2022-09-12 13:31:42 +02:00
})
top := container.New(
layout.NewVBoxLayout(),
2022-09-13 11:54:20 +02:00
createMargin(),
2022-09-12 13:31:42 +02:00
container.New(
layout.NewHBoxLayout(),
notice,
2022-09-12 14:00:24 +02:00
layout.NewSpacer(),
2022-09-13 11:54:20 +02:00
buttonStart,
buttonStop,
buttonRestart,
2022-09-12 13:31:42 +02:00
),
2022-09-13 11:54:20 +02:00
createMargin(),
2022-09-12 13:31:42 +02:00
)
2022-09-12 11:14:53 +02:00
2022-09-13 11:54:20 +02:00
textareaConfiguration := createTextarea()
updateTextareaConfiguration(textareaConfiguration, string(data))
2022-09-12 11:14:53 +02:00
form := &widget.Form{
Items: []*widget.FormItem{
{
Text: "Configuration",
Widget: textareaConfiguration,
},
},
OnSubmit: func() {
2022-09-13 11:54:20 +02:00
toggleNotice(notice, false)
configuration := lintConfiguration(textareaConfiguration.Text)
updateTextareaConfiguration(textareaConfiguration, configuration)
err := updateConfigFile(config, configuration)
2022-09-12 11:14:53 +02:00
2022-09-13 14:30:58 +02:00
log.Println("Configuration of", config.Name)
2022-09-12 11:14:53 +02:00
if err != nil {
2023-12-27 19:09:45 +01:00
updateNotice(notice, fmt.Sprintf("Error while updating: %s", err), widget.DangerImportance, true, false)
2022-09-12 11:14:53 +02:00
} else {
2023-12-27 19:09:45 +01:00
updateNotice(notice, fmt.Sprintf("Configuration updated"), widget.SuccessImportance, true, true)
2022-09-12 11:14:53 +02:00
}
},
SubmitText: "Save",
}
2022-09-12 13:31:42 +02:00
content := container.New(
layout.NewVBoxLayout(),
top,
form,
)
2022-09-12 11:14:53 +02:00
2022-09-12 13:31:42 +02:00
return content
2022-09-12 11:14:53 +02:00
}