From aa4cf401a077fb5d8f334041e1654186036c2323 Mon Sep 17 00:00:00 2001 From: Amy Gale Ruth Bowersox Date: Sun, 7 Dec 2025 21:54:38 -0700 Subject: [PATCH] moved more of the common preliminaries for conferences into middleware --- conference.go | 62 ------------------------------------------------ main.go | 15 ++++++------ ui/middleware.go | 56 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 61 insertions(+), 72 deletions(-) diff --git a/conference.go b/conference.go index 6b4903a..ccdb288 100644 --- a/conference.go +++ b/conference.go @@ -23,52 +23,6 @@ import ( "git.erbosoft.com/amy/amsterdam/ui" ) -// conferencesPrequel consolidates some of the basic conference checks into one function. -func conferencesPrequel(ctxt ui.AmContext) (string, any, error) { - comm := ctxt.CurrentCommunity() // set by middleware - b, err := database.AmTestService(comm, "Conference") - if err != nil { - return ui.ErrorPage(ctxt, err) - } - if !b { - ctxt.SetRC(http.StatusNotFound) - return ui.ErrorPage(ctxt, errors.New("this community does not use conferencing services")) - } - if comm.MembersOnly && !ctxt.IsMember() && !ctxt.TestPermission("Community.NoJoinRequired") { - ctxt.SetRC(http.StatusForbidden) - return ui.ErrorPage(ctxt, errors.New("you are not a member of this community")) - } - if !comm.TestPermission("Community.Read", ctxt.EffectiveLevel()) { - ctxt.SetRC(http.StatusForbidden) - return ui.ErrorPage(ctxt, errors.New("you are not authorized access to conferences")) - } - return "", nil, nil -} - -// singleConferencePrequel consolidates some of the basic conference checks into one function. -func singleConferencePrequel(ctxt ui.AmContext) (string, any, error) { - cmd, arg, err := conferencesPrequel(ctxt) - if cmd != "" { - return cmd, arg, err - } - var conf *database.Conference - conf, err = database.AmGetConferenceByAliasInCommunity(ctxt.CurrentCommunity().Id, ctxt.URLParam("confid")) - if err != nil { - return ui.ErrorPage(ctxt, err) - } - m, lvl, err := conf.Membership(ctxt.CurrentUser()) - if err != nil { - return ui.ErrorPage(ctxt, err) - } - myLevel := ctxt.EffectiveLevel() - if m && lvl > myLevel { - myLevel = lvl - } - ctxt.SetScratch("currentConference", conf) - ctxt.SetScratch("levelInConference", myLevel) - return "", nil, nil -} - /* Conferences displayes the list of conferences in a community. * Parameters: * ctxt - The AmContext for the request. @@ -78,10 +32,6 @@ func singleConferencePrequel(ctxt ui.AmContext) (string, any, error) { * Standard Go error status. */ func Conferences(ctxt ui.AmContext) (string, any, error) { - cmd, arg, err := conferencesPrequel(ctxt) - if cmd != "" { - return cmd, arg, err - } comm := ctxt.CurrentCommunity() ctxt.VarMap().Set("commName", comm.Name) ctxt.VarMap().Set("commAlias", comm.Alias) @@ -104,10 +54,6 @@ func Conferences(ctxt ui.AmContext) (string, any, error) { * Standard Go error status. */ func Topics(ctxt ui.AmContext) (string, any, error) { - cmd, arg, err := singleConferencePrequel(ctxt) - if cmd != "" { - return cmd, arg, err - } prefs, err := ctxt.CurrentUser().Prefs() if err != nil { return ui.ErrorPage(ctxt, err) @@ -176,10 +122,6 @@ func Topics(ctxt ui.AmContext) (string, any, error) { * Standard Go error status. */ func NewTopicForm(ctxt ui.AmContext) (string, any, error) { - cmd, arg, err := singleConferencePrequel(ctxt) - if cmd != "" { - return cmd, arg, err - } comm := ctxt.CurrentCommunity() conf := ctxt.GetScratch("currentConference").(*database.Conference) myLevel := ctxt.GetScratch("levelInConference").(uint16) @@ -217,10 +159,6 @@ func NewTopicForm(ctxt ui.AmContext) (string, any, error) { * Standard Go error status. */ func NewTopic(ctxt ui.AmContext) (string, any, error) { - cmd, arg, err := singleConferencePrequel(ctxt) - if cmd != "" { - return cmd, arg, err - } comm := ctxt.CurrentCommunity() conf := ctxt.GetScratch("currentConference").(*database.Conference) myLevel := ctxt.GetScratch("levelInConference").(uint16) diff --git a/main.go b/main.go index bf6e11f..5e4d24b 100644 --- a/main.go +++ b/main.go @@ -42,11 +42,8 @@ func setupEcho() *echo.Echo { } else { log.Warn("WARNING: --debug-panic in effect - DO NOT use this in production!") } - e.Use(LogrusMiddleware) - e.Use(session.Middleware(ui.SessionStore)) - e.Use(ui.ContextCreator) - e.Use(ui.IPBanTest) - e.Use(ui.CookieLoginTest) + e.Use(LogrusMiddleware, session.Middleware(ui.SessionStore)) + e.Use(ui.ContextCreator, ui.IPBanTest, ui.CookieLoginTest) fn := ui.AmWrap(NotImplPage) e.GET("/TODO/*", fn) @@ -79,6 +76,7 @@ func setupEcho() *echo.Echo { e.POST("/create_comm", ui.AmWrap(CreateCommunity)) e.POST("/attachment_upload", ui.AmWrap(AttachmentUpload)) + // community group commGroup := e.Group("/comm/:cid", ui.SetCommunity) commGroup.GET("/profile", ui.AmWrap(ShowCommunity)) commGroup.GET("/join", ui.AmWrap(JoinCommunity)) @@ -93,9 +91,10 @@ func setupEcho() *echo.Echo { commGroup.GET("/admin/logo", ui.AmWrap(CommunityLogoForm)) commGroup.POST("/admin/logo", ui.AmWrap(EditCommunityLogo)) - commGroup.GET("/conf", ui.AmWrap(Conferences)) - confGroup := commGroup.Group("/conf/:confid") - confGroup.GET("", ui.AmWrap(Topics)) + // conference group + commGroup.GET("/conf", ui.AmWrap(Conferences), ui.ValidateConference) + confGroup := commGroup.Group("/conf/:confid", ui.ValidateConference, ui.SetConference) + confGroup.GET("/", ui.AmWrap(Topics)) confGroup.GET("/new_topic", ui.AmWrap(NewTopicForm)) confGroup.POST("/new_topic", ui.AmWrap(NewTopic)) diff --git a/ui/middleware.go b/ui/middleware.go index cff5452..e6281dc 100644 --- a/ui/middleware.go +++ b/ui/middleware.go @@ -11,6 +11,7 @@ package ui import ( + "errors" "net/http" "net/url" @@ -20,6 +21,12 @@ import ( log "github.com/sirupsen/logrus" ) +// middlewareErrorPage is a shortcut to displaying an ErrorPage from middleware. +func middlewareErrorPage(c echo.Context, ctxt AmContext, err error) error { + cmd, data, _ := ErrorPage(ctxt, err) + return AmSendPageData(c, ctxt, cmd, data) +} + // IPBanTest is middleware that handles the IP banning. func IPBanTest(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { @@ -80,10 +87,55 @@ func SetCommunity(next echo.HandlerFunc) echo.HandlerFunc { err := ctxt.SetCommunityContext(ctxt.URLParam("cid")) if err != nil { ctxt.SetRC(http.StatusNotFound) - cmd, data, _ := ErrorPage(ctxt, err) - return AmSendPageData(c, ctxt, cmd, data) + return middlewareErrorPage(c, ctxt, err) } ctxt.SetLeftMenu("community") return next(c) } } + +// ValidateConference is middleware that validates the user has access to the community's conference facility. +func ValidateConference(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + ctxt := AmContextFromEchoContext(c) + comm := ctxt.CurrentCommunity() // set by middleware + b, err := database.AmTestService(comm, "Conference") + if err != nil { + return middlewareErrorPage(c, ctxt, err) + } + if !b { + ctxt.SetRC(http.StatusNotFound) + return middlewareErrorPage(c, ctxt, errors.New("this community does not use conferencing services")) + } + if comm.MembersOnly && !ctxt.IsMember() && !ctxt.TestPermission("Community.NoJoinRequired") { + ctxt.SetRC(http.StatusForbidden) + return middlewareErrorPage(c, ctxt, errors.New("you are not a member of this community")) + } + if !comm.TestPermission("Community.Read", ctxt.EffectiveLevel()) { + ctxt.SetRC(http.StatusForbidden) + return middlewareErrorPage(c, ctxt, errors.New("you are not authorized access to conferences")) + } + return next(c) + } +} + +func SetConference(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + ctxt := AmContextFromEchoContext(c) + conf, err := database.AmGetConferenceByAliasInCommunity(ctxt.CurrentCommunity().Id, ctxt.URLParam("confid")) + if err != nil { + return middlewareErrorPage(c, ctxt, err) + } + m, lvl, err := conf.Membership(ctxt.CurrentUser()) + if err != nil { + return middlewareErrorPage(c, ctxt, err) + } + myLevel := ctxt.EffectiveLevel() + if m && lvl > myLevel { + myLevel = lvl + } + ctxt.SetScratch("currentConference", conf) + ctxt.SetScratch("levelInConference", myLevel) + return next(c) + } +}