diff --git a/apis/collection_test.go b/apis/collection_test.go index c1bbe0f8..35a1b778 100644 --- a/apis/collection_test.go +++ b/apis/collection_test.go @@ -724,7 +724,7 @@ func TestCollectionCreate(t *testing.T) { ExpectedContent: []string{ `"name":"new"`, `"type":"view"`, - `"fields":[{"autogeneratePattern":"","hidden":false,"id":"text3208210256","max":0,"min":0,"name":"id","pattern":"","presentable":false,"primaryKey":true,"required":true,"system":true,"type":"text"}]`, + `"fields":[{"autogeneratePattern":"","hidden":false,"id":"text3208210256","max":0,"min":0,"name":"id","pattern":"^[a-z0-9]+$","presentable":false,"primaryKey":true,"required":true,"system":true,"type":"text"}]`, }, ExpectedEvents: map[string]int{ "*": 0, diff --git a/core/collection_model.go b/core/collection_model.go index f9a004ec..93b67fe2 100644 --- a/core/collection_model.go +++ b/core/collection_model.go @@ -902,6 +902,9 @@ func (c *Collection) initIdField() { field.Required = true field.PrimaryKey = true field.Hidden = false + if field.Pattern == "" { + field.Pattern = `^[a-z0-9]+$` + } } } diff --git a/core/collection_validate_test.go b/core/collection_validate_test.go index 2cf975ac..0f98de43 100644 --- a/core/collection_validate_test.go +++ b/core/collection_validate_test.go @@ -704,7 +704,7 @@ func TestCollectionValidate(t *testing.T) { collection: func(app core.App) (*core.Collection, error) { c := core.NewBaseCollection("new_auth") c.Fields = core.NewFieldsList( - &core.TextField{Name: "id", PrimaryKey: true, Required: true}, + &core.TextField{Name: "id", PrimaryKey: true, Required: true, Pattern: `\w+`}, ) return c, nil }, @@ -715,7 +715,7 @@ func TestCollectionValidate(t *testing.T) { collection: func(app core.App) (*core.Collection, error) { c := core.NewBaseCollection("new_auth") c.Fields = core.NewFieldsList( - &core.TextField{Name: "id", PrimaryKey: true, Required: true}, + &core.TextField{Name: "id", PrimaryKey: true, Required: true, Pattern: `\w+`}, &core.TextField{Id: "f1", Name: "Test"}, // case-insensitive &core.BoolField{Id: "f2", Name: "test"}, ) diff --git a/core/field_file.go b/core/field_file.go index 71930184..ec3ea269 100644 --- a/core/field_file.go +++ b/core/field_file.go @@ -391,7 +391,7 @@ func (f *FileField) Intercept( } func (f *FileField) getLatestOldValue(app App, record *Record) any { if !record.IsNew() { - latestOriginal, err := app.FindRecordById(record.Collection(), record.Original().Id) + latestOriginal, err := app.FindRecordById(record.Collection(), cast.ToString(record.LastSavedPK())) if err == nil { return latestOriginal.GetRaw(f.Name) } diff --git a/core/field_text.go b/core/field_text.go index 71e9a5fb..8091a23f 100644 --- a/core/field_text.go +++ b/core/field_text.go @@ -257,7 +257,7 @@ func (f *TextField) ValidateSettings(ctx context.Context, app App, collection *C validation.Field(&f.PrimaryKey, validation.By(f.checkOtherFieldsForPK(collection))), validation.Field(&f.Min, validation.Min(0)), validation.Field(&f.Max, validation.Min(f.Min)), - validation.Field(&f.Pattern, validation.By(validators.IsRegex)), + validation.Field(&f.Pattern, validation.When(f.PrimaryKey, validation.Required), validation.By(validators.IsRegex)), validation.Field(&f.Hidden, validation.When(f.PrimaryKey, validation.Empty)), validation.Field(&f.Required, validation.When(f.PrimaryKey, validation.Required)), validation.Field(&f.AutogeneratePattern, validation.By(validators.IsRegex), validation.By(f.checkAutogeneratePattern)), diff --git a/core/field_text_test.go b/core/field_text_test.go index 4883a8b1..8c8d9981 100644 --- a/core/field_text_test.go +++ b/core/field_text_test.go @@ -317,10 +317,23 @@ func TestTextFieldValidateSettings(t *testing.T) { Id: "test", Name: "id", PrimaryKey: true, + Pattern: `\d+`, } }, []string{"required"}, }, + { + "primaryKey without pattern", + func() *core.TextField { + return &core.TextField{ + Id: "test", + Name: "id", + PrimaryKey: true, + Required: true, + } + }, + []string{"pattern"}, + }, { "primaryKey with hidden", func() *core.TextField { @@ -330,6 +343,7 @@ func TestTextFieldValidateSettings(t *testing.T) { Required: true, PrimaryKey: true, Hidden: true, + Pattern: `\d+`, } }, []string{"hidden"}, @@ -342,6 +356,7 @@ func TestTextFieldValidateSettings(t *testing.T) { Name: "test", PrimaryKey: true, Required: true, + Pattern: `\d+`, } }, []string{"name"}, @@ -353,6 +368,7 @@ func TestTextFieldValidateSettings(t *testing.T) { Id: "test2", Name: "id", PrimaryKey: true, + Pattern: `\d+`, Required: true, } }, diff --git a/core/record_model_test.go b/core/record_model_test.go index c8a6bfa2..666a1da2 100644 --- a/core/record_model_test.go +++ b/core/record_model_test.go @@ -1564,13 +1564,15 @@ func TestRecordValidate(t *testing.T) { app, _ := tests.NewTestApp() defer app.Cleanup() - collection := core.NewBaseCollection("test") - + // dummy collection to ensure that the specified field validators are triggered + collection := core.NewBaseCollection("validate_test") collection.Fields.Add( - // dummy fields to ensure that its validators are triggered &core.TextField{Name: "f1", Min: 3}, &core.NumberField{Name: "f2", Required: true}, ) + if err := app.Save(collection); err != nil { + t.Fatal(err) + } record := core.NewRecord(collection) record.Id = "!invalid" @@ -1585,7 +1587,7 @@ func TestRecordValidate(t *testing.T) { }) t.Run("satisfying the fields validations", func(t *testing.T) { - record.Id = strings.Repeat("a", 15) + record.Id = strings.Repeat("b", 15) record.Set("f1", "abc") record.Set("f2", 1) tests.TestValidationErrors(t, app.Validate(record), nil) diff --git a/core/view.go b/core/view.go index da30d8b5..3567eef6 100644 --- a/core/view.go +++ b/core/view.go @@ -247,6 +247,7 @@ func parseQueryToFields(app App, selectQuery string) (map[string]*queryField, er System: true, Required: true, PrimaryKey: true, + Pattern: `^[a-z0-9]+$`, }, } continue