Adds upper limit validation to property fields and values (#33659)

Co-authored-by: Miguel de la Cruz <miguel@ctrlz.es>
This commit is contained in:
Miguel de la Cruz
2025-09-19 20:52:34 +02:00
committed by GitHub
parent eabea443a4
commit b9cf758756
4 changed files with 203 additions and 0 deletions
+29
View File
@@ -8,6 +8,7 @@ import (
"errors"
"fmt"
"net/http"
"unicode/utf8"
)
type PropertyFieldType string
@@ -19,6 +20,10 @@ const (
PropertyFieldTypeDate PropertyFieldType = "date"
PropertyFieldTypeUser PropertyFieldType = "user"
PropertyFieldTypeMultiuser PropertyFieldType = "multiuser"
PropertyFieldNameMaxRunes = 255
PropertyFieldTargetIDMaxRunes = 255
PropertyFieldTargetTypeMaxRunes = 255
)
type PropertyField struct {
@@ -74,6 +79,18 @@ func (pf *PropertyField) IsValid() error {
return NewAppError("PropertyField.IsValid", "model.property_field.is_valid.app_error", map[string]any{"FieldName": "name", "Reason": "value cannot be empty"}, "id="+pf.ID, http.StatusBadRequest)
}
if utf8.RuneCountInString(pf.Name) > PropertyFieldNameMaxRunes {
return NewAppError("PropertyField.IsValid", "model.property_field.is_valid.app_error", map[string]any{"FieldName": "name", "Reason": "value exceeds maximum length"}, "id="+pf.ID, http.StatusBadRequest)
}
if utf8.RuneCountInString(pf.TargetType) > PropertyFieldTargetTypeMaxRunes {
return NewAppError("PropertyField.IsValid", "model.property_field.is_valid.app_error", map[string]any{"FieldName": "target_type", "Reason": "value exceeds maximum length"}, "id="+pf.ID, http.StatusBadRequest)
}
if utf8.RuneCountInString(pf.TargetID) > PropertyFieldTargetIDMaxRunes {
return NewAppError("PropertyField.IsValid", "model.property_field.is_valid.app_error", map[string]any{"FieldName": "target_id", "Reason": "value exceeds maximum length"}, "id="+pf.ID, http.StatusBadRequest)
}
if pf.Type != PropertyFieldTypeText &&
pf.Type != PropertyFieldTypeSelect &&
pf.Type != PropertyFieldTypeMultiselect &&
@@ -117,6 +134,18 @@ func (pfp *PropertyFieldPatch) IsValid() error {
return NewAppError("PropertyFieldPatch.IsValid", "model.property_field.is_valid.app_error", map[string]any{"FieldName": "name", "Reason": "value cannot be empty"}, "", http.StatusBadRequest)
}
if pfp.Name != nil && utf8.RuneCountInString(*pfp.Name) > PropertyFieldNameMaxRunes {
return NewAppError("PropertyFieldPatch.IsValid", "model.property_field.is_valid.app_error", map[string]any{"FieldName": "name", "Reason": "value exceeds maximum length"}, "", http.StatusBadRequest)
}
if pfp.TargetType != nil && utf8.RuneCountInString(*pfp.TargetType) > PropertyFieldTargetTypeMaxRunes {
return NewAppError("PropertyFieldPatch.IsValid", "model.property_field.is_valid.app_error", map[string]any{"FieldName": "target_type", "Reason": "value exceeds maximum length"}, "", http.StatusBadRequest)
}
if pfp.TargetID != nil && utf8.RuneCountInString(*pfp.TargetID) > PropertyFieldTargetIDMaxRunes {
return NewAppError("PropertyFieldPatch.IsValid", "model.property_field.is_valid.app_error", map[string]any{"FieldName": "target_id", "Reason": "value exceeds maximum length"}, "", http.StatusBadRequest)
}
if pfp.Type != nil &&
*pfp.Type != PropertyFieldTypeText &&
*pfp.Type != PropertyFieldTypeSelect &&
+131
View File
@@ -5,6 +5,7 @@ package model
import (
"encoding/json"
"strings"
"testing"
"github.com/stretchr/testify/assert"
@@ -139,6 +140,88 @@ func TestPropertyField_IsValid(t *testing.T) {
}
require.Error(t, pf.IsValid())
})
t.Run("Name exceeds maximum length", func(t *testing.T) {
longName := strings.Repeat("a", PropertyFieldNameMaxRunes+1)
pf := &PropertyField{
ID: NewId(),
GroupID: NewId(),
Name: longName,
Type: PropertyFieldTypeText,
CreateAt: GetMillis(),
UpdateAt: GetMillis(),
}
require.Error(t, pf.IsValid())
})
t.Run("TargetType exceeds maximum length", func(t *testing.T) {
longTargetType := strings.Repeat("a", PropertyFieldTargetTypeMaxRunes+1)
pf := &PropertyField{
ID: NewId(),
GroupID: NewId(),
Name: "test field",
Type: PropertyFieldTypeText,
TargetType: longTargetType,
CreateAt: GetMillis(),
UpdateAt: GetMillis(),
}
require.Error(t, pf.IsValid())
})
t.Run("TargetID exceeds maximum length", func(t *testing.T) {
longTargetID := strings.Repeat("a", PropertyFieldTargetIDMaxRunes+1)
pf := &PropertyField{
ID: NewId(),
GroupID: NewId(),
Name: "test field",
Type: PropertyFieldTypeText,
TargetID: longTargetID,
CreateAt: GetMillis(),
UpdateAt: GetMillis(),
}
require.Error(t, pf.IsValid())
})
t.Run("Name at maximum length is valid", func(t *testing.T) {
maxLengthName := strings.Repeat("a", PropertyFieldNameMaxRunes)
pf := &PropertyField{
ID: NewId(),
GroupID: NewId(),
Name: maxLengthName,
Type: PropertyFieldTypeText,
CreateAt: GetMillis(),
UpdateAt: GetMillis(),
}
require.NoError(t, pf.IsValid())
})
t.Run("TargetType at maximum length is valid", func(t *testing.T) {
maxLengthTargetType := strings.Repeat("a", PropertyFieldTargetTypeMaxRunes)
pf := &PropertyField{
ID: NewId(),
GroupID: NewId(),
Name: "test field",
Type: PropertyFieldTypeText,
TargetType: maxLengthTargetType,
CreateAt: GetMillis(),
UpdateAt: GetMillis(),
}
require.NoError(t, pf.IsValid())
})
t.Run("TargetID at maximum length is valid", func(t *testing.T) {
maxLengthTargetID := strings.Repeat("a", PropertyFieldTargetIDMaxRunes)
pf := &PropertyField{
ID: NewId(),
GroupID: NewId(),
Name: "test field",
Type: PropertyFieldTypeText,
TargetID: maxLengthTargetID,
CreateAt: GetMillis(),
UpdateAt: GetMillis(),
}
require.NoError(t, pf.IsValid())
})
}
func TestPropertyFieldPatch_IsValid(t *testing.T) {
@@ -174,6 +257,54 @@ func TestPropertyFieldPatch_IsValid(t *testing.T) {
}
require.NoError(t, patch.IsValid())
})
t.Run("Name exceeds maximum length", func(t *testing.T) {
longName := strings.Repeat("a", PropertyFieldNameMaxRunes+1)
patch := &PropertyFieldPatch{
Name: &longName,
}
require.Error(t, patch.IsValid())
})
t.Run("TargetType exceeds maximum length", func(t *testing.T) {
longTargetType := strings.Repeat("a", PropertyFieldTargetTypeMaxRunes+1)
patch := &PropertyFieldPatch{
TargetType: &longTargetType,
}
require.Error(t, patch.IsValid())
})
t.Run("TargetID exceeds maximum length", func(t *testing.T) {
longTargetID := strings.Repeat("a", PropertyFieldTargetIDMaxRunes+1)
patch := &PropertyFieldPatch{
TargetID: &longTargetID,
}
require.Error(t, patch.IsValid())
})
t.Run("Name at maximum length is valid", func(t *testing.T) {
maxLengthName := strings.Repeat("a", PropertyFieldNameMaxRunes)
patch := &PropertyFieldPatch{
Name: &maxLengthName,
}
require.NoError(t, patch.IsValid())
})
t.Run("TargetType at maximum length is valid", func(t *testing.T) {
maxLengthTargetType := strings.Repeat("a", PropertyFieldTargetTypeMaxRunes)
patch := &PropertyFieldPatch{
TargetType: &maxLengthTargetType,
}
require.NoError(t, patch.IsValid())
})
t.Run("TargetID at maximum length is valid", func(t *testing.T) {
maxLengthTargetID := strings.Repeat("a", PropertyFieldTargetIDMaxRunes)
patch := &PropertyFieldPatch{
TargetID: &maxLengthTargetID,
}
require.NoError(t, patch.IsValid())
})
}
func TestPropertyField_Patch(t *testing.T) {
+14
View File
@@ -6,10 +6,16 @@ package model
import (
"encoding/json"
"net/http"
"unicode/utf8"
"github.com/pkg/errors"
)
const (
PropertyValueTargetIDMaxRunes = 255
PropertyValueTargetTypeMaxRunes = 255
)
type PropertyValue struct {
ID string `json:"id"`
TargetID string `json:"target_id"`
@@ -46,6 +52,14 @@ func (pv *PropertyValue) IsValid() error {
return NewAppError("PropertyValue.IsValid", "model.property_value.is_valid.app_error", map[string]any{"FieldName": "target_type", "Reason": "value cannot be empty"}, "id="+pv.ID, http.StatusBadRequest)
}
if utf8.RuneCountInString(pv.TargetType) > PropertyValueTargetTypeMaxRunes {
return NewAppError("PropertyValue.IsValid", "model.property_value.is_valid.app_error", map[string]any{"FieldName": "target_type", "Reason": "value exceeds maximum length"}, "id="+pv.ID, http.StatusBadRequest)
}
if utf8.RuneCountInString(pv.TargetID) > PropertyValueTargetIDMaxRunes {
return NewAppError("PropertyValue.IsValid", "model.property_value.is_valid.app_error", map[string]any{"FieldName": "target_id", "Reason": "value exceeds maximum length"}, "id="+pv.ID, http.StatusBadRequest)
}
if !IsValidId(pv.GroupID) {
return NewAppError("PropertyValue.IsValid", "model.property_value.is_valid.app_error", map[string]any{"FieldName": "group_id", "Reason": "invalid id"}, "id="+pv.ID, http.StatusBadRequest)
}
@@ -5,6 +5,7 @@ package model
import (
"encoding/json"
"strings"
"testing"
"github.com/stretchr/testify/assert"
@@ -144,6 +145,34 @@ func TestPropertyValue_IsValid(t *testing.T) {
}
require.Error(t, pv.IsValid())
})
t.Run("TargetType exceeds maximum length", func(t *testing.T) {
longTargetType := strings.Repeat("a", PropertyValueTargetTypeMaxRunes+1)
pv := &PropertyValue{
ID: NewId(),
TargetID: NewId(),
TargetType: longTargetType,
GroupID: NewId(),
FieldID: NewId(),
CreateAt: GetMillis(),
UpdateAt: GetMillis(),
}
require.Error(t, pv.IsValid())
})
t.Run("TargetType at maximum length is valid", func(t *testing.T) {
maxLengthTargetType := strings.Repeat("a", PropertyValueTargetTypeMaxRunes)
pv := &PropertyValue{
ID: NewId(),
TargetID: NewId(),
TargetType: maxLengthTargetType,
GroupID: NewId(),
FieldID: NewId(),
CreateAt: GetMillis(),
UpdateAt: GetMillis(),
}
require.NoError(t, pv.IsValid())
})
}
func TestPropertyValueSearchCursor_IsValid(t *testing.T) {