Move UUID validation from multiple places into a middleware func
This commit is contained in:
parent
3fddd78ebf
commit
a060d94cb5
37
handlers.go
37
handlers.go
|
@ -4,6 +4,7 @@ import (
|
|||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
|
@ -37,6 +38,8 @@ type pagination struct {
|
|||
Limit int `json:"limit"`
|
||||
}
|
||||
|
||||
var reUUID = regexp.MustCompile("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$")
|
||||
|
||||
// registerHandlers registers HTTP handlers.
|
||||
func registerHandlers(e *echo.Echo) {
|
||||
e.GET("/", handleIndexPage)
|
||||
|
@ -97,12 +100,18 @@ func registerHandlers(e *echo.Echo) {
|
|||
e.DELETE("/api/templates/:id", handleDeleteTemplate)
|
||||
|
||||
// Subscriber facing views.
|
||||
e.GET("/subscription/:campUUID/:subUUID", handleSubscriptionPage)
|
||||
e.POST("/subscription/:campUUID/:subUUID", handleSubscriptionPage)
|
||||
e.POST("/subscription/export/:subUUID", handleSelfExportSubscriberData)
|
||||
e.POST("/subscription/wipe/:subUUID", handleWipeSubscriberData)
|
||||
e.GET("/link/:linkUUID/:campUUID/:subUUID", handleLinkRedirect)
|
||||
e.GET("/campaign/:campUUID/:subUUID/px.png", handleRegisterCampaignView)
|
||||
e.GET("/subscription/:campUUID/:subUUID", validateUUID(handleSubscriptionPage,
|
||||
"campUUID", "subUUID"))
|
||||
e.POST("/subscription/:campUUID/:subUUID", validateUUID(handleSubscriptionPage,
|
||||
"campUUID", "subUUID"))
|
||||
e.POST("/subscription/export/:subUUID", validateUUID(handleSelfExportSubscriberData,
|
||||
"subUUID"))
|
||||
e.POST("/subscription/wipe/:subUUID", validateUUID(handleWipeSubscriberData,
|
||||
"subUUID"))
|
||||
e.GET("/link/:linkUUID/:campUUID/:subUUID", validateUUID(handleLinkRedirect,
|
||||
"linkUUID", "campUUID", "subUUID"))
|
||||
e.GET("/campaign/:campUUID/:subUUID/px.png", validateUUID(handleRegisterCampaignView,
|
||||
"campUUID", "subUUID"))
|
||||
|
||||
// Static views.
|
||||
e.GET("/lists", handleIndexPage)
|
||||
|
@ -130,6 +139,20 @@ func handleIndexPage(c echo.Context) error {
|
|||
return c.String(http.StatusOK, string(b))
|
||||
}
|
||||
|
||||
// validateUUID validates the UUID string format for a given set of params.
|
||||
func validateUUID(next echo.HandlerFunc, params ...string) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
for _, p := range params {
|
||||
if !reUUID.MatchString(c.Param(p)) {
|
||||
return c.Render(http.StatusBadRequest, "message",
|
||||
makeMsgTpl("Invalid request", "",
|
||||
`One or more UUIDs in the request are invalid.`))
|
||||
}
|
||||
}
|
||||
return next(c)
|
||||
}
|
||||
}
|
||||
|
||||
// makeAttribsBlob takes a list of keys and values and creates
|
||||
// a JSON map out of them.
|
||||
func makeAttribsBlob(keys []string, vals []string) ([]byte, bool) {
|
||||
|
@ -154,7 +177,6 @@ func makeAttribsBlob(keys []string, vals []string) ([]byte, bool) {
|
|||
val = s
|
||||
}
|
||||
}
|
||||
|
||||
attribs[key] = val
|
||||
}
|
||||
|
||||
|
@ -162,7 +184,6 @@ func makeAttribsBlob(keys []string, vals []string) ([]byte, bool) {
|
|||
j, _ := json.Marshal(attribs)
|
||||
return j, true
|
||||
}
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
|
|
37
public.go
37
public.go
|
@ -7,7 +7,6 @@ import (
|
|||
"image/png"
|
||||
"io"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/knadh/listmonk/messenger"
|
||||
|
@ -52,8 +51,7 @@ type msgTpl struct {
|
|||
}
|
||||
|
||||
var (
|
||||
regexValidUUID = regexp.MustCompile("^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$")
|
||||
pixelPNG = drawTransparentImage(3, 14)
|
||||
pixelPNG = drawTransparentImage(3, 14)
|
||||
)
|
||||
|
||||
// Render executes and renders a template for echo.
|
||||
|
@ -83,14 +81,6 @@ func handleSubscriptionPage(c echo.Context) error {
|
|||
out.AllowExport = app.Constants.Privacy.AllowExport
|
||||
out.AllowWipe = app.Constants.Privacy.AllowWipe
|
||||
|
||||
if !regexValidUUID.MatchString(campUUID) ||
|
||||
!regexValidUUID.MatchString(subUUID) {
|
||||
return c.Render(http.StatusBadRequest, "message",
|
||||
makeMsgTpl("Invalid request", "",
|
||||
`The unsubscription request contains invalid IDs.
|
||||
Please follow the correct link.`))
|
||||
}
|
||||
|
||||
// Unsubscribe.
|
||||
if unsub {
|
||||
// Is blacklisting allowed?
|
||||
|
@ -119,12 +109,6 @@ func handleLinkRedirect(c echo.Context) error {
|
|||
campUUID = c.Param("campUUID")
|
||||
subUUID = c.Param("subUUID")
|
||||
)
|
||||
if !regexValidUUID.MatchString(linkUUID) ||
|
||||
!regexValidUUID.MatchString(campUUID) ||
|
||||
!regexValidUUID.MatchString(subUUID) {
|
||||
return c.Render(http.StatusBadRequest, "message",
|
||||
makeMsgTpl("Invalid link", "", "The link you clicked is invalid."))
|
||||
}
|
||||
|
||||
var url string
|
||||
if err := app.Queries.RegisterLinkClick.Get(&url, linkUUID, campUUID, subUUID); err != nil {
|
||||
|
@ -146,13 +130,9 @@ func handleRegisterCampaignView(c echo.Context) error {
|
|||
campUUID = c.Param("campUUID")
|
||||
subUUID = c.Param("subUUID")
|
||||
)
|
||||
if regexValidUUID.MatchString(campUUID) &&
|
||||
regexValidUUID.MatchString(subUUID) {
|
||||
if _, err := app.Queries.RegisterCampaignView.Exec(campUUID, subUUID); err != nil {
|
||||
app.Logger.Printf("error registering campaign view: %s", err)
|
||||
}
|
||||
if _, err := app.Queries.RegisterCampaignView.Exec(campUUID, subUUID); err != nil {
|
||||
app.Logger.Printf("error registering campaign view: %s", err)
|
||||
}
|
||||
|
||||
c.Response().Header().Set("Cache-Control", "no-cache")
|
||||
return c.Blob(http.StatusOK, "image/png", pixelPNG)
|
||||
}
|
||||
|
@ -166,12 +146,6 @@ func handleSelfExportSubscriberData(c echo.Context) error {
|
|||
app = c.Get("app").(*App)
|
||||
subUUID = c.Param("subUUID")
|
||||
)
|
||||
if !regexValidUUID.MatchString(subUUID) {
|
||||
return c.Render(http.StatusInternalServerError, "message",
|
||||
makeMsgTpl("Invalid request", "",
|
||||
"The subscriber ID is invalid."))
|
||||
}
|
||||
|
||||
// Is export allowed?
|
||||
if !app.Constants.Privacy.AllowExport {
|
||||
return c.Render(http.StatusBadRequest, "message",
|
||||
|
@ -230,11 +204,6 @@ func handleWipeSubscriberData(c echo.Context) error {
|
|||
app = c.Get("app").(*App)
|
||||
subUUID = c.Param("subUUID")
|
||||
)
|
||||
if !regexValidUUID.MatchString(subUUID) {
|
||||
return c.Render(http.StatusInternalServerError, "message",
|
||||
makeMsgTpl("Invalid request", "",
|
||||
"The subscriber ID is invalid."))
|
||||
}
|
||||
|
||||
// Is wiping allowed?
|
||||
if !app.Constants.Privacy.AllowExport {
|
||||
|
|
Loading…
Reference in New Issue