3
0
Files
corteza/system/routes_test.go
Denis Arh 980b6d581c Refactor JWT encoder/handler
Handler is no longer passed as argument into routes etc but initialized in the Init()
and stored into auth.DefaultJwtHandler.
2019-04-27 13:17:37 +02:00

349 lines
10 KiB
Go

// +build integration-disabled
package service
import (
"context"
"encoding/json"
"fmt"
"io"
"log"
"net/url"
"os"
"strings"
"testing"
"time"
"net/http"
"net/http/httptest"
"net/http/httputil"
"github.com/crusttech/crust/internal/auth"
"github.com/crusttech/crust/internal/test"
systemRepository "github.com/crusttech/crust/system/internal/repository"
systemTypes "github.com/crusttech/crust/system/types"
"github.com/dgrijalva/jwt-go"
"github.com/namsral/flag"
)
type (
jsonResponse struct {
Error struct {
Message string `json:"message"`
Trace string `json:"trace,omitempty"`
} `json:"error"`
}
)
func TestUsers(t *testing.T) {
ctx := context.Background()
// we need to set this due to using Init()
os.Setenv("SYSTEM_DB_DSN", "crust:crust@tcp(crust-db:3306)/crust?collation=utf8mb4_general_ci")
mountFlags("system", Flags)
// log to stdout not stderr
log.SetOutput(os.Stdout)
log.SetFlags(log.LstdFlags | log.Lshortfile)
// Initialize routes and exit on failure.
err := Init(ctx)
test.Assert(t, err == nil, "Error initializing: %+v", err)
jwtSecret := "test-secret"
jwtAuth, err := auth.JWT(jwtSecret, 600)
test.NoError(t, err, "Error initializing: %v")
routes := Routes(ctx)
// Send check request with invalid JWT token.
{
req, err := http.NewRequest("GET", "http://127.0.0.1/auth/check", nil)
test.Assert(t, err == nil, "Error creating request: %+v", err)
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"id": "zblj",
"nbf": time.Date(2015, 10, 10, 12, 0, 0, 0, time.UTC).Unix(),
})
jwtAuth.Encode()
tokenString, err := token.SignedString([]byte(jwtSecret))
test.Assert(t, err == nil, "Error creating JWT token: %+v", err)
req.AddCookie(&http.Cookie{
Name: "jwt",
Value: tokenString,
Domain: ".localhost",
Expires: time.Now().Add(time.Hour),
HttpOnly: true,
MaxAge: 50000,
Path: "/auth",
})
recorder := httptest.NewRecorder()
routes.ServeHTTP(recorder, req)
resp := recorder.Result()
fmt.Println(">>> (request)")
fmt.Println(request(req))
fmt.Println("----")
fmt.Println("<<< (response)")
fmt.Println(response(resp))
jr, err := decodeJson(resp.Body)
test.Assert(t, err == nil, "Error decoding response body: %+v", err)
test.Assert(t, jr.Error.Message == "failed to authorize request: signature is invalid", "Expected error 'failed to authorize request: signature is invalid' got: %+v", jr.Error.Message)
}
// Send "Login" request without parameters.
{
req, err := http.NewRequest("POST", "http://localhost/auth/login", nil)
test.Assert(t, err == nil, "Error creating request: %+v", err)
recorder := httptest.NewRecorder()
routes.ServeHTTP(recorder, req)
resp := recorder.Result()
fmt.Println(">>> (request)")
fmt.Println(request(req))
fmt.Println("----")
fmt.Println("<<< (response)")
fmt.Println(response(resp))
jr, err := decodeJson(resp.Body)
test.Assert(t, err == nil, "Error decoding response body: %+v", err)
test.Assert(t, jr.Error.Message == "missing form body", "Expected error 'missing form body' got: %+v", jr.Error.Message)
}
// Send "Login" request with missing user.
{
jsonStr := `{"username":"test123","password":"test123"}`
req, err := http.NewRequest("POST", "http://localhost/auth/login", strings.NewReader(jsonStr))
req.Header.Set("Content-Type", "application/json")
test.Assert(t, err == nil, "Error creating request: %+v", err)
recorder := httptest.NewRecorder()
routes.ServeHTTP(recorder, req)
resp := recorder.Result()
fmt.Println(">>> (request)")
fmt.Println(request(req))
fmt.Println("----")
fmt.Println("<<< (response)")
fmt.Println(response(resp))
jr, err := decodeJson(resp.Body)
test.Assert(t, err == nil, "Error decoding response body: %+v", err)
test.Assert(t, jr.Error.Message == "crust.auth.repository.UserNotFound", "Expected error 'crust.auth.repository.UserNotFound' got: %+v", jr.Error.Message)
}
// Create user.
user := &systemTypes.User{
ID: 1337,
Username: "johndoe",
}
{
userAPI := systemRepository.User(context.Background(), nil)
_, err := userAPI.Create(user)
test.Assert(t, err == nil, "Error when inserting user: %+v", err)
}
// Send "Login" request with existing user.
if false {
form := url.Values{}
form.Add("username", "johndoe")
form.Add("password", "johndoe123")
req, err := http.NewRequest("POST", "http://localhost/auth/login", strings.NewReader(form.Encode()))
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
test.Assert(t, err == nil, "Error creating request: %+v", err)
recorder := httptest.NewRecorder()
routes.ServeHTTP(recorder, req)
resp := recorder.Result()
fmt.Println(">>> (request)")
fmt.Println(request(req))
fmt.Println("----")
fmt.Println("<<< (response)")
fmt.Println(response(resp))
c := resp.Cookies()
test.Assert(t, len(c) == 1, "Expected 1 cookie value, got: %+v", len(c))
test.Assert(t, c[0].Value != "", "Expected non empty jwt token, got: %+v", c[0].Value)
type jsonResponse struct {
Response struct {
UserID string `json:"userID"`
Username string `json:"username"`
} `json:"response"`
}
var jr jsonResponse
err = json.NewDecoder(resp.Body).Decode(&jr)
test.Assert(t, err == nil, "Error decoding response body: %+v", err)
test.Assert(t, jr.Response.UserID != "0", "Expected userID not to be 0, got: %+v", jr.Response.UserID)
test.Assert(t, jr.Response.Username == "johndoe", "Expected username 'johndoe', got: %+v", jr.Response.Username)
// Check JWT token after successful login.
req, err = http.NewRequest("GET", "http://localhost/auth/check", nil)
test.Assert(t, err == nil, "Error creating request: %+v", err)
routes.ServeHTTP(recorder, req)
resp = recorder.Result()
fmt.Println(">>> (request)")
fmt.Println(request(req))
fmt.Println("----")
fmt.Println("<<< (response)")
fmt.Println(response(resp))
test.Assert(t, resp.StatusCode == 200, "Expected http status code 200, got: %+v", resp.StatusCode)
test.Assert(t, len(c) == 1, "Expected 1 cookie value, got: %+v", len(c))
test.Assert(t, c[0].Value != "", "Expected non empty jwt token, got: %+v", c[0].Value)
}
// Send "Login" request with existing user.
{
jsonStr := `{"username": "johndoe", "password": "johndoe123"}`
req, err := http.NewRequest("POST", "http://localhost/auth/login", strings.NewReader(jsonStr))
req.Header.Add("Content-Type", "application/json")
test.Assert(t, err == nil, "Error creating request: %+v", err)
recorder := httptest.NewRecorder()
routes.ServeHTTP(recorder, req)
resp := recorder.Result()
fmt.Println(">>> (request)")
fmt.Println(request(req))
fmt.Println("----")
fmt.Println("<<< (response)")
fmt.Println(response(resp))
c := resp.Cookies()
test.Assert(t, len(c) == 1, "Expected 1 cookie value, got: %+v", len(c))
test.Assert(t, c[0].Value != "", "Expected non empty jwt token, got: %+v", c[0].Value)
type jsonResponse struct {
Response struct {
UserID string `json:"userID"`
Username string `json:"username"`
} `json:"response"`
}
var jr jsonResponse
err = json.NewDecoder(resp.Body).Decode(&jr)
test.Assert(t, err == nil, "Error decoding response body: %+v", err)
test.Assert(t, jr.Response.UserID != "0", "Expected userID not to be 0, got: %+v", jr.Response.UserID)
test.Assert(t, jr.Response.Username == "johndoe", "Expected username 'johndoe', got: %+v", jr.Response.Username)
// Check JWT token after successful login.
req, err = http.NewRequest("GET", "http://localhost/auth/check", nil)
test.Assert(t, err == nil, "Error creating request: %+v", err)
routes.ServeHTTP(recorder, req)
resp = recorder.Result()
fmt.Println(">>> (request)")
fmt.Println(request(req))
fmt.Println("----")
fmt.Println("<<< (response)")
fmt.Println(response(resp))
test.Assert(t, resp.StatusCode == 200, "Expected http status code 200, got: %+v", resp.StatusCode)
test.Assert(t, len(c) == 1, "Expected 1 cookie value, got: %+v", len(c))
test.Assert(t, c[0].Value != "", "Expected non empty jwt token, got: %+v", c[0].Value)
}
// Send "Logout" request and expect empty jwt token.
{
req, err := http.NewRequest("GET", "http://localhost/auth/logout", nil)
test.Assert(t, err == nil, "Error creating request: %+v", err)
recorder := httptest.NewRecorder()
routes.ServeHTTP(recorder, req)
resp := recorder.Result()
fmt.Println(">>> (request)")
fmt.Println(request(req))
fmt.Println("----")
fmt.Println("<<< (response)")
fmt.Println(response(resp))
c := resp.Cookies()
test.Assert(t, resp.StatusCode == 200, "Expected http status code 200, got: %+v", resp.StatusCode)
test.Assert(t, len(c) == 1, "Expected 1 cookie value, got: %+v", len(c))
test.Assert(t, c[0].Value == "", "Expected empty jwt token, got: %+v", c[0].Value)
}
// Send check request without JWT token.
{
req, err := http.NewRequest("GET", "http://127.0.0.1/auth/check", nil)
test.Assert(t, err == nil, "Error creating request: %+v", err)
recorder := httptest.NewRecorder()
routes.ServeHTTP(recorder, req)
resp := recorder.Result()
fmt.Println(">>> (request)")
fmt.Println(request(req))
fmt.Println("----")
fmt.Println("<<< (response)")
fmt.Println(response(resp))
jr, err := decodeJson(resp.Body)
test.Assert(t, err == nil, "Error decoding response body: %+v", err)
test.Assert(t, jr.Error.Message == "http: named cookie not present", "Expected error 'http: named cookie not present' got: %+v", jr.Error.Message)
}
}
func request(req *http.Request) string {
b, err := httputil.DumpRequestOut(req, true)
if err != nil {
return ">>> Error: " + err.Error()
}
if b != nil {
return strings.TrimSpace(string(b))
}
return ""
}
func response(resp *http.Response) string {
b, err := httputil.DumpResponse(resp, true)
if err != nil {
return "<<< Error: " + err.Error()
}
if b != nil {
return strings.TrimSpace(string(b))
}
return ""
}
func mountFlags(prefix string, mountFlags ...func(...string)) {
for _, mount := range mountFlags {
mount(prefix)
}
flag.Parse()
}
func decodeJson(r io.Reader) (jsonResponse, error) {
var ret jsonResponse
err := json.NewDecoder(r).Decode(&ret)
if err != nil {
return jsonResponse{}, err
}
return ret, nil
}