From be9d92930958ea6fcffea4181dc887f1b2d92c61 Mon Sep 17 00:00:00 2001 From: Daniel Svitan Date: Thu, 10 Apr 2025 22:01:03 +0200 Subject: [PATCH] :tada: Inits admin cli app --- .gitignore | 5 +++ admin/go.mod | 22 ++++++++++++ admin/go.sum | 38 ++++++++++++++++++++ admin/main.go | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++ server/main.go | 14 ++++---- 5 files changed, 167 insertions(+), 6 deletions(-) create mode 100644 .gitignore create mode 100644 admin/go.mod create mode 100644 admin/go.sum create mode 100644 admin/main.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..142e12e --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.idea/ + +data/ + +*/.env diff --git a/admin/go.mod b/admin/go.mod new file mode 100644 index 0000000..4808bbe --- /dev/null +++ b/admin/go.mod @@ -0,0 +1,22 @@ +module svitan.dev/keys/admin + +go 1.24.2 + +require ( + github.com/fsnotify/fsnotify v1.8.0 // indirect + github.com/go-viper/mapstructure/v2 v2.2.1 // indirect + github.com/pelletier/go-toml/v2 v2.2.3 // indirect + github.com/sagikazarmark/locafero v0.7.0 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.12.0 // indirect + github.com/spf13/cast v1.7.1 // indirect + github.com/spf13/pflag v1.0.6 // indirect + github.com/spf13/viper v1.20.1 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + github.com/urfave/cli/v3 v3.1.1 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.9.0 // indirect + golang.org/x/sys v0.29.0 // indirect + golang.org/x/text v0.21.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/admin/go.sum b/admin/go.sum new file mode 100644 index 0000000..4f366d4 --- /dev/null +++ b/admin/go.sum @@ -0,0 +1,38 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= +github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= +github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= +github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= +github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= +github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= +github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= +github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= +github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= +github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/urfave/cli/v3 v3.1.1 h1:bNnl8pFI5dxPOjeONvFCDFoECLQsceDG4ejahs4Jtxk= +github.com/urfave/cli/v3 v3.1.1/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/admin/main.go b/admin/main.go new file mode 100644 index 0000000..c214027 --- /dev/null +++ b/admin/main.go @@ -0,0 +1,94 @@ +package main + +import ( + "context" + "errors" + "fmt" + "io" + "log" + "net/http" + "os" + + "github.com/spf13/viper" + "github.com/urfave/cli/v3" +) + +var ( + server string + token string +) + +func load() error { + viper.SetConfigName("config") + viper.SetConfigType("toml") + viper.AddConfigPath("$HOME/.local/share/keys") + err := viper.ReadInConfig() + if err != nil { + return err + } + + server = viper.GetString("server") + if server == "" { + return errors.New("'server' property is required") + } + + token = viper.GetString("token") + if token == "" { + return errors.New("'token' property is required") + } + + return nil +} + +func main() { + cmd := &cli.Command{ + Name: "keys-admin", + Usage: "keys project server administration tool", + Commands: []*cli.Command{ + { + Name: "version", + Usage: "print version and exit", + Action: func(context.Context, *cli.Command) error { + fmt.Println("version 1.0") + return nil + }, + }, + { + Name: "clients", + Usage: "fetch all clients", + Action: func(context.Context, *cli.Command) error { + err := load() + if err != nil { + return err + } + + url := fmt.Sprintf("%s/admin/clients", server) + req, err := http.NewRequest(http.MethodGet, url, nil) + if err != nil { + return err + } + + req.Header.Set("Authorization", token) + + res, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + + body, err := io.ReadAll(res.Body) + if err != nil { + return err + } + + fmt.Printf("%s", body) + return nil + }, + }, + }, + } + + err := cmd.Run(context.Background(), os.Args) + if err != nil { + log.Fatal(err) + } +} diff --git a/server/main.go b/server/main.go index 2555b48..a79e7a9 100644 --- a/server/main.go +++ b/server/main.go @@ -106,7 +106,7 @@ func main() { app.Use(middleware.Secure()) app.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{ - Format: "${time_custom} ${method} ${uri} ---> ${status} in ${latency_human} (${bytes_out} bytes)", + Format: "${time_custom} ${method} ${uri} ---> ${status} in ${latency_human} (${bytes_out} bytes)\n", CustomTimeFormat: TimeFormat, })) app.Use(middleware.RemoveTrailingSlash()) @@ -140,15 +140,17 @@ func main() { } } + indent := "\t" + // client connection app.GET("/", func(c echo.Context) error { - return c.JSON(http.StatusOK, "Hello World!") + return c.JSONPretty(http.StatusOK, "Hello World!", indent) }) app.GET("/keys", keys) // administration app.GET("/admin/clients", authed(func(c echo.Context) error { - return c.JSON(http.StatusOK, clients) + return c.JSONPretty(http.StatusOK, clients, indent) })) app.GET("/admin/logs", authed(func(c echo.Context) error { @@ -162,13 +164,13 @@ func main() { filenames = append(filenames, file.Name()) } - return c.JSON(http.StatusOK, filenames) + return c.JSONPretty(http.StatusOK, filenames, indent) })) app.GET("/admin/:id", authed(idparam(func(c echo.Context, id uuid.UUID) error { for _, client := range clients { if client.ID == id { - return c.JSON(http.StatusOK, client) + return c.JSONPretty(http.StatusOK, client, indent) } } @@ -217,7 +219,7 @@ func main() { return c.NoContent(http.StatusInternalServerError) } - return c.JSON(http.StatusOK, bytes) + return c.JSONPretty(http.StatusOK, bytes, indent) }))) app.POST("/admin/:id/name", authed(idparam(func(c echo.Context, id uuid.UUID) error {