From b0bfe3abce22942c2d352ede30dc947adcbeec7b Mon Sep 17 00:00:00 2001 From: DaanSelen Date: Mon, 30 Mar 2026 16:58:19 +0200 Subject: [PATCH] chore: update code --- .gitignore | 5 +++ src/define.go | 2 +- src/draw.go | 1 - src/main.go | 18 ++++++++ src/modules/draw/define.go | 7 ++++ src/modules/draw/draw.go | 61 +++++++++++++++++++++++++++ src/modules/setup/books.go | 84 ++++++++++++++++++++++++++++++++++++++ src/modules/setup/files.go | 36 ++++++++++++++++ src/modules/setup/setup.go | 76 ++++++++++++++++++++++++++++------ src/modules/tasks/tasks.go | 35 ++++++++++++++++ 10 files changed, 311 insertions(+), 14 deletions(-) delete mode 100644 src/draw.go create mode 100644 src/modules/draw/define.go create mode 100644 src/modules/draw/draw.go create mode 100644 src/modules/setup/books.go create mode 100644 src/modules/setup/files.go create mode 100644 src/modules/tasks/tasks.go diff --git a/.gitignore b/.gitignore index df94313..986de2b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,8 @@ +api.conf +os_categories.json +bin/ +books/ + # ---> Go # If you prefer the allow list template instead of the deny list, see community template: # https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore diff --git a/src/define.go b/src/define.go index f2f3bf2..fa5dbce 100644 --- a/src/define.go +++ b/src/define.go @@ -3,5 +3,5 @@ package main import "fyne.io/fyne/v2" var ( - windowSize fyne.Size = fyne.NewSize(600, 550) + windowSize fyne.Size = fyne.NewSize(1280, 720) ) diff --git a/src/draw.go b/src/draw.go deleted file mode 100644 index 06ab7d0..0000000 --- a/src/draw.go +++ /dev/null @@ -1 +0,0 @@ -package main diff --git a/src/main.go b/src/main.go index 9548685..fa5d2b9 100644 --- a/src/main.go +++ b/src/main.go @@ -5,8 +5,11 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/app" + "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/theme" + "fyne.io/fyne/v2/widget" + draw "patchworks/src/modules/draw" setup "patchworks/src/modules/setup" _ "embed" @@ -30,5 +33,20 @@ func main() { w := app.NewWindow("PatchWorks") w.Resize(windowSize) + userEntry := widget.NewEntry() + passEntry := widget.NewPasswordEntry() + targEntry := widget.NewEntry() + var book string + inputContainer := draw.MakeInputContainer(userEntry, passEntry, targEntry, &book, w) + + content := container.NewBorder( + inputContainer, // top + nil, // bottom + nil, // left + nil, // right + nil, // center + ) + + w.SetContent(content) w.ShowAndRun() } diff --git a/src/modules/draw/define.go b/src/modules/draw/define.go new file mode 100644 index 0000000..28bfce6 --- /dev/null +++ b/src/modules/draw/define.go @@ -0,0 +1,7 @@ +package draw + +import "fyne.io/fyne/v2" + +var ( + entrySize fyne.Size = fyne.NewSize(300, 50) +) diff --git a/src/modules/draw/draw.go b/src/modules/draw/draw.go new file mode 100644 index 0000000..d65ed61 --- /dev/null +++ b/src/modules/draw/draw.go @@ -0,0 +1,61 @@ +package draw + +import ( + "log" + + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/container" + "fyne.io/fyne/v2/layout" + "fyne.io/fyne/v2/widget" + + tasks "patchworks/src/modules/tasks" +) + +func MakeInputContainer(userEntry, passEntry, targEntry *widget.Entry, book *string, win fyne.Window) *fyne.Container { + availBooks, err := tasks.ListAvailableBooks() + if err != nil { + log.Println("failed to read available books on disk") + } + + loginBox := container.NewVBox( + widget.NewLabel("Service Username"), + userEntry, + widget.NewLabel("Service Password"), + passEntry, + ) + + targetBox := container.NewVBox( + widget.NewLabel("Target Device or Group"), + targEntry, + ) + + bookList := widget.NewList( + func() int { + return len(availBooks) + }, + func() fyne.CanvasObject { + return widget.NewLabel("Books") + }, + func(i widget.ListItemID, o fyne.CanvasObject) { + o.(*widget.Label).SetText(availBooks[i]) + }, + ) + bookList.OnSelected = func(id widget.ListItemID) { + *book = availBooks[id] + log.Printf("Updated selected book to: %s", *book) + } + bookBox := container.NewBorder( + widget.NewLabel("Available Books"), // top + nil, nil, nil, // bottom, left, right + bookList, // center fills + ) + + inputBox := container.New( + layout.NewGridLayoutWithColumns(3), + loginBox, // column 1 + targetBox, // column 2 + bookBox, // column 3 + ) + + return inputBox +} diff --git a/src/modules/setup/books.go b/src/modules/setup/books.go new file mode 100644 index 0000000..59e5a58 --- /dev/null +++ b/src/modules/setup/books.go @@ -0,0 +1,84 @@ +package setup + +const rdpCheck = `--- +name: rdpCheck +target_os: "Linux" +tasks: + - name: Check RDP + command: "ps -aux | grep rdp | grep -v grep" +` + +const enableVncConsent = `--- +name: enableVncConsent +target_os: "Debian" +target_tag: "Linux-ThinClient" +variables: + - name: service-file + value: /etc/systemd/system/x11vnc.service +tasks: + - name: edit x11vnc.service + command: > + sed -i "s|ExecStart=/usr/bin/x11vnc.*|ExecStart=/usr/bin/x11vnc -xkb + -noxrecord -noxfixes -noxdamage -display :0 -auth /home/user/.Xauthority + -ncache 0 -nopw -accept 'popup'|" {{ service-file }} + - name: systemctl daemon-reload + command: systemctl daemon-reload + - name: systemctl restart + command: systemctl restart x11vnc +` + +const disableVncConsent = `--- +name: disableVncConsent +target_os: "Debian" +target_tag: "Linux-ThinClient" +variables: + - name: service-file + value: /etc/systemd/system/x11vnc.service +tasks: + - name: edit x11vnc.service + command: > + sed -i "s|ExecStart=/usr/bin/x11vnc.*|ExecStart=/usr/bin/x11vnc -xkb + -noxrecord -noxfixes -noxdamage -display :0 -auth /home/user/.Xauthority + -ncache 0 -nopw|" {{ service-file }} + - name: systemctl daemon-reload + command: systemctl daemon-reload + - name: systemctl restart + command: systemctl restart x11vnc +` + +const updateAptCache = `--- +name: updateAptCache +target_os: "Linux" +variables: + - name: pre + value: "DEBIAN_FRONTEND=noninteractive timeout 300" +tasks: + - name: apt-get update + command: "{{ pre }} apt-get update -y" + - name: apt list + command: "{{ pre }} apt list --upgradeable 2>/dev/null | tail -n +2" + - name: apt list amount + command: "{{ pre }} apt list --upgradable 2>/dev/null | tail -n +2 | wc -l" +` + +const updateOs = `--- +name: updateOs +target_os: "Linux" +variables: + - name: pre + value: "DEBIAN_FRONTEND=noninteractive timeout 300" +tasks: + - name: dpkg configure + command: "{{ pre }} dpkg --configure -a --force-confold" + - name: apt-get update + command: "{{ pre }} apt-get update" + - name: apt-get fix broken install + command: "{{ pre }} apt-get --fix-broken install -y" + - name: apt-get upgrade + command: >- + {{ pre }} apt-get -q + -o Dpkg::Options::='--force-confold' + upgrade -y + - name: apt-get autoremove + command: "{{ pre }} apt-get -q autoremove -y" +` diff --git a/src/modules/setup/files.go b/src/modules/setup/files.go new file mode 100644 index 0000000..20d8a98 --- /dev/null +++ b/src/modules/setup/files.go @@ -0,0 +1,36 @@ +package setup + +const apiConf = `[meshcentral-account] +hostname = +username = +password = +totp_secret = +` + +const osCategories = `{ + "Linux": { + "Debian": [ + "Debian GNU/Linux 13 (trixie)", + "Debian GNU/Linux 12 (bookworm)", + "Debian GNU/Linux 11 (bullseye)", + "Debian GNU/Linux 10 (buster)" + ], + "Ubuntu": [ + "Ubuntu 24.04.3 LTS", + "Ubuntu 22.04.5 LTS", + "Ubuntu 20.04.6 LTS" + ] + }, + "MacOS": { + "Sequoia": [ + "macOS 15.0.1" + ] + }, + "Windows": { + "11": [ + "Microsoft Windows 11 Home - 24H2/26100", + "Microsoft Windows 11 Pro - 24H2/26100" + ] + } +} +` diff --git a/src/modules/setup/setup.go b/src/modules/setup/setup.go index b408935..98d3ed3 100644 --- a/src/modules/setup/setup.go +++ b/src/modules/setup/setup.go @@ -1,33 +1,85 @@ package setup import ( + "fmt" "log" "os" ) func PrepareEnvironment() (bool, error) { - ok, err := fsCheck() + if ok, err := fsCheck(); !ok || err != nil { + return ok, err + } - return ok, err + if ok, err := ensState(); !ok || err != nil { + return ok, err + } + + log.Println("Validated or made state compliant") + return true, nil } +// Filesystem check func fsCheck() (bool, error) { - dirs := []string{"./bin", "./books", "./history"} - files := []string{"./api.conf", "./os_categories.json"} + dirs := []string{"./bin", "./books"} for _, d := range dirs { if _, err := os.Stat(d); err != nil { - log.Printf("Unable to stat dir: %s", d) - return false, err - } - } + log.Printf("unable to stat dir: %s, trying to make it...", d) - for _, f := range files { - if _, err := os.Stat(f); err != nil { - log.Printf("Unable to stat file: %s", f) - return false, err + err := os.Mkdir(d, 0755) + if err != nil { + return false, err + } } } return true, nil } + +// Basic state +func ensState() (bool, error) { + files := []string{"./api.conf", "./os_categories.json", + "./books/rdpCheck.yaml", + "./books/updateAptCache.yaml", "./books/updateOs.yaml", + "./books/enableVncConsent.yaml", "./books/disableVncConsent.yaml", + } + + failedState := false + for _, f := range files { + if _, err := os.Stat(f); err != nil { + log.Printf("unable to stat: %s, creating it from template...", f) + + var err error + switch f { + case "./api.conf": + err = os.WriteFile(f, []byte(apiConf), 0644) + case "./os_categories.json": + err = os.WriteFile(f, []byte(osCategories), 0644) + case "./books/rdpCheck.yaml": + err = os.WriteFile(f, []byte(rdpCheck), 0644) + case "./books/updateAptCache.yaml": + err = os.WriteFile(f, []byte(updateAptCache), 0644) + case "./books/updateOs.yaml": + err = os.WriteFile(f, []byte(updateOs), 0644) + case "./books/enableVncConsent.yaml": + err = os.WriteFile(f, []byte(enableVncConsent), 0644) + case "./books/disableVncConsent.yaml": + err = os.WriteFile(f, []byte(disableVncConsent), 0644) + default: + log.Println("no template defined for this file... not making it") + } + + if err != nil { + log.Printf("error trying to create from template: %v", err) + failedState = true + } + } + } + + if failedState { + return false, fmt.Errorf("failed to ensure the basic operating state. see above for details") + } else { + return true, nil + } +} diff --git a/src/modules/tasks/tasks.go b/src/modules/tasks/tasks.go new file mode 100644 index 0000000..29a392e --- /dev/null +++ b/src/modules/tasks/tasks.go @@ -0,0 +1,35 @@ +package tasks + +import ( + "log" + "os" + "strings" +) + +func isYaml(filename string) bool { + return strings.HasSuffix(filename, ".yaml") || strings.HasSuffix(filename, ".yml") +} + +func ListAvailableBooks() ([]string, error) { + files, err := os.ReadDir("./books") + if err != nil { + log.Printf("failed to read the './books' directory: %v", err) + return []string{}, err + } + + foundBooks := []string{} + for _, f := range files { + if f.IsDir() { + continue + } + + fName := f.Name() + log.Println(fName) + if isYaml(fName) { + fullRelPath := "./books/" + fName + foundBooks = append(foundBooks, fullRelPath) + } + } + + return foundBooks, nil +}