this repo has no description
1package knotserver 2 3import ( 4 "context" 5 "fmt" 6 "net/http" 7 8 "github.com/go-chi/chi/v5" 9 "github.com/sotangled/tangled/knotserver/config" 10 "github.com/sotangled/tangled/knotserver/db" 11 "github.com/sotangled/tangled/knotserver/jsclient" 12 "github.com/sotangled/tangled/rbac" 13) 14 15const ( 16 ThisServer = "thisserver" // resource identifier for rbac enforcement 17) 18 19type Handle struct { 20 c *config.Config 21 db *db.DB 22 js *jsclient.JetstreamClient 23 e *rbac.Enforcer 24 25 // 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. 27 init chan struct{} 28 knotInitialized bool 29} 30 31func Setup(ctx context.Context, c *config.Config, db *db.DB, e *rbac.Enforcer) (http.Handler, error) { 32 r := chi.NewRouter() 33 34 h := Handle{ 35 c: c, 36 db: db, 37 e: e, 38 init: make(chan struct{}), 39 } 40 41 err := e.AddDomain(ThisServer) 42 if err != nil { 43 return nil, fmt.Errorf("failed to setup enforcer: %w", err) 44 } 45 46 err = h.StartJetstream(ctx) 47 if err != nil { 48 return nil, fmt.Errorf("failed to start jetstream: %w", err) 49 } 50 51 // Check if the knot knows about any Dids; 52 // if it does, it is already initialized and we can repopulate the 53 // Jetstream subscriptions. 54 dids, err := db.GetAllDids() 55 if err != nil { 56 return nil, fmt.Errorf("failed to get all Dids: %w", err) 57 } 58 if len(dids) > 0 { 59 h.knotInitialized = true 60 close(h.init) 61 h.js.UpdateDids(dids) 62 } 63 64 r.Get("/", h.Index) 65 r.Route("/{did}", func(r chi.Router) { 66 // Repo routes 67 r.Route("/{name}", func(r chi.Router) { 68 r.Get("/", h.RepoIndex) 69 r.Get("/info/refs", h.InfoRefs) 70 r.Post("/git-upload-pack", h.UploadPack) 71 72 r.Route("/tree/{ref}", func(r chi.Router) { 73 r.Get("/*", h.RepoTree) 74 }) 75 76 r.Route("/blob/{ref}", func(r chi.Router) { 77 r.Get("/*", h.FileContent) 78 }) 79 80 r.Get("/log/{ref}", h.Log) 81 r.Get("/archive/{file}", h.Archive) 82 r.Get("/commit/{ref}", h.Diff) 83 r.Get("/refs/", h.Refs) 84 }) 85 }) 86 87 // Create a new repository. 88 r.Route("/repo", func(r chi.Router) { 89 r.Use(h.VerifySignature) 90 r.Put("/new", h.NewRepo) 91 }) 92 93 r.Route("/member", func(r chi.Router) { 94 r.Use(h.VerifySignature) 95 r.Put("/add", h.NewRepo) 96 }) 97 98 // Initialize the knot with an owner and public key. 99 r.With(h.VerifySignature).Post("/init", h.Init) 100 101 // Health check. Used for two-way verification with appview. 102 r.With(h.VerifySignature).Get("/health", h.Health) 103 104 // All public keys on the knot. 105 r.Get("/keys", h.Keys) 106 107 return r, nil 108}