tangled
alpha
login
or
join now
willdot.net
/
cocoon
forked from
hailey.at/cocoon
0
fork
atom
An atproto PDS written in Go
0
fork
atom
overview
issues
pulls
pipelines
better http client usage
hailey.at
11 months ago
d56b9154
b8a45307
+110
-69
7 changed files
expand all
collapse all
unified
split
identity
identity.go
passport.go
types.go
plc
client.go
server
handle_identity_update_handle.go
handle_server_create_account.go
server.go
+26
-61
identity/identity.go
···
10
10
"strings"
11
11
12
12
"github.com/bluesky-social/indigo/atproto/syntax"
13
13
+
"github.com/bluesky-social/indigo/util"
13
14
)
14
15
15
15
-
func ResolveHandle(ctx context.Context, handle string) (string, error) {
16
16
+
func ResolveHandle(ctx context.Context, cli *http.Client, handle string) (string, error) {
17
17
+
if cli == nil {
18
18
+
cli = util.RobustHTTPClient()
19
19
+
}
20
20
+
16
21
var did string
17
22
18
23
_, err := syntax.ParseHandle(handle)
···
71
76
return did, nil
72
77
}
73
78
74
74
-
type DidDoc struct {
75
75
-
Context []string `json:"@context"`
76
76
-
Id string `json:"id"`
77
77
-
AlsoKnownAs []string `json:"alsoKnownAs"`
78
78
-
VerificationMethods []DidDocVerificationMethod `json:"verificationMethods"`
79
79
-
Service []DidDocService `json:"service"`
80
80
-
}
81
81
-
82
82
-
type DidDocVerificationMethod struct {
83
83
-
Id string `json:"id"`
84
84
-
Type string `json:"type"`
85
85
-
Controller string `json:"controller"`
86
86
-
PublicKeyMultibase string `json:"publicKeyMultibase"`
87
87
-
}
88
88
-
89
89
-
type DidDocService struct {
90
90
-
Id string `json:"id"`
91
91
-
Type string `json:"type"`
92
92
-
ServiceEndpoint string `json:"serviceEndpoint"`
93
93
-
}
94
94
-
95
95
-
type DidData struct {
96
96
-
Did string `json:"did"`
97
97
-
VerificationMethods map[string]string `json:"verificationMethods"`
98
98
-
RotationKeys []string `json:"rotationKeys"`
99
99
-
AlsoKnownAs []string `json:"alsoKnownAs"`
100
100
-
Services map[string]OperationService `json:"services"`
101
101
-
}
102
102
-
103
103
-
type OperationService struct {
104
104
-
Type string `json:"type"`
105
105
-
Endpoint string `json:"endpoint"`
106
106
-
}
79
79
+
func FetchDidDoc(ctx context.Context, cli *http.Client, did string) (*DidDoc, error) {
80
80
+
if cli == nil {
81
81
+
cli = util.RobustHTTPClient()
82
82
+
}
107
83
108
108
-
type DidLog []DidLogEntry
109
109
-
110
110
-
type DidLogEntry struct {
111
111
-
Sig string `json:"sig"`
112
112
-
Prev *string `json:"prev"`
113
113
-
Type string `json:"string"`
114
114
-
Services map[string]OperationService `json:"services"`
115
115
-
AlsoKnownAs []string `json:"alsoKnownAs"`
116
116
-
RotationKeys []string `json:"rotationKeys"`
117
117
-
VerificationMethods map[string]string `json:"verificationMethods"`
118
118
-
}
119
119
-
120
120
-
type DidAuditEntry struct {
121
121
-
Did string `json:"did"`
122
122
-
Operation DidLogEntry `json:"operation"`
123
123
-
Cid string `json:"cid"`
124
124
-
Nullified bool `json:"nullified"`
125
125
-
CreatedAt string `json:"createdAt"`
126
126
-
}
127
127
-
128
128
-
type DidAuditLog []DidAuditEntry
129
129
-
130
130
-
func FetchDidDoc(ctx context.Context, did string) (*DidDoc, error) {
131
84
var ustr string
132
85
if strings.HasPrefix(did, "did:plc:") {
133
86
ustr = fmt.Sprintf("https://plc.directory/%s", did)
···
161
114
return &diddoc, nil
162
115
}
163
116
164
164
-
func FetchDidData(ctx context.Context, did string) (*DidData, error) {
117
117
+
func FetchDidData(ctx context.Context, cli *http.Client, did string) (*DidData, error) {
118
118
+
if cli == nil {
119
119
+
cli = util.RobustHTTPClient()
120
120
+
}
121
121
+
165
122
var ustr string
166
123
ustr = fmt.Sprintf("https://plc.directory/%s/data", did)
167
124
···
189
146
return &diddata, nil
190
147
}
191
148
192
192
-
func FetchDidAuditLog(ctx context.Context, did string) (DidAuditLog, error) {
149
149
+
func FetchDidAuditLog(ctx context.Context, cli *http.Client, did string) (DidAuditLog, error) {
150
150
+
if cli == nil {
151
151
+
cli = util.RobustHTTPClient()
152
152
+
}
153
153
+
193
154
var ustr string
194
155
ustr = fmt.Sprintf("https://plc.directory/%s/log/audit", did)
195
156
···
217
178
return didlog, nil
218
179
}
219
180
220
220
-
func ResolveService(ctx context.Context, did string) (string, error) {
221
221
-
diddoc, err := FetchDidDoc(ctx, did)
181
181
+
func ResolveService(ctx context.Context, cli *http.Client, did string) (string, error) {
182
182
+
if cli == nil {
183
183
+
cli = util.RobustHTTPClient()
184
184
+
}
185
185
+
186
186
+
diddoc, err := FetchDidDoc(ctx, cli, did)
222
187
if err != nil {
223
188
return "", err
224
189
}
+10
-3
identity/passport.go
···
2
2
3
3
import (
4
4
"context"
5
5
+
"net/http"
5
6
"sync"
6
7
)
7
8
···
16
17
}
17
18
18
19
type Passport struct {
20
20
+
h *http.Client
19
21
bc BackingCache
20
22
lk sync.Mutex
21
23
}
22
24
23
23
-
func NewPassport(bc BackingCache) *Passport {
25
25
+
func NewPassport(h *http.Client, bc BackingCache) *Passport {
26
26
+
if h == nil {
27
27
+
h = http.DefaultClient
28
28
+
}
29
29
+
24
30
return &Passport{
31
31
+
h: h,
25
32
bc: bc,
26
33
lk: sync.Mutex{},
27
34
}
···
40
47
p.lk.Lock() // this is pretty pathetic, and i should rethink this. but for now, fuck it
41
48
defer p.lk.Unlock()
42
49
43
43
-
doc, err := FetchDidDoc(ctx, did)
50
50
+
doc, err := FetchDidDoc(ctx, p.h, did)
44
51
if err != nil {
45
52
return nil, err
46
53
}
···
60
67
}
61
68
}
62
69
63
63
-
did, err := ResolveHandle(ctx, handle)
70
70
+
did, err := ResolveHandle(ctx, p.h, handle)
64
71
if err != nil {
65
72
return "", err
66
73
}
+57
identity/types.go
···
1
1
+
package identity
2
2
+
3
3
+
type DidDoc struct {
4
4
+
Context []string `json:"@context"`
5
5
+
Id string `json:"id"`
6
6
+
AlsoKnownAs []string `json:"alsoKnownAs"`
7
7
+
VerificationMethods []DidDocVerificationMethod `json:"verificationMethods"`
8
8
+
Service []DidDocService `json:"service"`
9
9
+
}
10
10
+
11
11
+
type DidDocVerificationMethod struct {
12
12
+
Id string `json:"id"`
13
13
+
Type string `json:"type"`
14
14
+
Controller string `json:"controller"`
15
15
+
PublicKeyMultibase string `json:"publicKeyMultibase"`
16
16
+
}
17
17
+
18
18
+
type DidDocService struct {
19
19
+
Id string `json:"id"`
20
20
+
Type string `json:"type"`
21
21
+
ServiceEndpoint string `json:"serviceEndpoint"`
22
22
+
}
23
23
+
24
24
+
type DidData struct {
25
25
+
Did string `json:"did"`
26
26
+
VerificationMethods map[string]string `json:"verificationMethods"`
27
27
+
RotationKeys []string `json:"rotationKeys"`
28
28
+
AlsoKnownAs []string `json:"alsoKnownAs"`
29
29
+
Services map[string]OperationService `json:"services"`
30
30
+
}
31
31
+
32
32
+
type OperationService struct {
33
33
+
Type string `json:"type"`
34
34
+
Endpoint string `json:"endpoint"`
35
35
+
}
36
36
+
37
37
+
type DidLog []DidLogEntry
38
38
+
39
39
+
type DidLogEntry struct {
40
40
+
Sig string `json:"sig"`
41
41
+
Prev *string `json:"prev"`
42
42
+
Type string `json:"string"`
43
43
+
Services map[string]OperationService `json:"services"`
44
44
+
AlsoKnownAs []string `json:"alsoKnownAs"`
45
45
+
RotationKeys []string `json:"rotationKeys"`
46
46
+
VerificationMethods map[string]string `json:"verificationMethods"`
47
47
+
}
48
48
+
49
49
+
type DidAuditEntry struct {
50
50
+
Did string `json:"did"`
51
51
+
Operation DidLogEntry `json:"operation"`
52
52
+
Cid string `json:"cid"`
53
53
+
Nullified bool `json:"nullified"`
54
54
+
CreatedAt string `json:"createdAt"`
55
55
+
}
56
56
+
57
57
+
type DidAuditLog []DidAuditEntry
+8
-2
plc/client.go
···
15
15
16
16
"github.com/bluesky-social/indigo/atproto/crypto"
17
17
"github.com/bluesky-social/indigo/util"
18
18
+
"github.com/haileyok/cocoon/identity"
18
19
)
19
20
20
21
type Client struct {
···
25
26
}
26
27
27
28
type ClientArgs struct {
29
29
+
H *http.Client
28
30
Service string
29
31
RotationKey []byte
30
32
PdsHostname string
···
35
37
args.Service = "https://plc.directory"
36
38
}
37
39
40
40
+
if args.H == nil {
41
41
+
args.H = util.RobustHTTPClient()
42
42
+
}
43
43
+
38
44
rk, err := crypto.ParsePrivateBytesK256([]byte(args.RotationKey))
39
45
if err != nil {
40
46
return nil, err
41
47
}
42
48
43
49
return &Client{
44
44
-
h: util.RobustHTTPClient(),
50
50
+
h: args.H,
45
51
service: args.Service,
46
52
rotationKey: rk,
47
53
pdsHostname: args.PdsHostname,
···
80
86
AlsoKnownAs: []string{
81
87
"at://" + handle,
82
88
},
83
83
-
Services: map[string]OperationService{
89
89
+
Services: map[string]identity.OperationService{
84
90
"atproto_pds": {
85
91
Type: "AtprotoPersonalDataServer",
86
92
Endpoint: "https://" + c.pdsHostname,
+1
-1
server/handle_identity_update_handle.go
···
39
39
ctx := context.WithValue(e.Request().Context(), "skip-cache", true)
40
40
41
41
if strings.HasPrefix(repo.Repo.Did, "did:plc:") {
42
42
-
log, err := identity.FetchDidAuditLog(ctx, repo.Repo.Did)
42
42
+
log, err := identity.FetchDidAuditLog(ctx, nil, repo.Repo.Did)
43
43
if err != nil {
44
44
s.logger.Error("error fetching doc", "error", err)
45
45
return helpers.ServerError(e, nil)
+1
-1
server/handle_server_create_account.go
···
116
116
return helpers.ServerError(e, nil)
117
117
}
118
118
119
119
-
did, op, err := s.plcClient.CreateDID(e.Request().Context(), k, "", request.Handle)
119
119
+
did, op, err := s.plcClient.CreateDID(k, "", request.Handle)
120
120
if err != nil {
121
121
s.logger.Error("error creating operation", "endpoint", "com.atproto.server.createAccount", "error", err)
122
122
return helpers.ServerError(e, nil)
+7
-1
server/server.go
···
15
15
"github.com/bluesky-social/indigo/api/atproto"
16
16
"github.com/bluesky-social/indigo/atproto/syntax"
17
17
"github.com/bluesky-social/indigo/events"
18
18
+
"github.com/bluesky-social/indigo/util"
18
19
"github.com/bluesky-social/indigo/xrpc"
19
20
"github.com/go-playground/validator"
20
21
"github.com/golang-jwt/jwt/v4"
···
31
32
)
32
33
33
34
type Server struct {
35
35
+
http *http.Client
34
36
httpd *http.Server
35
37
echo *echo.Echo
36
38
db *gorm.DB
···
268
270
return nil, err
269
271
}
270
272
273
273
+
h := util.RobustHTTPClient()
274
274
+
271
275
plcClient, err := plc.NewClient(&plc.ClientArgs{
276
276
+
H: h,
272
277
Service: "https://plc.directory",
273
278
PdsHostname: args.Hostname,
274
279
RotationKey: rkbytes,
···
293
298
}
294
299
295
300
s := &Server{
301
301
+
http: h,
296
302
httpd: httpd,
297
303
echo: e,
298
304
logger: args.Logger,
···
308
314
Relays: args.Relays,
309
315
},
310
316
evtman: events.NewEventManager(events.NewMemPersister()),
311
311
-
passport: identity.NewPassport(identity.NewMemCache(10_000)),
317
317
+
passport: identity.NewPassport(h, identity.NewMemCache(10_000)),
312
318
}
313
319
314
320
s.repoman = NewRepoMan(s) // TODO: this is way too lazy, stop it