keys/admin/main.go
2025-04-13 18:42:16 +02:00

242 lines
4.4 KiB
Go

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 makeReq(method string, url string) error {
req, err := http.NewRequest(method, url, nil)
if err != nil {
return err
}
req.Header.Set("Authorization", token)
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
recv, err := io.ReadAll(res.Body)
if err != nil {
return err
}
if res.StatusCode != 200 {
fmt.Printf("<-- %d\n", res.StatusCode)
}
fmt.Printf("%s", recv)
return nil
}
func main() {
cmd := &cli.Command{
Name: "keysctl",
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.1.0")
return nil
},
},
{
Name: "test",
Usage: "test server connection",
Action: test,
},
{
Name: "clients",
Usage: "fetch all clients",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "id",
Usage: "optional id of the client to fetch",
},
},
Action: clients,
},
{
Name: "logs",
Usage: "fetch all/specific logs",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "id",
Usage: "optional id of the client to log",
},
&cli.StringFlag{
Name: "date",
Usage: "optional date of the log, id required, in ISO8601 date format",
},
&cli.StringFlag{
Name: "skip",
Usage: "optional skip bytes in log file",
},
&cli.StringFlag{
Name: "take",
Usage: "optional take bytes from log file",
},
},
Action: logs,
},
{
Name: "name",
Usage: "rename a client",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "id",
Usage: "id of the client",
Required: true,
},
&cli.StringFlag{
Name: "new",
Usage: "new name of the client",
Required: true,
},
},
Action: name,
},
{
Name: "exit",
Usage: "request a client to disconnect",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "id",
Usage: "id of the client",
Required: true,
},
},
Action: exit,
},
},
}
err := cmd.Run(context.Background(), os.Args)
if err != nil {
log.Fatal(err)
}
}
func test(context.Context, *cli.Command) error {
err := load()
if err != nil {
return err
}
url := fmt.Sprintf("%s/", server)
return makeReq(http.MethodGet, url)
}
func clients(ctx context.Context, cmd *cli.Command) error {
err := load()
if err != nil {
return err
}
var url string
id := cmd.String("id")
if id != "" {
url = fmt.Sprintf("%s/admin/clients/%s", server, id)
} else {
url = fmt.Sprintf("%s/admin/clients", server)
}
return makeReq(http.MethodGet, url)
}
func logs(ctx context.Context, cmd *cli.Command) error {
err := load()
if err != nil {
return err
}
var url string
id := cmd.String("id")
if id != "" {
params := map[string]string{
"date": cmd.String("date"),
"skip": cmd.String("skip"),
"take": cmd.String("take"),
}
paramsStr := ""
for k, v := range params {
if v == "" {
continue
}
if paramsStr == "" {
paramsStr = fmt.Sprintf("?%s=%s", k, v)
} else {
paramsStr += fmt.Sprintf("&%s=%s", k, v)
}
}
url = fmt.Sprintf("%s/admin/logs/%s%s", server, id, paramsStr)
} else {
url = fmt.Sprintf("%s/admin/logs", server)
}
return makeReq(http.MethodGet, url)
}
func name(ctx context.Context, cmd *cli.Command) error {
err := load()
if err != nil {
return err
}
id := cmd.String("id")
name := cmd.String("new")
url := fmt.Sprintf("%s/admin/name/%s?name=%s", server, id, name)
return makeReq(http.MethodPost, url)
}
func exit(ctx context.Context, cmd *cli.Command) error {
err := load()
if err != nil {
return err
}
id := cmd.String("id")
url := fmt.Sprintf("%s/admin/exit/%s", server, id)
return makeReq(http.MethodPost, url)
}