forked from tangled.org/core
this repo has no description
1package state 2 3import ( 4 "net/http" 5 "strings" 6 7 "github.com/go-chi/chi/v5" 8 "github.com/gorilla/sessions" 9 "tangled.sh/tangled.sh/core/appview/middleware" 10 oauth "tangled.sh/tangled.sh/core/appview/oauth/handler" 11 "tangled.sh/tangled.sh/core/appview/pulls" 12 "tangled.sh/tangled.sh/core/appview/repo" 13 "tangled.sh/tangled.sh/core/appview/settings" 14 "tangled.sh/tangled.sh/core/appview/state/userutil" 15) 16 17func (s *State) Router() http.Handler { 18 router := chi.NewRouter() 19 middleware := middleware.New( 20 s.oauth, 21 s.db, 22 s.enforcer, 23 s.repoResolver, 24 s.idResolver, 25 s.pages, 26 ) 27 28 router.HandleFunc("/*", func(w http.ResponseWriter, r *http.Request) { 29 pat := chi.URLParam(r, "*") 30 if strings.HasPrefix(pat, "did:") || strings.HasPrefix(pat, "@") { 31 s.UserRouter(&middleware).ServeHTTP(w, r) 32 } else { 33 // Check if the first path element is a valid handle without '@' or a flattened DID 34 pathParts := strings.SplitN(pat, "/", 2) 35 if len(pathParts) > 0 { 36 if userutil.IsHandleNoAt(pathParts[0]) { 37 // Redirect to the same path but with '@' prefixed to the handle 38 redirectPath := "@" + pat 39 http.Redirect(w, r, "/"+redirectPath, http.StatusFound) 40 return 41 } else if userutil.IsFlattenedDid(pathParts[0]) { 42 // Redirect to the unflattened DID version 43 unflattenedDid := userutil.UnflattenDid(pathParts[0]) 44 var redirectPath string 45 if len(pathParts) > 1 { 46 redirectPath = unflattenedDid + "/" + pathParts[1] 47 } else { 48 redirectPath = unflattenedDid 49 } 50 http.Redirect(w, r, "/"+redirectPath, http.StatusFound) 51 return 52 } 53 } 54 s.StandardRouter(&middleware).ServeHTTP(w, r) 55 } 56 }) 57 58 return router 59} 60 61func (s *State) UserRouter(mw *middleware.Middleware) http.Handler { 62 r := chi.NewRouter() 63 64 // strip @ from user 65 r.Use(middleware.StripLeadingAt) 66 67 r.With(mw.ResolveIdent()).Route("/{user}", func(r chi.Router) { 68 r.Get("/", s.Profile) 69 70 r.With(mw.ResolveRepo()).Route("/{repo}", func(r chi.Router) { 71 r.Use(mw.GoImport()) 72 73 r.Mount("/", s.RepoRouter(mw)) 74 75 r.Mount("/pulls", s.PullsRouter(mw)) 76 77 // These routes get proxied to the knot 78 r.Get("/info/refs", s.InfoRefs) 79 r.Post("/git-upload-pack", s.UploadPack) 80 r.Post("/git-receive-pack", s.ReceivePack) 81 82 }) 83 }) 84 85 r.NotFound(func(w http.ResponseWriter, r *http.Request) { 86 s.pages.Error404(w) 87 }) 88 89 return r 90} 91 92func (s *State) StandardRouter(mw *middleware.Middleware) http.Handler { 93 r := chi.NewRouter() 94 95 r.Handle("/static/*", s.pages.Static()) 96 97 r.Get("/", s.Timeline) 98 99 r.With(middleware.AuthMiddleware(s.oauth)).Post("/logout", s.Logout) 100 101 r.Route("/knots", func(r chi.Router) { 102 r.Use(middleware.AuthMiddleware(s.oauth)) 103 r.Get("/", s.Knots) 104 r.Post("/key", s.RegistrationKey) 105 106 r.Route("/{domain}", func(r chi.Router) { 107 r.Post("/init", s.InitKnotServer) 108 r.Get("/", s.KnotServerInfo) 109 r.Route("/member", func(r chi.Router) { 110 r.Use(mw.KnotOwner()) 111 r.Get("/", s.ListMembers) 112 r.Put("/", s.AddMember) 113 r.Delete("/", s.RemoveMember) 114 }) 115 }) 116 }) 117 118 r.Route("/repo", func(r chi.Router) { 119 r.Route("/new", func(r chi.Router) { 120 r.Use(middleware.AuthMiddleware(s.oauth)) 121 r.Get("/", s.NewRepo) 122 r.Post("/", s.NewRepo) 123 }) 124 // r.Post("/import", s.ImportRepo) 125 }) 126 127 r.With(middleware.AuthMiddleware(s.oauth)).Route("/follow", func(r chi.Router) { 128 r.Post("/", s.Follow) 129 r.Delete("/", s.Follow) 130 }) 131 132 r.With(middleware.AuthMiddleware(s.oauth)).Route("/star", func(r chi.Router) { 133 r.Post("/", s.Star) 134 r.Delete("/", s.Star) 135 }) 136 137 r.Route("/profile", func(r chi.Router) { 138 r.Use(middleware.AuthMiddleware(s.oauth)) 139 r.Get("/edit-bio", s.EditBioFragment) 140 r.Get("/edit-pins", s.EditPinsFragment) 141 r.Post("/bio", s.UpdateProfileBio) 142 r.Post("/pins", s.UpdateProfilePins) 143 }) 144 145 r.Mount("/settings", s.SettingsRouter()) 146 r.Mount("/", s.OAuthRouter()) 147 148 r.Get("/keys/{user}", s.Keys) 149 150 r.NotFound(func(w http.ResponseWriter, r *http.Request) { 151 s.pages.Error404(w) 152 }) 153 return r 154} 155 156func (s *State) OAuthRouter() http.Handler { 157 store := sessions.NewCookieStore([]byte(s.config.Core.CookieSecret)) 158 oauth := oauth.New(s.config, s.pages, s.idResolver, s.db, store, s.oauth, s.enforcer, s.posthog) 159 return oauth.Router() 160} 161 162func (s *State) SettingsRouter() http.Handler { 163 settings := &settings.Settings{ 164 Db: s.db, 165 OAuth: s.oauth, 166 Pages: s.pages, 167 Config: s.config, 168 } 169 170 return settings.Router() 171} 172 173func (s *State) PullsRouter(mw *middleware.Middleware) http.Handler { 174 pulls := pulls.New(s.oauth, s.repoResolver, s.pages, s.idResolver, s.db, s.config) 175 return pulls.Router(mw) 176} 177 178func (s *State) RepoRouter(mw *middleware.Middleware) http.Handler { 179 repo := repo.New(s.oauth, s.repoResolver, s.pages, s.idResolver, s.db, s.config, s.posthog, s.enforcer) 180 return repo.Router(mw) 181}