package server import ( "encoding/json" "fmt" "local/dndex/server/auth" "net/http" "net/http/httptest" "strings" "testing" "github.com/google/uuid" ) func TestUsersRegister(t *testing.T) { rest, _, clean := testREST(t) defer clean() t.Run("register ok", func(t *testing.T) { user := uuid.New().String()[:5] pwd := uuid.New().String()[:5] testRegisterOK(t, rest, user, pwd) }) t.Run("register 400: nil body", func(t *testing.T) { r := httptest.NewRequest(http.MethodPost, "/register", nil) w := httptest.NewRecorder() rest.users(w, r) if w.Code < http.StatusBadRequest { t.Fatalf("wanted bad, got %v: %s", w.Code, w.Body.Bytes()) } }) t.Run("register 400: empty", func(t *testing.T) { r := httptest.NewRequest(http.MethodPost, "/register", strings.NewReader(``)) w := httptest.NewRecorder() rest.users(w, r) if w.Code < http.StatusBadRequest { t.Fatalf("wanted 400, got %v: %s", w.Code, w.Body.Bytes()) } }) t.Run("register 400: only ns", func(t *testing.T) { r := httptest.NewRequest(http.MethodPost, "/register", strings.NewReader(`DnDex-User=`+uuid.New().String())) w := httptest.NewRecorder() rest.users(w, r) if w.Code < http.StatusBadRequest { t.Fatalf("wanted 400, got %v: %s", w.Code, w.Body.Bytes()) } }) t.Run("register collision", func(t *testing.T) { user := uuid.New().String()[:5] for i := 0; i < 2; i++ { pwd := uuid.New().String()[:5] body := fmt.Sprintf(`%s=%s&%s=%s`, auth.UserKey, user, auth.AuthKey, pwd) r := httptest.NewRequest(http.MethodPost, "/register", strings.NewReader(body)) r.Header.Set("Content-Type", "application/x-www-form-urlencoded") w := httptest.NewRecorder() rest.users(w, r) if i == 0 { if w.Code != http.StatusOK { t.Fatalf("%d: wanted 200, got %v: %s", i, w.Code, w.Body.Bytes()) } } else { if w.Code < http.StatusBadRequest { t.Fatalf("%d: wanted 400, got %v: %s", i, w.Code, w.Body.Bytes()) } } } }) } func TestUsersLogin(t *testing.T) { rest, _, clean := testREST(t) defer clean() t.Run("login ok", func(t *testing.T) { user := uuid.New().String()[:5] pwd := uuid.New().String()[:5] testRegisterOK(t, rest, user, pwd) testLoginOK(t, rest, user, pwd) }) t.Run("login 404 user", func(t *testing.T) { pwd := uuid.New().String()[:5] testLoginNotOK(t, rest, "bad", pwd) }) t.Run("login bad user", func(t *testing.T) { user := uuid.New().String()[:5] pwd := uuid.New().String()[:5] testRegisterOK(t, rest, user, pwd) testLoginNotOK(t, rest, "bad", pwd) }) t.Run("login bad pwd", func(t *testing.T) { user := uuid.New().String()[:5] pwd := uuid.New().String()[:5] testRegisterOK(t, rest, user, pwd) testLoginNotOK(t, rest, user, "bad") }) } func testRegisterOK(t *testing.T, rest *REST, user, pwd string) { body := fmt.Sprintf(`%s=%s&%s=%s`, auth.UserKey, user, auth.AuthKey, pwd) r := httptest.NewRequest(http.MethodPost, "/register", strings.NewReader(body)) r.Header.Set("Content-Type", "application/x-www-form-urlencoded") w := httptest.NewRecorder() rest.users(w, r) if w.Code != http.StatusOK { t.Fatalf("wanted 200, got %v: %s", w.Code, w.Body.Bytes()) } } func testLoginNotOK(t *testing.T, rest *REST, user, pwd string) { body := fmt.Sprintf(`%s=%s`, auth.UserKey, user) r := httptest.NewRequest(http.MethodPost, "/login", strings.NewReader(body)) r.Header.Set("Content-Type", "application/x-www-form-urlencoded") w := httptest.NewRecorder() rest.users(w, r) if w.Code < http.StatusBadRequest { var resp struct { OK struct { Salt string `json:"salt"` Token string `json:"token"` } } if err := json.NewDecoder(w.Body).Decode(&resp); err != nil { t.Fatal(err) } token := auth.Token{} if err := token.Decode(resp.OK.Salt+pwd, resp.OK.Token); err == nil { t.Fatal(err, token) } } } func testLoginOK(t *testing.T, rest *REST, user, pwd string) string { body := fmt.Sprintf(`%s=%s`, auth.UserKey, user) r := httptest.NewRequest(http.MethodPost, "/login", strings.NewReader(body)) r.Header.Set("Content-Type", "application/x-www-form-urlencoded") w := httptest.NewRecorder() rest.users(w, r) if w.Code != http.StatusOK { t.Fatalf("wanted 200, got %v: %s", w.Code, w.Body.Bytes()) } var resp struct { OK struct { Salt string `json:"salt"` Token string `json:"token"` } } if err := json.NewDecoder(w.Body).Decode(&resp); err != nil { t.Fatal(err) } token := auth.Token{} if err := token.Decode(resp.OK.Salt+pwd, resp.OK.Token); err != nil { t.Fatal(err) } if token.Namespace != user { t.Fatal(token.Namespace) } if token.ID == "" { t.Fatal(token.ID) } return token.ID }