mirror of
https://github.com/volatiletech/authboss.git
synced 2025-01-04 03:49:32 +02:00
Add a lot of module related stuff.
- Leave a failing test to make hate not love.
This commit is contained in:
parent
a8a17318db
commit
92b3172a3e
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"
|
||||
|
Loading…
Reference in New Issue
Block a user