tangled
alpha
login
or
join now
bnewbold.net
/
cobalt
13
fork
atom
go scratch code for atproto
13
fork
atom
overview
issues
pulls
pipelines
DNS checking feature
bnewbold.net
5 months ago
a7d6b973
d42c673e
+131
2 changed files
expand all
collapse all
unified
split
cmd
glot
dns.go
main.go
+130
cmd/glot/dns.go
···
1
1
+
package main
2
2
+
3
3
+
import (
4
4
+
"context"
5
5
+
"encoding/json"
6
6
+
"fmt"
7
7
+
"io/fs"
8
8
+
"os"
9
9
+
"path"
10
10
+
"path/filepath"
11
11
+
"sort"
12
12
+
13
13
+
"github.com/bluesky-social/indigo/atproto/identity"
14
14
+
"github.com/bluesky-social/indigo/atproto/syntax"
15
15
+
16
16
+
"github.com/urfave/cli/v3"
17
17
+
)
18
18
+
19
19
+
var cmdCheckDNS = &cli.Command{
20
20
+
Name: "check-dns",
21
21
+
Usage: "checks for any schemas missing DNS NSID resolution",
22
22
+
ArgsUsage: `<file-or-dir>*`,
23
23
+
Flags: []cli.Flag{
24
24
+
&cli.StringFlag{
25
25
+
Name: "lexicons-dir",
26
26
+
Value: "./lexicons/",
27
27
+
Usage: "base directory for project Lexicon files",
28
28
+
Sources: cli.EnvVars("LEXICONS_DIR"),
29
29
+
},
30
30
+
&cli.StringFlag{
31
31
+
Name: "did",
32
32
+
Usage: "lexicon publication DID for example text",
33
33
+
Value: "did:web:lex.example.com",
34
34
+
},
35
35
+
},
36
36
+
Action: runCheckDNS,
37
37
+
}
38
38
+
39
39
+
/*
40
40
+
- enumerate all local groups
41
41
+
- resolve and record any missing
42
42
+
- print DNS configuration instructions
43
43
+
*/
44
44
+
func runCheckDNS(ctx context.Context, cmd *cli.Command) error {
45
45
+
46
46
+
paths := cmd.Args().Slice()
47
47
+
if !cmd.Args().Present() {
48
48
+
paths = []string{cmd.String("lexicons-dir")}
49
49
+
_, err := os.Stat(paths[0])
50
50
+
if err != nil {
51
51
+
return fmt.Errorf("no path arguments specified and default lexicon directory not found\n%w", err)
52
52
+
}
53
53
+
}
54
54
+
55
55
+
// collect all NSID/path mappings
56
56
+
localSchemas := map[syntax.NSID]json.RawMessage{}
57
57
+
58
58
+
for _, p := range paths {
59
59
+
finfo, err := os.Stat(p)
60
60
+
if err != nil {
61
61
+
return fmt.Errorf("failed loading %s: %w", p, err)
62
62
+
}
63
63
+
if finfo.IsDir() {
64
64
+
if err := filepath.WalkDir(p, func(fp string, d fs.DirEntry, err error) error {
65
65
+
if d.IsDir() || path.Ext(fp) != ".json" {
66
66
+
return nil
67
67
+
}
68
68
+
nsid, rec, err := loadSchemaPath(fp)
69
69
+
if err != nil {
70
70
+
return err
71
71
+
}
72
72
+
localSchemas[nsid] = *rec
73
73
+
return nil
74
74
+
}); err != nil {
75
75
+
return err
76
76
+
}
77
77
+
continue
78
78
+
}
79
79
+
nsid, rec, err := loadSchemaPath(p)
80
80
+
if err != nil {
81
81
+
return err
82
82
+
}
83
83
+
localSchemas[nsid] = *rec
84
84
+
}
85
85
+
86
86
+
localGroups := map[string]bool{}
87
87
+
for k := range localSchemas {
88
88
+
g := nsidGroup(k)
89
89
+
localGroups[g] = true
90
90
+
}
91
91
+
92
92
+
dir := identity.BaseDirectory{}
93
93
+
missingGroups := []string{}
94
94
+
for g := range localGroups {
95
95
+
_, err := dir.ResolveNSID(ctx, syntax.NSID(g+"name"))
96
96
+
if err != nil {
97
97
+
missingGroups = append(missingGroups, g)
98
98
+
}
99
99
+
}
100
100
+
101
101
+
if len(missingGroups) == 0 {
102
102
+
fmt.Println("all lexicon schema NSIDs resolved successfully")
103
103
+
return nil
104
104
+
}
105
105
+
sort.Strings(missingGroups)
106
106
+
107
107
+
fmt.Println("Some lexicon NSIDs did not resolve via DNS:")
108
108
+
fmt.Println("")
109
109
+
for _, g := range missingGroups {
110
110
+
fmt.Printf(" %s*\n", g)
111
111
+
}
112
112
+
fmt.Println("")
113
113
+
fmt.Println("To make these resolve, add DNS TXT entries like:")
114
114
+
fmt.Println("")
115
115
+
for _, g := range missingGroups {
116
116
+
nsid, err := syntax.ParseNSID(g + "name")
117
117
+
if err != nil {
118
118
+
return err
119
119
+
}
120
120
+
fmt.Printf(" _lexicon.%s\tTXT\t\"did=%s\"\n", nsid.Authority(), cmd.String("did"))
121
121
+
}
122
122
+
if !cmd.IsSet("did") {
123
123
+
fmt.Println("")
124
124
+
fmt.Println("(substituting your account DID for the example value)")
125
125
+
}
126
126
+
fmt.Println("")
127
127
+
fmt.Println("Note that DNS management interfaces commonly require only the sub-domain parts of a name, not the full registered domain.")
128
128
+
129
129
+
return nil
130
130
+
}
+1
cmd/glot/main.go
···
37
37
cmdNew,
38
38
cmdPublish,
39
39
cmdUnpublish,
40
40
+
cmdCheckDNS,
40
41
}
41
42
return app.Run(context.Background(), args)
42
43
}