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