Skip to content

Commit

Permalink
Merge pull request #145 from macyan13/feature/validations_for_app_que…
Browse files Browse the repository at this point in the history
…ries

Add validation for query's structure to prevent request to DB on invalid params
  • Loading branch information
macyan13 authored Jan 5, 2024
2 parents 6ad64c4 + ca0f5ce commit 1ce387c
Show file tree
Hide file tree
Showing 23 changed files with 516 additions and 197 deletions.
13 changes: 10 additions & 3 deletions backend/pkg/app/query/all_langs.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
package query

import "github.com/go-playground/validator/v10"

type AllLangs struct {
AuthorID string
AuthorID string `validate:"required"`
}

type AllLangsHandler struct {
langRepo LangViewRepository
sanitizer *strictSanitizer
validator *validator.Validate
}

func NewAllLangsHandler(langRepo LangViewRepository) AllLangsHandler {
return AllLangsHandler{langRepo: langRepo, sanitizer: newStrictSanitizer()}
func NewAllLangsHandler(langRepo LangViewRepository, validate *validator.Validate) AllLangsHandler {
return AllLangsHandler{langRepo: langRepo, sanitizer: newStrictSanitizer(), validator: validate}
}

func (h AllLangsHandler) Handle(query AllLangs) ([]LangView, error) {
if err := h.validator.Struct(query); err != nil {
return nil, err
}

langs, err := h.langRepo.GetAllViews(query.AuthorID)

if err != nil {
Expand Down
14 changes: 13 additions & 1 deletion backend/pkg/app/query/all_langs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package query

import (
"errors"
"github.com/go-playground/validator/v10"
"reflect"
"testing"
)
Expand All @@ -20,6 +21,15 @@ func TestAllLangsHandler_Handle(t *testing.T) {
want []LangView
wantErr bool
}{
{
"Error validation",
func() fields {
return fields{langRepo: &MockLangViewRepository{}}
},
args{cmd: AllLangs{AuthorID: ""}},
nil,
true,
},
{
"Error on DB query",
func() fields {
Expand Down Expand Up @@ -66,10 +76,12 @@ func TestAllLangsHandler_Handle(t *testing.T) {
false,
},
}

for _, tt := range tests {
v := validator.New()
t.Run(tt.name, func(t *testing.T) {
f := tt.fieldsFn()
h := NewAllLangsHandler(f.langRepo)
h := NewAllLangsHandler(f.langRepo, v)
got, err := h.Handle(tt.args.cmd)
if (err != nil) != tt.wantErr {
t.Errorf("Handle() error = %v, wantErr %v", err, tt.wantErr)
Expand Down
13 changes: 10 additions & 3 deletions backend/pkg/app/query/all_tags.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
package query

import "github.com/go-playground/validator/v10"

// AllTags get all tags for author query
type AllTags struct {
AuthorID string
AuthorID string `validate:"required"`
}

// AllTagsHandler get all tags for author query
type AllTagsHandler struct {
tagRepo TagViewRepository
sanitizer *strictSanitizer
validator *validator.Validate
}

func NewAllTagsHandler(tagRepository TagViewRepository) AllTagsHandler {
return AllTagsHandler{tagRepo: tagRepository, sanitizer: newStrictSanitizer()}
func NewAllTagsHandler(tagRepository TagViewRepository, validate *validator.Validate) AllTagsHandler {
return AllTagsHandler{tagRepo: tagRepository, sanitizer: newStrictSanitizer(), validator: validate}
}

// Handle performs query to receive all tags for author
func (h AllTagsHandler) Handle(query AllTags) ([]TagView, error) {
if err := h.validator.Struct(query); err != nil {
return nil, err
}

tags, err := h.tagRepo.GetAllViews(query.AuthorID)

if err != nil {
Expand Down
20 changes: 16 additions & 4 deletions backend/pkg/app/query/all_tags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package query

import (
"errors"
"github.com/go-playground/validator/v10"
"reflect"
"testing"
)
Expand All @@ -21,7 +22,16 @@ func TestAllTagsHandler_Handle(t *testing.T) {
wantErr bool
}{
{
"Case 1: error on DB query",
"Error on validation",
func() fields {
return fields{tagRepo: &MockTagViewRepository{}}
},
args{cmd: AllTags{AuthorID: ""}},
nil,
true,
},
{
"Error on DB query",
func() fields {
repo := MockTagViewRepository{}
repo.On("GetAllViews", "testAuthor").Return(nil, errors.New("testErr"))
Expand All @@ -32,7 +42,7 @@ func TestAllTagsHandler_Handle(t *testing.T) {
true,
},
{
"Case 2: positive case",
"Positive case",
func() fields {
repo := MockTagViewRepository{}
repo.On("GetAllViews", "testAuthor").Return([]TagView{{
Expand All @@ -49,7 +59,7 @@ func TestAllTagsHandler_Handle(t *testing.T) {
false,
},
{
"Case 3: check sanitization",
"Check sanitization",
func() fields {
repo := MockTagViewRepository{}
repo.On("GetAllViews", "testAuthor").Return([]TagView{{
Expand All @@ -66,10 +76,12 @@ func TestAllTagsHandler_Handle(t *testing.T) {
false,
},
}

v := validator.New()
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
fields := tt.fieldsFn()
h := NewAllTagsHandler(fields.tagRepo)
h := NewAllTagsHandler(fields.tagRepo, v)
got, err := h.Handle(tt.args.cmd)
if (err != nil) != tt.wantErr {
t.Errorf("Handle() error = %v, wantErr %v", err, tt.wantErr)
Expand Down
5 changes: 0 additions & 5 deletions backend/pkg/app/query/all_users.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
package query

// AllUsers get all users
type AllUsers struct {
AuthorID string
}

// AllUsersHandler get all users
type AllUsersHandler struct {
userRepo UserViewRepository
Expand Down
28 changes: 13 additions & 15 deletions backend/pkg/app/query/random_translations.go
Original file line number Diff line number Diff line change
@@ -1,25 +1,31 @@
package query

import "github.com/go-playground/validator/v10"

type RandomTranslations struct {
AuthorID string
LangID string
AuthorID string `validate:"required"`
LangID string `validate:"required"`
TagIds []string
Limit int
Limit int `validate:"gte=1,lte=200"`
}

type RandomTranslationsHandler struct {
translationRepo TranslationViewRepository
validator *validator.Validate
strictSntz *strictSanitizer
richSntz *richTextSanitizer
}

func NewRandomTranslationsHandler(translationRepo TranslationViewRepository) RandomTranslationsHandler {
return RandomTranslationsHandler{translationRepo: translationRepo, strictSntz: newStrictSanitizer(), richSntz: newRichTextSanitizer()}
func NewRandomTranslationsHandler(translationRepo TranslationViewRepository, validate *validator.Validate) RandomTranslationsHandler {
return RandomTranslationsHandler{translationRepo: translationRepo, validator: validate, strictSntz: newStrictSanitizer(), richSntz: newRichTextSanitizer()}
}

func (h RandomTranslationsHandler) Handle(query RandomTranslations) (RandomViews, error) {
limit := h.processLimit(query)
randomViews, err := h.translationRepo.GetRandomViews(query.AuthorID, query.LangID, query.TagIds, limit)
if err := h.validator.Struct(query); err != nil {
return RandomViews{}, err
}

randomViews, err := h.translationRepo.GetRandomViews(query.AuthorID, query.LangID, query.TagIds, query.Limit)

if err != nil {
return randomViews, err
Expand All @@ -31,11 +37,3 @@ func (h RandomTranslationsHandler) Handle(query RandomTranslations) (RandomViews

return randomViews, nil
}

func (h RandomTranslationsHandler) processLimit(query RandomTranslations) int {
if query.Limit < 1 || query.Limit > 100 {
return 10
}

return query.Limit
}
130 changes: 91 additions & 39 deletions backend/pkg/app/query/random_translations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,11 @@ package query

import (
"fmt"
"github.com/go-playground/validator/v10"
"github.com/stretchr/testify/assert"
"testing"
)

func TestRandomTranslationsHandler_processLimit(t *testing.T) {
type args struct {
query RandomTranslations
}
tests := []struct {
name string
args args
want int
}{
{
"Limit is below min, default value is expecting",
args{query: RandomTranslations{Limit: -4}},
10,
},
{
"Limit is below min, default value is expecting",
args{query: RandomTranslations{Limit: 0}},
10,
},
{
"Limit is higher max, default value is expecting",
args{query: RandomTranslations{Limit: 101}},
10,
},
{
"Limit is in acceptable range",
args{query: RandomTranslations{Limit: 54}},
54,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
h := RandomTranslationsHandler{}
assert.Equalf(t, tt.want, h.processLimit(tt.args.query), "processLimit(%v)", tt.args.query)
})
}
}

func TestRandomTranslationsHandler_Handle(t *testing.T) {
type fields struct {
translationRepo TranslationViewRepository
Expand All @@ -58,6 +21,15 @@ func TestRandomTranslationsHandler_Handle(t *testing.T) {
want RandomViews
wantErr assert.ErrorAssertionFunc
}{
{
"Error on query validation",
func() fields {
return fields{translationRepo: &MockTranslationViewRepository{}}
},
args{RandomTranslations{AuthorID: "authorID", LangID: "EN", TagIds: []string{}, Limit: 0}},
RandomViews{},
assert.Error,
},
{
"Error on getting random views from db",
func() fields {
Expand Down Expand Up @@ -96,10 +68,11 @@ func TestRandomTranslationsHandler_Handle(t *testing.T) {
assert.NoError,
},
}
v := validator.New()
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
f := tt.fieldsFn()
h := NewRandomTranslationsHandler(f.translationRepo)
h := NewRandomTranslationsHandler(f.translationRepo, v)
got, err := h.Handle(tt.args.query)
if !tt.wantErr(t, err, fmt.Sprintf("Handle(%v)", tt.args.query)) {
return
Expand All @@ -108,3 +81,82 @@ func TestRandomTranslationsHandler_Handle(t *testing.T) {
})
}
}

func TestRandomTranslationsValidation(t *testing.T) {
type args struct {
query RandomTranslations
}

tests := []struct {
name string
args args
wantErr assert.ErrorAssertionFunc
}{
{
name: "Valid case",
args: args{
query: RandomTranslations{
AuthorID: "123",
LangID: "en",
TagIds: []string{"tag1", "tag2"},
Limit: 100,
},
},
wantErr: assert.NoError,
},
{
name: "Missing AuthorID",
args: args{
query: RandomTranslations{
LangID: "en",
TagIds: []string{"tag1", "tag2"},
Limit: 100,
},
},
wantErr: assert.Error,
},
{
name: "Missing LangID",
args: args{
query: RandomTranslations{
AuthorID: "123",
TagIds: []string{"tag1", "tag2"},
Limit: 100,
},
},
wantErr: assert.Error,
},
{
name: "Invalid Limit (less than 1)",
args: args{
query: RandomTranslations{
AuthorID: "123",
LangID: "en",
TagIds: []string{"tag1", "tag2"},
Limit: 0,
},
},
wantErr: assert.Error,
},
{
name: "Invalid Limit (greater than 200)",
args: args{
query: RandomTranslations{
AuthorID: "123",
LangID: "en",
TagIds: []string{"tag1", "tag2"},
Limit: 201,
},
},
wantErr: assert.Error,
},
}

v := validator.New()
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
err := v.Struct(test.args.query)
test.wantErr(t, err)
})
}
}
3 changes: 2 additions & 1 deletion backend/pkg/app/query/search_translations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ func TestLastTranslationsHandler_Handle(t *testing.T) {
}
}

func TestSearchTranslations_Validations(t *testing.T) {
func TestSearchTranslationsValidation(t *testing.T) {
type args struct {
query SearchTranslations
}
Expand Down Expand Up @@ -221,6 +221,7 @@ func TestSearchTranslations_Validations(t *testing.T) {
assert.NoError,
},
}

v := validator.New()
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down
Loading

0 comments on commit 1ce387c

Please sign in to comment.