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 }