+45
appview/state/middleware.go
+45
appview/state/middleware.go
···
1
1
package state
2
2
3
3
import (
4
+
"context"
4
5
"log"
5
6
"net/http"
6
7
"strings"
7
8
"time"
8
9
9
10
comatproto "github.com/bluesky-social/indigo/api/atproto"
11
+
"github.com/bluesky-social/indigo/atproto/identity"
10
12
"github.com/bluesky-social/indigo/xrpc"
11
13
"github.com/go-chi/chi/v5"
12
14
"github.com/sotangled/tangled/appview"
···
110
112
next.ServeHTTP(w, req)
111
113
})
112
114
}
115
+
116
+
func ResolveIdent(next http.Handler) http.Handler {
117
+
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
118
+
didOrHandle := chi.URLParam(req, "user")
119
+
120
+
log.Println(didOrHandle)
121
+
id, err := auth.ResolveIdent(req.Context(), didOrHandle)
122
+
if err != nil {
123
+
// invalid did or handle
124
+
log.Println("failed to resolve did/handle")
125
+
w.WriteHeader(http.StatusNotFound)
126
+
return
127
+
}
128
+
129
+
ctx := context.WithValue(req.Context(), "resolvedId", *id)
130
+
next.ServeHTTP(w, req.WithContext(ctx))
131
+
})
132
+
}
133
+
134
+
func ResolveRepoDomain(s *State) Middleware {
135
+
return func(next http.Handler) http.Handler {
136
+
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
137
+
repoName := chi.URLParam(req, "repo")
138
+
id, ok := req.Context().Value("resolvedId").(identity.Identity)
139
+
if !ok {
140
+
log.Println("malformed middleware")
141
+
w.WriteHeader(http.StatusInternalServerError)
142
+
return
143
+
}
144
+
145
+
repo, err := s.db.GetRepo(id.DID.String(), repoName)
146
+
if err != nil {
147
+
// invalid did or handle
148
+
log.Println("failed to resolve repo")
149
+
w.WriteHeader(http.StatusNotFound)
150
+
return
151
+
}
152
+
153
+
ctx := context.WithValue(req.Context(), "domain", repo.Knot)
154
+
next.ServeHTTP(w, req.WithContext(ctx))
155
+
})
156
+
}
157
+
}
+41
appview/state/repo.go
+41
appview/state/repo.go
···
1
+
package state
2
+
3
+
import (
4
+
"fmt"
5
+
"io"
6
+
"log"
7
+
"net/http"
8
+
9
+
"github.com/bluesky-social/indigo/atproto/identity"
10
+
"github.com/go-chi/chi/v5"
11
+
)
12
+
13
+
func (s *State) RepoIndex(w http.ResponseWriter, r *http.Request) {
14
+
ctx := r.Context()
15
+
repoName := chi.URLParam(r, "repo")
16
+
17
+
domain, ok := ctx.Value("domain").(string)
18
+
if !ok {
19
+
log.Println("malformed middleware")
20
+
w.WriteHeader(http.StatusInternalServerError)
21
+
return
22
+
}
23
+
24
+
id, ok := ctx.Value("resolvedId").(identity.Identity)
25
+
if !ok {
26
+
log.Println("malformed middleware")
27
+
w.WriteHeader(http.StatusInternalServerError)
28
+
return
29
+
}
30
+
31
+
resp, err := http.Get(fmt.Sprintf("http://%s/%s/%s", domain, id.DID.String(), repoName))
32
+
if err != nil {
33
+
log.Println("failed to reach knotserver", err)
34
+
return
35
+
}
36
+
37
+
txt, err := io.ReadAll(resp.Body)
38
+
log.Println(resp.Status, string(txt))
39
+
40
+
return
41
+
}
+18
-6
appview/state/signer.go
+18
-6
appview/state/signer.go
···
59
59
return http.NewRequest(method, s.Url.JoinPath(endpoint).String(), bytes.NewReader(body))
60
60
}
61
61
62
-
func (s *SignedClient) Init(did string, keys []string) (*http.Response, error) {
62
+
func (s *SignedClient) Init(did string) (*http.Response, error) {
63
63
const (
64
64
Method = "POST"
65
65
Endpoint = "/init"
66
66
)
67
67
68
68
body, _ := json.Marshal(map[string]interface{}{
69
-
"did": did,
70
-
"keys": keys,
69
+
"did": did,
71
70
})
72
71
73
72
req, err := s.newRequest(Method, Endpoint, body)
···
97
96
return s.client.Do(req)
98
97
}
99
98
100
-
func (s *SignedClient) AddMember(did string, keys []string) (*http.Response, error) {
99
+
func (s *SignedClient) AddMember(did string) (*http.Response, error) {
101
100
const (
102
101
Method = "PUT"
103
102
Endpoint = "/member/add"
104
103
)
105
104
106
105
body, _ := json.Marshal(map[string]interface{}{
107
-
"did": did,
108
-
"keys": keys,
106
+
"did": did,
109
107
})
110
108
111
109
req, err := s.newRequest(Method, Endpoint, body)
···
115
113
116
114
return s.client.Do(req)
117
115
}
116
+
117
+
func (s *SignedClient) RepoIndex(did, repo string) (*http.Response, error) {
118
+
const (
119
+
Method = "GET"
120
+
)
121
+
endpoint := fmt.Sprint("/%s/%s", did, repo)
122
+
123
+
req, err := s.newRequest(Method, endpoint, nil)
124
+
if err != nil {
125
+
return nil, err
126
+
}
127
+
128
+
return s.client.Do(req)
129
+
}
+9
-4
appview/state/state.go
+9
-4
appview/state/state.go
···
201
201
case http.MethodPut:
202
202
did := s.auth.GetDid(r)
203
203
key := r.FormValue("key")
204
+
key = strings.TrimSpace(key)
204
205
name := r.FormValue("name")
205
206
client, _ := s.auth.AuthorizedClient(r)
206
207
···
261
262
log.Println("failed to create client to ", domain)
262
263
}
263
264
264
-
resp, err := client.Init(user.Did, []string{})
265
+
resp, err := client.Init(user.Did)
265
266
if err != nil {
266
267
w.Write([]byte("no dice"))
267
268
log.Println("domain was unreachable after 5 seconds")
···
455
456
return
456
457
}
457
458
458
-
ksResp, err := ksClient.AddMember(memberIdent.DID.String(), []string{})
459
+
ksResp, err := ksClient.AddMember(memberIdent.DID.String())
459
460
if err != nil {
460
-
log.Printf("failet to make request to %s: %s", domain, err)
461
+
log.Printf("failed to make request to %s: %s", domain, err)
461
462
}
462
463
463
464
if ksResp.StatusCode != http.StatusNoContent {
···
596
597
// strip @ from user
597
598
r.Use(StripLeadingAt)
598
599
599
-
r.Route("/{user}", func(r chi.Router) {
600
+
r.With(ResolveIdent).Route("/{user}", func(r chi.Router) {
600
601
r.Get("/", s.ProfilePage)
602
+
r.With(ResolveRepoDomain(s)).Route("/{repo}", func(r chi.Router) {
603
+
r.Get("/", s.RepoIndex)
604
+
// r.Get("/info/refs", s.InfoRefs)
605
+
})
601
606
})
602
607
603
608
return r
-4
knotserver/jetstream.go
-4
knotserver/jetstream.go
···
182
182
return nil
183
183
}
184
184
185
-
if ct := resp.Header.Get("Content-Type"); !strings.HasPrefix(ct, "text/plain") {
186
-
return fmt.Errorf("unexpected content type: %s", ct)
187
-
}
188
-
189
185
plaintext, err := io.ReadAll(resp.Body)
190
186
if err != nil {
191
187
l.Error("error reading response body", "error", err)