···3import (
4 "context"
5 "fmt"
06 "net/http"
78 "github.com/go-chi/chi/v5"
···21 db *db.DB
22 js *jsclient.JetstreamClient
23 e *rbac.Enforcer
02425 // init is a channel that is closed when the knot has been initailized
26 // i.e. when the first user (knot owner) has been added.
···28 knotInitialized bool
29}
3031-func Setup(ctx context.Context, c *config.Config, db *db.DB, e *rbac.Enforcer) (http.Handler, error) {
32 r := chi.NewRouter()
3334 h := Handle{
35 c: c,
36 db: db,
37 e: e,
038 init: make(chan struct{}),
39 }
40
···3import (
4 "context"
5 "fmt"
6+ "log/slog"
7 "net/http"
89 "github.com/go-chi/chi/v5"
···22 db *db.DB
23 js *jsclient.JetstreamClient
24 e *rbac.Enforcer
25+ l *slog.Logger
2627 // init is a channel that is closed when the knot has been initailized
28 // i.e. when the first user (knot owner) has been added.
···30 knotInitialized bool
31}
3233+func Setup(ctx context.Context, c *config.Config, db *db.DB, e *rbac.Enforcer, l *slog.Logger) (http.Handler, error) {
34 r := chi.NewRouter()
3536 h := Handle{
37 c: c,
38 db: db,
39 e: e,
40+ l: l,
41 init: make(chan struct{}),
42 }
43
+66-34
knotserver/jetstream.go
···5 "encoding/json"
6 "fmt"
7 "io"
8- "log"
9 "net/http"
10 "net/url"
11 "strings"
···14 "github.com/sotangled/tangled/api/tangled"
15 "github.com/sotangled/tangled/knotserver/db"
16 "github.com/sotangled/tangled/knotserver/jsclient"
017)
1819func (h *Handle) StartJetstream(ctx context.Context) error {
0020 collections := []string{tangled.PublicKeyNSID, tangled.KnotMemberNSID}
21 dids := []string{}
2223- lastTimeUs, err := h.getLastTimeUs()
24 if err != nil {
25 return err
26 }
···31 return fmt.Errorf("failed to read from jetstream: %w", err)
32 }
3334- go h.processMessages(messages)
3536 return nil
37}
3839-func (h *Handle) getLastTimeUs() (int64, error) {
040 lastTimeUs, err := h.db.GetLastTimeUs()
41 if err != nil {
42- log.Println("couldn't get last time us, starting from now")
43 lastTimeUs = time.Now().UnixMicro()
44 }
4546 // If last time is older than a week, start from now
47 if time.Now().UnixMicro()-lastTimeUs > 7*24*60*60*1000*1000 {
48 lastTimeUs = time.Now().UnixMicro()
49- log.Printf("last time us is older than a week. discarding that and starting from now.")
50 err = h.db.SaveLastTimeUs(lastTimeUs)
51 if err != nil {
52- log.Println("failed to save last time us")
53 }
54 }
5556- log.Printf("found last time_us %d", lastTimeUs)
57 return lastTimeUs, nil
58}
5960-func (h *Handle) processPublicKey(did string, record map[string]interface{}) {
061 if err := h.db.AddPublicKeyFromRecord(did, record); err != nil {
62- log.Printf("failed to add public key: %v", err)
63- } else {
64- log.Printf("added public key from firehose: %s", did)
65 }
0066}
6768-func (h *Handle) fetchAndAddKeys(did string) {
0069 keysEndpoint, err := url.JoinPath(h.c.AppViewEndpoint, "keys", did)
70 if err != nil {
71- log.Printf("error building endpoint url: %s: %v", did, err)
72- return
73 }
7475 resp, err := http.Get(keysEndpoint)
76 if err != nil {
77- log.Printf("error getting keys for %s: %v", did, err)
78- return
79 }
80 defer resp.Body.Close()
8182 plaintext, err := io.ReadAll(resp.Body)
83 if err != nil {
84- log.Printf("error reading response body: %v", err)
85- return
86 }
8788 for _, key := range strings.Split(string(plaintext), "\n") {
···94 }
95 pk.Key = key
96 if err := h.db.AddPublicKey(pk); err != nil {
97- log.Printf("failed to add public key: %v", err)
098 }
99 }
0100}
101102-func (h *Handle) processKnotMember(did string, record map[string]interface{}) {
0103 ok, err := h.e.E.Enforce(did, ThisServer, ThisServer, "server:invite")
104 if err != nil || !ok {
105- log.Printf("failed to add member from did %s", did)
106- return
107 }
108109- log.Printf("adding member")
110 if err := h.e.AddMember(ThisServer, record["member"].(string)); err != nil {
111- log.Printf("failed to add member: %v", err)
112- } else {
113- log.Printf("added member from firehose: %s", record["member"])
00000114 }
115116- h.fetchAndAddKeys(did)
000117 h.js.UpdateDids([]string{did})
0118}
119120-func (h *Handle) processMessages(messages <-chan []byte) {
00121 <-h.init
122- log.Println("initalized jetstream watcher")
123124 for msg := range messages {
125 var data map[string]interface{}
126 if err := json.Unmarshal(msg, &data); err != nil {
127- log.Printf("error unmarshaling message: %v", err)
128 continue
129 }
130···133 did := data["did"].(string)
134 record := commit["record"].(map[string]interface{})
1350136 switch commit["collection"].(string) {
137 case tangled.PublicKeyNSID:
138- h.processPublicKey(did, record)
00139 case tangled.KnotMemberNSID:
140- h.processKnotMember(did, record)
0000000141 }
142143 lastTimeUs := int64(data["time_us"].(float64))
144 if err := h.db.SaveLastTimeUs(lastTimeUs); err != nil {
145- log.Printf("failed to save last time us: %v", err)
0146 }
147 }
148 }
···5 "encoding/json"
6 "fmt"
7 "io"
08 "net/http"
9 "net/url"
10 "strings"
···13 "github.com/sotangled/tangled/api/tangled"
14 "github.com/sotangled/tangled/knotserver/db"
15 "github.com/sotangled/tangled/knotserver/jsclient"
16+ "github.com/sotangled/tangled/log"
17)
1819func (h *Handle) StartJetstream(ctx context.Context) error {
20+ l := h.l.With("component", "jetstream")
21+ ctx = log.IntoContext(ctx, l)
22 collections := []string{tangled.PublicKeyNSID, tangled.KnotMemberNSID}
23 dids := []string{}
2425+ lastTimeUs, err := h.getLastTimeUs(ctx)
26 if err != nil {
27 return err
28 }
···33 return fmt.Errorf("failed to read from jetstream: %w", err)
34 }
3536+ go h.processMessages(ctx, messages)
3738 return nil
39}
4041+func (h *Handle) getLastTimeUs(ctx context.Context) (int64, error) {
42+ l := log.FromContext(ctx)
43 lastTimeUs, err := h.db.GetLastTimeUs()
44 if err != nil {
45+ l.Info("couldn't get last time us, starting from now")
46 lastTimeUs = time.Now().UnixMicro()
47 }
4849 // If last time is older than a week, start from now
50 if time.Now().UnixMicro()-lastTimeUs > 7*24*60*60*1000*1000 {
51 lastTimeUs = time.Now().UnixMicro()
52+ l.Info("last time us is older than a week. discarding that and starting from now")
53 err = h.db.SaveLastTimeUs(lastTimeUs)
54 if err != nil {
55+ l.Error("failed to save last time us")
56 }
57 }
5859+ l.Info("found last time_us", "time_us", lastTimeUs)
60 return lastTimeUs, nil
61}
6263+func (h *Handle) processPublicKey(ctx context.Context, did string, record map[string]interface{}) error {
64+ l := log.FromContext(ctx)
65 if err := h.db.AddPublicKeyFromRecord(did, record); err != nil {
66+ l.Error("failed to add public key", "error", err)
67+ return fmt.Errorf("failed to add public key: %w", err)
068 }
69+ l.Info("added public key from firehose", "did", did)
70+ return nil
71}
7273+func (h *Handle) fetchAndAddKeys(ctx context.Context, did string) error {
74+ l := log.FromContext(ctx)
75+76 keysEndpoint, err := url.JoinPath(h.c.AppViewEndpoint, "keys", did)
77 if err != nil {
78+ l.Error("error building endpoint url", "did", did, "error", err.Error())
79+ return fmt.Errorf("error building endpoint url: %w", err)
80 }
8182 resp, err := http.Get(keysEndpoint)
83 if err != nil {
84+ l.Error("error getting keys", "did", did, "error", err)
85+ return fmt.Errorf("error getting keys: %w", err)
86 }
87 defer resp.Body.Close()
8889 plaintext, err := io.ReadAll(resp.Body)
90 if err != nil {
91+ l.Error("error reading response body", "error", err)
92+ return fmt.Errorf("error reading response body: %w", err)
93 }
9495 for _, key := range strings.Split(string(plaintext), "\n") {
···101 }
102 pk.Key = key
103 if err := h.db.AddPublicKey(pk); err != nil {
104+ l.Error("failed to add public key", "error", err)
105+ return fmt.Errorf("failed to add public key: %w", err)
106 }
107 }
108+ return nil
109}
110111+func (h *Handle) processKnotMember(ctx context.Context, did string, record map[string]interface{}) error {
112+ l := log.FromContext(ctx)
113 ok, err := h.e.E.Enforce(did, ThisServer, ThisServer, "server:invite")
114 if err != nil || !ok {
115+ l.Error("failed to add member", "did", did)
116+ return fmt.Errorf("failed to enforce permissions: %w", err)
117 }
118119+ l.Info("adding member")
120 if err := h.e.AddMember(ThisServer, record["member"].(string)); err != nil {
121+ l.Error("failed to add member", "error", err)
122+ return fmt.Errorf("failed to add member: %w", err)
123+ }
124+ l.Info("added member from firehose", "member", record["member"])
125+126+ if err := h.db.AddDid(did); err != nil {
127+ l.Error("failed to add did", "error", err)
128+ return fmt.Errorf("failed to add did: %w", err)
129 }
130131+ if err := h.fetchAndAddKeys(ctx, did); err != nil {
132+ return fmt.Errorf("failed to fetch and add keys: %w", err)
133+ }
134+135 h.js.UpdateDids([]string{did})
136+ return nil
137}
138139+func (h *Handle) processMessages(ctx context.Context, messages <-chan []byte) {
140+ l := log.FromContext(ctx)
141+ l.Info("waiting for knot to be initialized")
142 <-h.init
143+ l.Info("initialized jetstream watcher")
144145 for msg := range messages {
146 var data map[string]interface{}
147 if err := json.Unmarshal(msg, &data); err != nil {
148+ l.Error("error unmarshaling message", "error", err)
149 continue
150 }
151···154 did := data["did"].(string)
155 record := commit["record"].(map[string]interface{})
156157+ var processErr error
158 switch commit["collection"].(string) {
159 case tangled.PublicKeyNSID:
160+ if err := h.processPublicKey(ctx, did, record); err != nil {
161+ processErr = fmt.Errorf("failed to process public key: %w", err)
162+ }
163 case tangled.KnotMemberNSID:
164+ if err := h.processKnotMember(ctx, did, record); err != nil {
165+ processErr = fmt.Errorf("failed to process knot member: %w", err)
166+ }
167+ }
168+169+ if processErr != nil {
170+ l.Error("error processing message", "error", processErr)
171+ continue
172 }
173174 lastTimeUs := int64(data["time_us"].(float64))
175 if err := h.db.SaveLastTimeUs(lastTimeUs); err != nil {
176+ l.Error("failed to save last time us", "error", err)
177+ continue
178 }
179 }
180 }
+45-22
knotserver/routes.go
···9 "errors"
10 "fmt"
11 "html/template"
12- "log"
13 "net/http"
14 "path/filepath"
15 "strconv"
···3031func (h *Handle) RepoIndex(w http.ResponseWriter, r *http.Request) {
32 path := filepath.Join(h.c.Repo.ScanPath, didPath(r))
03334 gr, err := git.Open(path, "")
35 if err != nil {
···37 writeMsg(w, "repo empty")
38 return
39 } else {
40- log.Println(err)
41 notFound(w)
42 return
43 }
···45 commits, err := gr.Commits()
46 if err != nil {
47 writeError(w, err.Error(), http.StatusInternalServerError)
48- log.Println(err)
49 return
50 }
51···73 }
7475 if readmeContent == "" {
76- log.Printf("no readme found for %s", path)
77 }
7879 mainBranch, err := gr.FindMainBranch(h.c.Repo.MainBranch)
80 if err != nil {
81 writeError(w, err.Error(), http.StatusInternalServerError)
82- log.Println(err)
83 return
84 }
85···100 treePath := chi.URLParam(r, "*")
101 ref := chi.URLParam(r, "ref")
10200103 path := filepath.Join(h.c.Repo.ScanPath, didPath(r))
104 gr, err := git.Open(path, ref)
105 if err != nil {
···110 files, err := gr.FileTree(treePath)
111 if err != nil {
112 writeError(w, err.Error(), http.StatusInternalServerError)
113- log.Println(err)
114 return
115 }
116···133 treePath := chi.URLParam(r, "*")
134 ref := chi.URLParam(r, "ref")
13500136 path := filepath.Join(h.c.Repo.ScanPath, didPath(r))
137 gr, err := git.Open(path, ref)
138 if err != nil {
···155 if raw {
156 h.showRaw(string(safe), w)
157 } else {
158- h.showFile(string(safe), data, w)
159 }
160}
161162func (h *Handle) Archive(w http.ResponseWriter, r *http.Request) {
163 name := chi.URLParam(r, "name")
164 file := chi.URLParam(r, "file")
00165166 // TODO: extend this to add more files compression (e.g.: xz)
167 if !strings.HasSuffix(file, ".tar.gz") {
···192 if err != nil {
193 // once we start writing to the body we can't report error anymore
194 // so we are only left with printing the error.
195- log.Println(err)
196 return
197 }
198···200 if err != nil {
201 // once we start writing to the body we can't report error anymore
202 // so we are only left with printing the error.
203- log.Println(err)
204 return
205 }
206}
207208func (h *Handle) Log(w http.ResponseWriter, r *http.Request) {
209- fmt.Println(r.URL.Path)
210 ref := chi.URLParam(r, "ref")
0211212- path := filepath.Join(h.c.Repo.ScanPath, didPath(r))
0213 gr, err := git.Open(path, ref)
214 if err != nil {
215 notFound(w)
···219 commits, err := gr.Commits()
220 if err != nil {
221 writeError(w, err.Error(), http.StatusInternalServerError)
222- log.Println(err)
223 return
224 }
225···269func (h *Handle) Diff(w http.ResponseWriter, r *http.Request) {
270 ref := chi.URLParam(r, "ref")
27100272 path := filepath.Join(h.c.Repo.ScanPath, didPath(r))
273 gr, err := git.Open(path, ref)
274 if err != nil {
···279 diff, err := gr.Diff()
280 if err != nil {
281 writeError(w, err.Error(), http.StatusInternalServerError)
282- log.Println(err)
283 return
284 }
285···297298func (h *Handle) Refs(w http.ResponseWriter, r *http.Request) {
299 path := filepath.Join(h.c.Repo.ScanPath, didPath(r))
00300 gr, err := git.Open(path, "")
301 if err != nil {
302 notFound(w)
···306 tags, err := gr.Tags()
307 if err != nil {
308 // Non-fatal, we *should* have at least one branch to show.
309- log.Println(err)
310 }
311312 branches, err := gr.Branches()
313 if err != nil {
314- log.Println(err)
315 writeError(w, err.Error(), http.StatusInternalServerError)
316 return
317 }
···327}
328329func (h *Handle) Keys(w http.ResponseWriter, r *http.Request) {
00330 switch r.Method {
331 case http.MethodGet:
332 keys, err := h.db.GetAllPublicKeys()
333 if err != nil {
334 writeError(w, err.Error(), http.StatusInternalServerError)
335- log.Println(err)
336 return
337 }
338···358359 if err := h.db.AddPublicKey(pk); err != nil {
360 writeError(w, err.Error(), http.StatusInternalServerError)
361- log.Printf("adding public key: %s", err)
362 return
363 }
364···368}
369370func (h *Handle) NewRepo(w http.ResponseWriter, r *http.Request) {
00371 data := struct {
372 Did string `json:"did"`
373 Name string `json:"name"`
···385 repoPath := filepath.Join(h.c.Repo.ScanPath, relativeRepoPath)
386 err := git.InitBare(repoPath)
387 if err != nil {
388- log.Println(err)
389 writeError(w, err.Error(), http.StatusInternalServerError)
390 return
391 }
···393 // add perms for this user to access the repo
394 err = h.e.AddRepo(did, ThisServer, relativeRepoPath)
395 if err != nil {
396- log.Println(err)
397 writeError(w, err.Error(), http.StatusInternalServerError)
398 return
399 }
···402}
403404func (h *Handle) AddMember(w http.ResponseWriter, r *http.Request) {
00405 data := struct {
406 Did string `json:"did"`
407 PublicKeys []string `json:"keys"`
···427428 h.js.UpdateDids([]string{did})
429 if err := h.e.AddMember(ThisServer, did); err != nil {
430- log.Println(err)
431 writeError(w, err.Error(), http.StatusInternalServerError)
432 return
433 }
···436}
437438func (h *Handle) Init(w http.ResponseWriter, r *http.Request) {
00439 if h.knotInitialized {
440 writeError(w, "knot already initialized", http.StatusConflict)
441 return
···447 }{}
448449 if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
0450 writeError(w, "invalid request body", http.StatusBadRequest)
451 return
452 }
453454 if data.Did == "" {
0455 writeError(w, "did is empty", http.StatusBadRequest)
456 return
457 }
···464 pk.Key = k
465 err := h.db.AddPublicKey(pk)
466 if err != nil {
0467 writeError(w, err.Error(), http.StatusInternalServerError)
468 return
469 }
470 }
471 } else {
0472 writeError(w, err.Error(), http.StatusInternalServerError)
473 return
474 }
475476 h.js.UpdateDids([]string{data.Did})
477 if err := h.e.AddOwner(ThisServer, data.Did); err != nil {
478- log.Println(err)
479 writeError(w, err.Error(), http.StatusInternalServerError)
480 return
481 }
482- // Signal that the knot is ready
483 close(h.init)
484485 mac := hmac.New(sha256.New, []byte(h.c.Server.Secret))
···9 "errors"
10 "fmt"
11 "html/template"
012 "net/http"
13 "path/filepath"
14 "strconv"
···2930func (h *Handle) RepoIndex(w http.ResponseWriter, r *http.Request) {
31 path := filepath.Join(h.c.Repo.ScanPath, didPath(r))
32+ l := h.l.With("path", path, "handler", "RepoIndex")
3334 gr, err := git.Open(path, "")
35 if err != nil {
···37 writeMsg(w, "repo empty")
38 return
39 } else {
40+ l.Error("opening repo", "error", err.Error())
41 notFound(w)
42 return
43 }
···45 commits, err := gr.Commits()
46 if err != nil {
47 writeError(w, err.Error(), http.StatusInternalServerError)
48+ l.Error("fetching commits", "error", err.Error())
49 return
50 }
51···73 }
7475 if readmeContent == "" {
76+ l.Warn("no readme found")
77 }
7879 mainBranch, err := gr.FindMainBranch(h.c.Repo.MainBranch)
80 if err != nil {
81 writeError(w, err.Error(), http.StatusInternalServerError)
82+ l.Error("finding main branch", "error", err.Error())
83 return
84 }
85···100 treePath := chi.URLParam(r, "*")
101 ref := chi.URLParam(r, "ref")
102103+ l := h.l.With("handler", "RepoTree", "ref", ref, "treePath", treePath)
104+105 path := filepath.Join(h.c.Repo.ScanPath, didPath(r))
106 gr, err := git.Open(path, ref)
107 if err != nil {
···112 files, err := gr.FileTree(treePath)
113 if err != nil {
114 writeError(w, err.Error(), http.StatusInternalServerError)
115+ l.Error("file tree", "error", err.Error())
116 return
117 }
118···135 treePath := chi.URLParam(r, "*")
136 ref := chi.URLParam(r, "ref")
137138+ l := h.l.With("handler", "FileContent", "ref", ref, "treePath", treePath)
139+140 path := filepath.Join(h.c.Repo.ScanPath, didPath(r))
141 gr, err := git.Open(path, ref)
142 if err != nil {
···159 if raw {
160 h.showRaw(string(safe), w)
161 } else {
162+ h.showFile(string(safe), data, w, l)
163 }
164}
165166func (h *Handle) Archive(w http.ResponseWriter, r *http.Request) {
167 name := chi.URLParam(r, "name")
168 file := chi.URLParam(r, "file")
169+170+ l := h.l.With("handler", "Archive", "name", name, "file", file)
171172 // TODO: extend this to add more files compression (e.g.: xz)
173 if !strings.HasSuffix(file, ".tar.gz") {
···198 if err != nil {
199 // once we start writing to the body we can't report error anymore
200 // so we are only left with printing the error.
201+ l.Error("writing tar file", "error", err.Error())
202 return
203 }
204···206 if err != nil {
207 // once we start writing to the body we can't report error anymore
208 // so we are only left with printing the error.
209+ l.Error("flushing?", "error", err.Error())
210 return
211 }
212}
213214func (h *Handle) Log(w http.ResponseWriter, r *http.Request) {
0215 ref := chi.URLParam(r, "ref")
216+ path := filepath.Join(h.c.Repo.ScanPath, didPath(r))
217218+ l := h.l.With("handler", "Log", "ref", ref, "path", path)
219+220 gr, err := git.Open(path, ref)
221 if err != nil {
222 notFound(w)
···226 commits, err := gr.Commits()
227 if err != nil {
228 writeError(w, err.Error(), http.StatusInternalServerError)
229+ l.Error("fetching commits", "error", err.Error())
230 return
231 }
232···276func (h *Handle) Diff(w http.ResponseWriter, r *http.Request) {
277 ref := chi.URLParam(r, "ref")
278279+ l := h.l.With("handler", "Diff", "ref", ref)
280+281 path := filepath.Join(h.c.Repo.ScanPath, didPath(r))
282 gr, err := git.Open(path, ref)
283 if err != nil {
···288 diff, err := gr.Diff()
289 if err != nil {
290 writeError(w, err.Error(), http.StatusInternalServerError)
291+ l.Error("getting diff", "error", err.Error())
292 return
293 }
294···306307func (h *Handle) Refs(w http.ResponseWriter, r *http.Request) {
308 path := filepath.Join(h.c.Repo.ScanPath, didPath(r))
309+ l := h.l.With("handler", "Refs")
310+311 gr, err := git.Open(path, "")
312 if err != nil {
313 notFound(w)
···317 tags, err := gr.Tags()
318 if err != nil {
319 // Non-fatal, we *should* have at least one branch to show.
320+ l.Error("getting tags", "error", err.Error())
321 }
322323 branches, err := gr.Branches()
324 if err != nil {
325+ l.Error("getting branches", "error", err.Error())
326 writeError(w, err.Error(), http.StatusInternalServerError)
327 return
328 }
···338}
339340func (h *Handle) Keys(w http.ResponseWriter, r *http.Request) {
341+ l := h.l.With("handler", "Keys")
342+343 switch r.Method {
344 case http.MethodGet:
345 keys, err := h.db.GetAllPublicKeys()
346 if err != nil {
347 writeError(w, err.Error(), http.StatusInternalServerError)
348+ l.Error("getting public keys", "error", err.Error())
349 return
350 }
351···371372 if err := h.db.AddPublicKey(pk); err != nil {
373 writeError(w, err.Error(), http.StatusInternalServerError)
374+ l.Error("adding public key", "error", err.Error())
375 return
376 }
377···381}
382383func (h *Handle) NewRepo(w http.ResponseWriter, r *http.Request) {
384+ l := h.l.With("handler", "NewRepo")
385+386 data := struct {
387 Did string `json:"did"`
388 Name string `json:"name"`
···400 repoPath := filepath.Join(h.c.Repo.ScanPath, relativeRepoPath)
401 err := git.InitBare(repoPath)
402 if err != nil {
403+ l.Error("initializing bare repo", "error", err.Error())
404 writeError(w, err.Error(), http.StatusInternalServerError)
405 return
406 }
···408 // add perms for this user to access the repo
409 err = h.e.AddRepo(did, ThisServer, relativeRepoPath)
410 if err != nil {
411+ l.Error("adding repo permissions", "error", err.Error())
412 writeError(w, err.Error(), http.StatusInternalServerError)
413 return
414 }
···417}
418419func (h *Handle) AddMember(w http.ResponseWriter, r *http.Request) {
420+ l := h.l.With("handler", "AddMember")
421+422 data := struct {
423 Did string `json:"did"`
424 PublicKeys []string `json:"keys"`
···444445 h.js.UpdateDids([]string{did})
446 if err := h.e.AddMember(ThisServer, did); err != nil {
447+ l.Error("adding member", "error", err.Error())
448 writeError(w, err.Error(), http.StatusInternalServerError)
449 return
450 }
···453}
454455func (h *Handle) Init(w http.ResponseWriter, r *http.Request) {
456+ l := h.l.With("handler", "Init")
457+458 if h.knotInitialized {
459 writeError(w, "knot already initialized", http.StatusConflict)
460 return
···466 }{}
467468 if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
469+ l.Error("failed to decode request body", "error", err.Error())
470 writeError(w, "invalid request body", http.StatusBadRequest)
471 return
472 }
473474 if data.Did == "" {
475+ l.Error("empty DID in request")
476 writeError(w, "did is empty", http.StatusBadRequest)
477 return
478 }
···485 pk.Key = k
486 err := h.db.AddPublicKey(pk)
487 if err != nil {
488+ l.Error("failed to add public key", "error", err.Error())
489 writeError(w, err.Error(), http.StatusInternalServerError)
490 return
491 }
492 }
493 } else {
494+ l.Error("failed to add DID", "error", err.Error())
495 writeError(w, err.Error(), http.StatusInternalServerError)
496 return
497 }
498499 h.js.UpdateDids([]string{data.Did})
500 if err := h.e.AddOwner(ThisServer, data.Did); err != nil {
501+ l.Error("adding owner", "error", err.Error())
502 writeError(w, err.Error(), http.StatusInternalServerError)
503 return
504 }
505+506 close(h.init)
507508 mac := hmac.New(sha256.New, []byte(h.c.Server.Secret))