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.RepoIndex)
13 r.Get("/feed.atom", rp.RepoAtomFeed)
14 r.Get("/commits/{ref}", rp.RepoLog)
15 r.Route("/tree/{ref}", func(r chi.Router) {
16 r.Get("/", rp.RepoIndex)
17 r.Get("/*", rp.RepoTree)
18 })
19 r.Get("/commit/{ref}", rp.RepoCommit)
20 r.Get("/branches", rp.RepoBranches)
21 r.Route("/tags", func(r chi.Router) {
22 r.Get("/", rp.RepoTags)
23 r.Route("/{tag}", func(r chi.Router) {
24 r.Get("/download/{file}", rp.DownloadArtifact)
25
26 // require repo:push to upload or delete artifacts
27 //
28 // additionally: only the uploader can truly delete an artifact
29 // (record+blob will live on their pds)
30 r.Group(func(r chi.Router) {
31 r.Use(middleware.AuthMiddleware(rp.oauth))
32 r.Use(mw.RepoPermissionMiddleware("repo:push"))
33 r.Post("/upload", rp.AttachArtifact)
34 r.Delete("/{file}", rp.DeleteArtifact)
35 })
36 })
37 })
38 r.Get("/blob/{ref}/*", rp.RepoBlob)
39 r.Get("/raw/{ref}/*", rp.RepoBlobRaw)
40
41 // intentionally doesn't use /* as this isn't
42 // a file path
43 r.Get("/archive/{ref}", rp.DownloadArchive)
44
45 r.Route("/fork", func(r chi.Router) {
46 r.Use(middleware.AuthMiddleware(rp.oauth))
47 r.Get("/", rp.ForkRepo)
48 r.Post("/", rp.ForkRepo)
49 r.With(mw.RepoPermissionMiddleware("repo:owner")).Route("/sync", func(r chi.Router) {
50 r.Post("/", rp.SyncRepoFork)
51 })
52 })
53
54 r.Route("/compare", func(r chi.Router) {
55 r.Get("/", rp.RepoCompareNew) // start an new comparison
56
57 // we have to wildcard here since we want to support GitHub's compare syntax
58 // /compare/{ref1}...{ref2}
59 // for example:
60 // /compare/master...some/feature
61 // /compare/master...example.com:another/feature <- this is a fork
62 r.Get("/{base}/{head}", rp.RepoCompare)
63 r.Get("/*", rp.RepoCompare)
64 })
65
66 // label panel in issues/pulls/discussions/tasks
67 r.Route("/label", func(r chi.Router) {
68 r.Get("/", rp.LabelPanel)
69 r.Get("/edit", rp.EditLabelPanel)
70 })
71
72 // settings routes, needs auth
73 r.Group(func(r chi.Router) {
74 r.Use(middleware.AuthMiddleware(rp.oauth))
75 // repo description can only be edited by owner
76 r.With(mw.RepoPermissionMiddleware("repo:owner")).Route("/description", func(r chi.Router) {
77 r.Put("/", rp.RepoDescription)
78 r.Get("/", rp.RepoDescription)
79 r.Get("/edit", rp.RepoDescriptionEdit)
80 })
81 r.With(mw.RepoPermissionMiddleware("repo:settings")).Route("/settings", func(r chi.Router) {
82 r.Get("/", rp.RepoSettings)
83 r.With(mw.RepoPermissionMiddleware("repo:owner")).Post("/spindle", rp.EditSpindle)
84 r.With(mw.RepoPermissionMiddleware("repo:owner")).Put("/label", rp.AddLabelDef)
85 r.With(mw.RepoPermissionMiddleware("repo:owner")).Delete("/label", rp.DeleteLabelDef)
86 r.With(mw.RepoPermissionMiddleware("repo:owner")).Post("/label/subscribe", rp.SubscribeLabel)
87 r.With(mw.RepoPermissionMiddleware("repo:owner")).Post("/label/unsubscribe", rp.UnsubscribeLabel)
88 r.With(mw.RepoPermissionMiddleware("repo:invite")).Put("/collaborator", rp.AddCollaborator)
89 r.With(mw.RepoPermissionMiddleware("repo:delete")).Delete("/delete", rp.DeleteRepo)
90 r.Put("/branches/default", rp.SetDefaultBranch)
91 r.Put("/secrets", rp.Secrets)
92 r.Delete("/secrets", rp.Secrets)
93 })
94 })
95
96 return r
97}