Author | Jakob Wakeling <[email protected]> |
Date | 2024-01-29 09:10:46 |
Commit | 2ac8bbb62765cdf913e0516e728406c8c5e37f01 |
Parent | 813b687f0799ead13f2d7eb6982c2754659f826b |
Replace XDG dependency with a custom solution
Also use /etc/goit, /var/lib/goit, /var/log/goit, and /run instead of XDG directories when running as root.
Diffstat
M | go.mod | | | 1 | - |
M | go.sum | | | 3 | --- |
A | src/goit/config.go | | | 123 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | src/goit/goit.go | | | 68 | ++++++++++++++++---------------------------------------------------- |
M | src/main.go | | | 7 | +++---- |
5 files changed, 142 insertions, 60 deletions
diff --git a/go.mod b/go.mod index 89c75f6..334edbc 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,6 @@ module github.com/Jamozed/Goit go 1.21.0 require ( - github.com/adrg/xdg v0.4.0 github.com/alecthomas/chroma v0.10.0 github.com/buildkite/terminal-to-html/v3 v3.10.1 github.com/dustin/go-humanize v1.0.1 diff --git a/go.sum b/go.sum index 3c9e76f..ed00554 100644 --- a/go.sum +++ b/go.sum @@ -5,8 +5,6 @@ github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migc github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c h1:kMFnB0vCcX7IL/m9Y5LO+KQYv+t1CQOiFe6+SV2J7bE= github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= -github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls= -github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E= github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek= github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= @@ -123,7 +121,6 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/src/goit/config.go b/src/goit/config.go new file mode 100644 index 0000000..be54bff --- /dev/null +++ b/src/goit/config.go @@ -0,0 +1,123 @@ +// Copyright (C) 2024, Jakob Wakeling +// All rights reserved. + +package goit + +import ( + "encoding/json" + "errors" + "os" + "path/filepath" +) + +type config struct { + DataPath string `json:"data_path"` + LogsPath string `json:"logs_path"` + RuntimePath string `json:"runtime_path"` + HttpAddr string `json:"http_addr"` + HttpPort string `json:"http_port"` + GitPath string `json:"git_path"` + IpSessions bool `json:"ip_sessions"` + UsesHttps bool `json:"uses_https"` + IpForwarded bool `json:"ip_forwarded"` + CsrfSecret string `json:"csrf_secret"` +} + +func loadConfig() (config, error) { + conf := config{ + DataPath: dataPath(), + LogsPath: logsPath(), + RuntimePath: runtimePath(), + HttpAddr: "", + HttpPort: "8080", + GitPath: "git", + IpSessions: true, + UsesHttps: false, + IpForwarded: false, + CsrfSecret: "1234567890abcdef1234567890abcdef", + } + + /* Load config file(s) */ + configs := []string{ + filepath.Join("/etc", "goit", "goit.conf"), + } + + if os.Getuid() != 0 { + configs = append(configs, filepath.Join(userConfigBase(), "goit", "goit.conf")) + } + + for _, file := range configs { + if data, err := os.ReadFile(file); err != nil { + if !errors.Is(err, os.ErrNotExist) { + return config{}, err + } + } else if data != nil { + if json.Unmarshal(data, &conf); err != nil { + return config{}, err + } + } + } + + /* Check required config values */ + if conf.DataPath == "" { + return config{}, errors.New("data path unset") + } + + return conf, nil +} + +func userConfigBase() string { + if path := os.Getenv("XDG_CONFIG_HOME"); path != "" { + return path + } + + if path := os.Getenv("HOME"); path != "" { + return filepath.Join(path, ".config") + } + + return "" +} + +func dataPath() string { + if os.Getuid() == 0 { + return "/var/lib/goit" + } + + if path := os.Getenv("XDG_DATA_HOME"); path != "" { + return filepath.Join(path, "goit") + } + + if path := os.Getenv("HOME"); path != "" { + return filepath.Join(path, ".local", "share", "goit") + } + + return "" +} + +func logsPath() string { + if os.Getuid() == 0 { + return "/var/log/goit" + } + + if path := os.Getenv("XDG_STATE_HOME"); path != "" { + return filepath.Join(path, "goit") + } + + if path := os.Getenv("HOME"); path != "" { + return filepath.Join(path, ".local", "state", "goit") + } + + return "" +} + +func runtimePath() string { + if os.Getuid() == 0 { + return "/run" + } + + if path := os.Getenv("XDG_RUNTIME_DIR"); path != "" { + return filepath.Join(path) + } + + return "" +} diff --git a/src/goit/goit.go b/src/goit/goit.go index f2ed0c8..0a799b2 100644 --- a/src/goit/goit.go +++ b/src/goit/goit.go @@ -21,34 +21,12 @@ import ( "github.com/Jamozed/Goit/res" "github.com/Jamozed/Goit/src/cron" "github.com/Jamozed/Goit/src/util" - "github.com/adrg/xdg" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing/transport" _ "github.com/mattn/go-sqlite3" ) -type Config struct { - DataPath string `json:"data_path"` - HttpAddr string `json:"http_addr"` - HttpPort string `json:"http_port"` - GitPath string `json:"git_path"` - IpSessions bool `json:"ip_sessions"` - UsesHttps bool `json:"uses_https"` - IpForwarded bool `json:"ip_forwarded"` - CsrfSecret string `json:"csrf_secret"` -} - -var Conf = Config{ - DataPath: filepath.Join(xdg.DataHome, "goit"), - HttpAddr: "", - HttpPort: "8080", - GitPath: "git", - IpSessions: true, - UsesHttps: false, - IpForwarded: false, - CsrfSecret: "1234567890abcdef1234567890abcdef", -} - +var Conf config var db *sql.DB var Favicon []byte var Cron *cron.Cron @@ -57,23 +35,18 @@ var Reserved []string = []string{"admin", "repo", "static", "user"} var StartTime = time.Now() -func Goit(conf string) (err error) { - if dat, err := os.ReadFile(conf); err != nil { - if !errors.Is(err, os.ErrNotExist) { - return fmt.Errorf("[Config] %w", err) - } - } else if dat != nil { - if json.Unmarshal(dat, &Conf); err != nil { - return fmt.Errorf("[Config] %w", err) - } +func Goit() error { + if conf, err := loadConfig(); err != nil { + return err + } else { + Conf = conf } - logPath, err := xdg.StateFile(filepath.Join("goit", fmt.Sprint("goit_", time.Now().Unix(), ".log"))) - if err != nil { - log.Fatalln("[log]", err.Error()) + if err := os.MkdirAll(Conf.LogsPath, 0o777); err != nil { + return fmt.Errorf("[config] %w", err) } - logFile, err := os.Create(logPath) + logFile, err := os.Create(filepath.Join(Conf.LogsPath, fmt.Sprint("goit_", time.Now().Unix(), ".log"))) if err != nil { log.Fatalln("[log]", err.Error()) } @@ -83,37 +56,37 @@ func Goit(conf string) (err error) { log.Println("[Config] using data path:", Conf.DataPath) if err := os.MkdirAll(Conf.DataPath, 0o777); err != nil { - return fmt.Errorf("[Config] %w", err) + return fmt.Errorf("[config] %w", err) } if dat, err := os.ReadFile(filepath.Join(Conf.DataPath, "favicon.png")); err != nil { - log.Println("[Favicon]", err.Error()) + log.Println("[favicon]", err.Error()) } else { Favicon = dat } if db, err = sql.Open("sqlite3", filepath.Join(Conf.DataPath, "goit.db")); err != nil { - return fmt.Errorf("[Database] %w", err) + return fmt.Errorf("[database] %w", err) } /* Update the database if necessary */ if err := dbUpdate(db); err != nil { - return fmt.Errorf("[Database] %w", err) + return fmt.Errorf("[database] %w", err) } /* Create an admin user if one does not exist */ if exists, err := UserExists("admin"); err != nil { - log.Println("[admin Exists]", err.Error()) + log.Println("[admin:exists]", err.Error()) err = nil /* ignored */ } else if !exists { if salt, err := Salt(); err != nil { - log.Println("[admin Salt]", err.Error()) + log.Println("[admin:salt]", err.Error()) err = nil /* ignored */ } else if _, err = db.Exec( "INSERT INTO users (id, name, name_full, pass, pass_algo, salt, is_admin) VALUES (?, ?, ?, ?, ?, ?, ?)", 0, "admin", "Administrator", Hash("admin", salt), "argon2", salt, true, ); err != nil { - log.Println("[admin INSERT]", err.Error()) + log.Println("[admin:INSERT]", err.Error()) err = nil /* ignored */ } } @@ -148,15 +121,6 @@ func Goit(conf string) (err error) { return nil } -func ConfPath() string { - if p, err := xdg.SearchConfigFile(filepath.Join("goit", "goit.json")); err != nil { - log.Println("[config]", err.Error()) - return "" - } else { - return p - } -} - func RepoPath(name string, abs bool) string { return util.If(abs, filepath.Join(Conf.DataPath, "repos", name+".git"), filepath.Join(name+".git")) } diff --git a/src/main.go b/src/main.go index 8ac6ce1..590a187 100644 --- a/src/main.go +++ b/src/main.go @@ -24,7 +24,6 @@ import ( "github.com/Jamozed/Goit/src/repo" "github.com/Jamozed/Goit/src/user" "github.com/Jamozed/Goit/src/util" - "github.com/adrg/xdg" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" "github.com/gorilla/csrf" @@ -40,7 +39,7 @@ func main() { flag.Parse() if backup /* IPC client */ { - c, err := net.Dial("unix", filepath.Join(xdg.RuntimeDir, "goit-"+goit.Conf.HttpPort+".sock")) + c, err := net.Dial("unix", filepath.Join(goit.Conf.RuntimePath, "goit-"+goit.Conf.HttpPort+".sock")) if err != nil { log.Fatalln(err.Error()) } @@ -77,7 +76,7 @@ func main() { }() /* Initialise Goit */ - if err := goit.Goit(goit.ConfPath()); err != nil { + if err := goit.Goit(); err != nil { log.Fatalln(err.Error()) } @@ -156,7 +155,7 @@ func main() { // h.Post("/{repo}/git-receive-pack", goit.HandleReceivePack) /* Listen for IPC */ - ipc, err := net.Listen("unix", filepath.Join(xdg.RuntimeDir, "goit-"+goit.Conf.HttpPort+".sock")) + ipc, err := net.Listen("unix", filepath.Join(goit.Conf.RuntimePath, "goit-"+goit.Conf.HttpPort+".sock")) if err != nil { log.Fatalln("[sock]", err.Error()) }