forked from
tangled.org/core
fork
Configure Feed
Select the types of activity you want to include in your feed.
this repo has no description
fork
Configure Feed
Select the types of activity you want to include in your feed.
1package state
2
3import (
4 "net/http"
5 "strings"
6
7 "github.com/go-chi/chi/v5"
8 "tangled.sh/tangled.sh/core/appview/state/userutil"
9)
10
11func (s *State) Router() http.Handler {
12 router := chi.NewRouter()
13
14 router.HandleFunc("/*", func(w http.ResponseWriter, r *http.Request) {
15 pat := chi.URLParam(r, "*")
16 if strings.HasPrefix(pat, "did:") || strings.HasPrefix(pat, "@") {
17 s.UserRouter().ServeHTTP(w, r)
18 } else {
19 // Check if the first path element is a valid handle without '@' or a flattened DID
20 pathParts := strings.SplitN(pat, "/", 2)
21 if len(pathParts) > 0 {
22 if userutil.IsHandleNoAt(pathParts[0]) {
23 // Redirect to the same path but with '@' prefixed to the handle
24 redirectPath := "@" + pat
25 http.Redirect(w, r, "/"+redirectPath, http.StatusFound)
26 return
27 } else if userutil.IsFlattenedDid(pathParts[0]) {
28 // Redirect to the unflattened DID version
29 unflattenedDid := userutil.UnflattenDid(pathParts[0])
30 var redirectPath string
31 if len(pathParts) > 1 {
32 redirectPath = unflattenedDid + "/" + pathParts[1]
33 } else {
34 redirectPath = unflattenedDid
35 }
36 http.Redirect(w, r, "/"+redirectPath, http.StatusFound)
37 return
38 }
39 }
40 s.StandardRouter().ServeHTTP(w, r)
41 }
42 })
43
44 return router
45}
46
47func (s *State) UserRouter() http.Handler {
48 r := chi.NewRouter()
49
50 // strip @ from user
51 r.Use(StripLeadingAt)
52
53 r.With(ResolveIdent(s)).Route("/{user}", func(r chi.Router) {
54 r.Get("/", s.ProfilePage)
55 r.With(ResolveRepo(s)).Route("/{repo}", func(r chi.Router) {
56 r.Get("/", s.RepoIndex)
57 r.Get("/commits/{ref}", s.RepoLog)
58 r.Route("/tree/{ref}", func(r chi.Router) {
59 r.Get("/", s.RepoIndex)
60 r.Get("/*", s.RepoTree)
61 })
62 r.Get("/commit/{ref}", s.RepoCommit)
63 r.Get("/branches", s.RepoBranches)
64 r.Get("/tags", s.RepoTags)
65 r.Get("/blob/{ref}/*", s.RepoBlob)
66 r.Get("/blob/{ref}/raw/*", s.RepoBlobRaw)
67
68 r.Route("/issues", func(r chi.Router) {
69 r.Get("/", s.RepoIssues)
70 r.Get("/{issue}", s.RepoSingleIssue)
71
72 r.Group(func(r chi.Router) {
73 r.Use(AuthMiddleware(s))
74 r.Get("/new", s.NewIssue)
75 r.Post("/new", s.NewIssue)
76 r.Post("/{issue}/comment", s.NewIssueComment)
77 r.Route("/{issue}/comment/{comment_id}/", func(r chi.Router) {
78 r.Get("/", s.IssueComment)
79 r.Delete("/", s.DeleteIssueComment)
80 r.Get("/edit", s.EditIssueComment)
81 r.Post("/edit", s.EditIssueComment)
82 })
83 r.Post("/{issue}/close", s.CloseIssue)
84 r.Post("/{issue}/reopen", s.ReopenIssue)
85 })
86 })
87
88 r.Route("/fork", func(r chi.Router) {
89 r.Use(AuthMiddleware(s))
90 r.Get("/", s.ForkRepo)
91 r.Post("/", s.ForkRepo)
92 })
93
94 r.Route("/pulls", func(r chi.Router) {
95 r.Get("/", s.RepoPulls)
96 r.With(AuthMiddleware(s)).Route("/new", func(r chi.Router) {
97 r.Get("/", s.NewPull)
98 r.Get("/patch-upload", s.PatchUploadFragment)
99 r.Get("/compare-branches", s.CompareBranchesFragment)
100 r.Get("/compare-forks", s.CompareForksFragment)
101 r.Get("/fork-branches", s.CompareForksBranchesFragment)
102 r.Post("/", s.NewPull)
103 })
104
105 r.Route("/{pull}", func(r chi.Router) {
106 r.Use(ResolvePull(s))
107 r.Get("/", s.RepoSinglePull)
108
109 r.Route("/round/{round}", func(r chi.Router) {
110 r.Get("/", s.RepoPullPatch)
111 r.Get("/actions", s.PullActions)
112 r.With(AuthMiddleware(s)).Route("/comment", func(r chi.Router) {
113 r.Get("/", s.PullComment)
114 r.Post("/", s.PullComment)
115 })
116 })
117
118 r.Route("/round/{round}.patch", func(r chi.Router) {
119 r.Get("/", s.RepoPullPatchRaw)
120 })
121
122 r.Group(func(r chi.Router) {
123 r.Use(AuthMiddleware(s))
124 r.Route("/resubmit", func(r chi.Router) {
125 r.Get("/", s.ResubmitPull)
126 r.Post("/", s.ResubmitPull)
127 })
128 r.Post("/close", s.ClosePull)
129 r.Post("/reopen", s.ReopenPull)
130 // collaborators only
131 r.Group(func(r chi.Router) {
132 r.Use(RepoPermissionMiddleware(s, "repo:push"))
133 r.Post("/merge", s.MergePull)
134 // maybe lock, etc.
135 })
136 })
137 })
138 })
139
140 // These routes get proxied to the knot
141 r.Get("/info/refs", s.InfoRefs)
142 r.Post("/git-upload-pack", s.UploadPack)
143
144 // settings routes, needs auth
145 r.Group(func(r chi.Router) {
146 r.Use(AuthMiddleware(s))
147 // repo description can only be edited by owner
148 r.With(RepoPermissionMiddleware(s, "repo:owner")).Route("/description", func(r chi.Router) {
149 r.Put("/", s.RepoDescription)
150 r.Get("/", s.RepoDescription)
151 r.Get("/edit", s.RepoDescriptionEdit)
152 })
153 r.With(RepoPermissionMiddleware(s, "repo:settings")).Route("/settings", func(r chi.Router) {
154 r.Get("/", s.RepoSettings)
155 r.With(RepoPermissionMiddleware(s, "repo:invite")).Put("/collaborator", s.AddCollaborator)
156 r.With(RepoPermissionMiddleware(s, "repo:delete")).Delete("/delete", s.DeleteRepo)
157 r.Put("/branches/default", s.SetDefaultBranch)
158 })
159 })
160 })
161 })
162
163 r.NotFound(func(w http.ResponseWriter, r *http.Request) {
164 s.pages.Error404(w)
165 })
166
167 return r
168}
169
170func (s *State) StandardRouter() http.Handler {
171 r := chi.NewRouter()
172
173 r.Handle("/static/*", s.pages.Static())
174
175 r.Get("/", s.Timeline)
176
177 r.With(AuthMiddleware(s)).Post("/logout", s.Logout)
178
179 r.Route("/login", func(r chi.Router) {
180 r.Get("/", s.Login)
181 r.Post("/", s.Login)
182 })
183
184 r.Route("/knots", func(r chi.Router) {
185 r.Use(AuthMiddleware(s))
186 r.Get("/", s.Knots)
187 r.Post("/key", s.RegistrationKey)
188
189 r.Route("/{domain}", func(r chi.Router) {
190 r.Post("/init", s.InitKnotServer)
191 r.Get("/", s.KnotServerInfo)
192 r.Route("/member", func(r chi.Router) {
193 r.Use(KnotOwner(s))
194 r.Get("/", s.ListMembers)
195 r.Put("/", s.AddMember)
196 r.Delete("/", s.RemoveMember)
197 })
198 })
199 })
200
201 r.Route("/repo", func(r chi.Router) {
202 r.Route("/new", func(r chi.Router) {
203 r.Use(AuthMiddleware(s))
204 r.Get("/", s.NewRepo)
205 r.Post("/", s.NewRepo)
206 })
207 // r.Post("/import", s.ImportRepo)
208 })
209
210 r.With(AuthMiddleware(s)).Route("/follow", func(r chi.Router) {
211 r.Post("/", s.Follow)
212 r.Delete("/", s.Follow)
213 })
214
215 r.With(AuthMiddleware(s)).Route("/star", func(r chi.Router) {
216 r.Post("/", s.Star)
217 r.Delete("/", s.Star)
218 })
219
220 r.Route("/settings", func(r chi.Router) {
221 r.Use(AuthMiddleware(s))
222 r.Get("/", s.Settings)
223 r.Put("/keys", s.SettingsKeys)
224 r.Delete("/keys", s.SettingsKeys)
225 r.Put("/emails", s.SettingsEmails)
226 r.Delete("/emails", s.SettingsEmails)
227 r.Get("/emails/verify", s.SettingsEmailsVerify)
228 r.Post("/emails/verify/resend", s.SettingsEmailsVerifyResend)
229 r.Post("/emails/primary", s.SettingsEmailsPrimary)
230 })
231
232 r.Get("/keys/{user}", s.Keys)
233
234 r.NotFound(func(w http.ResponseWriter, r *http.Request) {
235 s.pages.Error404(w)
236 })
237 return r
238}