···26 pragma auto_vacuum = incremental;
27 pragma busy_timeout = 5000;
2800000029 create table if not exists known_dids (
30 did text primary key
31 );
···26 pragma auto_vacuum = incremental;
27 pragma busy_timeout = 5000;
2829+ create table if not exists owner (
30+ id integer primary key check (id = 0),
31+ did text not null,
32+ createdAt text not null default (strftime('%Y-%m-%dT%H:%M:%SZ', 'now'))
33+ );
34+35 create table if not exists known_dids (
36 did text primary key
37 );
+18
knotserver/db/owner.go
···000000000000000000
···1+package db
2+3+func (d *DB) SetOwner(did string) error {
4+ query := `insert into owner (id, did) values (?, ?)`
5+ _, err := d.db.Exec(query, 0, did)
6+ return err
7+}
8+9+func (d *DB) Owner() (string, error) {
10+ query := `select did from owner`
11+12+ var did string
13+ err := d.db.QueryRow(query).Scan(&did)
14+ if err != nil {
15+ return "", err
16+ }
17+ return did, nil
18+}
+100-27
knotserver/handler.go
···6 "log/slog"
7 "net/http"
8 "runtime/debug"
09000010 "github.com/go-chi/chi/v5"
011 "tangled.sh/tangled.sh/core/jetstream"
12 "tangled.sh/tangled.sh/core/knotserver/config"
13 "tangled.sh/tangled.sh/core/knotserver/db"
14 "tangled.sh/tangled.sh/core/rbac"
015)
1617const (
···19)
2021type Handle struct {
22- c *config.Config
23- db *db.DB
24- jc *jetstream.JetstreamClient
25- e *rbac.Enforcer
26- l *slog.Logger
27-28- // init is a channel that is closed when the knot has been initailized
29- // i.e. when the first user (knot owner) has been added.
30- init chan struct{}
31- knotInitialized bool
32}
3334func Setup(ctx context.Context, c *config.Config, db *db.DB, e *rbac.Enforcer, jc *jetstream.JetstreamClient, l *slog.Logger) (http.Handler, error) {
35- r := chi.NewRouter()
36-37 h := Handle{
38- c: c,
39- db: db,
40- e: e,
41- l: l,
42- jc: jc,
43- init: make(chan struct{}),
44 }
4546 err := e.AddDomain(ThisServer)
···48 return nil, fmt.Errorf("failed to setup enforcer: %w", err)
49 }
500000000000051 err = h.jc.StartJetstream(ctx, h.processMessages)
52 if err != nil {
53 return nil, fmt.Errorf("failed to start jetstream: %w", err)
54 }
5556- // Check if the knot knows about any Dids;
57- // if it does, it is already initialized and we can repopulate the
58- // Jetstream subscriptions.
59 dids, err := db.GetAllDids()
60 if err != nil {
61 return nil, fmt.Errorf("failed to get all Dids: %w", err)
62 }
6364- if len(dids) > 0 {
65- h.knotInitialized = true
66- close(h.init)
67- for _, d := range dids {
68- h.jc.AddDid(d)
69- }
70 }
007172 r.Get("/", h.Index)
73 r.Get("/capabilities", h.Capabilities)
···184 w.Header().Set("Content-Type", "text/plain")
185 fmt.Fprintf(w, "knotserver/%s", version)
186}
0000000000000000000000000000000000000000000000000000000000000000000