Compare commits

...

2 Commits

Author SHA1 Message Date
6dd91f5a1b Adds tests for auth route
All checks were successful
gitea-deepak/gogmagog/pipeline/head This commit looks good
gitea-deepak/gogmagog/pipeline/pr-master This commit looks good
2021-01-25 16:23:42 -06:00
249fabbd7a Adds tests for register route 2021-01-25 15:18:56 -06:00
6 changed files with 477 additions and 2 deletions

View File

@@ -9,7 +9,8 @@ import (
"net/http"
)
func newAuthRouter(m *models.Model, tok tokens.Toker) http.Handler {
// NewAuthRouter returns a new auth router.
func NewAuthRouter(m *models.Model, tok tokens.Toker) http.Handler {
router := chi.NewRouter()
router.Post("/register", postUserFunc(m))
router.Post("/tokens", createTokenFunc(m, tok))

202
routes/auth_login_test.go Normal file
View File

@@ -0,0 +1,202 @@
package routes_test
import (
"bytes"
"gitea.deepak.science/deepak/gogmagog/models"
"gitea.deepak.science/deepak/gogmagog/routes"
"gitea.deepak.science/deepak/gogmagog/tokens"
"github.com/stretchr/testify/assert"
"net/http"
"net/http/httptest"
"testing"
)
func TestLoginAuth(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
username := "testing_username"
displayName := "testing_name"
password := "pass"
m.CreateUser(&models.CreateUserRequest{Username: username, DisplayName: displayName, Password: password})
toker := tokens.GetDeterministicToker()
data := []byte(`{
"username": "testing_username",
"password": "pass"
}`)
req, _ := http.NewRequest("POST", "/tokens", bytes.NewBuffer(data))
rr := httptest.NewRecorder()
// function under test
router := routes.NewAuthRouter(m, toker)
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusOK, status)
expected := `{
"token": "{\"ID\":1,\"Username\":\"testing_username\"}"
}`
assert.JSONEq(expected, rr.Body.String())
contentType := rr.Header().Get("Content-Type")
assert.Equal("application/json", contentType)
}
func TestLoginBadCreds(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
toker := tokens.GetDeterministicToker()
data := []byte(`{
"username": "testing_use
}`)
req, _ := http.NewRequest("POST", "/tokens", bytes.NewBuffer(data))
rr := httptest.NewRecorder()
// function under test
router := routes.NewAuthRouter(m, toker)
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusBadRequest, status)
}
func TestLoginBadRequestTwoBodies(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
toker := tokens.GetDeterministicToker()
data := []byte(`{
"username": "testing_username",
"password": "pass"
}{
"username": "testing_username",
"password": "pass"
}`)
req, _ := http.NewRequest("POST", "/tokens", bytes.NewBuffer(data))
rr := httptest.NewRecorder()
// function under test
router := routes.NewAuthRouter(m, toker)
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusBadRequest, status)
}
func TestLoginAuthWrongPass(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
username := "testing_username"
displayName := "testing_name"
password := "pass"
m.CreateUser(&models.CreateUserRequest{Username: username, DisplayName: displayName, Password: password})
toker := tokens.GetDeterministicToker()
data := []byte(`{
"username": "testing_username",
"password": "badpass"
}`)
req, _ := http.NewRequest("POST", "/tokens", bytes.NewBuffer(data))
rr := httptest.NewRecorder()
// function under test
router := routes.NewAuthRouter(m, toker)
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusUnauthorized, status)
}
func TestLoginErrorModel(t *testing.T) {
// set up
assert := assert.New(t)
m := getErrorModel("error")
toker := tokens.GetDeterministicToker()
data := []byte(`{
"username": "testing_username",
"password": "badpass"
}`)
req, _ := http.NewRequest("POST", "/tokens", bytes.NewBuffer(data))
rr := httptest.NewRecorder()
// function under test
router := routes.NewAuthRouter(m, toker)
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusInternalServerError, status)
}
func TestLoginBadWriter(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
username := "testing_username"
displayName := "testing_name"
password := "pass"
m.CreateUser(&models.CreateUserRequest{Username: username, DisplayName: displayName, Password: password})
toker := tokens.GetDeterministicToker()
data := []byte(`{
"username": "testing_username",
"password": "pass"
}`)
req, _ := http.NewRequest("POST", "/tokens", bytes.NewBuffer(data))
rr := NewBadWriter()
// function under test
router := routes.NewAuthRouter(m, toker)
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusInternalServerError, status)
}
//
// func TestRegisterBadWriter(t *testing.T) {
// // set up
// assert := assert.New(t)
// m := getEmptyModel()
// toker := tokens.New("secret")
// data := []byte(`{
// "username": "test",
// "password": "pass",
// "display_name": "My Display Name"
// }`)
// req, _ := http.NewRequest("POST", "/register", bytes.NewBuffer(data))
//
// rr := NewBadWriter()
//
// // function under test
// router := routes.NewAuthRouter(m, toker)
// router.ServeHTTP(rr, req)
//
// // check results
// status := rr.Code
// assert.Equal(http.StatusInternalServerError, status)
//
// }

View File

@@ -0,0 +1,139 @@
package routes_test
import (
"bytes"
"gitea.deepak.science/deepak/gogmagog/routes"
"gitea.deepak.science/deepak/gogmagog/tokens"
"github.com/stretchr/testify/assert"
"net/http"
"net/http/httptest"
"testing"
)
func TestRegisterAuth(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
toker := tokens.New("secret")
data := []byte(`{
"username": "test",
"password": "pass",
"display_name": "My Display Name"
}`)
req, _ := http.NewRequest("POST", "/register", bytes.NewBuffer(data))
rr := httptest.NewRecorder()
// function under test
router := routes.NewAuthRouter(m, toker)
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusCreated, status)
expected := `{
"username": "test"
}`
assert.JSONEq(expected, rr.Body.String())
contentType := rr.Header().Get("Content-Type")
assert.Equal("application/json", contentType)
}
func TestRegisterBadRequestAuth(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
toker := tokens.New("secret")
data := []byte(`{
"username": y Display Name"
}`)
req, _ := http.NewRequest("POST", "/register", bytes.NewBuffer(data))
rr := httptest.NewRecorder()
// function under test
router := routes.NewAuthRouter(m, toker)
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusBadRequest, status)
}
func TestRegisterBadRequestTwoBodies(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
toker := tokens.New("secret")
data := []byte(`{
"username": "test",
"password": "pass",
"display_name": "My Display Name"
}, {
"username": "test",
"password": "pass",
"display_name": "My Display Name"
}`)
req, _ := http.NewRequest("POST", "/register", bytes.NewBuffer(data))
rr := httptest.NewRecorder()
// function under test
router := routes.NewAuthRouter(m, toker)
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusBadRequest, status)
}
func TestRegisterErrorModel(t *testing.T) {
// set up
assert := assert.New(t)
m := getErrorModel("here's an error")
toker := tokens.New("secret")
data := []byte(`{
"username": "test",
"password": "pass",
"display_name": "My Display Name"
}`)
req, _ := http.NewRequest("POST", "/register", bytes.NewBuffer(data))
rr := httptest.NewRecorder()
// function under test
router := routes.NewAuthRouter(m, toker)
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusInternalServerError, status)
}
func TestRegisterBadWriter(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
toker := tokens.New("secret")
data := []byte(`{
"username": "test",
"password": "pass",
"display_name": "My Display Name"
}`)
req, _ := http.NewRequest("POST", "/register", bytes.NewBuffer(data))
rr := NewBadWriter()
// function under test
router := routes.NewAuthRouter(m, toker)
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusInternalServerError, status)
}

View File

@@ -19,7 +19,7 @@ func NewRouter(m *models.Model, tok tokens.Toker) http.Handler {
r.Mount("/plans", NewPlanRouter(m))
r.Mount("/me", NewCurrentUserRouter(m))
})
router.Mount("/auth", newAuthRouter(m, tok))
router.Mount("/auth", NewAuthRouter(m, tok))
router.Mount("/health", newHealthRouter(m))
router.Get("/ping", ping)
return router

View File

@@ -0,0 +1,53 @@
package tokens
import (
"context"
"encoding/json"
"gitea.deepak.science/deepak/gogmagog/models"
"log"
"net/http"
)
type deterministicToker struct{}
// GetDeterministicToker returns a zero security toker for testing purposes.
// Do not use in production.
func GetDeterministicToker() Toker {
return &deterministicToker{}
}
func (d *deterministicToker) EncodeUser(user *models.UserNoPassword) string {
tok := &UserToken{ID: user.UserID, Username: user.Username}
ret, _ := json.Marshal(tok)
return string(ret)
}
func (d *deterministicToker) DecodeTokenString(tokenString string) (*UserToken, error) {
var tok UserToken
err := json.Unmarshal([]byte(tokenString), &tok)
return &tok, err
}
func (d *deterministicToker) Authenticator(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
tokenString := TokenFromHeader(r)
if tokenString == "" {
log.Print("No valid token found")
unauthorized(w, r)
return
}
userToken, err := d.DecodeTokenString(tokenString)
if err != nil {
log.Printf("Error while verifying token: %s", err)
unauthorized(w, r)
return
}
log.Printf("Got user with ID: [%d]", userToken.ID)
ctx := context.WithValue(r.Context(), userIDCtxKey, userToken.ID)
ctx = context.WithValue(ctx, usernameCtxKey, userToken.Username)
// Authenticated
next.ServeHTTP(w, r.WithContext(ctx))
})
}

View File

@@ -0,0 +1,80 @@
package tokens_test
import (
"gitea.deepak.science/deepak/gogmagog/models"
"gitea.deepak.science/deepak/gogmagog/tokens"
"github.com/stretchr/testify/assert"
"log"
"net/http"
"net/http/httptest"
"testing"
)
var dtMiddlewareURL string = "/"
func dtRequestAuth(header string) *http.Request {
req, _ := http.NewRequest("GET", dtMiddlewareURL, nil)
req.Header.Add(authKey, header)
return req
}
func verifyingHandlerdt(t *testing.T, username string, userID int) http.Handler {
assert := assert.New(t)
toker := tokens.GetDeterministicToker()
dummyHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
receivedID, _ := tokens.GetUserID(ctx)
receivedUsername, _ := tokens.GetUsername(ctx)
assert.EqualValues(userID, receivedID)
assert.Equal(username, receivedUsername)
})
return toker.Authenticator(dummyHandler)
}
func TestMiddlewareNoTokendt(t *testing.T) {
assert := assert.New(t)
req := httptest.NewRequest(http.MethodGet, dtMiddlewareURL, nil)
rr := httptest.NewRecorder()
middlewareHandler := verifyingHandlerdt(t, "", 0)
middlewareHandler.ServeHTTP(rr, req)
status := rr.Code
assert.Equal(http.StatusUnauthorized, status)
}
func TestMiddlewareBadTokendt(t *testing.T) {
assert := assert.New(t)
req := mwRequestAuth("Bearer bad")
rr := httptest.NewRecorder()
middlewareHandler := verifyingHandlerdt(t, "", 0)
middlewareHandler.ServeHTTP(rr, req)
status := rr.Code
assert.Equal(http.StatusUnauthorized, status)
}
func TestMiddlewareGoodTokendt(t *testing.T) {
assert := assert.New(t)
idToUse := 3
username := "username"
displayName := "display name"
user := &models.UserNoPassword{UserID: int64(idToUse), Username: username, DisplayName: displayName}
toker := tokens.GetDeterministicToker()
validToken := toker.EncodeUser(user)
log.Print(validToken)
req := mwRequestAuth("Bearer " + validToken)
rr := httptest.NewRecorder()
middlewareHandler := verifyingHandlerdt(t, username, idToUse)
middlewareHandler.ServeHTTP(rr, req)
status := rr.Code
assert.Equal(http.StatusOK, status)
}