github.com/volatiletech/authboss@v2.4.1+incompatible/register/register_test.go (about)

     1  package register
     2  
     3  import (
     4  	"net/http"
     5  	"net/http/httptest"
     6  	"testing"
     7  
     8  	"golang.org/x/crypto/bcrypt"
     9  
    10  	"github.com/pkg/errors"
    11  	"github.com/volatiletech/authboss"
    12  	"github.com/volatiletech/authboss/mocks"
    13  )
    14  
    15  func TestRegisterInit(t *testing.T) {
    16  	t.Parallel()
    17  
    18  	ab := authboss.New()
    19  
    20  	router := &mocks.Router{}
    21  	renderer := &mocks.Renderer{}
    22  	errHandler := &mocks.ErrorHandler{}
    23  	ab.Config.Core.Router = router
    24  	ab.Config.Core.ViewRenderer = renderer
    25  	ab.Config.Core.ErrorHandler = errHandler
    26  	ab.Config.Storage.Server = &mocks.ServerStorer{}
    27  
    28  	reg := &Register{}
    29  	if err := reg.Init(ab); err != nil {
    30  		t.Fatal(err)
    31  	}
    32  
    33  	if err := renderer.HasLoadedViews(PageRegister); err != nil {
    34  		t.Error(err)
    35  	}
    36  
    37  	if err := router.HasGets("/register"); err != nil {
    38  		t.Error(err)
    39  	}
    40  	if err := router.HasPosts("/register"); err != nil {
    41  		t.Error(err)
    42  	}
    43  }
    44  
    45  func TestRegisterGet(t *testing.T) {
    46  	t.Parallel()
    47  
    48  	ab := authboss.New()
    49  	responder := &mocks.Responder{}
    50  	ab.Config.Core.Responder = responder
    51  
    52  	a := &Register{ab}
    53  	if err := a.Get(nil, nil); err != nil {
    54  		t.Error(err)
    55  	}
    56  
    57  	if responder.Page != PageRegister {
    58  		t.Error("wanted login page, got:", responder.Page)
    59  	}
    60  
    61  	if responder.Status != http.StatusOK {
    62  		t.Error("wanted ok status, got:", responder.Status)
    63  	}
    64  }
    65  
    66  type testHarness struct {
    67  	reg *Register
    68  	ab  *authboss.Authboss
    69  
    70  	bodyReader *mocks.BodyReader
    71  	responder  *mocks.Responder
    72  	redirector *mocks.Redirector
    73  	session    *mocks.ClientStateRW
    74  	storer     *mocks.ServerStorer
    75  }
    76  
    77  func testSetup() *testHarness {
    78  	harness := &testHarness{}
    79  
    80  	harness.ab = authboss.New()
    81  	harness.bodyReader = &mocks.BodyReader{}
    82  	harness.redirector = &mocks.Redirector{}
    83  	harness.responder = &mocks.Responder{}
    84  	harness.session = mocks.NewClientRW()
    85  	harness.storer = mocks.NewServerStorer()
    86  
    87  	harness.ab.Paths.RegisterOK = "/ok"
    88  
    89  	harness.ab.Config.Core.BodyReader = harness.bodyReader
    90  	harness.ab.Config.Core.Logger = mocks.Logger{}
    91  	harness.ab.Config.Core.Responder = harness.responder
    92  	harness.ab.Config.Core.Redirector = harness.redirector
    93  	harness.ab.Config.Storage.SessionState = harness.session
    94  	harness.ab.Config.Storage.Server = harness.storer
    95  
    96  	harness.reg = &Register{harness.ab}
    97  
    98  	return harness
    99  }
   100  
   101  func TestRegisterPostSuccess(t *testing.T) {
   102  	t.Parallel()
   103  
   104  	setupMore := func(harness *testHarness) *testHarness {
   105  		harness.ab.Modules.RegisterPreserveFields = []string{"email", "another"}
   106  		harness.bodyReader.Return = mocks.ArbValues{
   107  			Values: map[string]string{
   108  				"email":    "test@test.com",
   109  				"password": "hello world",
   110  				"another":  "value",
   111  			},
   112  		}
   113  
   114  		return harness
   115  	}
   116  
   117  	t.Run("normal", func(t *testing.T) {
   118  		t.Parallel()
   119  		h := setupMore(testSetup())
   120  
   121  		r := mocks.Request("POST")
   122  		resp := httptest.NewRecorder()
   123  		w := h.ab.NewResponse(resp)
   124  
   125  		if err := h.reg.Post(w, r); err != nil {
   126  			t.Error(err)
   127  		}
   128  
   129  		user, ok := h.storer.Users["test@test.com"]
   130  		if !ok {
   131  			t.Error("user was not persisted in the DB")
   132  		}
   133  		if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte("hello world")); err != nil {
   134  			t.Error("password was not properly encrypted:", err)
   135  		}
   136  
   137  		if user.Arbitrary["another"] != "value" {
   138  			t.Error("arbitrary values not saved")
   139  		}
   140  
   141  		if h.session.ClientValues[authboss.SessionKey] != "test@test.com" {
   142  			t.Error("user should have been logged in:", h.session.ClientValues)
   143  		}
   144  
   145  		if resp.Code != http.StatusTemporaryRedirect {
   146  			t.Error("code was wrong:", resp.Code)
   147  		}
   148  		if h.redirector.Options.RedirectPath != "/ok" {
   149  			t.Error("redirect path was wrong:", h.redirector.Options.RedirectPath)
   150  		}
   151  	})
   152  
   153  	t.Run("handledAfter", func(t *testing.T) {
   154  		t.Parallel()
   155  		h := setupMore(testSetup())
   156  
   157  		var afterCalled bool
   158  		h.ab.Events.After(authboss.EventRegister, func(w http.ResponseWriter, r *http.Request, handled bool) (bool, error) {
   159  			w.WriteHeader(http.StatusTeapot)
   160  			afterCalled = true
   161  			return true, nil
   162  		})
   163  
   164  		r := mocks.Request("POST")
   165  		resp := httptest.NewRecorder()
   166  		w := h.ab.NewResponse(resp)
   167  
   168  		if err := h.reg.Post(w, r); err != nil {
   169  			t.Error(err)
   170  		}
   171  
   172  		user, ok := h.storer.Users["test@test.com"]
   173  		if !ok {
   174  			t.Error("user was not persisted in the DB")
   175  		}
   176  		if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte("hello world")); err != nil {
   177  			t.Error("password was not properly encrypted:", err)
   178  		}
   179  
   180  		if val, ok := h.session.ClientValues[authboss.SessionKey]; ok {
   181  			t.Error("user should not have been logged in:", val)
   182  		}
   183  
   184  		if resp.Code != http.StatusTeapot {
   185  			t.Error("code was wrong:", resp.Code)
   186  		}
   187  
   188  		if !afterCalled {
   189  			t.Error("the after handler should have been called")
   190  		}
   191  	})
   192  }
   193  
   194  func TestRegisterPostValidationFailure(t *testing.T) {
   195  	t.Parallel()
   196  
   197  	h := testSetup()
   198  
   199  	// Ensure the below is sorted, the sort normally happens in Init()
   200  	// that we don't call
   201  	h.ab.Modules.RegisterPreserveFields = []string{"another", "email"}
   202  	h.bodyReader.Return = mocks.ArbValues{
   203  		Values: map[string]string{
   204  			"email":    "test@test.com",
   205  			"password": "hello world",
   206  			"another":  "value",
   207  		},
   208  		Errors: []error{
   209  			errors.New("bad password"),
   210  		},
   211  	}
   212  
   213  	r := mocks.Request("POST")
   214  	resp := httptest.NewRecorder()
   215  	w := h.ab.NewResponse(resp)
   216  
   217  	if err := h.reg.Post(w, r); err != nil {
   218  		t.Error(err)
   219  	}
   220  
   221  	if h.responder.Status != http.StatusOK {
   222  		t.Error("wrong status:", h.responder.Status)
   223  	}
   224  	if h.responder.Page != PageRegister {
   225  		t.Error("rendered wrong page:", h.responder.Page)
   226  	}
   227  
   228  	errList := h.responder.Data[authboss.DataValidation].(map[string][]string)
   229  	if e := errList[""][0]; e != "bad password" {
   230  		t.Error("validation error wrong:", e)
   231  	}
   232  
   233  	intfD, ok := h.responder.Data[authboss.DataPreserve]
   234  	if !ok {
   235  		t.Fatal("there was no preserved data")
   236  	}
   237  
   238  	d := intfD.(map[string]string)
   239  	if d["email"] != "test@test.com" {
   240  		t.Error("e-mail was not preserved:", d)
   241  	} else if d["another"] != "value" {
   242  		t.Error("another value was not preserved", d)
   243  	} else if _, ok = d["password"]; ok {
   244  		t.Error("password was preserved", d)
   245  	}
   246  }
   247  
   248  func TestRegisterPostUserExists(t *testing.T) {
   249  	t.Parallel()
   250  
   251  	h := testSetup()
   252  
   253  	// Ensure the below is sorted, the sort normally happens in Init()
   254  	// that we don't call
   255  	h.ab.Modules.RegisterPreserveFields = []string{"another", "email"}
   256  	h.storer.Users["test@test.com"] = &mocks.User{}
   257  	h.bodyReader.Return = mocks.ArbValues{
   258  		Values: map[string]string{
   259  			"email":    "test@test.com",
   260  			"password": "hello world",
   261  			"another":  "value",
   262  		},
   263  	}
   264  
   265  	r := mocks.Request("POST")
   266  	resp := httptest.NewRecorder()
   267  	w := h.ab.NewResponse(resp)
   268  
   269  	if err := h.reg.Post(w, r); err != nil {
   270  		t.Error(err)
   271  	}
   272  
   273  	if h.responder.Status != http.StatusOK {
   274  		t.Error("wrong status:", h.responder.Status)
   275  	}
   276  	if h.responder.Page != PageRegister {
   277  		t.Error("rendered wrong page:", h.responder.Page)
   278  	}
   279  
   280  	errList := h.responder.Data[authboss.DataValidation].(map[string][]string)
   281  	if e := errList[""][0]; e != "user already exists" {
   282  		t.Error("validation error wrong:", e)
   283  	}
   284  
   285  	intfD, ok := h.responder.Data[authboss.DataPreserve]
   286  	if !ok {
   287  		t.Fatal("there was no preserved data")
   288  	}
   289  
   290  	d := intfD.(map[string]string)
   291  	if d["email"] != "test@test.com" {
   292  		t.Error("e-mail was not preserved:", d)
   293  	} else if d["another"] != "value" {
   294  		t.Error("another value was not preserved", d)
   295  	} else if _, ok = d["password"]; ok {
   296  		t.Error("password was preserved", d)
   297  	}
   298  }
   299  
   300  func TestHasString(t *testing.T) {
   301  	t.Parallel()
   302  
   303  	strs := []string{"b", "c", "d", "e"}
   304  
   305  	if !hasString(strs, "b") {
   306  		t.Error("should have a")
   307  	}
   308  	if !hasString(strs, "e") {
   309  		t.Error("should have d")
   310  	}
   311  
   312  	if hasString(strs, "a") {
   313  		t.Error("should not have a")
   314  	}
   315  	if hasString(strs, "f") {
   316  		t.Error("should not have f")
   317  	}
   318  }