fix(filters): validate filter expression when creating or updating filter

Resolves https://github.com/go-vikunja/vikunja/issues/354
This commit is contained in:
kolaente 2024-11-18 11:02:21 +01:00
parent 1db1333d8a
commit bd3eab8c34
No known key found for this signature in database
GPG Key ID: F40E70337AB24C9B
2 changed files with 74 additions and 26 deletions

View File

@ -123,6 +123,11 @@ func (sf *SavedFilter) toProject() *Project {
// @Failure 500 {object} models.Message "Internal error"
// @Router /filters [put]
func (sf *SavedFilter) Create(s *xorm.Session, auth web.Auth) (err error) {
_, err = getTaskFiltersFromFilterString(sf.Filters.Filter, sf.Filters.FilterTimezone)
if err != nil {
return
}
sf.OwnerID = auth.GetID()
sf.ID = 0
_, err = s.Insert(sf)
@ -190,6 +195,11 @@ func (sf *SavedFilter) Update(s *xorm.Session, _ web.Auth) error {
sf.Filters = origFilter.Filters
}
_, err = getTaskFiltersFromFilterString(sf.Filters.Filter, sf.Filters.FilterTimezone)
if err != nil {
return err
}
_, err = s.
Where("id = ?", sf.ID).
Cols(

View File

@ -46,34 +46,56 @@ func TestSavedFilter_getFilterIDFromProjectID(t *testing.T) {
}
func TestSavedFilter_Create(t *testing.T) {
db.LoadAndAssertFixtures(t)
s := db.NewSession()
defer s.Close()
t.Run("empty filter", func(t *testing.T) {
db.LoadAndAssertFixtures(t)
s := db.NewSession()
defer s.Close()
sf := &SavedFilter{
Title: "test",
Description: "Lorem Ipsum dolor sit amet",
Filters: &TaskCollection{}, // Empty filter
}
sf := &SavedFilter{
Title: "test",
Description: "Lorem Ipsum dolor sit amet",
Filters: &TaskCollection{}, // Empty filter
}
u := &user.User{ID: 1}
err := sf.Create(s, u)
require.NoError(t, err)
assert.Equal(t, u.ID, sf.OwnerID)
err = s.Commit()
require.NoError(t, err)
vals := map[string]interface{}{
"title": "'test'",
"description": "'Lorem Ipsum dolor sit amet'",
"filters": "'{\"sort_by\":null,\"order_by\":null,\"filter\":\"\",\"filter_include_nulls\":false}'",
"owner_id": 1,
}
// Postgres can't compare json values directly, see https://dba.stackexchange.com/a/106290/210721
if db.Type() == schemas.POSTGRES {
vals["filters::jsonb"] = vals["filters"].(string) + "::jsonb"
delete(vals, "filters")
}
db.AssertExists(t, "saved_filters", vals, true)
u := &user.User{ID: 1}
err := sf.Create(s, u)
require.NoError(t, err)
assert.Equal(t, u.ID, sf.OwnerID)
err = s.Commit()
require.NoError(t, err)
vals := map[string]interface{}{
"title": "'test'",
"description": "'Lorem Ipsum dolor sit amet'",
"filters": "'{\"sort_by\":null,\"order_by\":null,\"filter\":\"\",\"filter_include_nulls\":false}'",
"owner_id": 1,
}
// Postgres can't compare json values directly, see https://dba.stackexchange.com/a/106290/210721
if db.Type() == schemas.POSTGRES {
vals["filters::jsonb"] = vals["filters"].(string) + "::jsonb"
delete(vals, "filters")
}
db.AssertExists(t, "saved_filters", vals, true)
})
t.Run("invalid filter string", func(t *testing.T) {
db.LoadAndAssertFixtures(t)
s := db.NewSession()
defer s.Close()
sf := &SavedFilter{
Title: "test",
Description: "Lorem Ipsum dolor sit amet",
Filters: &TaskCollection{
Filter: "foo = value",
},
}
u := &user.User{ID: 1}
err := sf.Create(s, u)
require.Error(t, err)
db.AssertMissing(t, "saved_filters", map[string]interface{}{
"title": "test",
})
})
}
func TestSavedFilter_ReadOne(t *testing.T) {
@ -134,6 +156,22 @@ func TestSavedFilter_Update(t *testing.T) {
"is_favorite": true,
}, false)
})
t.Run("invalid filter string", func(t *testing.T) {
db.LoadAndAssertFixtures(t)
s := db.NewSession()
defer s.Close()
sf := &SavedFilter{
ID: 1,
Title: "NewTitle",
Description: "", // Explicitly reset the description
Filters: &TaskCollection{
Filter: "foo = bar",
},
}
err := sf.Update(s, &user.User{ID: 1})
require.Error(t, err)
})
}
func TestSavedFilter_Delete(t *testing.T) {