diff options
Diffstat (limited to 'internal/web/server.go')
| -rw-r--r-- | internal/web/server.go | 37 |
1 files changed, 29 insertions, 8 deletions
diff --git a/internal/web/server.go b/internal/web/server.go index 483663e..a7af06b 100644 --- a/internal/web/server.go +++ b/internal/web/server.go @@ -66,9 +66,10 @@ func hostname(h string) string { type ctxKey int const ( - ctxUser ctxKey = iota - ctxBlog // the blog a handler operates on (public page, or /b/{sub}/ management) - ctxHostSub // subdomain derived from the Host header + ctxUser ctxKey = iota + ctxBlog // the blog a handler operates on (public page, or /b/{sub}/ management) + ctxBlogStore // that blog's store, bound to its own database + ctxHostSub // subdomain derived from the Host header ) func currentUser(r *http.Request) *store.User { @@ -81,13 +82,33 @@ func currentBlog(r *http.Request) *store.Blog { return b } +// blogStore is the store of the blog in the context; only valid behind hostBlog or withBlog. +func blogStore(r *http.Request) *store.BlogStore { + bs, _ := r.Context().Value(ctxBlogStore).(*store.BlogStore) + return bs +} + // ---- middleware ---------------------------------------------------------- +// resolveBlog looks a subdomain up in the registry and opens its database. +func (s *Server) resolveBlog(r *http.Request, sub string) (*http.Request, error) { + blog, err := s.st.BlogBySubdomain(r.Context(), sub) + if err != nil { + return r, err + } + bs, err := s.st.Open(r.Context(), blog) + if err != nil { + return r, err + } + ctx := context.WithValue(r.Context(), ctxBlog, blog) + return r.WithContext(context.WithValue(ctx, ctxBlogStore, bs)), nil +} + // hostBlog resolves the blog named by the Host header into the context for public pages. func (s *Server) hostBlog(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { sub, _ := r.Context().Value(ctxHostSub).(string) - blog, err := s.st.BlogBySubdomain(r.Context(), sub) + r, err := s.resolveBlog(r, sub) if err != nil { if errors.Is(err, store.ErrNotFound) { s.plainError(w, http.StatusNotFound, "No blog here (yet).") @@ -96,7 +117,7 @@ func (s *Server) hostBlog(next http.HandlerFunc) http.HandlerFunc { s.serverError(w, err) return } - next(w, r.WithContext(context.WithValue(r.Context(), ctxBlog, blog))) + next(w, r) } } @@ -176,7 +197,7 @@ func (s *Server) requireAdmin(next http.HandlerFunc) http.HandlerFunc { func (s *Server) withBlog(next http.HandlerFunc) http.HandlerFunc { return s.requireAuth(func(w http.ResponseWriter, r *http.Request) { u := currentUser(r) - blog, err := s.st.BlogBySubdomain(r.Context(), r.PathValue("sub")) + r, err := s.resolveBlog(r, r.PathValue("sub")) if err != nil { if errors.Is(err, store.ErrNotFound) { http.NotFound(w, r) @@ -185,11 +206,11 @@ func (s *Server) withBlog(next http.HandlerFunc) http.HandlerFunc { s.serverError(w, err) return } - if blog.OwnerID != u.ID && !u.IsSuperadmin() { + if blog := currentBlog(r); blog.OwnerID != u.ID && !u.IsSuperadmin() { s.plainError(w, http.StatusForbidden, "This is not your blog.") return } - next(w, r.WithContext(context.WithValue(r.Context(), ctxBlog, blog))) + next(w, r) }) } |
