forked from
tangled.org/core
fork
Configure Feed
Select the types of activity you want to include in your feed.
this repo has no description
fork
Configure Feed
Select the types of activity you want to include in your feed.
1package keyfetch
2
3import (
4 "context"
5 "encoding/json"
6 "fmt"
7 "io"
8 "net/http"
9 "os"
10 "strings"
11
12 "github.com/urfave/cli/v3"
13 "tangled.org/core/log"
14)
15
16func Command() *cli.Command {
17 return &cli.Command{
18 Name: "keys",
19 Usage: "fetch public keys from the knot server",
20 Action: Run,
21 Flags: []cli.Flag{
22 &cli.StringFlag{
23 Name: "output",
24 Aliases: []string{"o"},
25 Usage: "output format (table, json, authorized-keys)",
26 Value: "table",
27 },
28 &cli.StringFlag{
29 Name: "internal-api",
30 Usage: "internal API endpoint",
31 Value: "http://localhost:5444",
32 },
33 &cli.StringFlag{
34 Name: "git-dir",
35 Usage: "base directory for git repos",
36 Value: "/home/git",
37 },
38 &cli.StringFlag{
39 Name: "log-path",
40 Usage: "path to log file",
41 Value: "/home/git/log",
42 },
43 },
44 }
45}
46
47func Run(ctx context.Context, cmd *cli.Command) error {
48 l := log.FromContext(ctx)
49
50 internalApi := cmd.String("internal-api")
51 gitDir := cmd.String("git-dir")
52 logPath := cmd.String("log-path")
53 output := cmd.String("output")
54
55 executablePath, err := os.Executable()
56 if err != nil {
57 l.Error("error getting path of executable", "error", err)
58 return err
59 }
60
61 resp, err := http.Get(internalApi + "/keys")
62 if err != nil {
63 l.Error("error reaching internal API endpoint; is the knot server running?", "error", err)
64 return err
65 }
66 defer resp.Body.Close()
67
68 body, err := io.ReadAll(resp.Body)
69 if err != nil {
70 l.Error("error reading response body", "error", err)
71 return err
72 }
73
74 var data []map[string]any
75 err = json.Unmarshal(body, &data)
76 if err != nil {
77 l.Error("error unmarshalling response body", "error", err)
78 return err
79 }
80
81 switch output {
82 case "json":
83 prettyJSON, err := json.MarshalIndent(data, "", " ")
84 if err != nil {
85 l.Error("error pretty printing JSON", "error", err)
86 return err
87 }
88
89 if _, err := os.Stdout.Write(prettyJSON); err != nil {
90 l.Error("error writing to stdout", "error", err)
91 return err
92 }
93 case "authorized-keys":
94 formatted := formatKeyData(executablePath, gitDir, logPath, internalApi, data)
95 _, err := os.Stdout.Write([]byte(formatted))
96 if err != nil {
97 l.Error("error writing to stdout", "error", err)
98 return err
99 }
100 case "table":
101 fmt.Printf("%-40s %-40s\n", "DID", "KEY")
102 fmt.Println(strings.Repeat("-", 80))
103
104 for _, entry := range data {
105 did, _ := entry["did"].(string)
106 key, _ := entry["key"].(string)
107 fmt.Printf("%-40s %-40s\n", did, key)
108 }
109 }
110 return nil
111}
112
113func formatKeyData(executablePath, gitDir, logPath, endpoint string, data []map[string]any) string {
114 var result string
115 for _, entry := range data {
116 result += fmt.Sprintf(
117 `command="%s guard -git-dir %s -user %s -log-path %s -internal-api %s",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty %s`+"\n",
118 executablePath, gitDir, entry["did"], logPath, endpoint, entry["key"])
119 }
120 return result
121}