diff --git a/auth/auth.go b/auth/auth.go index 8fbc48b..1d0ba88 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -23,6 +23,13 @@ type Env struct { jwtCredential *comm.JWTCredential } +func Router(env Env) *mux.Router { + r := mux.NewRouter() + r.HandleFunc("/auth", env.authCreateHandler).Methods(http.MethodPost) + r.HandleFunc("/auth", env.authReadHandler).Methods(http.MethodGet) + return r +} + func main() { configPtr := flag.String("config", "/etc/auth-service/config.json", "configuration filepath") flag.Parse() @@ -48,10 +55,7 @@ func main() { env := Env{d, c, jwtCredential} - r := mux.NewRouter() - r.HandleFunc("/auth", env.authCreateHandler).Methods(http.MethodPost) - r.HandleFunc("/auth", env.authReadHandler).Methods(http.MethodGet) - log.Fatal(http.ListenAndServe(":82", r)) + log.Fatal(http.ListenAndServe(":82", Router(env))) } func (env *Env) authCreateHandler(w http.ResponseWriter, r *http.Request) { diff --git a/auth/auth_test.go b/auth/auth_test.go new file mode 100644 index 0000000..aabaa1b --- /dev/null +++ b/auth/auth_test.go @@ -0,0 +1,125 @@ +package main + +import ( + "encoding/json" + "net/http" + "net/http/httptest" + "strings" + "testing" + + "github.com/TempleEight/spec-golang/auth/comm" + "github.com/TempleEight/spec-golang/auth/dao" + "github.com/dgrijalva/jwt-go" +) + +type MockAuth struct { + ID int + Email string + Password string +} + +type MockDAO struct { + AuthList []MockAuth +} + +type MockComm struct{} + +func (md *MockDAO) CreateAuth(request dao.AuthCreateRequest) (*dao.Auth, error) { + mockAuth := MockAuth{len(md.AuthList), request.Email, request.Password} + md.AuthList = append(md.AuthList, mockAuth) + return &dao.Auth{ + Id: mockAuth.ID, + Email: mockAuth.Email, + Password: mockAuth.Password, + }, nil +} + +func (md *MockDAO) ReadAuth(request dao.AuthReadRequest) (*dao.Auth, error) { + for _, auth := range md.AuthList { + if auth.Email == request.Email { + return &dao.Auth{ + Id: auth.ID, + Email: auth.Email, + Password: auth.Password, + }, nil + } + } + return nil, dao.ErrAuthNotFound +} + +func (mc *MockComm) CreateJWTCredential() (*comm.JWTCredential, error) { + return &comm.JWTCredential{ + Key: "MyKey", + Secret: "ShhItsASecret", + }, nil +} + +func makeRequest(env Env, method string, url string, body string) (*httptest.ResponseRecorder, error) { + rec := httptest.NewRecorder() + req, err := http.NewRequest(method, url, strings.NewReader(body)) + if err != nil { + return nil, err + } + + Router(env).ServeHTTP(rec, req) + return rec, nil +} + +// Test that an auth can be successfully created +func TestAuthCreateHandlerSucceeds(t *testing.T) { + mockComm := MockComm{} + cred, _ := mockComm.CreateJWTCredential() + mockEnv := Env{ + &MockDAO{AuthList: make([]MockAuth, 0)}, + &mockComm, + cred, + } + + res, err := makeRequest(mockEnv, http.MethodPost, "/auth", `{"email": "jay@test.com", "password": "BlackcurrantCrush123"}`) + if err != nil { + t.Fatalf("Could not make request: %s", err.Error()) + } + + if res.Code != http.StatusOK { + t.Errorf("Wrong status code %v", res.Code) + } + + var decoded map[string]string + err = json.Unmarshal([]byte(res.Body.String()), &decoded) + if err != nil { + t.Fatalf("Could not decode json: %s", err.Error()) + } + + rawToken, ok := decoded["AccessToken"] + if !ok { + t.Fatalf("Token doesn't contain an access token: %s", err.Error()) + } + + token, _, err := new(jwt.Parser).ParseUnverified(rawToken, jwt.MapClaims{}) + if err != nil { + t.Fatalf("Could not decode JWT: %s", err.Error()) + } + + claims, ok := token.Claims.(jwt.MapClaims) + if !ok { + t.Fatalf("Could not decode claims") + } + + id, ok := claims["id"] + if !ok { + t.Fatalf("Claims doesn't contain an ID key") + } + + if id.(float64) != 0 { + t.Fatalf("ID is incorrect: found %+v, wanted: 0", id) + } + + iss, ok := claims["iss"] + if !ok { + t.Fatalf("Claims doesn't contain an iss key") + } + + if iss.(string) != cred.Key { + t.Fatalf("iss is incorrect: found %v, wanted: %s", iss, cred.Key) + } +} diff --git a/auth/go.mod b/auth/go.mod index 2584b0d..cb1c5d7 100644 --- a/auth/go.mod +++ b/auth/go.mod @@ -4,8 +4,8 @@ go 1.13 require ( github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496 - github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect + github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/gorilla/mux v1.7.4 github.com/lib/pq v1.3.0 - golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d // indirect + golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d )