mirror of
				https://github.com/volatiletech/authboss.git
				synced 2025-10-30 23:47:59 +02:00 
			
		
		
		
	Add a lot of module related stuff.
- Leave a failing test to make hate not love.
This commit is contained in:
		
							
								
								
									
										43
									
								
								authboss.go
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								authboss.go
									
									
									
									
									
								
							| @@ -6,3 +6,46 @@ races without having to think about the hard questions like how to store | ||||
| Remember Me tokens, or passwords. | ||||
| */ | ||||
| package authboss // import "gopkg.in/authboss.v0" | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
| 	"net/http" | ||||
| 	"path" | ||||
| ) | ||||
|  | ||||
| var logger io.Writer = ioutil.Discard | ||||
|  | ||||
| // Init authboss and it's loaded modules with a configuration. | ||||
| func Init(config *Config) error { | ||||
| 	if config.Storer == nil { | ||||
| 		return errors.New("Configuration must provide a storer.") | ||||
| 	} | ||||
|  | ||||
| 	logger = config.LogWriter | ||||
|  | ||||
| 	for name, mod := range modules { | ||||
| 		fmt.Fprintf(logger, "[%-10s] Initializing\n", name) | ||||
| 		if err := mod.Initialize(config); err != nil { | ||||
| 			return fmt.Errorf("[%s] Error Initializing: %v", name, err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Router returns a router to be mounted at some mountpoint. | ||||
| func Router(config *Config) http.Handler { | ||||
| 	mux := http.NewServeMux() | ||||
|  | ||||
| 	for name, mod := range modules { | ||||
| 		for route, handler := range mod.Routes() { | ||||
| 			fmt.Fprintf(logger, "[%-10s] Register Route: %s\n", name) | ||||
| 			mux.HandleFunc(path.Join(config.MountPath, route), handler) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return http.StripPrefix(config.MountPath, mux) | ||||
| } | ||||
|   | ||||
							
								
								
									
										52
									
								
								authboss_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								authboss_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| package authboss | ||||
|  | ||||
| import ( | ||||
| 	"net/http" | ||||
| 	"net/http/httptest" | ||||
| 	"os" | ||||
| 	"strings" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| func TestMain(main *testing.M) { | ||||
| 	RegisterModule("testmodule", testMod) | ||||
| 	code := main.Run() | ||||
| 	os.Exit(code) | ||||
| } | ||||
|  | ||||
| func TestAuthBossInit(t *testing.T) { | ||||
| 	c := NewConfig() | ||||
|  | ||||
| 	err := Init(c) | ||||
| 	if err == nil || !strings.Contains(err.Error(), "storer") { | ||||
| 		t.Error("Expected error about a storer, got:", err) | ||||
| 	} | ||||
|  | ||||
| 	c.Storer = testStorer(0) | ||||
| 	err = Init(c) | ||||
| 	if err != nil { | ||||
| 		t.Error("Unexpected error:", err) | ||||
| 	} | ||||
| 	if testMod.c == nil { | ||||
| 		t.Error("Expected the modules to be passed the config.") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestAuthBossRouter(t *testing.T) { | ||||
| 	t.Parallel() | ||||
|  | ||||
| 	c := NewConfig() | ||||
| 	c.MountPath = "/candycanes" | ||||
| 	c.LogWriter = os.Stdout | ||||
|  | ||||
| 	router := Router(c) | ||||
|  | ||||
| 	r, _ := http.NewRequest("GET", "/candycanes/testroute", nil) | ||||
| 	response := httptest.NewRecorder() | ||||
|  | ||||
| 	router.ServeHTTP(response, r) | ||||
|  | ||||
| 	if response.Header().Get("testmodule") != "test" { | ||||
| 		t.Error("Expected a header to have been set.") | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										18
									
								
								config.go
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								config.go
									
									
									
									
									
								
							| @@ -1,14 +1,24 @@ | ||||
| package authboss | ||||
|  | ||||
| // Config is a map to provide configuration key-values. | ||||
| // | ||||
| import ( | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
| ) | ||||
|  | ||||
| // Config holds all the configuration for both authboss and it's modules. | ||||
| type Config struct { | ||||
| 	MountPath string `json:"mountPath" xml:"mountPath"` | ||||
|  | ||||
| 	AuthLoginPageURI   string `json:"authLoginPage" xml:"authLoginPage"` | ||||
| 	AuthLogoutRedirect string `json:"authLogoutRedirect" xml:"authLogoutRedirect"` | ||||
|  | ||||
| 	Storer    Storer    `json:"-" xml:"-"` | ||||
| 	LogWriter io.Writer `json:"-" xml:"-"` | ||||
| } | ||||
|  | ||||
| func NewConfig() { | ||||
|  | ||||
| // NewConfig creates a new config full of default values ready to override. | ||||
| func NewConfig() *Config { | ||||
| 	return &Config{ | ||||
| 		LogWriter: ioutil.Discard, | ||||
| 	} | ||||
| } | ||||
|   | ||||
							
								
								
									
										18
									
								
								core.go
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								core.go
									
									
									
									
									
								
							| @@ -1,18 +0,0 @@ | ||||
| package authboss | ||||
|  | ||||
| import ( | ||||
| 	"net/http" | ||||
| ) | ||||
|  | ||||
| type Routes map[string]http.HandlerFunc | ||||
|  | ||||
| type Modularizer interface { | ||||
| 	Initialize(Config) error | ||||
| 	Routes() Routes | ||||
| 	Style() ([]byte, error) | ||||
| 	Storage() | ||||
| } | ||||
|  | ||||
| func Register(m Modularizer) { | ||||
|  | ||||
| } | ||||
							
								
								
									
										50
									
								
								core/core.go
									
									
									
									
									
								
							
							
						
						
									
										50
									
								
								core/core.go
									
									
									
									
									
								
							| @@ -1,50 +0,0 @@ | ||||
| /* | ||||
| Package core is essentially just a namespacing for the module system. This | ||||
| allows the main package for user consumption to remain free of cruft. | ||||
| */ | ||||
| package core // import "gopkg.in/authboss.v0/core | ||||
|  | ||||
| // dataType represents the various types that clients must be able to store. | ||||
| // This type is duplicated from storer.go that we might avoid having users | ||||
| // importing the core package. | ||||
| type dataType int | ||||
|  | ||||
| const ( | ||||
| 	Integer dataType = iota | ||||
| 	String | ||||
| 	DateTime | ||||
| ) | ||||
|  | ||||
| var modules = make(map[string]module) | ||||
|  | ||||
| type module struct { | ||||
| 	Name           string | ||||
| 	Storage        StorageOptions | ||||
| 	RequiredConfig []string | ||||
| } | ||||
|  | ||||
| // StorageOptions is a map depicting the things a module must be able to store. | ||||
| type StorageOptions map[string]DataType | ||||
|  | ||||
| // Register a module with the core providing all the necessary information to | ||||
| // integrate into authboss. | ||||
| func Register(name string, storage StorageOptions, requiredConfig ...string) { | ||||
| } | ||||
|  | ||||
| // LoadedModules returns a list of modules that are currently loaded. | ||||
| func LoadedModules() []string { | ||||
| 	mods := make([]string, len(modules)) | ||||
| 	i := 0 | ||||
| 	for k, _ := range modules { | ||||
| 		mods[i] = k | ||||
| 		i++ | ||||
| 	} | ||||
|  | ||||
| 	return mods | ||||
| } | ||||
|  | ||||
| // IsLoaded checks if a specific module is loaded. | ||||
| func IsLoaded(mod string) bool { | ||||
| 	_, ok := modules[mod] | ||||
| 	return ok | ||||
| } | ||||
							
								
								
									
										43
									
								
								module.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								module.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| package authboss | ||||
|  | ||||
| import ( | ||||
| 	"net/http" | ||||
| ) | ||||
|  | ||||
| var modules = make(map[string]Modularizer) | ||||
|  | ||||
| // RouteTable is a routing table from a path to a handlerfunc. | ||||
| type RouteTable map[string]http.HandlerFunc | ||||
|  | ||||
| // StorageOptions is a map depicting the things a module must be able to store. | ||||
| type StorageOptions map[string]DataType | ||||
|  | ||||
| type Modularizer interface { | ||||
| 	Initialize(*Config) error | ||||
| 	Routes() RouteTable | ||||
| 	Storage() StorageOptions | ||||
| } | ||||
|  | ||||
| // RegisterModule with the core providing all the necessary information to | ||||
| // integrate into authboss. | ||||
| func RegisterModule(name string, m Modularizer) { | ||||
| 	modules[name] = m | ||||
| } | ||||
|  | ||||
| // LoadedModules returns a list of modules that are currently loaded. | ||||
| func LoadedModules() []string { | ||||
| 	mods := make([]string, len(modules)) | ||||
| 	i := 0 | ||||
| 	for k, _ := range modules { | ||||
| 		mods[i] = k | ||||
| 		i++ | ||||
| 	} | ||||
|  | ||||
| 	return mods | ||||
| } | ||||
|  | ||||
| // IsLoaded checks if a specific module is loaded. | ||||
| func IsLoaded(mod string) bool { | ||||
| 	_, ok := modules[mod] | ||||
| 	return ok | ||||
| } | ||||
							
								
								
									
										60
									
								
								module_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								module_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | ||||
| package authboss | ||||
|  | ||||
| import ( | ||||
| 	"net/http" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| const testModName = "testmodule" | ||||
|  | ||||
| type testModule struct { | ||||
| 	c *Config | ||||
| 	s StorageOptions | ||||
| 	r RouteTable | ||||
| } | ||||
|  | ||||
| var testMod = &testModule{ | ||||
| 	r: RouteTable{ | ||||
| 		"/testroute": testHandler, | ||||
| 	}, | ||||
| } | ||||
|  | ||||
| func testHandler(w http.ResponseWriter, r *http.Request) { | ||||
| 	w.Header().Set("testhandler", "test") | ||||
| } | ||||
|  | ||||
| func (t *testModule) Initialize(c *Config) error { | ||||
| 	t.c = c | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (t *testModule) Routes() RouteTable { | ||||
| 	return t.r | ||||
| } | ||||
|  | ||||
| func (t *testModule) Storage() StorageOptions { | ||||
| 	return t.s | ||||
| } | ||||
|  | ||||
| func TestRegister(t *testing.T) { | ||||
| 	t.Parallel() | ||||
|  | ||||
| 	// RegisterModule called by TestMain. | ||||
|  | ||||
| 	if _, ok := modules["testmodule"]; !ok { | ||||
| 		t.Error("Expected module to be saved.") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestLoadedModules(t *testing.T) { | ||||
| 	t.Parallel() | ||||
|  | ||||
| 	// RegisterModule called by TestMain. | ||||
|  | ||||
| 	loadedMods := LoadedModules() | ||||
| 	if len(loadedMods) != 1 { | ||||
| 		t.Error("Expected only a single module to be loaded.") | ||||
| 	} else if loadedMods[0] != "testmodule" { | ||||
| 		t.Error("Expected testmodule to be loaded.") | ||||
| 	} | ||||
| } | ||||
| @@ -6,6 +6,12 @@ import ( | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| type testStorer int | ||||
|  | ||||
| func (t testStorer) Create(key string, attr Attributes) error                    { return nil } | ||||
| func (t testStorer) Put(key string, attr Attributes) error                       { return nil } | ||||
| func (t testStorer) Get(key string, attrMeta AttributeMeta) (interface{}, error) { return nil, nil } | ||||
|  | ||||
| func TestAttributes_Bind(t *testing.T) { | ||||
| 	anInteger := 5 | ||||
| 	aString := "string" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user