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