1
0
mirror of https://github.com/volatiletech/authboss.git synced 2024-11-24 08:42:17 +02:00

Add JSON Renderer and JSON body reading.

This commit is contained in:
Aaron L 2018-05-09 07:59:19 -07:00
parent 48b33b0217
commit 63888bdfc1
4 changed files with 86 additions and 13 deletions

View File

@ -16,14 +16,14 @@ import (
// SetCore creates instances of all the default pieces
// with the exception of ViewRenderer which should be already set
// before calling this method.
func SetCore(config *authboss.Config, useUsername bool) {
func SetCore(config *authboss.Config, readJSON, useUsername bool) {
logger := NewLogger(os.Stdout)
config.Core.Router = NewRouter()
config.Core.ErrorHandler = NewErrorHandler(logger)
config.Core.Responder = NewResponder(config.Core.ViewRenderer)
config.Core.Redirector = NewRedirector(config.Core.ViewRenderer, RedirectFormValueName)
config.Core.BodyReader = NewHTTPFormReader(useUsername)
config.Core.BodyReader = NewHTTPBodyReader(readJSON, useUsername)
config.Core.Mailer = NewLogMailer(os.Stdout)
config.Core.Logger = logger
}

29
defaults/renderer.go Normal file
View File

@ -0,0 +1,29 @@
package defaults
import (
"context"
"encoding/json"
"github.com/volatiletech/authboss"
)
// There is a separate package that does HTML Rendering authboss-renderer
// JSONRenderer simply renders the data provided in JSON
type JSONRenderer struct {
}
// Load is a no-op since json doesn't require any templates
func (JSONRenderer) Load(names ...string) error {
return nil
}
// Render the data
func (JSONRenderer) Render(ctx context.Context, page string, data authboss.HTMLData) (output []byte, contentType string, err error) {
b, err := json.Marshal(data)
if err != nil {
return nil, "", err
}
return b, "application/json", nil
}

View File

@ -1,6 +1,8 @@
package defaults
import (
"encoding/json"
"io/ioutil"
"net/http"
"net/url"
"regexp"
@ -90,9 +92,13 @@ func (r RecoverEndValues) GetToken() string { return r.Token }
// GetPassword for recovery
func (r RecoverEndValues) GetPassword() string { return r.NewPassword }
// HTTPFormReader reads forms from various pages and decodes
// HTTPBodyReader reads forms from various pages and decodes
// them.
type HTTPFormReader struct {
type HTTPBodyReader struct {
// ReadJSON if turned on reads json from the http request
// instead of a encoded form.
ReadJSON bool
// UseUsername instead of e-mail address
UseUsername bool
@ -108,10 +114,10 @@ type HTTPFormReader struct {
Whitelist map[string][]string
}
// NewHTTPFormReader creates a form reader with default validation rules
// NewHTTPBodyReader creates a form reader with default validation rules
// and fields for each page. If no defaults are required, simply construct
// this using the struct members itself for more control.
func NewHTTPFormReader(useUsernameNotEmail bool) *HTTPFormReader {
func NewHTTPBodyReader(readJSON, useUsernameNotEmail bool) *HTTPBodyReader {
var pid string
var pidRules Rules
@ -140,7 +146,9 @@ func NewHTTPFormReader(useUsernameNotEmail bool) *HTTPFormReader {
MinLower: 1,
}
return &HTTPFormReader{
return &HTTPBodyReader{
UseUsername: useUsernameNotEmail,
ReadJSON: readJSON,
Rulesets: map[string][]Rules{
"login": {pidRules},
"register": {pidRules, passwordRule},
@ -159,15 +167,29 @@ func NewHTTPFormReader(useUsernameNotEmail bool) *HTTPFormReader {
}
// Read the form pages
func (h HTTPFormReader) Read(page string, r *http.Request) (authboss.Validator, error) {
if err := r.ParseForm(); err != nil {
return nil, errors.Wrapf(err, "failed to parse form on page: %s", page)
func (h HTTPBodyReader) Read(page string, r *http.Request) (authboss.Validator, error) {
var values map[string]string
if h.ReadJSON {
b, err := ioutil.ReadAll(r.Body)
r.Body.Close()
if err != nil {
return nil, errors.Wrap(err, "failed to read http body")
}
if err = json.Unmarshal(b, &values); err != nil {
return nil, errors.Wrap(err, "failed to parse json http body")
}
} else {
if err := r.ParseForm(); err != nil {
return nil, errors.Wrapf(err, "failed to parse form on page: %s", page)
}
values = URLValuesToMap(r.Form)
}
rules := h.Rulesets[page]
confirms := h.Confirms[page]
whitelist := h.Whitelist[page]
values := URLValuesToMap(r.Form)
switch page {
case "confirm":

View File

@ -1,16 +1,18 @@
package defaults
import (
"net/http/httptest"
"strings"
"testing"
"github.com/volatiletech/authboss"
"github.com/volatiletech/authboss/internal/mocks"
)
func TestHTTPFormReader(t *testing.T) {
func TestHTTPBodyReader(t *testing.T) {
t.Parallel()
h := NewHTTPFormReader(false)
h := NewHTTPBodyReader(false, false)
r := mocks.Request("POST", "email", "john@john.john", "password", "flowers")
validator, err := h.Read("login", r)
@ -26,3 +28,23 @@ func TestHTTPFormReader(t *testing.T) {
t.Error("wrong password:", uv.GetPassword())
}
}
func TestHTTPBodyReaderJSON(t *testing.T) {
t.Parallel()
h := NewHTTPBodyReader(true, false)
r := httptest.NewRequest("POST", "/", strings.NewReader(`{"email":"john@john.john","password":"flowers"}`))
validator, err := h.Read("login", r)
if err != nil {
t.Error(err)
}
uv := validator.(authboss.UserValuer)
if "john@john.john" != uv.GetPID() {
t.Error("wrong e-mail:", uv.GetPID())
}
if "flowers" != uv.GetPassword() {
t.Error("wrong password:", uv.GetPassword())
}
}