From a9c161e94093b73e09b24c874b03435d9bda3957 Mon Sep 17 00:00:00 2001 From: Aaron L Date: Mon, 30 Apr 2018 18:21:56 -0700 Subject: [PATCH] Add module list middleware --- html_data.go | 4 ++++ module.go | 35 ++++++++++++++++++++++++++++++++++- module_test.go | 31 +++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) diff --git a/html_data.go b/html_data.go index 9dc47c4..7a33f49 100644 --- a/html_data.go +++ b/html_data.go @@ -9,6 +9,10 @@ const ( DataValidation = "errors" // DataPreserve preserves fields DataPreserve = "preserve" + // DataModules contains a map[string]Moduler of which modules are loaded + // the Init() method should NEVER be called in a template. This structure + // is only returned to avoid allocations. + DataModules = "modules" ) // HTMLData is used to render templates with. diff --git a/module.go b/module.go index b142d2b..ac3980c 100644 --- a/module.go +++ b/module.go @@ -1,6 +1,10 @@ package authboss -import "reflect" +import ( + "context" + "net/http" + "reflect" +) var registeredModules = make(map[string]Moduler) @@ -80,3 +84,32 @@ func (a *Authboss) loadModule(name string) error { a.loadedModules[name] = mod return mod.Init(a) } + +// ModuleListMiddleware puts a map in the data that can be used +// to provide the renderer with information about which pieces of the +// views to show. +// Data looks like: +// map[modulename] = Moduler +// +// The Moduler interface type should be ignored, and the key being present +// or not is the only important point. Copying this data structure ignores +// allocations. +func ModuleListMiddleware(ab *Authboss) func(http.Handler) http.Handler { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var data HTMLData + + ctx := r.Context() + dataIntf := ctx.Value(CTXKeyData) + if dataIntf != nil { + data = dataIntf.(HTMLData) + } else { + data = HTMLData{} + } + + data[DataModules] = ab.loadedModules + r = r.WithContext(context.WithValue(ctx, CTXKeyData, data)) + next.ServeHTTP(w, r) + }) + } +} diff --git a/module_test.go b/module_test.go index 430d1c8..a83f0a0 100644 --- a/module_test.go +++ b/module_test.go @@ -2,6 +2,7 @@ package authboss import ( "net/http" + "net/http/httptest" "testing" ) @@ -68,3 +69,33 @@ func TestIsLoaded(t *testing.T) { t.Error("Loaded modules wrong:", loaded) } } + +func TestModuleLoadedMiddleware(t *testing.T) { + t.Parallel() + + ab := New() + + ab.loadedModules = map[string]Moduler{ + "recover": nil, + "auth": nil, + } + + var mods map[string]Moduler + server := ModuleListMiddleware(ab)(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + data := r.Context().Value(CTXKeyData).(HTMLData) + mods = data[DataModules].(map[string]Moduler) + })) + + server.ServeHTTP(nil, httptest.NewRequest("GET", "/", nil)) + + if len(mods) != 2 { + t.Error("want two modules, got:", len(mods)) + } + + if _, ok := mods["auth"]; !ok { + t.Error("auth should be loaded") + } + if _, ok := mods["recover"]; !ok { + t.Error("auth should be loaded") + } +}