Monorepo for Tangled
1package repo
2
3import (
4 "net/http"
5
6 "github.com/go-chi/chi/v5"
7 "tangled.org/core/appview/middleware"
8)
9
10func (rp *Repo) Router(mw *middleware.Middleware) http.Handler {
11 r := chi.NewRouter()
12 r.Get("/", rp.Index)
13 r.Get("/opengraph", rp.Opengraph)
14 r.Get("/feed.atom", rp.AtomFeed)
15 r.Get("/commits/{ref}", rp.Log)
16 r.Route("/tree/{ref}", func(r chi.Router) {
17 r.Get("/", rp.Index)
18 r.Get("/*", rp.Tree)
19 })
20 r.Get("/commit/{ref}", rp.Commit)
21 r.Get("/branches", rp.Branches)
22 r.Delete("/branches", rp.DeleteBranch)
23 r.Route("/tags", func(r chi.Router) {
24 r.Get("/", rp.Tags)
25 r.Route("/{tag}", func(r chi.Router) {
26 r.Get("/", rp.Tag)
27 r.Get("/download/{file}", rp.DownloadArtifact)
28
29 // require repo:push to upload or delete artifacts
30 //
31 // additionally: only the uploader can truly delete an artifact
32 // (record+blob will live on their pds)
33 r.Group(func(r chi.Router) {
34 r.Use(middleware.AuthMiddleware(rp.oauth))
35 r.Use(mw.RepoPermissionMiddleware("repo:push"))
36 r.Post("/upload", rp.AttachArtifact)
37 r.Delete("/{file}", rp.DeleteArtifact)
38 })
39 })
40 })
41 r.Get("/blob/{ref}/*", rp.Blob)
42 r.Get("/raw/{ref}/*", rp.RepoBlobRaw)
43
44 // intentionally doesn't use /* as this isn't
45 // a file path
46 r.Get("/archive/{ref}", rp.DownloadArchive)
47
48 r.Route("/fork", func(r chi.Router) {
49 r.Use(middleware.AuthMiddleware(rp.oauth))
50 r.Get("/", rp.ForkRepo)
51 r.Post("/", rp.ForkRepo)
52 r.With(mw.RepoPermissionMiddleware("repo:owner")).Route("/sync", func(r chi.Router) {
53 r.Post("/", rp.SyncRepoFork)
54 })
55 })
56
57 r.Route("/compare", func(r chi.Router) {
58 r.Get("/", rp.CompareNew) // start an new comparison
59
60 // we have to wildcard here since we want to support GitHub's compare syntax
61 // /compare/{ref1}...{ref2}
62 // for example:
63 // /compare/master...some/feature
64 // /compare/master...example.com:another/feature <- this is a fork
65 r.Get("/*", rp.Compare)
66 })
67
68 // label panel in issues/pulls/discussions/tasks
69 r.Route("/label", func(r chi.Router) {
70 r.Get("/", rp.LabelPanel)
71 r.Get("/edit", rp.EditLabelPanel)
72 })
73
74 // settings routes, needs auth
75 r.Group(func(r chi.Router) {
76 r.Use(middleware.AuthMiddleware(rp.oauth))
77 r.With(mw.RepoPermissionMiddleware("repo:settings")).Route("/settings", func(r chi.Router) {
78 r.Get("/", rp.Settings)
79 r.With(mw.RepoPermissionMiddleware("repo:owner")).Put("/base", rp.EditBaseSettings)
80 r.With(mw.RepoPermissionMiddleware("repo:owner")).Post("/spindle", rp.EditSpindle)
81 r.With(mw.RepoPermissionMiddleware("repo:owner")).Put("/label", rp.AddLabelDef)
82 r.With(mw.RepoPermissionMiddleware("repo:owner")).Delete("/label", rp.DeleteLabelDef)
83 r.With(mw.RepoPermissionMiddleware("repo:owner")).Post("/label/subscribe", rp.SubscribeLabel)
84 r.With(mw.RepoPermissionMiddleware("repo:owner")).Post("/label/unsubscribe", rp.UnsubscribeLabel)
85 r.With(mw.RepoPermissionMiddleware("repo:invite")).Put("/collaborator", rp.AddCollaborator)
86 r.With(mw.RepoPermissionMiddleware("repo:delete")).Delete("/delete", rp.DeleteRepo)
87 r.Put("/branches/default", rp.SetDefaultBranch)
88 r.Put("/secrets", rp.Secrets)
89 r.Delete("/secrets", rp.Secrets)
90 r.With(mw.RepoPermissionMiddleware("repo:owner")).Route("/hooks", func(r chi.Router) {
91 r.Get("/", rp.Webhooks)
92 r.Post("/", rp.AddWebhook)
93 r.Put("/{id}", rp.UpdateWebhook)
94 r.Delete("/{id}", rp.DeleteWebhook)
95 r.Post("/{id}/toggle", rp.ToggleWebhook)
96 r.Get("/{id}/deliveries", rp.WebhookDeliveries)
97 })
98 })
99 })
100
101 return r
102}