this repo has no description

knotserver: setup known_dids and dev mode

Changed files
+101 -72
cmd
knotserver
knotserver
+5
cmd/knotserver/main.go
··· 24 24 if err != nil { 25 25 log.Fatal(err) 26 26 } 27 + 28 + if c.Server.Dev { 29 + log.Println("running in dev mode, signature verification is disabled") 30 + } 31 + 27 32 db, err := db.Setup(c.Server.DBPath) 28 33 if err != nil { 29 34 log.Fatalf("failed to setup db: %s", err)
+2
knotserver/config/config.go
··· 17 17 Port int `env:"PORT, default=5555"` 18 18 Secret string `env:"SECRET, required"` 19 19 DBPath string `env:"DB_PATH, default=knotserver.db"` 20 + // This disables signature verification so use with caution. 21 + Dev bool `env:"DEV, default=false"` 20 22 } 21 23 22 24 type Config struct {
+6 -8
knotserver/db/init.go
··· 17 17 } 18 18 19 19 _, err = db.Exec(` 20 + create table if not exists known_dids ( 21 + did text primary key 22 + ); 20 23 create table if not exists public_keys ( 21 24 id integer primary key autoincrement, 22 25 did text not null, 23 - name text not null, 24 26 key text not null, 25 27 created timestamp default current_timestamp, 26 - unique(did, name, key) 27 - ); 28 - create table if not exists users ( 29 - id integer primary key autoincrement, 30 - did text not null, 31 - unique(did), 32 - foreign key (did) references public_keys(did) on delete cascade 28 + unique(did, key), 29 + foreign key (did) references known_dids(did) on delete cascade 33 30 ); 31 + 34 32 create table if not exists repos ( 35 33 id integer primary key autoincrement, 36 34 did text not null,
+44
knotserver/db/known_dids.go
··· 1 + package db 2 + 3 + func (d *DB) AddDID(did string) error { 4 + _, err := d.db.Exec(`insert into known_dids (did) values (?)`, did) 5 + return err 6 + } 7 + 8 + func (d *DB) RemoveDID(did string) error { 9 + _, err := d.db.Exec(`delete from known_dids where did = ?`, did) 10 + return err 11 + } 12 + 13 + func (d *DB) GetAllDIDs() ([]string, error) { 14 + var dids []string 15 + 16 + rows, err := d.db.Query(`select did from known_dids`) 17 + if err != nil { 18 + return nil, err 19 + } 20 + defer rows.Close() 21 + 22 + for rows.Next() { 23 + var did string 24 + if err := rows.Scan(&did); err != nil { 25 + return nil, err 26 + } 27 + dids = append(dids, did) 28 + } 29 + 30 + if err := rows.Err(); err != nil { 31 + return nil, err 32 + } 33 + 34 + return dids, nil 35 + } 36 + 37 + func (d *DB) HasKnownDIDs() bool { 38 + var count int 39 + err := d.db.QueryRow(`select count(*) from known_dids`).Scan(&count) 40 + if err != nil { 41 + return false 42 + } 43 + return count > 0 44 + }
+6 -8
knotserver/db/pubkeys.go
··· 22 22 pk := PublicKey{ 23 23 Did: did, 24 24 } 25 - pk.Name = record["name"] 26 25 pk.Key = record["key"] 27 26 pk.Created = record["created"] 28 27 ··· 34 33 pk.Created = time.Now().Format("2006-01-02 15:04:05.99999999 -0700 MST m=-0000.000000000") 35 34 } 36 35 37 - query := `insert into public_keys (did, name, key, created) values (?, ?, ?, ?)` 38 - _, err := d.db.Exec(query, pk.Did, pk.Name, pk.Key, pk.Created) 36 + query := `insert into public_keys (did, key, created) values (?, ?, ?)` 37 + _, err := d.db.Exec(query, pk.Did, pk.Key, pk.Created) 39 38 return err 40 39 } 41 40 ··· 49 48 return map[string]interface{}{ 50 49 pk.Did: map[string]interface{}{ 51 50 "key": pk.Key, 52 - "name": pk.Name, 53 51 "created": pk.Created, 54 52 }, 55 53 } ··· 58 56 func (d *DB) GetAllPublicKeys() ([]PublicKey, error) { 59 57 var keys []PublicKey 60 58 61 - rows, err := d.db.Query(`select key, name, did, created from public_keys`) 59 + rows, err := d.db.Query(`select key, did, created from public_keys`) 62 60 if err != nil { 63 61 return nil, err 64 62 } ··· 66 64 67 65 for rows.Next() { 68 66 var publicKey PublicKey 69 - if err := rows.Scan(&publicKey.Key, &publicKey.Name, &publicKey.Did, &publicKey.Created); err != nil { 67 + if err := rows.Scan(&publicKey.Key, &publicKey.Did, &publicKey.Created); err != nil { 70 68 return nil, err 71 69 } 72 70 keys = append(keys, publicKey) ··· 82 80 func (d *DB) GetPublicKeys(did string) ([]PublicKey, error) { 83 81 var keys []PublicKey 84 82 85 - rows, err := d.db.Query(`select did, key, name, created from public_keys where did = ?`, did) 83 + rows, err := d.db.Query(`select did, key, created from public_keys where did = ?`, did) 86 84 if err != nil { 87 85 return nil, err 88 86 } ··· 90 88 91 89 for rows.Next() { 92 90 var publicKey PublicKey 93 - if err := rows.Scan(&publicKey.Did, &publicKey.Key, &publicKey.Name, &publicKey.Created); err != nil { 91 + if err := rows.Scan(&publicKey.Did, &publicKey.Key, &publicKey.Created); err != nil { 94 92 return nil, err 95 93 } 96 94 keys = append(keys, publicKey)
-11
knotserver/db/users.go
··· 1 - package db 2 - 3 - func (d *DB) AddUser(did string) error { 4 - _, err := d.db.Exec(`insert into users (did) values (?)`, did) 5 - return err 6 - } 7 - 8 - func (d *DB) RemoveUser(did string) error { 9 - _, err := d.db.Exec(`delete from users where did = ?`, did) 10 - return err 11 - }
+17 -9
knotserver/handler.go
··· 39 39 return nil, fmt.Errorf("failed to start jetstream: %w", err) 40 40 } 41 41 42 - // TODO: close this channel and set h.knotInitialized *only after* 43 - // checking if we have an owner. 44 - close(h.init) 45 - h.knotInitialized = true 42 + // Check if the knot knows about any DIDs; 43 + // if it does, it is already initialized and we can repopulate the 44 + // Jetstream subscriptions. 45 + dids, err := db.GetAllDIDs() 46 + if err != nil { 47 + return nil, fmt.Errorf("failed to get all DIDs: %w", err) 48 + } 49 + if len(dids) > 0 { 50 + h.knotInitialized = true 51 + close(h.init) 52 + h.js.UpdateDids(dids) 53 + } 46 54 47 55 r.Get("/", h.Index) 48 56 r.Route("/{did}", func(r chi.Router) { ··· 67 75 }) 68 76 }) 69 77 70 - // Create a new repository 78 + // Create a new repository. 71 79 r.Route("/repo", func(r chi.Router) { 72 80 r.Use(h.VerifySignature) 73 81 r.Put("/new", h.NewRepo) 74 82 }) 75 83 76 - // Add a new user to the knot 77 - r.With(h.VerifySignature).Put("/user", h.AddUser) 84 + // Initialize the knot with an owner and public key. 78 85 r.With(h.VerifySignature).Post("/init", h.Init) 79 86 80 87 // Health check. Used for two-way verification with appview. 81 88 r.With(h.VerifySignature).Get("/health", h.Health) 82 89 83 - // All public keys on the knot 90 + // All public keys on the knot. 84 91 r.Get("/keys", h.Keys) 85 92 86 93 return r, nil ··· 117 124 record := commit["record"].(map[string]interface{}) 118 125 if err := h.db.AddPublicKeyFromRecord(did, record); err != nil { 119 126 log.Printf("failed to add public key: %v", err) 127 + } else { 128 + log.Printf("added public key from firehose: %s", data["did"]) 120 129 } 121 - log.Printf("added public key from firehose: %s", data["did"]) 122 130 default: 123 131 } 124 132 }
+3
knotserver/middleware.go
··· 10 10 ) 11 11 12 12 func (h *Handle) VerifySignature(next http.Handler) http.Handler { 13 + if h.c.Server.Dev { 14 + return next 15 + } 13 16 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 14 17 signature := r.Header.Get("X-Signature") 15 18 log.Println(signature)
+18 -36
knotserver/routes.go
··· 391 391 w.WriteHeader(http.StatusNoContent) 392 392 } 393 393 394 - func (h *Handle) AddUser(w http.ResponseWriter, r *http.Request) { 394 + // TODO: make this set the initial user as the owner 395 + func (h *Handle) Init(w http.ResponseWriter, r *http.Request) { 396 + if h.knotInitialized { 397 + writeError(w, "knot already initialized", http.StatusConflict) 398 + return 399 + } 400 + 395 401 data := struct { 396 402 DID string `json:"did"` 397 - PublicKey string `json:"pubkey"` 403 + PublicKey string `json:"key"` 404 + Created string `json:"created"` 398 405 }{} 399 406 400 407 if err := json.NewDecoder(r.Body).Decode(&data); err != nil { ··· 404 411 405 412 did := data.DID 406 413 key := data.PublicKey 414 + created := data.Created 407 415 408 - if err := h.db.AddUser(did); err == nil { 409 - pk := db.PublicKey{ 410 - Did: did, 411 - } 412 - pk.Key = key 413 - pk.Name = "default" 414 - err := h.db.AddPublicKey(pk) 415 - if err != nil { 416 - writeError(w, err.Error(), http.StatusInternalServerError) 417 - return 418 - } 419 - } else { 420 - writeError(w, err.Error(), http.StatusInternalServerError) 416 + if did == "" { 417 + writeError(w, "did is empty", http.StatusBadRequest) 421 418 return 422 419 } 423 420 424 - h.js.UpdateDids([]string{did}) 425 - 426 - w.WriteHeader(http.StatusNoContent) 427 - } 428 - 429 - // TODO: make this set the initial user as the owner 430 - func (h *Handle) Init(w http.ResponseWriter, r *http.Request) { 431 - if h.knotInitialized { 432 - writeError(w, "knot already initialized", http.StatusConflict) 421 + if key == "" { 422 + writeError(w, "key is empty", http.StatusBadRequest) 433 423 return 434 424 } 435 425 436 - data := struct { 437 - DID string `json:"did"` 438 - PublicKey string `json:"pubkey"` 439 - }{} 440 - 441 - if err := json.NewDecoder(r.Body).Decode(&data); err != nil { 442 - writeError(w, "invalid request body", http.StatusBadRequest) 426 + if created == "" { 427 + writeError(w, "created timestamp is empty", http.StatusBadRequest) 443 428 return 444 429 } 445 430 446 - did := data.DID 447 - key := data.PublicKey 448 - 449 - if err := h.db.AddUser(did); err == nil { 431 + if err := h.db.AddDID(did); err == nil { 450 432 pk := db.PublicKey{ 451 433 Did: did, 452 434 } 453 435 pk.Key = key 454 - pk.Name = "default" 436 + pk.Created = created 455 437 err := h.db.AddPublicKey(pk) 456 438 if err != nil { 457 439 writeError(w, err.Error(), http.StatusInternalServerError)