mirror of
https://github.com/volatiletech/authboss.git
synced 2025-01-06 03:54:17 +02:00
Start the register module.
This commit is contained in:
parent
73dcb5beb1
commit
6f074543f4
@ -5,7 +5,6 @@ import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/smtp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
@ -105,8 +104,8 @@ func NewConfig() *Config {
|
||||
},
|
||||
},
|
||||
ConfirmFields: []string{
|
||||
StoreEmail, "confirm" + strings.Title(StoreEmail),
|
||||
StorePassword, "confirm" + strings.Title(StorePassword),
|
||||
StoreEmail, ConfirmPrefix + StoreEmail,
|
||||
StorePassword, ConfirmPrefix + StorePassword,
|
||||
},
|
||||
|
||||
RecoverRedirect: "/login",
|
||||
|
@ -76,7 +76,7 @@ func confirm_email_html_tpl() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindata_file_info{name: "confirm_email.html.tpl", size: 26, mode: os.FileMode(438), modTime: time.Unix(1424471280, 0)}
|
||||
info := bindata_file_info{name: "confirm_email.html.tpl", size: 26, mode: os.FileMode(438), modTime: time.Unix(1424498554, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@ -96,12 +96,12 @@ func confirm_email_txt_tpl() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindata_file_info{name: "confirm_email.txt.tpl", size: 9, mode: os.FileMode(438), modTime: time.Unix(1424471280, 0)}
|
||||
info := bindata_file_info{name: "confirm_email.txt.tpl", size: 9, mode: os.FileMode(438), modTime: time.Unix(1424498554, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _login_tpl = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x7c\x52\x5b\x6e\x83\x30\x10\xfc\xaf\xd4\x3b\xac\xf6\xbf\xe5\x02\x80\xd4\xff\x3e\xa2\x36\x3d\x80\x31\x4b\x41\xc1\x5e\xb4\xd8\x49\x2a\xc4\xdd\x6b\x07\x9c\x87\x14\x95\xaf\xd5\xec\x30\x33\xcc\x92\x37\x2c\x06\x94\x76\x1d\xdb\x02\xb3\x9e\x7f\x3a\x8b\x60\xc8\xb5\x5c\x17\xb8\xf9\xf8\xda\x62\xf9\xf8\x00\xe1\x99\xa6\xae\x81\x67\x12\x61\x99\xe7\x69\x4a\x53\x5e\x09\x64\xe5\x34\x91\xad\xe7\x79\x61\xe6\x9d\x1d\xbc\x03\xf7\x3b\x50\x81\x8e\x8e\x0e\x41\xf7\x6a\x1c\x0b\x8c\x66\x4f\x9a\xad\x13\xee\x11\xac\x32\x81\xe0\x47\x92\x38\x21\x0c\xbd\xd2\xd4\x72\x5f\x93\x14\xf8\x7d\x86\xf7\xaa\xf7\x81\x17\x2c\x13\x75\x9e\x53\xa8\xd5\x6a\xf5\x1a\x82\xc9\x81\xa5\xfe\xd7\xef\x42\xba\xf1\xdb\x24\xb8\xbc\xf3\x11\x6d\x57\xd7\x64\x93\x42\x48\x72\x1c\xa5\x79\x5f\x92\x5c\xe5\x8b\xe8\x96\x77\x64\x23\x9c\xdd\xf4\x36\xb6\x7c\xf8\x24\x43\xa6\xa2\x58\xda\xb5\xb8\x6e\x49\xef\x2a\x3e\x26\x79\x31\x67\x4d\x27\x9e\xb0\x84\xf4\x22\xbc\xd1\x6d\xd1\xa7\xee\xd3\xec\x9d\x63\xbb\x6a\x8e\xbe\x32\x9d\xc3\xf2\x35\xde\x33\xcf\x96\xdd\x9d\x40\x9a\xf7\xa7\x3c\x0a\x5a\xa1\x26\xfc\x00\xb2\x40\x58\xae\x3b\x78\xd1\x9a\xbd\x75\x79\xa6\x2e\x47\xce\xb3\x58\x6c\xf9\x17\x00\x00\xff\xff\x1e\x0e\xca\x3a\x3c\x02\x00\x00")
|
||||
var _login_tpl = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x7c\x92\x4d\x6e\x83\x30\x10\x85\xf7\x95\x7a\x87\xd1\xec\x5b\x2e\x00\x96\xba\xef\x4f\xd4\xa6\x07\x30\x66\x28\x28\xd8\x83\x06\x3b\x49\x85\xb8\x7b\xed\x12\x12\x90\xaa\xb2\xb2\x9e\x1f\xef\x7b\xcc\x90\xd7\x2c\x16\xb4\xf1\x2d\xbb\x02\xb3\x8e\xbf\x5a\x87\x60\xc9\x37\x5c\x15\xb8\x7b\xfb\xd8\xa3\xba\xbf\x83\xf8\x8c\x63\x5b\xc3\x23\x89\xb0\x4c\xd3\x38\x2e\xa7\xbc\x14\xc8\xd4\x38\x92\xab\xa6\x69\x76\xe6\xad\xeb\x83\x07\xff\xdd\x53\x81\x9e\xce\x1e\xc1\x74\x7a\x18\x0a\x4c\xb0\x07\xc3\xce\x0b\x77\x08\x4e\xdb\x68\x08\x03\x49\x3a\x21\xf4\x9d\x36\xd4\x70\x57\x91\x14\xf8\x79\x95\x8f\xba\x0b\xd1\x17\x91\x8b\x75\x9a\x50\xcd\xdc\x0d\xf0\x42\xec\x23\xea\xc4\x52\xfd\x4b\xbd\x99\x36\xd4\xdd\x22\xff\x95\x3f\xc7\x37\x6d\x55\x91\x5b\x72\x62\xab\xf3\x20\xf5\xeb\xdc\x6a\xd5\x35\xa9\x7b\x3e\x90\x4b\x72\xb6\x99\xe1\xd0\xf0\xe9\x9d\x2c\xd9\x92\xd2\x00\xd7\xe1\xa6\x21\x73\x28\xf9\xbc\xc4\x8b\xbd\x66\x7a\x09\x84\x0a\x96\x17\xe1\x85\xb6\x43\x5f\xf7\x2d\x83\xf7\xec\x2e\x99\x43\x28\x6d\xeb\x51\x3d\xa7\xdd\xe6\xd9\x7c\xb7\xf9\xbe\x75\x2d\xc3\xc7\xdf\x56\x1a\x1a\xa1\x3a\xfe\x12\x32\x4b\xa8\x2e\x77\xf0\x64\x0c\x07\xe7\xf3\x4c\xdf\xd6\x9e\x67\x69\xc8\xea\x27\x00\x00\xff\xff\xe8\x9d\xff\x88\x4e\x02\x00\x00")
|
||||
|
||||
func login_tpl_bytes() ([]byte, error) {
|
||||
return bindata_read(
|
||||
@ -116,7 +116,7 @@ func login_tpl() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindata_file_info{name: "login.tpl", size: 572, mode: os.FileMode(438), modTime: time.Unix(1424503580, 0)}
|
||||
info := bindata_file_info{name: "login.tpl", size: 590, mode: os.FileMode(438), modTime: time.Unix(1424567032, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@ -136,7 +136,7 @@ func recover_complete_tpl() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindata_file_info{name: "recover-complete.tpl", size: 1235, mode: os.FileMode(438), modTime: time.Unix(1424471280, 0)}
|
||||
info := bindata_file_info{name: "recover-complete.tpl", size: 1235, mode: os.FileMode(438), modTime: time.Unix(1424498554, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@ -156,7 +156,7 @@ func recover_html_email() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindata_file_info{name: "recover-html.email", size: 26, mode: os.FileMode(438), modTime: time.Unix(1424471280, 0)}
|
||||
info := bindata_file_info{name: "recover-html.email", size: 26, mode: os.FileMode(438), modTime: time.Unix(1424498554, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@ -176,7 +176,7 @@ func recover_text_email() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindata_file_info{name: "recover-text.email", size: 9, mode: os.FileMode(438), modTime: time.Unix(1424471280, 0)}
|
||||
info := bindata_file_info{name: "recover-text.email", size: 9, mode: os.FileMode(438), modTime: time.Unix(1424498554, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@ -196,7 +196,27 @@ func recover_tpl() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindata_file_info{name: "recover.tpl", size: 1623, mode: os.FileMode(438), modTime: time.Unix(1424541421, 0)}
|
||||
info := bindata_file_info{name: "recover.tpl", size: 1623, mode: os.FileMode(438), modTime: time.Unix(1424567032, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _register_html_tpl = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x94\x93\x41\x6f\xea\x30\x0c\xc7\xcf\xf4\x53\x58\x11\xe7\xf6\x8e\xd2\x5e\xde\xbb\x3c\xe9\x69\xe2\x30\xed\x3a\x85\xc6\xa5\xd1\xd2\x24\x4a\xc2\x00\x55\xfd\xee\x4b\x68\xd7\x12\xd0\x36\x76\x81\xd8\xfa\xdb\xfe\xff\x2c\x97\x36\xda\x76\xc0\x6a\x2f\xb4\x2a\x89\xc5\xbd\x70\x1e\x2d\x81\x0e\x7d\xab\x79\x49\x8c\x76\x9e\x54\xd9\x8a\x4a\xb6\x43\x09\x41\x5d\x92\xbe\xcf\x8d\x15\x1d\xb3\xe7\x7f\x7f\x87\x81\x54\x69\xbc\xa1\xc5\x45\x1b\x8b\x84\x32\x07\x0f\x8a\x75\x58\xa6\x22\xf0\x67\x83\x25\xf1\x78\xf2\x04\xde\x99\x3c\x60\x6c\x2b\x1a\x58\x44\x2f\x31\x3b\x0c\xd7\x75\x73\x0a\x15\x0f\x83\xc1\x48\x56\x63\xab\x25\xc7\x7b\x57\x50\x54\x74\x67\xc3\x6f\xb6\xea\xfb\xb5\x11\x1c\x36\x25\x5c\x2b\xfa\xfe\x28\x7c\x0b\x39\x5a\xeb\xe6\x68\x1d\x22\x19\x56\x10\xc5\x42\x71\x3c\x41\x0e\xb1\x38\x0a\x2c\x53\x7b\x9c\x15\xc3\x40\x9d\x61\x2a\xc2\x87\x67\x71\x79\x8f\x03\x27\x7b\xe9\x5f\xba\x41\xc3\x9c\x3b\x6a\xcb\x49\xb5\x9d\x5e\x5f\x6c\x6d\x51\x4e\x1b\x5b\xe2\x04\x7e\x3b\xa7\xaf\xb1\x53\xc0\xd1\x7f\xfe\xd9\xe1\x51\x80\xd4\x79\xad\x55\x23\x6c\xf7\xba\x10\xfc\x19\x33\xf0\x13\xc9\x5d\xe5\xf7\x44\xb7\x6d\x1f\x20\xbb\x9d\xf0\x0b\xc2\xd1\xe8\x68\xc8\x1d\x76\x9d\x58\xce\xf2\xbf\xde\x0b\x45\xe6\xd9\x94\x41\x6b\xb1\x29\x49\x11\xd0\x99\xaa\x51\xd2\x82\x55\xd9\x4d\x8f\x56\x70\x8e\x8a\x4c\xe8\xc1\xc0\xc9\xd9\xe6\x29\x04\xf1\x32\xe7\x7b\xbf\x64\x9f\xf5\x1b\xaa\xf1\x60\x33\x5a\xc4\xcf\xb1\xfa\x08\x00\x00\xff\xff\x3c\x36\x7b\x13\x95\x03\x00\x00")
|
||||
|
||||
func register_html_tpl_bytes() ([]byte, error) {
|
||||
return bindata_read(
|
||||
_register_html_tpl,
|
||||
"register.html.tpl",
|
||||
)
|
||||
}
|
||||
|
||||
func register_html_tpl() (*asset, error) {
|
||||
bytes, err := register_html_tpl_bytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindata_file_info{name: "register.html.tpl", size: 917, mode: os.FileMode(438), modTime: time.Unix(1424682732, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@ -249,6 +269,7 @@ var _bindata = map[string]func() (*asset, error){
|
||||
"recover-html.email": recover_html_email,
|
||||
"recover-text.email": recover_text_email,
|
||||
"recover.tpl": recover_tpl,
|
||||
"register.html.tpl": register_html_tpl,
|
||||
}
|
||||
|
||||
// AssetDir returns the file names below a certain
|
||||
@ -305,6 +326,8 @@ var _bintree = &_bintree_t{nil, map[string]*_bintree_t{
|
||||
}},
|
||||
"recover.tpl": &_bintree_t{recover_tpl, map[string]*_bintree_t{
|
||||
}},
|
||||
"register.html.tpl": &_bintree_t{register_html_tpl, map[string]*_bintree_t{
|
||||
}},
|
||||
}}
|
||||
|
||||
// Restore an asset under the given directory
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/authboss.v0"
|
||||
)
|
||||
@ -19,6 +20,10 @@ import (
|
||||
var (
|
||||
// ErrTemplateNotFound should be returned from Get when the view is not found
|
||||
ErrTemplateNotFound = errors.New("Template not found")
|
||||
|
||||
funcMap = template.FuncMap{
|
||||
"title": strings.Title,
|
||||
}
|
||||
)
|
||||
|
||||
// Templates is a map depicting the forms a template needs wrapped within the specified layout
|
||||
@ -47,7 +52,7 @@ func LoadTemplates(layout *template.Template, path string, files ...string) (Tem
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = clone.New("authboss").Parse(string(b))
|
||||
_, err = clone.New("authboss").Funcs(funcMap).Parse(string(b))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -71,12 +76,12 @@ func (t Templates) Render(ctx *authboss.Context, w http.ResponseWriter, r *http.
|
||||
data.Merge(authboss.Cfg.LayoutDataMaker(w, r))
|
||||
}
|
||||
|
||||
if flash, ok := ctx.CookieStorer.Get(authboss.FlashSuccessKey); ok {
|
||||
ctx.CookieStorer.Del(authboss.FlashSuccessKey)
|
||||
if flash, ok := ctx.SessionStorer.Get(authboss.FlashSuccessKey); ok {
|
||||
ctx.SessionStorer.Del(authboss.FlashSuccessKey)
|
||||
data.MergeKV(authboss.FlashSuccessKey, flash)
|
||||
}
|
||||
if flash, ok := ctx.CookieStorer.Get(authboss.FlashErrorKey); ok {
|
||||
ctx.CookieStorer.Del(authboss.FlashErrorKey)
|
||||
if flash, ok := ctx.SessionStorer.Get(authboss.FlashErrorKey); ok {
|
||||
ctx.SessionStorer.Del(authboss.FlashErrorKey)
|
||||
data.MergeKV(authboss.FlashErrorKey, flash)
|
||||
}
|
||||
|
||||
|
15
internal/render/templates/register.html.tpl
Normal file
15
internal/render/templates/register.html.tpl
Normal file
@ -0,0 +1,15 @@
|
||||
<form action="register" method="post">
|
||||
<label for="{{.primaryID}}">{{.primaryID}}:</label>
|
||||
<input name={{.primaryID}} type="text" value="{{if .primaryIDValue}}{{.primaryIDValue}}{{end}}" placeholder="{{.primaryID}}" /><br />
|
||||
{{$pid := .primaryID}}{{with .errs}}{{with $errlist := index . $pid}}{{range $errlist}}<span>{{.}}</span><br />{{end}}{{end}}{{end}}
|
||||
<label for="password">Password:</label>
|
||||
<input name="password" type="password" placeholder="Password" /><br />
|
||||
{{with .errs}}{{range .password}}<span>{{.}}</span><br />{{end}}{{end}}
|
||||
<label for="confirm_password">Confirm Password:</label>
|
||||
<input name="confirm_password" type="password" placeholder="Confirm Password" /><br />
|
||||
{{with .errs}}{{range .confirm_password}}<span>{{.}}</span><br />{{end}}{{end}}
|
||||
<input type="submit" value="Login"><br />
|
||||
<a href="/">Cancel</a>
|
||||
|
||||
<input type="hidden" name="{{.xsrfName}}" value="{{.xsrfToken}}" />
|
||||
</form>
|
107
register/register.go
Normal file
107
register/register.go
Normal file
@ -0,0 +1,107 @@
|
||||
// Package register allows for user registration.
|
||||
package register
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"gopkg.in/authboss.v0"
|
||||
"gopkg.in/authboss.v0/internal/render"
|
||||
)
|
||||
|
||||
const (
|
||||
tplRegister = "register.html.tpl"
|
||||
)
|
||||
|
||||
// R is the singleton instance of the register module which will have been
|
||||
// configured and ready to use after authboss.Init()
|
||||
var R *Register
|
||||
|
||||
func init() {
|
||||
R = &Register{}
|
||||
authboss.RegisterModule("register", R)
|
||||
}
|
||||
|
||||
// Register module.
|
||||
type Register struct {
|
||||
templates render.Templates
|
||||
}
|
||||
|
||||
// Initialize the module.
|
||||
func (r *Register) Initialize() (err error) {
|
||||
if r.templates, err = render.LoadTemplates(authboss.Cfg.Layout, authboss.Cfg.ViewsPath, tplRegister); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Routes creates the routing table.
|
||||
func (r *Register) Routes() authboss.RouteTable {
|
||||
return authboss.RouteTable{
|
||||
"/register": r.registerHandler,
|
||||
}
|
||||
}
|
||||
|
||||
// Storage returns storage requirements.
|
||||
func (r *Register) Storage() authboss.StorageOptions {
|
||||
return authboss.StorageOptions{
|
||||
authboss.Cfg.PrimaryID: authboss.String,
|
||||
authboss.StorePassword: authboss.String,
|
||||
}
|
||||
}
|
||||
|
||||
func (reg *Register) registerHandler(ctx *authboss.Context, w http.ResponseWriter, r *http.Request) error {
|
||||
switch r.Method {
|
||||
case "GET":
|
||||
data := authboss.HTMLData{
|
||||
"primaryID": authboss.Cfg.PrimaryID,
|
||||
"primaryIDValue": "",
|
||||
}
|
||||
return reg.templates.Render(ctx, w, r, tplRegister, data)
|
||||
case "POST":
|
||||
return reg.registerPostHandler(ctx, w, r)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (reg *Register) registerPostHandler(ctx *authboss.Context, w http.ResponseWriter, r *http.Request) error {
|
||||
key, _ := ctx.FirstPostFormValue(authboss.Cfg.PrimaryID)
|
||||
password, _ := ctx.FirstPostFormValue(authboss.StorePassword)
|
||||
|
||||
policies := authboss.FilterValidators(authboss.Cfg.Policies, authboss.Cfg.PrimaryID, authboss.StorePassword)
|
||||
validationErrs := ctx.Validate(policies, authboss.Cfg.ConfirmFields...)
|
||||
|
||||
if len(validationErrs) != 0 {
|
||||
data := authboss.HTMLData{
|
||||
"primaryID": authboss.Cfg.PrimaryID,
|
||||
"primaryIDValue": key,
|
||||
"errs": validationErrs.Map(),
|
||||
}
|
||||
|
||||
return reg.templates.Render(ctx, w, r, tplRegister, data)
|
||||
}
|
||||
|
||||
attr, err := ctx.Attributes() // Attributes from overriden forms
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
attr[authboss.Cfg.PrimaryID] = key
|
||||
attr[authboss.StorePassword] = password
|
||||
ctx.User = attr
|
||||
|
||||
if err := authboss.Cfg.Storer.Create(key, attr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
authboss.Cfg.Callbacks.FireAfter(authboss.EventRegister, ctx)
|
||||
|
||||
if authboss.IsLoaded("confirm") {
|
||||
render.Redirect(ctx, w, r, "/", "Account successfully created, please verify your e-mail address.", "")
|
||||
return nil
|
||||
}
|
||||
|
||||
ctx.SessionStorer.Put(authboss.SessionKey, key)
|
||||
render.Redirect(ctx, w, r, "/", "Account successfully created, you are now logged in.", "")
|
||||
|
||||
return nil
|
||||
}
|
69
register/register_test.go
Normal file
69
register/register_test.go
Normal file
@ -0,0 +1,69 @@
|
||||
package register
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"gopkg.in/authboss.v0"
|
||||
"gopkg.in/authboss.v0/internal/mocks"
|
||||
)
|
||||
|
||||
func TestRegister(t *testing.T) {
|
||||
authboss.Cfg = authboss.NewConfig()
|
||||
r := Register{}
|
||||
|
||||
if err := r.Initialize(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if r.Routes()["/register"] == nil {
|
||||
t.Error("Expected a register handler at /register.")
|
||||
}
|
||||
|
||||
sto := r.Storage()
|
||||
if sto[authboss.Cfg.PrimaryID] != authboss.String {
|
||||
t.Error("Wanted primary ID to be a string.")
|
||||
}
|
||||
if sto[authboss.StorePassword] != authboss.String {
|
||||
t.Error("Wanted password to be a string.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegisterGet(t *testing.T) {
|
||||
authboss.Cfg = &authboss.Config{
|
||||
Layout: template.Must(template.New("").Parse(`{{template "authboss"}}`)),
|
||||
XSRFName: "xsrf",
|
||||
XSRFMaker: func(_ http.ResponseWriter, _ *http.Request) string {
|
||||
return "xsrfvalue"
|
||||
},
|
||||
}
|
||||
reg := Register{}
|
||||
|
||||
if err := reg.Initialize(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
r, _ := http.NewRequest("GET", "/register", nil)
|
||||
ctx, _ := authboss.ContextFromRequest(r)
|
||||
ctx.SessionStorer = mocks.NewMockClientStorer()
|
||||
|
||||
if err := reg.registerHandler(ctx, w, r); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if w.Code != http.StatusOK {
|
||||
t.Error("It should have written a 200:", w.Code)
|
||||
}
|
||||
|
||||
if w.Body.Len() == 0 {
|
||||
t.Error("It should have wrote a response.")
|
||||
}
|
||||
|
||||
if str := w.Body.String(); !strings.Contains(str, "<form") {
|
||||
t.Error("It should have rendered a nice form:", str)
|
||||
}
|
||||
}
|
@ -5,6 +5,11 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const (
|
||||
// ConfirmPrefix is prepended to names of confirm fields.
|
||||
ConfirmPrefix = "confirm_"
|
||||
)
|
||||
|
||||
// Validator is anything that can validate a string and provide a list of errors
|
||||
// and describe its set of rules.
|
||||
type Validator interface {
|
||||
|
Loading…
Reference in New Issue
Block a user