feat: add feature to delegate visibility per permissions (#4)
All checks were successful
Cross-Compile Binaries / compile-linux (push) Successful in 4m6s
Cross-Compile Binaries / compile-windows (push) Successful in 9m37s

Reviewed-on: #4
This commit was merged in pull request #4.
This commit is contained in:
2026-02-11 09:27:17 +00:00
parent 50feef9589
commit 6ad4a886b3
5 changed files with 80 additions and 22 deletions

2
.gitignore vendored
View File

@@ -3,6 +3,8 @@
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore # https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
# #
# Binaries for programs and plugins # Binaries for programs and plugins
*
!*.*
*.exe *.exe
*.exe~ *.exe~
*.dll *.dll

View File

@@ -137,6 +137,10 @@ func drawTargetSection(raspiNames []string, raspiTarget *string, uploadBtn, relo
var previousTarget string var previousTarget string
var verifyBtn *widget.Button var verifyBtn *widget.Button
if len(raspiNames) == 0 {
raspiNames = append(raspiNames, "No available targets...")
}
// Left side for selection of target // Left side for selection of target
piSelection := widget.NewRadioGroup(raspiNames, func(selected string) { piSelection := widget.NewRadioGroup(raspiNames, func(selected string) {
if selected == previousTarget { if selected == previousTarget {

View File

@@ -2,6 +2,8 @@ package main
import ( import (
"log" "log"
"os/user"
"slices"
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"fyne.io/fyne/v2/app" "fyne.io/fyne/v2/app"
@@ -46,12 +48,18 @@ func main() {
w.Resize(windowSize) w.Resize(windowSize)
w.SetIcon(iconResource) w.SetIcon(iconResource)
uCtx, err := user.Current()
if err != nil {
log.Fatal("Unable to determine user")
}
username := uCtx.Username
cfg, ok := readConfig() cfg, ok := readConfig()
if !ok { if !ok {
dialog.ShowInformation("Failed to initialize", "Failed to read or unmarshal the raspis.yaml", w) dialog.ShowInformation("Failed to initialize", "Failed to read or unmarshal the raspis.yaml", w)
} }
raspiNames := getRaspiNames(cfg) raspiNames := getRaspiNames(cfg, username)
// Define variables and print them out for debug // Define variables and print them out for debug
// Presentation = 1 // Presentation = 1
@@ -60,6 +68,19 @@ func main() {
var raspiTarget string = "" var raspiTarget string = ""
var localUploadPath string var localUploadPath string
// Predefine the containers in total
var modeBtnRow *fyne.Container
var fileSelectRow *fyne.Container
var tgrtSelectionRow *fyne.Container
var footerRow *fyne.Container
// Predefine the buttons for future reference
var uploadBtn *widget.Button
var reloadBtn *widget.Button
// Predefine some of the labels
var pathLabel *widget.Label
log.Println("Current mode:", targetMode) log.Println("Current mode:", targetMode)
if raspiTarget == "" { if raspiTarget == "" {
log.Println("Current target: None") log.Println("Current target: None")
@@ -68,28 +89,24 @@ func main() {
} }
// Call the draw functions -> ./src/draw.go // Call the draw functions -> ./src/draw.go
footerRow, uploadBtn, reloadBtn := drawFooter(app, &raspiTarget, &localUploadPath, &targetMode, cfg) footerRow, uploadBtn, reloadBtn = drawFooter(app, &raspiTarget, &localUploadPath, &targetMode, cfg)
fileSelectRow, pathLabel := drawFileSelection(&localUploadPath, &targetMode, w) fileSelectRow, pathLabel = drawFileSelection(&localUploadPath, &targetMode, w)
modeBtnRow := drawModeRow(pathLabel, &localUploadPath, &targetMode) modeBtnRow = drawModeRow(pathLabel, &localUploadPath, &targetMode)
selectionRow := drawTargetSection(raspiNames, &raspiTarget, uploadBtn, reloadBtn, cfg) tgrtSelectionRow = drawTargetSection(raspiNames, &raspiTarget, uploadBtn, reloadBtn, cfg)
center := container.NewVBox( center := container.NewVBox(
modeBtnRow, modeBtnRow,
widget.NewLabel(""), widget.NewLabel(""),
fileSelectRow, fileSelectRow,
drawSeparator(true, true), drawSeparator(true, true),
selectionRow, tgrtSelectionRow,
)
top := container.NewVBox(
widget.NewLabel(appName),
drawSeparator(false, false),
) )
content := container.NewBorder( content := container.NewBorder(
top, // top nil,
footerRow, // bottom footerRow, // bottom
nil, nil, // left, right nil,
nil, // left, right
center, //center center, //center
) )
@@ -107,14 +124,40 @@ func refreshButtons(givenButtons ...*widget.Button) {
} }
// The raspiList is defined in the other go file, must me maintained separately // The raspiList is defined in the other go file, must me maintained separately
func getRaspiNames(cfg RaspiConfig) []string { func getRaspiNames(cfg RaspiConfig, username string) []string {
raspiNames := make([]string, 0, len(cfg.Raspis)) raspiNames := make([]string, 0, len(cfg.Raspis))
var superAdminPresent bool
if len(cfg.SuperAdmin) == 0 {
superAdminPresent = false
} else {
superAdminPresent = true
}
log.Printf("Adding super_admin to the authorized_users at runtime: %s", cfg.SuperAdmin)
// Append the name of the pi to the list we need for the radio button // Append the name of the pi to the list we need for the radio button
// i is the index field correlated to the name as per defined in rpi-list.go // i is the index field correlated to the name as per defined in rpi-list.go
for _, n := range cfg.Raspis { for _, indPi := range cfg.Raspis {
raspiNames = append(raspiNames, n.Name) // append only the first element if superAdminPresent {
indPi.AuthorizedUsers = append(indPi.AuthorizedUsers, cfg.SuperAdmin) // Append the superadmin to the authorized users
}
if allowedUser(indPi.AuthorizedUsers, username) {
raspiNames = append(raspiNames, indPi.Name) // append only the first element
}
} }
return raspiNames return raspiNames
} }
func allowedUser(authorized_users []string, username string) bool {
if len(authorized_users) == 0 {
return false
}
if slices.Contains(authorized_users, username) {
log.Printf("Found a match for the user %s", username)
return true
} else {
return false
}
}

View File

@@ -8,15 +8,17 @@ import (
) )
type RaspberryPi struct { type RaspberryPi struct {
Name string `yaml:"name"` Name string `yaml:"name"`
Hostname string `yaml:"hostname"` AuthorizedUsers []string `yaml:"authorized_users"`
Port string `yaml:"port"` Hostname string `yaml:"hostname"`
Username string `yaml:"username"` Port string `yaml:"port"`
Password string `yaml:"password,omitempty"` // optional Username string `yaml:"username"`
Password string `yaml:"password,omitempty"` // optional
} }
type RaspiConfig struct { type RaspiConfig struct {
Raspis []RaspberryPi `yaml:"raspis"` SuperAdmin string `yaml:"super_admin"`
Raspis []RaspberryPi `yaml:"raspis"`
} }
func readConfig() (RaspiConfig, bool) { func readConfig() (RaspiConfig, bool) {

View File

@@ -1,3 +1,4 @@
super_admin: SYSTEMECCLOUD\systemecadmin
raspis: raspis:
- name: rpi1 - name: rpi1
ip: 192.168.1.10 ip: 192.168.1.10
@@ -5,11 +6,17 @@ raspis:
user: pi user: pi
password: mypassword1 password: mypassword1
- name: rpi2 - name: rpi2
authorized_users:
- WORKGROUP\username
ip: 192.168.1.11 ip: 192.168.1.11
port: 2222 port: 2222
user: pi user: pi
password: mypassword2 password: mypassword2
- name: rpi3 - name: rpi3
authorized_users:
- WORKGROUP\username
- AZUREAD\username
- DOMAIN\username
ip: 192.168.1.12 ip: 192.168.1.12
port: 22 port: 22
user: pi user: pi