mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-04-14 17:52:10 -04:00
greeter: Add support for Debian greetd user/group name (#1685)
* greeter: Detect user and group used by greetd On most distros greetd runs as user and group "greeter", but on Debian the user and group "_greetd" are used. * greeter: Use correct group in sync command * greeter: more generic group detection --------- Co-authored-by: bbedward <bbedward@gmail.com>
This commit is contained in:
committed by
GitHub
parent
f2a6d2c7da
commit
81bce74612
@@ -169,7 +169,8 @@ func syncGreeter() error {
|
|||||||
return fmt.Errorf("greeter cache directory not found at %s\nPlease install the greeter first", cacheDir)
|
return fmt.Errorf("greeter cache directory not found at %s\nPlease install the greeter first", cacheDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
greeterGroupExists := checkGroupExists("greeter")
|
greeterGroup := greeter.DetectGreeterGroup()
|
||||||
|
greeterGroupExists := utils.HasGroup(greeterGroup)
|
||||||
if greeterGroupExists {
|
if greeterGroupExists {
|
||||||
currentUser, err := user.Current()
|
currentUser, err := user.Current()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -182,24 +183,24 @@ func syncGreeter() error {
|
|||||||
return fmt.Errorf("failed to check groups: %w", err)
|
return fmt.Errorf("failed to check groups: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
inGreeterGroup := strings.Contains(string(groupsOutput), "greeter")
|
inGreeterGroup := strings.Contains(string(groupsOutput), greeterGroup)
|
||||||
if !inGreeterGroup {
|
if !inGreeterGroup {
|
||||||
fmt.Println("\n⚠ Warning: You are not in the greeter group.")
|
fmt.Printf("\n⚠ Warning: You are not in the %s group.\n", greeterGroup)
|
||||||
fmt.Print("Would you like to add your user to the greeter group? (Y/n): ")
|
fmt.Printf("Would you like to add your user to the %s group? (Y/n): ", greeterGroup)
|
||||||
|
|
||||||
var response string
|
var response string
|
||||||
fmt.Scanln(&response)
|
fmt.Scanln(&response)
|
||||||
response = strings.ToLower(strings.TrimSpace(response))
|
response = strings.ToLower(strings.TrimSpace(response))
|
||||||
|
|
||||||
if response != "n" && response != "no" {
|
if response != "n" && response != "no" {
|
||||||
fmt.Println("\nAdding user to greeter group...")
|
fmt.Printf("\nAdding user to %s group...\n", greeterGroup)
|
||||||
addUserCmd := exec.Command("sudo", "usermod", "-aG", "greeter", currentUser.Username)
|
addUserCmd := exec.Command("sudo", "usermod", "-aG", greeterGroup, currentUser.Username)
|
||||||
addUserCmd.Stdout = os.Stdout
|
addUserCmd.Stdout = os.Stdout
|
||||||
addUserCmd.Stderr = os.Stderr
|
addUserCmd.Stderr = os.Stderr
|
||||||
if err := addUserCmd.Run(); err != nil {
|
if err := addUserCmd.Run(); err != nil {
|
||||||
return fmt.Errorf("failed to add user to greeter group: %w", err)
|
return fmt.Errorf("failed to add user to %s group: %w", greeterGroup, err)
|
||||||
}
|
}
|
||||||
fmt.Println("✓ User added to greeter group")
|
fmt.Printf("✓ User added to %s group\n", greeterGroup)
|
||||||
fmt.Println("⚠ You will need to log out and back in for the group change to take effect")
|
fmt.Println("⚠ You will need to log out and back in for the group change to take effect")
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("aborted: user must be in the greeter group before syncing")
|
return fmt.Errorf("aborted: user must be in the greeter group before syncing")
|
||||||
@@ -245,21 +246,6 @@ func syncGreeter() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkGroupExists(groupName string) bool {
|
|
||||||
data, err := os.ReadFile("/etc/group")
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
lines := strings.SplitSeq(string(data), "\n")
|
|
||||||
for line := range lines {
|
|
||||||
if strings.HasPrefix(line, groupName+":") {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func disableDisplayManager(dmName string) (bool, error) {
|
func disableDisplayManager(dmName string) (bool, error) {
|
||||||
state, err := getSystemdServiceState(dmName)
|
state, err := getSystemdServiceState(dmName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -22,6 +22,21 @@ func DetectDMSPath() (string, error) {
|
|||||||
return config.LocateDMSConfig()
|
return config.LocateDMSConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DetectGreeterGroup() string {
|
||||||
|
data, err := os.ReadFile("/etc/group")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, "⚠ Warning: could not read /etc/group, defaulting to greeter")
|
||||||
|
return "greeter"
|
||||||
|
}
|
||||||
|
|
||||||
|
if group, found := utils.FindGroupData(string(data), "greeter", "greetd", "_greeter"); found {
|
||||||
|
return group
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintln(os.Stderr, "⚠ Warning: no greeter group found in /etc/group, defaulting to greeter")
|
||||||
|
return "greeter"
|
||||||
|
}
|
||||||
|
|
||||||
// DetectCompositors checks which compositors are installed
|
// DetectCompositors checks which compositors are installed
|
||||||
func DetectCompositors() []string {
|
func DetectCompositors() []string {
|
||||||
var compositors []string
|
var compositors []string
|
||||||
@@ -194,14 +209,17 @@ func CopyGreeterFiles(dmsPath, compositor string, logFunc func(string), sudoPass
|
|||||||
return fmt.Errorf("failed to create cache directory: %w", err)
|
return fmt.Errorf("failed to create cache directory: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := runSudoCmd(sudoPassword, "chown", "greeter:greeter", cacheDir); err != nil {
|
group := DetectGreeterGroup()
|
||||||
|
owner := fmt.Sprintf("%s:%s", group, group)
|
||||||
|
|
||||||
|
if err := runSudoCmd(sudoPassword, "chown", owner, cacheDir); err != nil {
|
||||||
return fmt.Errorf("failed to set cache directory owner: %w", err)
|
return fmt.Errorf("failed to set cache directory owner: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := runSudoCmd(sudoPassword, "chmod", "755", cacheDir); err != nil {
|
if err := runSudoCmd(sudoPassword, "chmod", "755", cacheDir); err != nil {
|
||||||
return fmt.Errorf("failed to set cache directory permissions: %w", err)
|
return fmt.Errorf("failed to set cache directory permissions: %w", err)
|
||||||
}
|
}
|
||||||
logFunc(fmt.Sprintf("✓ Created cache directory %s (owner: greeter:greeter, permissions: 755)", cacheDir))
|
logFunc(fmt.Sprintf("✓ Created cache directory %s (owner: %s, permissions: 755)", cacheDir, owner))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -234,6 +252,8 @@ func SetupParentDirectoryACLs(logFunc func(string), sudoPassword string) error {
|
|||||||
{filepath.Join(homeDir, ".local", "share"), ".local/share directory"},
|
{filepath.Join(homeDir, ".local", "share"), ".local/share directory"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
owner := DetectGreeterGroup()
|
||||||
|
|
||||||
logFunc("\nSetting up parent directory ACLs for greeter user access...")
|
logFunc("\nSetting up parent directory ACLs for greeter user access...")
|
||||||
|
|
||||||
for _, dir := range parentDirs {
|
for _, dir := range parentDirs {
|
||||||
@@ -245,9 +265,9 @@ func SetupParentDirectoryACLs(logFunc func(string), sudoPassword string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set ACL to allow greeter user read+execute permission (for session discovery)
|
// Set ACL to allow greeter user read+execute permission (for session discovery)
|
||||||
if err := runSudoCmd(sudoPassword, "setfacl", "-m", "u:greeter:rx", dir.path); err != nil {
|
if err := runSudoCmd(sudoPassword, "setfacl", "-m", fmt.Sprintf("u:%s:rx", owner), dir.path); err != nil {
|
||||||
logFunc(fmt.Sprintf("⚠ Warning: Failed to set ACL on %s: %v", dir.desc, err))
|
logFunc(fmt.Sprintf("⚠ Warning: Failed to set ACL on %s: %v", dir.desc, err))
|
||||||
logFunc(fmt.Sprintf(" You may need to run manually: setfacl -m u:greeter:x %s", dir.path))
|
logFunc(fmt.Sprintf(" You may need to run manually: setfacl -m u:%s:x %s", owner, dir.path))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,17 +291,19 @@ func SetupDMSGroup(logFunc func(string), sudoPassword string) error {
|
|||||||
return fmt.Errorf("failed to determine current user")
|
return fmt.Errorf("failed to determine current user")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
group := DetectGreeterGroup()
|
||||||
|
|
||||||
// Check if user is already in greeter group
|
// Check if user is already in greeter group
|
||||||
groupsCmd := exec.Command("groups", currentUser)
|
groupsCmd := exec.Command("groups", currentUser)
|
||||||
groupsOutput, err := groupsCmd.Output()
|
groupsOutput, err := groupsCmd.Output()
|
||||||
if err == nil && strings.Contains(string(groupsOutput), "greeter") {
|
if err == nil && strings.Contains(string(groupsOutput), group) {
|
||||||
logFunc(fmt.Sprintf("✓ %s is already in greeter group", currentUser))
|
logFunc(fmt.Sprintf("✓ %s is already in %s group", currentUser, group))
|
||||||
} else {
|
} else {
|
||||||
// Add current user to greeter group for file access permissions
|
// Add current user to greeter group for file access permissions
|
||||||
if err := runSudoCmd(sudoPassword, "usermod", "-aG", "greeter", currentUser); err != nil {
|
if err := runSudoCmd(sudoPassword, "usermod", "-aG", group, currentUser); err != nil {
|
||||||
return fmt.Errorf("failed to add %s to greeter group: %w", currentUser, err)
|
return fmt.Errorf("failed to add %s to %s group: %w", currentUser, group, err)
|
||||||
}
|
}
|
||||||
logFunc(fmt.Sprintf("✓ Added %s to greeter group (logout/login required for changes to take effect)", currentUser))
|
logFunc(fmt.Sprintf("✓ Added %s to %s group (logout/login required for changes to take effect)", currentUser, group))
|
||||||
}
|
}
|
||||||
|
|
||||||
configDirs := []struct {
|
configDirs := []struct {
|
||||||
@@ -304,7 +326,7 @@ func SetupDMSGroup(logFunc func(string), sudoPassword string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := runSudoCmd(sudoPassword, "chgrp", "-R", "greeter", dir.path); err != nil {
|
if err := runSudoCmd(sudoPassword, "chgrp", "-R", group, dir.path); err != nil {
|
||||||
logFunc(fmt.Sprintf("⚠ Warning: Failed to set group for %s: %v", dir.desc, err))
|
logFunc(fmt.Sprintf("⚠ Warning: Failed to set group for %s: %v", dir.desc, err))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -436,10 +458,11 @@ func syncNiriGreeterConfig(logFunc func(string), sudoPassword string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
greeterDir := "/etc/greetd/niri"
|
greeterDir := "/etc/greetd/niri"
|
||||||
|
greeterGroup := DetectGreeterGroup()
|
||||||
if err := runSudoCmd(sudoPassword, "mkdir", "-p", greeterDir); err != nil {
|
if err := runSudoCmd(sudoPassword, "mkdir", "-p", greeterDir); err != nil {
|
||||||
return fmt.Errorf("failed to create greetd niri directory: %w", err)
|
return fmt.Errorf("failed to create greetd niri directory: %w", err)
|
||||||
}
|
}
|
||||||
if err := runSudoCmd(sudoPassword, "chown", "root:greeter", greeterDir); err != nil {
|
if err := runSudoCmd(sudoPassword, "chown", fmt.Sprintf("root:%s", greeterGroup), greeterDir); err != nil {
|
||||||
return fmt.Errorf("failed to set greetd niri directory ownership: %w", err)
|
return fmt.Errorf("failed to set greetd niri directory ownership: %w", err)
|
||||||
}
|
}
|
||||||
if err := runSudoCmd(sudoPassword, "chmod", "755", greeterDir); err != nil {
|
if err := runSudoCmd(sudoPassword, "chmod", "755", greeterDir); err != nil {
|
||||||
@@ -464,7 +487,7 @@ func syncNiriGreeterConfig(logFunc func(string), sudoPassword string) error {
|
|||||||
if err := backupFileIfExists(sudoPassword, dmsPath, ".backup"); err != nil {
|
if err := backupFileIfExists(sudoPassword, dmsPath, ".backup"); err != nil {
|
||||||
return fmt.Errorf("failed to backup %s: %w", dmsPath, err)
|
return fmt.Errorf("failed to backup %s: %w", dmsPath, err)
|
||||||
}
|
}
|
||||||
if err := runSudoCmd(sudoPassword, "install", "-o", "root", "-g", "greeter", "-m", "0644", dmsTemp.Name(), dmsPath); err != nil {
|
if err := runSudoCmd(sudoPassword, "install", "-o", "root", "-g", greeterGroup, "-m", "0644", dmsTemp.Name(), dmsPath); err != nil {
|
||||||
return fmt.Errorf("failed to install greetd niri dms config: %w", err)
|
return fmt.Errorf("failed to install greetd niri dms config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -487,7 +510,7 @@ func syncNiriGreeterConfig(logFunc func(string), sudoPassword string) error {
|
|||||||
if err := backupFileIfExists(sudoPassword, mainPath, ".backup"); err != nil {
|
if err := backupFileIfExists(sudoPassword, mainPath, ".backup"); err != nil {
|
||||||
return fmt.Errorf("failed to backup %s: %w", mainPath, err)
|
return fmt.Errorf("failed to backup %s: %w", mainPath, err)
|
||||||
}
|
}
|
||||||
if err := runSudoCmd(sudoPassword, "install", "-o", "root", "-g", "greeter", "-m", "0644", mainTemp.Name(), mainPath); err != nil {
|
if err := runSudoCmd(sudoPassword, "install", "-o", "root", "-g", greeterGroup, "-m", "0644", mainTemp.Name(), mainPath); err != nil {
|
||||||
return fmt.Errorf("failed to install greetd niri main config: %w", err)
|
return fmt.Errorf("failed to install greetd niri main config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -736,17 +759,19 @@ func ConfigureGreetd(dmsPath, compositor string, logFunc func(string), sudoPassw
|
|||||||
logFunc(fmt.Sprintf("✓ Backed up existing config to %s", backupPath))
|
logFunc(fmt.Sprintf("✓ Backed up existing config to %s", backupPath))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
greeterUser := DetectGreeterGroup()
|
||||||
|
|
||||||
var configContent string
|
var configContent string
|
||||||
if data, err := os.ReadFile(configPath); err == nil {
|
if data, err := os.ReadFile(configPath); err == nil {
|
||||||
configContent = string(data)
|
configContent = string(data)
|
||||||
} else {
|
} else {
|
||||||
configContent = `[terminal]
|
configContent = fmt.Sprintf(`[terminal]
|
||||||
vt = 1
|
vt = 1
|
||||||
|
|
||||||
[default_session]
|
[default_session]
|
||||||
|
|
||||||
user = "greeter"
|
user = "%s"
|
||||||
`
|
`, greeterUser)
|
||||||
}
|
}
|
||||||
|
|
||||||
lines := strings.Split(configContent, "\n")
|
lines := strings.Split(configContent, "\n")
|
||||||
@@ -755,7 +780,7 @@ user = "greeter"
|
|||||||
trimmed := strings.TrimSpace(line)
|
trimmed := strings.TrimSpace(line)
|
||||||
if !strings.HasPrefix(trimmed, "command =") && !strings.HasPrefix(trimmed, "command=") {
|
if !strings.HasPrefix(trimmed, "command =") && !strings.HasPrefix(trimmed, "command=") {
|
||||||
if strings.HasPrefix(trimmed, "user =") || strings.HasPrefix(trimmed, "user=") {
|
if strings.HasPrefix(trimmed, "user =") || strings.HasPrefix(trimmed, "user=") {
|
||||||
newLines = append(newLines, `user = "greeter"`)
|
newLines = append(newLines, fmt.Sprintf(`user = "%s"`, greeterUser))
|
||||||
} else {
|
} else {
|
||||||
newLines = append(newLines, line)
|
newLines = append(newLines, line)
|
||||||
}
|
}
|
||||||
@@ -807,7 +832,7 @@ user = "greeter"
|
|||||||
return fmt.Errorf("failed to move config to /etc/greetd: %w", err)
|
return fmt.Errorf("failed to move config to /etc/greetd: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
logFunc(fmt.Sprintf("✓ Updated greetd configuration (user: greeter, command: %s --command %s -p %s)", wrapperCmd, compositorLower, dmsPath))
|
logFunc(fmt.Sprintf("✓ Updated greetd configuration (user: %s, command: %s --command %s -p %s)", greeterUser, wrapperCmd, compositorLower, dmsPath))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
37
core/internal/utils/group.go
Normal file
37
core/internal/utils/group.go
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func HasGroup(groupName string) bool {
|
||||||
|
return HasGroupIn(groupName, "/etc/group")
|
||||||
|
}
|
||||||
|
|
||||||
|
func HasGroupIn(groupName, path string) bool {
|
||||||
|
data, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return HasGroupData(groupName, string(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
func HasGroupData(groupName, data string) bool {
|
||||||
|
prefix := groupName + ":"
|
||||||
|
for line := range strings.SplitSeq(data, "\n") {
|
||||||
|
if strings.HasPrefix(line, prefix) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func FindGroupData(data string, candidates ...string) (string, bool) {
|
||||||
|
for _, candidate := range candidates {
|
||||||
|
if HasGroupData(candidate, data) {
|
||||||
|
return candidate, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
142
core/internal/utils/group_test.go
Normal file
142
core/internal/utils/group_test.go
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
const testGroupData = `root:x:0:brltty,root
|
||||||
|
sys:x:3:bin,testuser
|
||||||
|
mem:x:8:
|
||||||
|
ftp:x:11:
|
||||||
|
mail:x:12:
|
||||||
|
log:x:19:
|
||||||
|
smmsp:x:25:
|
||||||
|
proc:x:26:
|
||||||
|
games:x:50:
|
||||||
|
lock:x:54:
|
||||||
|
network:x:90:
|
||||||
|
floppy:x:94:
|
||||||
|
scanner:x:96:
|
||||||
|
power:x:98:
|
||||||
|
nobody:x:65534:
|
||||||
|
adm:x:999:daemon
|
||||||
|
wheel:x:998:testuser
|
||||||
|
utmp:x:997:
|
||||||
|
audio:x:996:brltty
|
||||||
|
disk:x:995:
|
||||||
|
input:x:994:brltty,testuser,greeter
|
||||||
|
kmem:x:993:
|
||||||
|
kvm:x:992:libvirt-qemu,qemu,testuser
|
||||||
|
lp:x:991:cups,testuser
|
||||||
|
optical:x:990:
|
||||||
|
render:x:989:
|
||||||
|
sgx:x:988:
|
||||||
|
storage:x:987:
|
||||||
|
tty:x:5:brltty
|
||||||
|
uucp:x:986:brltty
|
||||||
|
video:x:985:cosmic-greeter,greeter,testuser
|
||||||
|
users:x:984:
|
||||||
|
groups:x:983:
|
||||||
|
systemd-journal:x:982:
|
||||||
|
rfkill:x:981:
|
||||||
|
bin:x:1:daemon
|
||||||
|
daemon:x:2:bin
|
||||||
|
http:x:33:
|
||||||
|
dbus:x:81:
|
||||||
|
systemd-coredump:x:980:
|
||||||
|
systemd-network:x:979:
|
||||||
|
systemd-oom:x:978:
|
||||||
|
systemd-journal-remote:x:977:
|
||||||
|
systemd-resolve:x:976:
|
||||||
|
systemd-timesync:x:975:
|
||||||
|
tss:x:974:
|
||||||
|
uuidd:x:973:
|
||||||
|
alpm:x:972:
|
||||||
|
polkitd:x:102:
|
||||||
|
testuser:x:1000:
|
||||||
|
avahi:x:971:
|
||||||
|
git:x:970:
|
||||||
|
nvidia-persistenced:x:143:
|
||||||
|
i2c:x:969:testuser
|
||||||
|
seat:x:968:
|
||||||
|
rtkit:x:133:
|
||||||
|
brlapi:x:967:brltty
|
||||||
|
gdm:x:120:
|
||||||
|
brltty:x:966:
|
||||||
|
colord:x:965:
|
||||||
|
flatpak:x:964:
|
||||||
|
geoclue:x:963:testuser
|
||||||
|
gnome-remote-desktop:x:962:
|
||||||
|
saned:x:961:
|
||||||
|
usbmux:x:140:
|
||||||
|
cosmic-greeter:x:960:
|
||||||
|
greeter:x:959:testuser
|
||||||
|
openvpn:x:958:
|
||||||
|
nm-openvpn:x:957:
|
||||||
|
named:x:40:
|
||||||
|
_talkd:x:956:
|
||||||
|
keyd:x:955:
|
||||||
|
cups:x:209:testuser
|
||||||
|
docker:x:954:testuser
|
||||||
|
mysql:x:953:
|
||||||
|
radicale:x:952:
|
||||||
|
onepassword:x:1001:
|
||||||
|
nixbld:x:951:nixbld01,nixbld02,nixbld03,nixbld04,nixbld05,nixbld06,nixbld07,nixbld08,nixbld09,nixbld10
|
||||||
|
virtlogin:x:940:
|
||||||
|
libvirt:x:939:testuser
|
||||||
|
libvirt-qemu:x:938:
|
||||||
|
qemu:x:937:
|
||||||
|
dnsmasq:x:936:
|
||||||
|
clock:x:935:
|
||||||
|
dms-greeter:x:1002:greeter,testuser
|
||||||
|
pcscd:x:934:
|
||||||
|
test:x:1003:
|
||||||
|
empower:x:933:
|
||||||
|
`
|
||||||
|
|
||||||
|
func TestHasGroupData(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
group string
|
||||||
|
want bool
|
||||||
|
}{
|
||||||
|
{"greeter", true},
|
||||||
|
{"root", true},
|
||||||
|
{"docker", true},
|
||||||
|
{"cosmic-greeter", true},
|
||||||
|
{"dms-greeter", true},
|
||||||
|
{"nonexistent", false},
|
||||||
|
{"greet", false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
if got := HasGroupData(tt.group, testGroupData); got != tt.want {
|
||||||
|
t.Errorf("HasGroupData(%q) = %v, want %v", tt.group, got, tt.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindGroupData(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
candidates []string
|
||||||
|
wantGroup string
|
||||||
|
wantFound bool
|
||||||
|
}{
|
||||||
|
{"first match wins", []string{"greeter", "greetd", "_greeter"}, "greeter", true},
|
||||||
|
{"fallback to second", []string{"greetd", "greeter"}, "greeter", true},
|
||||||
|
{"none found", []string{"_greetd", "greetd"}, "", false},
|
||||||
|
{"single match", []string{"docker"}, "docker", true},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
got, found := FindGroupData(testGroupData, tt.candidates...)
|
||||||
|
if got != tt.wantGroup || found != tt.wantFound {
|
||||||
|
t.Errorf("%s: FindGroupData(%v) = (%q, %v), want (%q, %v)",
|
||||||
|
tt.name, tt.candidates, got, found, tt.wantGroup, tt.wantFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHasGroupDataEmpty(t *testing.T) {
|
||||||
|
if HasGroupData("greeter", "") {
|
||||||
|
t.Error("expected false for empty data")
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user