wallet-sync-server/server/auth_test.go

167 lines
5.4 KiB
Go
Raw Normal View History

package server
2021-12-10 22:35:47 +01:00
import (
"bytes"
"encoding/json"
"fmt"
2021-12-10 22:35:47 +01:00
"io/ioutil"
"net/http"
"net/http/httptest"
"strings"
2021-12-10 22:35:47 +01:00
"testing"
"lbryio/lbry-id/auth"
"lbryio/lbry-id/store"
2021-12-10 22:35:47 +01:00
)
func TestServerAuthHandlerSuccess(t *testing.T) {
testAuth := TestAuth{TestNewAuthTokenString: auth.AuthTokenString("seekrit")}
2021-12-10 22:35:47 +01:00
testStore := TestStore{}
s := Server{&testAuth, &testStore, &TestEnv{}, &TestMail{}}
2021-12-10 22:35:47 +01:00
requestBody := []byte(`{"deviceId": "dev-1", "email": "abc@example.com", "password": "123"}`)
2021-12-10 22:35:47 +01:00
req := httptest.NewRequest(http.MethodPost, PathAuthToken, bytes.NewBuffer(requestBody))
2021-12-10 22:35:47 +01:00
w := httptest.NewRecorder()
s.getAuthToken(w, req)
2021-12-10 22:35:47 +01:00
body, _ := ioutil.ReadAll(w.Body)
2022-06-21 17:52:03 +02:00
expectStatusCode(t, w, http.StatusOK)
2021-12-10 22:35:47 +01:00
2022-06-20 00:54:59 +02:00
var result auth.AuthToken
2021-12-10 22:35:47 +01:00
err := json.Unmarshal(body, &result)
if err != nil || result.Token != testAuth.TestNewAuthTokenString {
2021-12-10 22:35:47 +01:00
t.Errorf("Expected auth response to contain token: result: %+v err: %+v", string(body), err)
}
if testStore.Called.SaveToken != testAuth.TestNewAuthTokenString {
t.Errorf("Expected Store.SaveToken to be called with %s", testAuth.TestNewAuthTokenString)
2021-12-10 22:35:47 +01:00
}
}
func TestServerAuthHandlerErrors(t *testing.T) {
2021-12-10 22:35:47 +01:00
tt := []struct {
name string
2022-06-22 17:06:05 +02:00
email string
2021-12-10 22:35:47 +01:00
expectedStatusCode int
expectedErrorString string
storeErrors TestStoreFunctionsErrors
2021-12-10 22:35:47 +01:00
authFailGenToken bool
}{
{
name: "validation error", // missing email address
email: "",
expectedStatusCode: http.StatusBadRequest,
expectedErrorString: http.StatusText(http.StatusBadRequest) + ": Request failed validation: Invalid 'email'",
// Just check one validation error (missing email address) to make sure the
// validate function is called. We'll check the rest of the validation
// errors in the other test below.
},
2021-12-10 22:35:47 +01:00
{
name: "login fail",
email: "abc@example.com",
expectedStatusCode: http.StatusUnauthorized,
expectedErrorString: http.StatusText(http.StatusUnauthorized) + ": No match for email and/or password",
2021-12-10 22:35:47 +01:00
2022-07-06 18:44:35 +02:00
storeErrors: TestStoreFunctionsErrors{GetUserId: store.ErrWrongCredentials},
2021-12-10 22:35:47 +01:00
},
{
name: "unverified account",
email: "abc@example.com",
expectedStatusCode: http.StatusUnauthorized,
expectedErrorString: http.StatusText(http.StatusUnauthorized) + ": Account is not verified",
storeErrors: TestStoreFunctionsErrors{GetUserId: store.ErrNotVerified},
},
2021-12-10 22:35:47 +01:00
{
name: "generate token fail",
email: "abc@example.com",
2021-12-10 22:35:47 +01:00
expectedStatusCode: http.StatusInternalServerError,
expectedErrorString: http.StatusText(http.StatusInternalServerError),
2021-12-10 22:35:47 +01:00
authFailGenToken: true,
},
{
name: "save token fail",
email: "abc@example.com",
2021-12-10 22:35:47 +01:00
expectedStatusCode: http.StatusInternalServerError,
expectedErrorString: http.StatusText(http.StatusInternalServerError),
2021-12-10 22:35:47 +01:00
storeErrors: TestStoreFunctionsErrors{SaveToken: fmt.Errorf("TestStore.SaveToken fail")},
2021-12-10 22:35:47 +01:00
},
}
for _, tc := range tt {
t.Run(tc.name, func(t *testing.T) {
// Set this up to fail according to specification
testAuth := TestAuth{TestNewAuthTokenString: auth.AuthTokenString("seekrit")}
testStore := TestStore{Errors: tc.storeErrors}
if tc.authFailGenToken { // TODO - TestAuth{Errors:authErrors}
2021-12-10 22:35:47 +01:00
testAuth.FailGenToken = true
}
server := Server{&testAuth, &testStore, &TestEnv{}, &TestMail{}}
2021-12-10 22:35:47 +01:00
// Make request
// So long as the JSON is well-formed, the content doesn't matter here since the password check will be stubbed out
requestBody := fmt.Sprintf(`{"deviceId": "dev-1", "email": "%s", "password": "123"}`, tc.email)
req := httptest.NewRequest(http.MethodPost, PathAuthToken, bytes.NewBuffer([]byte(requestBody)))
2021-12-10 22:35:47 +01:00
w := httptest.NewRecorder()
server.getAuthToken(w, req)
2021-12-10 22:35:47 +01:00
2022-06-22 17:37:03 +02:00
body, _ := ioutil.ReadAll(w.Body)
2022-06-21 17:52:03 +02:00
expectStatusCode(t, w, tc.expectedStatusCode)
2022-06-22 17:37:03 +02:00
expectErrorString(t, body, tc.expectedErrorString)
2021-12-10 22:35:47 +01:00
})
}
}
func TestServerValidateAuthRequest(t *testing.T) {
2022-06-08 02:08:41 +02:00
authRequest := AuthRequest{DeviceId: "dId", Email: "joe@example.com", Password: "aoeu"}
if authRequest.validate() != nil {
t.Errorf("Expected valid AuthRequest to successfully validate")
2022-06-08 02:08:41 +02:00
}
tt := []struct {
authRequest AuthRequest
expectedErrorSubstr string
failureDescription string
}{
{
AuthRequest{Email: "joe@example.com", Password: "aoeu"},
"deviceId",
"Expected AuthRequest with missing device to not successfully validate",
}, {
AuthRequest{DeviceId: "dId", Email: "joe-example.com", Password: "aoeu"},
"email",
"Expected AuthRequest with invalid email to not successfully validate",
}, {
// Note that Golang's email address parser, which I use, will accept
// "Joe <joe@example.com>" so we need to make sure to avoid accepting it. See
// the implementation.
AuthRequest{DeviceId: "dId", Email: "Joe <joe@example.com>", Password: "aoeu"},
"email",
"Expected AuthRequest with email with unexpected formatting to not successfully validate",
}, {
AuthRequest{DeviceId: "dId", Password: "aoeu"},
"email",
"Expected AuthRequest with missing email to not successfully validate",
}, {
AuthRequest{DeviceId: "dId", Email: "joe@example.com"},
"password",
"Expected AuthRequest with missing password to not successfully validate",
},
2022-06-17 22:15:27 +02:00
}
for _, tc := range tt {
err := tc.authRequest.validate()
if !strings.Contains(err.Error(), tc.expectedErrorSubstr) {
t.Errorf(tc.failureDescription)
}
2022-06-08 02:08:41 +02:00
}
}