From 1b3151e8f36a1e3ecbebded0348eaaf6f3c0bcbd Mon Sep 17 00:00:00 2001 From: Peter Sanchez Date: Fri, 28 Jun 2024 07:31:52 -0600 Subject: [PATCH] Adding ability to override template variables and disable collision protection all together --- server/server.go | 13 +++++++++++++ validate/template.go | 27 ++++++++++++++++++++++++--- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/server/server.go b/server/server.go index f40b968..9e1a830 100644 --- a/server/server.go +++ b/server/server.go @@ -457,6 +457,19 @@ func (s *Server) AddStaticFunc(fs ...validate.StaticFunc) { } } +// TemplateAllowOverride adds template map keys values that can be overridden by +// handlers. For instance, if a static func sets a template Map value of "seoData", +// your handlers can override that value if set to be allowed. +func (s *Server) TemplateAllowOverride(keys ...string) { + s.e.Renderer.(*validate.Template).AddOverride(keys...) +} + +// TemplateProtectVariables will set whether or not to protect variable name collisions +// from handler Map data. +func (s *Server) TemplateProtectVariables(protect bool) { + s.e.Renderer.(*validate.Template).ProtectVariables(protect) +} + // addDefaultTemplateData will set the default functions and static vars in // the template renderer func (s *Server) addDefaultTemplateData() { diff --git a/validate/template.go b/validate/template.go index 22cbcaa..ce80fcd 100644 --- a/validate/template.go +++ b/validate/template.go @@ -8,6 +8,7 @@ import ( "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" + "golang.org/x/exp/slices" "netlandish.com/x/gobwebs" ) @@ -26,7 +27,10 @@ type ( staticMap Map staticFuncs []func(c echo.Context) Map - cloned bool + + cloned bool + protect bool + allowed []string } ) @@ -36,6 +40,8 @@ func NewTemplate() *Template { templateBase: template.New(""), templates: template.New(""), staticMap: make(Map), + protect: true, + allowed: []string{}, } } @@ -93,8 +99,11 @@ func (t *Template) tmplPayload(c echo.Context, data Map) (Map, error) { } if data != nil { for k, v := range data { - if _, ok := input[k]; ok { - return nil, fmt.Errorf("Template context conflict (handler data). Reserved key: %v", k) + if t.protect && !slices.Contains(t.allowed, k) { + if _, ok := input[k]; ok { + return nil, fmt.Errorf( + "Template context conflict (handler data). Reserved key: %v", k) + } } input[k] = v } @@ -127,6 +136,18 @@ func (t *Template) RenderTemplate( return t.render(tmpl, w, name, data, c) } +// AddOverride will add an override value to the allowed slice +func (t *Template) AddOverride(keys ...string) { + t.allowed = append(t.allowed, keys...) +} + +// ProtectVariables will set the `protect` value. If false, when adding +// to the template values Map we will not check for name collisions from +// handler provided maps. +func (t *Template) ProtectVariables(protect bool) { + t.protect = protect +} + // LoadTemplates parses templates given the glob pattern path func (t *Template) LoadTemplates(path string, tfs fs.FS) error { var ( -- 2.45.2