mirror of
https://github.com/volatiletech/authboss.git
synced 2025-02-09 13:47:09 +02:00
Add new auth testing and tempaltes
This commit is contained in:
parent
f716720759
commit
0928720a3f
13
auth/auth.go
13
auth/auth.go
@ -31,6 +31,14 @@ func (a *Auth) Initialize() (err error) {
|
||||
return errors.New("auth: Need a Storer.")
|
||||
}
|
||||
|
||||
if len(authboss.Cfg.XSRFName) == 0 {
|
||||
return errors.New("auth: XSRFName must be set")
|
||||
}
|
||||
|
||||
if authboss.Cfg.XSRFMaker == nil {
|
||||
return errors.New("auth: XSRFMaker must be defined")
|
||||
}
|
||||
|
||||
a.templates, err = render.LoadTemplates(authboss.Cfg.Layout, authboss.Cfg.ViewsPath, tplLogin)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -59,6 +67,7 @@ func (a *Auth) loginHandlerFunc(ctx *authboss.Context, w http.ResponseWriter, r
|
||||
if _, ok := ctx.SessionStorer.Get(authboss.SessionKey); ok {
|
||||
if halfAuthed, ok := ctx.SessionStorer.Get(authboss.SessionHalfAuthKey); !ok || halfAuthed == "false" {
|
||||
http.Redirect(w, r, authboss.Cfg.AuthLoginSuccessRoute, http.StatusFound)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,7 +90,7 @@ func (a *Auth) loginHandlerFunc(ctx *authboss.Context, w http.ResponseWriter, r
|
||||
case authboss.InterruptAccountNotConfirmed:
|
||||
reason = "Your account has not been confirmed."
|
||||
}
|
||||
render.Redirect(ctx, w, r, "/", "", reason)
|
||||
render.Redirect(ctx, w, r, "/login", "", reason)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -98,12 +107,10 @@ func (a *Auth) loginHandlerFunc(ctx *authboss.Context, w http.ResponseWriter, r
|
||||
|
||||
policies := authboss.FilterValidators(authboss.Cfg.Policies, authboss.Cfg.PrimaryID, authboss.StorePassword)
|
||||
if validationErrs := ctx.Validate(policies); len(validationErrs) > 0 {
|
||||
fmt.Fprintln(authboss.Cfg.LogWriter, "auth: form validation failed:", validationErrs.Map())
|
||||
return a.templates.Render(ctx, w, r, tplLogin, errData)
|
||||
}
|
||||
|
||||
if err := validateCredentials(ctx, key, password); err != nil {
|
||||
fmt.Fprintln(authboss.Cfg.LogWriter, "auth: failed to validate credentials:", err)
|
||||
return a.templates.Render(ctx, w, r, tplLogin, errData)
|
||||
}
|
||||
|
||||
|
@ -1 +1,356 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"gopkg.in/authboss.v0"
|
||||
"gopkg.in/authboss.v0/internal/mocks"
|
||||
)
|
||||
|
||||
func testSetup() (a *Auth, s *mocks.MockStorer) {
|
||||
s = mocks.NewMockStorer()
|
||||
|
||||
authboss.Cfg = authboss.NewConfig()
|
||||
authboss.Cfg.Layout = template.Must(template.New("").Parse(`{{template "authboss" .}}`))
|
||||
authboss.Cfg.Storer = s
|
||||
authboss.Cfg.XSRFName = "xsrf"
|
||||
authboss.Cfg.XSRFMaker = func(_ http.ResponseWriter, _ *http.Request) string {
|
||||
return "xsrfvalue"
|
||||
}
|
||||
authboss.Cfg.PrimaryID = authboss.StoreUsername
|
||||
|
||||
a = &Auth{}
|
||||
if err := a.Initialize(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return a, s
|
||||
}
|
||||
|
||||
func testRequest(method string, postFormValues ...string) (*authboss.Context, *httptest.ResponseRecorder, *http.Request, authboss.ClientStorerErr) {
|
||||
r, err := http.NewRequest(method, "", nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
sessionStorer := mocks.NewMockClientStorer()
|
||||
ctx := mocks.MockRequestContext(postFormValues...)
|
||||
ctx.SessionStorer = sessionStorer
|
||||
|
||||
return ctx, httptest.NewRecorder(), r, sessionStorer
|
||||
}
|
||||
|
||||
func TestAuth(t *testing.T) {
|
||||
a, _ := testSetup()
|
||||
|
||||
if err := a.Initialize(); err != nil {
|
||||
t.Error("Unexcpeted error:", err)
|
||||
}
|
||||
|
||||
storage := a.Storage()
|
||||
|
||||
if storage[authboss.Cfg.PrimaryID] != authboss.String {
|
||||
t.Error("Expected storage KV:", authboss.Cfg.PrimaryID, authboss.String)
|
||||
}
|
||||
|
||||
if storage[authboss.StorePassword] != authboss.String {
|
||||
t.Error("Expected storage KV:", authboss.StorePassword, authboss.String)
|
||||
}
|
||||
|
||||
routes := a.Routes()
|
||||
|
||||
if routes["login"] == nil {
|
||||
t.Error("Expected route 'login' with handleFunc")
|
||||
}
|
||||
|
||||
if routes["logout"] == nil {
|
||||
t.Error("Expected route 'logout' with handleFunc")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuth_loginHandlerFunc_GET_RedirectsWhenHalfAuthed(t *testing.T) {
|
||||
a, _ := testSetup()
|
||||
ctx, w, r, sessionStore := testRequest("GET")
|
||||
|
||||
sessionStore.Put(authboss.SessionKey, "a")
|
||||
sessionStore.Put(authboss.SessionHalfAuthKey, "false")
|
||||
|
||||
authboss.Cfg.AuthLoginSuccessRoute = "/dashboard"
|
||||
|
||||
if err := a.loginHandlerFunc(ctx, w, r); err != nil {
|
||||
t.Error("Unexpeced error:", err)
|
||||
}
|
||||
|
||||
if w.Code != http.StatusFound {
|
||||
t.Error("Unexpcted status:", w.Code)
|
||||
}
|
||||
|
||||
loc := w.Header().Get("Location")
|
||||
if loc != authboss.Cfg.AuthLoginSuccessRoute {
|
||||
t.Error("Unexpected redirect:", loc)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuth_loginHandlerFunc_GET(t *testing.T) {
|
||||
a, _ := testSetup()
|
||||
ctx, w, r, _ := testRequest("GET")
|
||||
|
||||
if err := a.loginHandlerFunc(ctx, w, r); err != nil {
|
||||
t.Error("Unexpected error:", err)
|
||||
}
|
||||
|
||||
if w.Code != http.StatusOK {
|
||||
t.Error("Unexpected status:", w.Code)
|
||||
}
|
||||
|
||||
body := w.Body.String()
|
||||
if !strings.Contains(body, "<form") {
|
||||
t.Error("Should have rendered a form")
|
||||
}
|
||||
if !strings.Contains(body, `name="`+authboss.Cfg.PrimaryID) {
|
||||
t.Error("Form should contain the primary ID field:", body)
|
||||
}
|
||||
if !strings.Contains(body, `name="password"`) {
|
||||
t.Error("Form should contain password field:", body)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuth_loginHandlerFunc_POST_ReturnsErrorOnCallbackFailure(t *testing.T) {
|
||||
a, _ := testSetup()
|
||||
|
||||
authboss.Cfg.Callbacks = authboss.NewCallbacks()
|
||||
authboss.Cfg.Callbacks.Before(authboss.EventAuth, func(_ *authboss.Context) (authboss.Interrupt, error) {
|
||||
return authboss.InterruptNone, errors.New("explode")
|
||||
})
|
||||
|
||||
ctx, w, r, _ := testRequest("POST")
|
||||
|
||||
if err := a.loginHandlerFunc(ctx, w, r); err.Error() != "explode" {
|
||||
t.Error("Unexpected error:", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuth_loginHandlerFunc_POST_RedirectsWhenInterrupted(t *testing.T) {
|
||||
a, _ := testSetup()
|
||||
|
||||
authboss.Cfg.Callbacks = authboss.NewCallbacks()
|
||||
authboss.Cfg.Callbacks.Before(authboss.EventAuth, func(_ *authboss.Context) (authboss.Interrupt, error) {
|
||||
return authboss.InterruptAccountLocked, nil
|
||||
})
|
||||
|
||||
ctx, w, r, sessionStore := testRequest("POST")
|
||||
|
||||
if err := a.loginHandlerFunc(ctx, w, r); err != nil {
|
||||
t.Error("Unexpected error:", err)
|
||||
}
|
||||
|
||||
if w.Code != http.StatusFound {
|
||||
t.Error("Unexpected status:", w.Code)
|
||||
}
|
||||
|
||||
loc := w.Header().Get("Location")
|
||||
if loc != "/login" {
|
||||
t.Error("Unexpeced location:", loc)
|
||||
}
|
||||
|
||||
expectedMsg := "Your account has been locked."
|
||||
if msg, ok := sessionStore.Get(authboss.FlashErrorKey); !ok || msg != expectedMsg {
|
||||
t.Error("Expected error flash message:", expectedMsg)
|
||||
}
|
||||
|
||||
authboss.Cfg.Callbacks = authboss.NewCallbacks()
|
||||
authboss.Cfg.Callbacks.Before(authboss.EventAuth, func(_ *authboss.Context) (authboss.Interrupt, error) {
|
||||
return authboss.InterruptAccountNotConfirmed, nil
|
||||
})
|
||||
|
||||
if err := a.loginHandlerFunc(ctx, w, r); err != nil {
|
||||
t.Error("Unexpected error:", err)
|
||||
}
|
||||
|
||||
if w.Code != http.StatusFound {
|
||||
t.Error("Unexpected status:", w.Code)
|
||||
}
|
||||
|
||||
loc = w.Header().Get("Location")
|
||||
if loc != "/login" {
|
||||
t.Error("Unexpeced location:", loc)
|
||||
}
|
||||
|
||||
expectedMsg = "Your account has not been confirmed."
|
||||
if msg, ok := sessionStore.Get(authboss.FlashErrorKey); !ok || msg != expectedMsg {
|
||||
t.Error("Expected error flash message:", expectedMsg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuth_loginHandlerFunc_POST_AuthenticationFailure(t *testing.T) {
|
||||
a, _ := testSetup()
|
||||
|
||||
ctx, w, r, _ := testRequest("POST", "username", "john", "password", "1")
|
||||
|
||||
if err := a.loginHandlerFunc(ctx, w, r); err != nil {
|
||||
t.Error("Unexpected error:", err)
|
||||
}
|
||||
|
||||
if w.Code != http.StatusOK {
|
||||
t.Error("Unexpected status:", w.Code)
|
||||
}
|
||||
|
||||
body := w.Body.String()
|
||||
if !strings.Contains(body, "invalid username and/or password") {
|
||||
t.Error("Should have rendered with error")
|
||||
}
|
||||
|
||||
ctx, w, r, _ = testRequest("POST", "username", "john", "password", "1234")
|
||||
|
||||
if err := a.loginHandlerFunc(ctx, w, r); err != nil {
|
||||
t.Error("Unexpected error:", err)
|
||||
}
|
||||
|
||||
if w.Code != http.StatusOK {
|
||||
t.Error("Unexpected status:", w.Code)
|
||||
}
|
||||
|
||||
body = w.Body.String()
|
||||
if !strings.Contains(body, "invalid username and/or password") {
|
||||
t.Error("Should have rendered with error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuth_loginHandlerFunc_POST(t *testing.T) {
|
||||
a, storer := testSetup()
|
||||
storer.Users["john"] = authboss.Attributes{"password": "$2a$10$B7aydtqVF9V8RSNx3lCKB.l09jqLV/aMiVqQHajtL7sWGhCS9jlOu"}
|
||||
|
||||
ctx, w, r, _ := testRequest("POST", "username", "john", "password", "1234")
|
||||
cb := mocks.NewMockAfterCallback()
|
||||
|
||||
authboss.Cfg.Callbacks = authboss.NewCallbacks()
|
||||
authboss.Cfg.Callbacks.After(authboss.EventAuth, cb.Fn)
|
||||
authboss.Cfg.AuthLoginSuccessRoute = "/dashboard"
|
||||
|
||||
if err := a.loginHandlerFunc(ctx, w, r); err != nil {
|
||||
t.Error("Unexpected error:", err)
|
||||
}
|
||||
|
||||
if !cb.HasBeenCalled {
|
||||
t.Error("Expected after callback to have been called")
|
||||
}
|
||||
|
||||
if w.Code != http.StatusFound {
|
||||
t.Error("Unexpected status:", w.Code)
|
||||
}
|
||||
|
||||
loc := w.Header().Get("Location")
|
||||
if loc != authboss.Cfg.AuthLoginSuccessRoute {
|
||||
t.Error("Unexpeced location:", loc)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuth_loginHandlerFunc_OtherMethods(t *testing.T) {
|
||||
a, _ := testSetup()
|
||||
methods := []string{"HEAD", "PUT", "DELETE", "TRACE", "CONNECT"}
|
||||
|
||||
for i, method := range methods {
|
||||
r, err := http.NewRequest(method, "/login", nil)
|
||||
if err != nil {
|
||||
t.Errorf("%d> Unexpected error '%s'", i, err)
|
||||
}
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
if err := a.loginHandlerFunc(nil, w, r); err != nil {
|
||||
t.Errorf("%d> Unexpected error: %s", i, err)
|
||||
}
|
||||
|
||||
if http.StatusMethodNotAllowed != w.Code {
|
||||
t.Errorf("%d> Expected status code %d, got %d", i, http.StatusMethodNotAllowed, w.Code)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuth_validateCredentials(t *testing.T) {
|
||||
authboss.Cfg = authboss.NewConfig()
|
||||
|
||||
storer := mocks.NewMockStorer()
|
||||
storer.GetErr = "Failed to load user"
|
||||
authboss.Cfg.Storer = storer
|
||||
|
||||
ctx := authboss.Context{}
|
||||
|
||||
if err := validateCredentials(&ctx, "", ""); err.Error() != "Failed to load user" {
|
||||
t.Error("Unexpected error:", err)
|
||||
}
|
||||
|
||||
storer.GetErr = ""
|
||||
storer.Users["john"] = authboss.Attributes{"password": "$2a$10$pgFsuQwdhwOdZp/v52dvHeEi53ZaI7dGmtwK4bAzGGN5A4nT6doqm"}
|
||||
if err := validateCredentials(&ctx, "john", "b"); err == nil {
|
||||
t.Error("Expected error about passwords mismatch")
|
||||
}
|
||||
|
||||
sessions := mocks.NewMockClientStorer()
|
||||
ctx.SessionStorer = sessions
|
||||
if err := validateCredentials(&ctx, "john", "a"); err != nil {
|
||||
t.Error("Unexpected error:", err)
|
||||
}
|
||||
|
||||
val, ok := sessions.Values[authboss.SessionKey]
|
||||
if !ok {
|
||||
t.Error("Expected session to be set")
|
||||
} else if val != "john" {
|
||||
t.Error("Expected session value to be authed username")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuth_logoutHandlerFunc_GET(t *testing.T) {
|
||||
a, _ := testSetup()
|
||||
|
||||
authboss.Cfg.AuthLogoutRoute = "/dashboard"
|
||||
|
||||
ctx, w, r, sessionStorer := testRequest("GET")
|
||||
|
||||
sessionStorer.Put(authboss.SessionKey, "asdf")
|
||||
|
||||
if err := a.logoutHandlerFunc(ctx, w, r); err != nil {
|
||||
t.Error("Unexpected error:", err)
|
||||
}
|
||||
|
||||
if _, ok := sessionStorer.Get(authboss.SessionKey); ok {
|
||||
t.Errorf("Expected to be logged out")
|
||||
}
|
||||
|
||||
if http.StatusFound != w.Code {
|
||||
t.Errorf("Expected status code %d, got %d", http.StatusFound, w.Code)
|
||||
}
|
||||
|
||||
location := w.Header().Get("Location")
|
||||
if location != "/dashboard" {
|
||||
t.Errorf("Expected lcoation %s, got %s", "/dashboard", location)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuth_logoutHandlerFunc_OtherMethods(t *testing.T) {
|
||||
a, _ := testSetup()
|
||||
|
||||
methods := []string{"HEAD", "POST", "PUT", "DELETE", "TRACE", "CONNECT"}
|
||||
|
||||
for i, method := range methods {
|
||||
r, err := http.NewRequest(method, "/logout", nil)
|
||||
if err != nil {
|
||||
t.Errorf("%d> Unexpected error '%s'", i, err)
|
||||
}
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
if err := a.logoutHandlerFunc(nil, w, r); err != nil {
|
||||
t.Errorf("%d> Unexpected error: %s", i, err)
|
||||
}
|
||||
|
||||
if http.StatusMethodNotAllowed != w.Code {
|
||||
t.Errorf("%d> Expected status code %d, got %d", i, http.StatusMethodNotAllowed, w.Code)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -182,10 +182,18 @@ type MockClientStorer struct {
|
||||
GetShouldFail bool
|
||||
}
|
||||
|
||||
func NewMockClientStorer() *MockClientStorer {
|
||||
return &MockClientStorer{
|
||||
Values: make(map[string]string),
|
||||
func NewMockClientStorer(data ...string) *MockClientStorer {
|
||||
if len(data)%2 != 0 {
|
||||
panic("It should be a key value list of arguments.")
|
||||
}
|
||||
|
||||
values := make(map[string]string)
|
||||
|
||||
for i := 0; i < len(data)-1; i += 2 {
|
||||
values[data[i]] = data[i+1]
|
||||
}
|
||||
|
||||
return &MockClientStorer{Values: values}
|
||||
}
|
||||
|
||||
func (m *MockClientStorer) Get(key string) (string, bool) {
|
||||
@ -252,3 +260,19 @@ func (m *MockMailer) Send(email authboss.Email) error {
|
||||
m.Last = email
|
||||
return nil
|
||||
}
|
||||
|
||||
type MockAfterCallback struct {
|
||||
HasBeenCalled bool
|
||||
Fn authboss.After
|
||||
}
|
||||
|
||||
func NewMockAfterCallback() *MockAfterCallback {
|
||||
m := MockAfterCallback{}
|
||||
|
||||
m.Fn = func(_ *authboss.Context) error {
|
||||
m.HasBeenCalled = true
|
||||
return nil
|
||||
}
|
||||
|
||||
return &m
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ func confirm_email_txt_tpl() (*asset, error) {
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _login_tpl = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x7c\x92\x4d\x6b\xf3\x30\x0c\x80\xef\x85\xfe\x07\xe3\xfb\xdb\xfc\x81\x24\xf0\xc2\x2e\x83\x7d\x94\xad\xf7\xe1\x38\xca\x62\x1a\x5b\x41\x96\xfb\x41\xc8\x7f\x9f\xbd\xa4\x6b\x02\x63\x39\x05\x49\x7e\xf4\x58\xf2\x30\xec\x9a\x4e\xf9\xf6\xc3\x07\xad\xc1\xfb\x71\xdc\x6e\xf2\x06\xc9\x0a\xa5\xd9\xa0\x2b\x64\xd6\xe1\xa7\x71\x52\x58\xe0\x16\xeb\x42\xee\x5f\xdf\x0f\xb2\xdc\x6e\x44\xfc\x86\xc1\x34\x62\x07\x44\x48\xe3\x18\x51\xf3\x5f\x5e\x91\xc8\xca\x61\x00\x57\x27\x5e\xaa\xcc\x8d\xeb\x03\x0b\xbe\xf6\x50\x48\x86\x0b\x4b\xa1\x63\x5f\x5f\xc8\xd4\xec\x9f\x46\xc7\x84\x9d\x14\x4e\xd9\x58\x10\x51\x3d\x19\xab\xe8\xfa\xf8\x30\x8e\x52\xf4\x9d\xd2\xd0\x62\x57\x03\xa5\x24\x1b\xee\x40\xac\x4b\x4e\xaa\x0b\xd3\xc9\xe0\x81\x12\x26\x46\xcb\xc9\x64\xa5\x30\x3b\xf4\xb1\xf9\x19\xa9\xfe\xd3\xe3\x5e\xb4\x32\xd8\xdf\xc2\xbf\xf1\x27\x7c\x6b\xea\x1a\xdc\xe2\x3e\x17\x4f\xcd\xcb\x64\xb5\x70\x4d\xd1\x03\x1e\xc1\xa5\x70\xb6\x9a\xaa\x6f\xf1\xfc\x06\x16\x6c\x05\x69\xa4\x4b\xb8\x6e\x41\x1f\x2b\xbc\xdc\xf0\x64\x7f\x98\x4c\x01\x64\x29\x6e\x07\xc5\x33\xac\xd7\x50\x05\x66\x74\x33\xc7\x87\xca\x1a\x96\xe5\x53\xda\x70\x9e\x4d\xb9\xd5\x9d\x96\x2a\x1a\x4f\xdf\x26\x4a\xb4\x04\x4d\x7c\x18\x34\x85\x64\x39\xe7\xc4\x7f\xad\x31\x38\xce\x33\x75\x5f\x7e\x9e\xa5\xc1\x96\x5f\x01\x00\x00\xff\xff\xe7\xed\x2e\xa4\x68\x02\x00\x00")
|
||||
var _login_tpl = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x7c\x92\xcb\x6a\xeb\x30\x10\x86\xf7\x81\xbc\x83\xd0\xfe\xc4\x2f\x60\x1b\x0e\x74\x53\xe8\x25\xb4\xa1\xdb\x22\xcb\xe3\x5a\xc4\xd2\x98\xd1\x38\x17\x8c\xdf\xbd\x52\xed\x34\x51\x29\xcd\x2a\xfe\x67\xf4\xe9\xd3\x48\xe3\xb8\x69\x3a\xe5\xdb\x77\x3f\x68\x0d\xde\x4f\xd3\x7a\x95\x37\x48\x56\x28\xcd\x06\x5d\x21\xb3\x0e\x3f\x8c\x93\xc2\x02\xb7\x58\x17\x72\xfb\xfc\xba\x93\xe5\x7a\x25\xc2\x6f\x1c\x4d\x23\x36\x40\x84\x34\x4d\x01\xb5\xfc\xcb\x2b\x12\x59\x39\x8e\xe0\xea\xc8\x8b\x9d\xb9\x71\xfd\xc0\x82\xcf\x3d\x14\x92\xe1\xc4\x52\xe8\xb0\xaf\x2f\x64\xdc\xec\x9f\x46\xc7\x84\x9d\x14\x4e\xd9\xd0\x10\x50\x3d\x19\xab\xe8\x7c\x7f\x37\x4d\x52\xf4\x9d\xd2\xd0\x62\x57\x03\xc5\x22\x1b\xee\x40\xa4\x2d\x07\xd5\x0d\x3f\x56\xbe\xc5\x28\xd4\xca\xd9\x27\x11\x59\x4c\xfa\xa0\x70\x44\xaa\xff\xb4\xb9\x36\x25\x1e\xdb\x4b\xfc\x1b\x7f\xc6\xb7\xa6\xae\xc1\xdd\x9c\xea\xe4\xa9\x79\x0a\x1f\xa9\x71\x4c\x77\xb8\x07\x17\xe3\x2c\x99\xad\x6f\xf1\xf8\x02\x16\x6c\x05\x71\xb0\xb7\x70\xdd\x82\xde\x57\x78\xba\xe0\xc9\x7e\x33\x99\x06\x90\xa5\xb8\x2c\x14\x8f\x90\x5e\x46\x35\x30\xa3\x5b\x38\x7e\xa8\xac\x61\x59\x3e\xc4\x7b\xce\xb3\xb9\x96\x9c\xe9\x56\x45\xe3\xe1\xcb\x44\x89\x96\xa0\x09\xcf\x83\xe6\x48\x96\x4b\x4d\xfc\xd7\x1a\x07\xc7\x79\xa6\xae\x4f\x20\xcf\xe2\x60\xcb\xcf\x00\x00\x00\xff\xff\x7f\x7f\xf0\x07\x6e\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: 616, mode: os.FileMode(438), modTime: time.Unix(1424735294, 0)}
|
||||
info := bindata_file_info{name: "login.tpl", size: 622, mode: os.FileMode(438), modTime: time.Unix(1424815807, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -138,5 +138,5 @@ func Redirect(ctx *authboss.Context, w http.ResponseWriter, r *http.Request, pat
|
||||
if len(flashError) > 0 {
|
||||
ctx.SessionStorer.Put(authboss.FlashErrorKey, flashError)
|
||||
}
|
||||
http.Redirect(w, r, path, http.StatusTemporaryRedirect)
|
||||
http.Redirect(w, r, path, http.StatusFound)
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
{{.flash_success}}
|
||||
<form action="/login" method="POST">
|
||||
{{if .error}}{{.error}}<br />{{end}}
|
||||
<input type="text" class="form-control" name="{{.primaryID}}" placeholder="{{title .primaryID}}" value="{{.username}}"><br />
|
||||
<input type="text" class="form-control" name="{{.primaryID}}" placeholder="{{title .primaryID}}" value="{{.primaryIDValue}}"><br />
|
||||
<input type="password" class="form-control" name="password" placeholder="Password"><br />
|
||||
<input type="hidden" name="{{.xsrfName}}" value="{{.xsrfToken}}" />
|
||||
{{if .showRemember}}<input type="checkbox" name="rm" value="true"> Remember Me{{end}}
|
||||
|
1
recover/recover_test.go
Normal file
1
recover/recover_test.go
Normal file
@ -0,0 +1 @@
|
||||
package recover
|
Loading…
x
Reference in New Issue
Block a user