[bugfix] Use SignatureCheck middleware for web profile endpoints too (#1451)

This commit is contained in:
tobi 2023-02-07 14:57:09 +01:00 committed by GitHub
parent 0ed50c172e
commit 4e4da19720
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 30 additions and 29 deletions

View file

@ -191,7 +191,7 @@ var Start action.GTSAction = func(ctx context.Context) error {
wellKnownModule = api.NewWellKnown(processor) // .well-known endpoints wellKnownModule = api.NewWellKnown(processor) // .well-known endpoints
nodeInfoModule = api.NewNodeInfo(processor) // nodeinfo endpoint nodeInfoModule = api.NewNodeInfo(processor) // nodeinfo endpoint
activityPubModule = api.NewActivityPub(dbService, processor) // ActivityPub endpoints activityPubModule = api.NewActivityPub(dbService, processor) // ActivityPub endpoints
webModule = web.New(processor) // web pages + user profiles + settings panels etc webModule = web.New(dbService, processor) // web pages + user profiles + settings panels etc
) )
// create required middleware // create required middleware

View file

@ -129,7 +129,7 @@ var Start action.GTSAction = func(ctx context.Context) error {
wellKnownModule = api.NewWellKnown(processor) // .well-known endpoints wellKnownModule = api.NewWellKnown(processor) // .well-known endpoints
nodeInfoModule = api.NewNodeInfo(processor) // nodeinfo endpoint nodeInfoModule = api.NewNodeInfo(processor) // nodeinfo endpoint
activityPubModule = api.NewActivityPub(dbService, processor) // ActivityPub endpoints activityPubModule = api.NewActivityPub(dbService, processor) // ActivityPub endpoints
webModule = web.New(processor) // web pages + user profiles + settings panels etc webModule = web.New(dbService, processor) // web pages + user profiles + settings panels etc
) )
// these should be routed in order // these should be routed in order

View file

@ -19,13 +19,17 @@
package web package web
import ( import (
"context"
"net/http" "net/http"
"net/url"
"path/filepath" "path/filepath"
"codeberg.org/gruf/go-cache/v3" "codeberg.org/gruf/go-cache/v3"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/superseriousbusiness/gotosocial/internal/config" "github.com/superseriousbusiness/gotosocial/internal/config"
"github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/log" "github.com/superseriousbusiness/gotosocial/internal/log"
"github.com/superseriousbusiness/gotosocial/internal/middleware"
"github.com/superseriousbusiness/gotosocial/internal/processing" "github.com/superseriousbusiness/gotosocial/internal/processing"
"github.com/superseriousbusiness/gotosocial/internal/router" "github.com/superseriousbusiness/gotosocial/internal/router"
"github.com/superseriousbusiness/gotosocial/internal/uris" "github.com/superseriousbusiness/gotosocial/internal/uris"
@ -33,10 +37,10 @@ import (
const ( const (
confirmEmailPath = "/" + uris.ConfirmEmailPath confirmEmailPath = "/" + uris.ConfirmEmailPath
profilePath = "/@:" + usernameKey profileGroupPath = "/@:" + usernameKey
customCSSPath = profilePath + "/custom.css" statusPath = "/statuses/:" + statusIDKey // leave out the '/@:username' prefix as this will be served within the profile group
rssFeedPath = profilePath + "/feed.rss" customCSSPath = profileGroupPath + "/custom.css"
statusPath = profilePath + "/statuses/:" + statusIDKey rssFeedPath = profileGroupPath + "/feed.rss"
assetsPathPrefix = "/assets" assetsPathPrefix = "/assets"
distPathPrefix = assetsPathPrefix + "/dist" distPathPrefix = assetsPathPrefix + "/dist"
settingsPathPrefix = "/settings" settingsPathPrefix = "/settings"
@ -57,55 +61,52 @@ const (
) )
type Module struct { type Module struct {
processor processing.Processor processor processing.Processor
eTagCache cache.Cache[string, eTagCacheEntry] eTagCache cache.Cache[string, eTagCacheEntry]
isURIBlocked func(context.Context, *url.URL) (bool, db.Error)
} }
func New(processor processing.Processor) *Module { func New(db db.DB, processor processing.Processor) *Module {
return &Module{ return &Module{
processor: processor, processor: processor,
eTagCache: newETagCache(), eTagCache: newETagCache(),
isURIBlocked: db.IsURIBlocked,
} }
} }
func (m *Module) Route(r router.Router, mi ...gin.HandlerFunc) { func (m *Module) Route(r router.Router, mi ...gin.HandlerFunc) {
// serve static files from assets dir at /assets // Group all static files from assets dir at /assets,
assetsGroup := r.AttachGroup(assetsPathPrefix) // so that they can use the same cache control middleware.
webAssetsAbsFilePath, err := filepath.Abs(config.GetWebAssetBaseDir()) webAssetsAbsFilePath, err := filepath.Abs(config.GetWebAssetBaseDir())
if err != nil { if err != nil {
log.Panicf("error getting absolute path of assets dir: %s", err) log.Panicf("error getting absolute path of assets dir: %s", err)
} }
fs := fileSystem{http.Dir(webAssetsAbsFilePath)} fs := fileSystem{http.Dir(webAssetsAbsFilePath)}
assetsGroup := r.AttachGroup(assetsPathPrefix)
// use the cache middleware on all handlers in this group
assetsGroup.Use(m.assetsCacheControlMiddleware(fs)) assetsGroup.Use(m.assetsCacheControlMiddleware(fs))
assetsGroup.Use(mi...) assetsGroup.Use(mi...)
// serve static file system in the root of this group,
// will end up being something like "/assets/"
assetsGroup.StaticFS("/", fs) assetsGroup.StaticFS("/", fs)
/* // handlers that serve profiles and statuses should use the SignatureCheck
Attach individual web handlers which require no specific middlewares // middleware, so that requests with content-type application/activity+json
*/ // can still be served
profileGroup := r.AttachGroup(profileGroupPath)
profileGroup.Use(mi...)
profileGroup.Use(middleware.SignatureCheck(m.isURIBlocked), middleware.CacheControl("no-store"))
profileGroup.Handle(http.MethodGet, "", m.profileGETHandler) // use empty path here since it's the base of the group
profileGroup.Handle(http.MethodGet, statusPath, m.threadGETHandler)
// Attach individual web handlers which require no specific middlewares
r.AttachHandler(http.MethodGet, "/", m.baseHandler) // front-page r.AttachHandler(http.MethodGet, "/", m.baseHandler) // front-page
r.AttachHandler(http.MethodGet, settingsPathPrefix, m.SettingsPanelHandler) r.AttachHandler(http.MethodGet, settingsPathPrefix, m.SettingsPanelHandler)
r.AttachHandler(http.MethodGet, settingsPanelGlob, m.SettingsPanelHandler) r.AttachHandler(http.MethodGet, settingsPanelGlob, m.SettingsPanelHandler)
r.AttachHandler(http.MethodGet, profilePath, m.profileGETHandler)
r.AttachHandler(http.MethodGet, customCSSPath, m.customCSSGETHandler) r.AttachHandler(http.MethodGet, customCSSPath, m.customCSSGETHandler)
r.AttachHandler(http.MethodGet, rssFeedPath, m.rssFeedGETHandler) r.AttachHandler(http.MethodGet, rssFeedPath, m.rssFeedGETHandler)
r.AttachHandler(http.MethodGet, statusPath, m.threadGETHandler)
r.AttachHandler(http.MethodGet, confirmEmailPath, m.confirmEmailGETHandler) r.AttachHandler(http.MethodGet, confirmEmailPath, m.confirmEmailGETHandler)
r.AttachHandler(http.MethodGet, robotsPath, m.robotsGETHandler) r.AttachHandler(http.MethodGet, robotsPath, m.robotsGETHandler)
r.AttachHandler(http.MethodGet, domainBlockListPath, m.domainBlockListGETHandler) r.AttachHandler(http.MethodGet, domainBlockListPath, m.domainBlockListGETHandler)
/* // Attach redirects from old endpoints to current ones for backwards compatibility
Attach redirects from old endpoints to current ones for backwards compatibility
*/
r.AttachHandler(http.MethodGet, "/auth/edit", func(c *gin.Context) { c.Redirect(http.StatusMovedPermanently, userPanelPath) }) r.AttachHandler(http.MethodGet, "/auth/edit", func(c *gin.Context) { c.Redirect(http.StatusMovedPermanently, userPanelPath) })
r.AttachHandler(http.MethodGet, "/user", func(c *gin.Context) { c.Redirect(http.StatusMovedPermanently, userPanelPath) }) r.AttachHandler(http.MethodGet, "/user", func(c *gin.Context) { c.Redirect(http.StatusMovedPermanently, userPanelPath) })
r.AttachHandler(http.MethodGet, "/admin", func(c *gin.Context) { c.Redirect(http.StatusMovedPermanently, adminPanelPath) }) r.AttachHandler(http.MethodGet, "/admin", func(c *gin.Context) { c.Redirect(http.StatusMovedPermanently, adminPanelPath) })