forked from tangled.org/core
this repo has no description

knotserver: setup known_dids and dev mode

anirudh.fi 22193609 abdf4e5f

verified
Changed files
+101 -72
cmd
knotserver
knotserver
+5
cmd/knotserver/main.go
···
if err != nil {
log.Fatal(err)
}
+
+
if c.Server.Dev {
+
log.Println("running in dev mode, signature verification is disabled")
+
}
+
db, err := db.Setup(c.Server.DBPath)
if err != nil {
log.Fatalf("failed to setup db: %s", err)
+2
knotserver/config/config.go
···
Port int `env:"PORT, default=5555"`
Secret string `env:"SECRET, required"`
DBPath string `env:"DB_PATH, default=knotserver.db"`
+
// This disables signature verification so use with caution.
+
Dev bool `env:"DEV, default=false"`
}
type Config struct {
+6 -8
knotserver/db/init.go
···
}
_, err = db.Exec(`
+
create table if not exists known_dids (
+
did text primary key
+
);
create table if not exists public_keys (
id integer primary key autoincrement,
did text not null,
-
name text not null,
key text not null,
created timestamp default current_timestamp,
-
unique(did, name, key)
-
);
-
create table if not exists users (
-
id integer primary key autoincrement,
-
did text not null,
-
unique(did),
-
foreign key (did) references public_keys(did) on delete cascade
+
unique(did, key),
+
foreign key (did) references known_dids(did) on delete cascade
);
+
create table if not exists repos (
id integer primary key autoincrement,
did text not null,
+44
knotserver/db/known_dids.go
···
+
package db
+
+
func (d *DB) AddDID(did string) error {
+
_, err := d.db.Exec(`insert into known_dids (did) values (?)`, did)
+
return err
+
}
+
+
func (d *DB) RemoveDID(did string) error {
+
_, err := d.db.Exec(`delete from known_dids where did = ?`, did)
+
return err
+
}
+
+
func (d *DB) GetAllDIDs() ([]string, error) {
+
var dids []string
+
+
rows, err := d.db.Query(`select did from known_dids`)
+
if err != nil {
+
return nil, err
+
}
+
defer rows.Close()
+
+
for rows.Next() {
+
var did string
+
if err := rows.Scan(&did); err != nil {
+
return nil, err
+
}
+
dids = append(dids, did)
+
}
+
+
if err := rows.Err(); err != nil {
+
return nil, err
+
}
+
+
return dids, nil
+
}
+
+
func (d *DB) HasKnownDIDs() bool {
+
var count int
+
err := d.db.QueryRow(`select count(*) from known_dids`).Scan(&count)
+
if err != nil {
+
return false
+
}
+
return count > 0
+
}
+6 -8
knotserver/db/pubkeys.go
···
pk := PublicKey{
Did: did,
}
-
pk.Name = record["name"]
pk.Key = record["key"]
pk.Created = record["created"]
···
pk.Created = time.Now().Format("2006-01-02 15:04:05.99999999 -0700 MST m=-0000.000000000")
}
-
query := `insert into public_keys (did, name, key, created) values (?, ?, ?, ?)`
-
_, err := d.db.Exec(query, pk.Did, pk.Name, pk.Key, pk.Created)
+
query := `insert into public_keys (did, key, created) values (?, ?, ?)`
+
_, err := d.db.Exec(query, pk.Did, pk.Key, pk.Created)
return err
}
···
return map[string]interface{}{
pk.Did: map[string]interface{}{
"key": pk.Key,
-
"name": pk.Name,
"created": pk.Created,
},
}
···
func (d *DB) GetAllPublicKeys() ([]PublicKey, error) {
var keys []PublicKey
-
rows, err := d.db.Query(`select key, name, did, created from public_keys`)
+
rows, err := d.db.Query(`select key, did, created from public_keys`)
if err != nil {
return nil, err
}
···
for rows.Next() {
var publicKey PublicKey
-
if err := rows.Scan(&publicKey.Key, &publicKey.Name, &publicKey.Did, &publicKey.Created); err != nil {
+
if err := rows.Scan(&publicKey.Key, &publicKey.Did, &publicKey.Created); err != nil {
return nil, err
}
keys = append(keys, publicKey)
···
func (d *DB) GetPublicKeys(did string) ([]PublicKey, error) {
var keys []PublicKey
-
rows, err := d.db.Query(`select did, key, name, created from public_keys where did = ?`, did)
+
rows, err := d.db.Query(`select did, key, created from public_keys where did = ?`, did)
if err != nil {
return nil, err
}
···
for rows.Next() {
var publicKey PublicKey
-
if err := rows.Scan(&publicKey.Did, &publicKey.Key, &publicKey.Name, &publicKey.Created); err != nil {
+
if err := rows.Scan(&publicKey.Did, &publicKey.Key, &publicKey.Created); err != nil {
return nil, err
}
keys = append(keys, publicKey)
-11
knotserver/db/users.go
···
-
package db
-
-
func (d *DB) AddUser(did string) error {
-
_, err := d.db.Exec(`insert into users (did) values (?)`, did)
-
return err
-
}
-
-
func (d *DB) RemoveUser(did string) error {
-
_, err := d.db.Exec(`delete from users where did = ?`, did)
-
return err
-
}
+17 -9
knotserver/handler.go
···
return nil, fmt.Errorf("failed to start jetstream: %w", err)
}
-
// TODO: close this channel and set h.knotInitialized *only after*
-
// checking if we have an owner.
-
close(h.init)
-
h.knotInitialized = true
+
// Check if the knot knows about any DIDs;
+
// if it does, it is already initialized and we can repopulate the
+
// Jetstream subscriptions.
+
dids, err := db.GetAllDIDs()
+
if err != nil {
+
return nil, fmt.Errorf("failed to get all DIDs: %w", err)
+
}
+
if len(dids) > 0 {
+
h.knotInitialized = true
+
close(h.init)
+
h.js.UpdateDids(dids)
+
}
r.Get("/", h.Index)
r.Route("/{did}", func(r chi.Router) {
···
})
})
-
// Create a new repository
+
// Create a new repository.
r.Route("/repo", func(r chi.Router) {
r.Use(h.VerifySignature)
r.Put("/new", h.NewRepo)
})
-
// Add a new user to the knot
-
r.With(h.VerifySignature).Put("/user", h.AddUser)
+
// Initialize the knot with an owner and public key.
r.With(h.VerifySignature).Post("/init", h.Init)
// Health check. Used for two-way verification with appview.
r.With(h.VerifySignature).Get("/health", h.Health)
-
// All public keys on the knot
+
// All public keys on the knot.
r.Get("/keys", h.Keys)
return r, nil
···
record := commit["record"].(map[string]interface{})
if err := h.db.AddPublicKeyFromRecord(did, record); err != nil {
log.Printf("failed to add public key: %v", err)
+
} else {
+
log.Printf("added public key from firehose: %s", data["did"])
}
-
log.Printf("added public key from firehose: %s", data["did"])
default:
}
}
+3
knotserver/middleware.go
···
)
func (h *Handle) VerifySignature(next http.Handler) http.Handler {
+
if h.c.Server.Dev {
+
return next
+
}
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
signature := r.Header.Get("X-Signature")
log.Println(signature)
+18 -36
knotserver/routes.go
···
w.WriteHeader(http.StatusNoContent)
}
-
func (h *Handle) AddUser(w http.ResponseWriter, r *http.Request) {
+
// TODO: make this set the initial user as the owner
+
func (h *Handle) Init(w http.ResponseWriter, r *http.Request) {
+
if h.knotInitialized {
+
writeError(w, "knot already initialized", http.StatusConflict)
+
return
+
}
+
data := struct {
DID string `json:"did"`
-
PublicKey string `json:"pubkey"`
+
PublicKey string `json:"key"`
+
Created string `json:"created"`
}{}
if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
···
did := data.DID
key := data.PublicKey
+
created := data.Created
-
if err := h.db.AddUser(did); err == nil {
-
pk := db.PublicKey{
-
Did: did,
-
}
-
pk.Key = key
-
pk.Name = "default"
-
err := h.db.AddPublicKey(pk)
-
if err != nil {
-
writeError(w, err.Error(), http.StatusInternalServerError)
-
return
-
}
-
} else {
-
writeError(w, err.Error(), http.StatusInternalServerError)
+
if did == "" {
+
writeError(w, "did is empty", http.StatusBadRequest)
return
}
-
h.js.UpdateDids([]string{did})
-
-
w.WriteHeader(http.StatusNoContent)
-
}
-
-
// TODO: make this set the initial user as the owner
-
func (h *Handle) Init(w http.ResponseWriter, r *http.Request) {
-
if h.knotInitialized {
-
writeError(w, "knot already initialized", http.StatusConflict)
+
if key == "" {
+
writeError(w, "key is empty", http.StatusBadRequest)
return
}
-
data := struct {
-
DID string `json:"did"`
-
PublicKey string `json:"pubkey"`
-
}{}
-
-
if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
-
writeError(w, "invalid request body", http.StatusBadRequest)
+
if created == "" {
+
writeError(w, "created timestamp is empty", http.StatusBadRequest)
return
}
-
did := data.DID
-
key := data.PublicKey
-
-
if err := h.db.AddUser(did); err == nil {
+
if err := h.db.AddDID(did); err == nil {
pk := db.PublicKey{
Did: did,
}
pk.Key = key
-
pk.Name = "default"
+
pk.Created = created
err := h.db.AddPublicKey(pk)
if err != nil {
writeError(w, err.Error(), http.StatusInternalServerError)