updated error messages
This commit is contained in:
		
							parent
							
								
									5a5211d7f2
								
							
						
					
					
						commit
						fab334fca6
					
				|  | @ -2,6 +2,8 @@ | ||||||
| 
 | 
 | ||||||
| - Added `RequestEvent.Blob(status, contentType string, bytes)` response write helper ([#5940](https://github.com/pocketbase/pocketbase/discussions/5940)). | - Added `RequestEvent.Blob(status, contentType string, bytes)` response write helper ([#5940](https://github.com/pocketbase/pocketbase/discussions/5940)). | ||||||
| 
 | 
 | ||||||
|  | - Added more descriptive error messages. | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| ## v0.23.0 | ## v0.23.0 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -175,7 +175,7 @@ type recordOAuth2LoginForm struct { | ||||||
| 
 | 
 | ||||||
| func (form *recordOAuth2LoginForm) validate() error { | func (form *recordOAuth2LoginForm) validate() error { | ||||||
| 	return validation.ValidateStruct(form, | 	return validation.ValidateStruct(form, | ||||||
| 		validation.Field(&form.Provider, validation.Required, validation.By(form.checkProviderName)), | 		validation.Field(&form.Provider, validation.Required, validation.Length(0, 100), validation.By(form.checkProviderName)), | ||||||
| 		validation.Field(&form.Code, validation.Required), | 		validation.Field(&form.Code, validation.Required), | ||||||
| 		validation.Field(&form.RedirectURL, validation.Required), | 		validation.Field(&form.RedirectURL, validation.Required), | ||||||
| 	) | 	) | ||||||
|  | @ -186,7 +186,7 @@ func (form *recordOAuth2LoginForm) checkProviderName(value any) error { | ||||||
| 
 | 
 | ||||||
| 	_, ok := form.collection.OAuth2.GetProviderConfig(name) | 	_, ok := form.collection.OAuth2.GetProviderConfig(name) | ||||||
| 	if !ok { | 	if !ok { | ||||||
| 		return validation.NewError("validation_invalid_provider", fmt.Sprintf("Provider with name %q is missing or is not enabled.", name)). | 		return validation.NewError("validation_invalid_provider", "Provider with name {{.name}} is missing or is not enabled."). | ||||||
| 			SetParams(map[string]any{"name": name}) | 			SetParams(map[string]any{"name": name}) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -445,7 +445,7 @@ func checkForDuplicatedProviders(value any) error { | ||||||
| 		if _, ok := existing[c.Name]; ok { | 		if _, ok := existing[c.Name]; ok { | ||||||
| 			return validation.Errors{ | 			return validation.Errors{ | ||||||
| 				strconv.Itoa(i): validation.Errors{ | 				strconv.Itoa(i): validation.Errors{ | ||||||
| 					"name": validation.NewError("validation_duplicated_provider", "The provider "+c.Name+" is already registered."). | 					"name": validation.NewError("validation_duplicated_provider", "The provider {{.name}} is already registered."). | ||||||
| 						SetParams(map[string]any{"name": c.Name}), | 						SetParams(map[string]any{"name": c.Name}), | ||||||
| 				}, | 				}, | ||||||
| 			} | 			} | ||||||
|  | @ -493,7 +493,7 @@ func checkProviderName(value any) error { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if _, err := auth.NewProviderByName(name); err != nil { | 	if _, err := auth.NewProviderByName(name); err != nil { | ||||||
| 		return validation.NewError("validation_missing_provider", "Invalid or missing provider with name "+name+"."). | 		return validation.NewError("validation_missing_provider", "Invalid or missing provider with name {{.name}}."). | ||||||
| 			SetParams(map[string]any{"name": name}) | 			SetParams(map[string]any{"name": name}) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -349,9 +349,7 @@ func createCollectionIndexes(app App, collection *Collection) error { | ||||||
| 				errs[strconv.Itoa(i)] = validation.NewError( | 				errs[strconv.Itoa(i)] = validation.NewError( | ||||||
| 					"validation_invalid_index_expression", | 					"validation_invalid_index_expression", | ||||||
| 					fmt.Sprintf("Failed to create index %s - %v.", parsed.IndexName, err.Error()), | 					fmt.Sprintf("Failed to create index %s - %v.", parsed.IndexName, err.Error()), | ||||||
| 				).SetParams(map[string]any{ | 				) | ||||||
| 					"indexName": parsed.IndexName, |  | ||||||
| 				}) |  | ||||||
| 				continue | 				continue | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -268,7 +268,7 @@ func (validator *collectionValidator) checkFieldDuplicates(value any) error { | ||||||
| 				strconv.Itoa(i): validation.Errors{ | 				strconv.Itoa(i): validation.Errors{ | ||||||
| 					"name": validation.NewError( | 					"name": validation.NewError( | ||||||
| 						"validation_duplicated_field_name", | 						"validation_duplicated_field_name", | ||||||
| 						fmt.Sprintf("Duplicated or invalid field name %q", field.GetName()), | 						"Duplicated or invalid field name {{.fieldName}}", | ||||||
| 					).SetParams(map[string]any{ | 					).SetParams(map[string]any{ | ||||||
| 						"fieldName": field.GetName(), | 						"fieldName": field.GetName(), | ||||||
| 					}), | 					}), | ||||||
|  | @ -452,12 +452,12 @@ func (cv *collectionValidator) checkFieldsForUniqueIndex(value any) error { | ||||||
| 	for _, name := range names { | 	for _, name := range names { | ||||||
| 		field := cv.new.Fields.GetByName(name) | 		field := cv.new.Fields.GetByName(name) | ||||||
| 		if field == nil { | 		if field == nil { | ||||||
| 			return validation.NewError("validation_missing_field", fmt.Sprintf("Invalid or missing field %q", name)). | 			return validation.NewError("validation_missing_field", "Invalid or missing field {{.fieldName}}"). | ||||||
| 				SetParams(map[string]any{"fieldName": name}) | 				SetParams(map[string]any{"fieldName": name}) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if !dbutils.HasSingleColumnUniqueIndex(name, cv.new.Indexes) { | 		if !dbutils.HasSingleColumnUniqueIndex(name, cv.new.Indexes) { | ||||||
| 			return validation.NewError("validation_missing_unique_constraint", fmt.Sprintf("The field %q doesn't have a UNIQUE constraint.", name)). | 			return validation.NewError("validation_missing_unique_constraint", "The field {{.fieldName}} doesn't have a UNIQUE constraint."). | ||||||
| 				SetParams(map[string]any{"fieldName": name}) | 				SetParams(map[string]any{"fieldName": name}) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -566,7 +566,7 @@ func (cv *collectionValidator) checkIndexes(value any) error { | ||||||
| 			return validation.Errors{ | 			return validation.Errors{ | ||||||
| 				strconv.Itoa(i): validation.NewError( | 				strconv.Itoa(i): validation.NewError( | ||||||
| 					"validation_existing_index_name", | 					"validation_existing_index_name", | ||||||
| 					"The index name is already used in "+usedTblName+" collection.", | 					"The index name is already used in {{.usedTableName}} collection.", | ||||||
| 				).SetParams(map[string]any{"usedTableName": usedTblName}), | 				).SetParams(map[string]any{"usedTableName": usedTblName}), | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | @ -649,7 +649,7 @@ func (cv *collectionValidator) checkIndexes(value any) error { | ||||||
| 					if !hasMatch { | 					if !hasMatch { | ||||||
| 						return validation.NewError( | 						return validation.NewError( | ||||||
| 							"validation_invalid_unique_system_field_index", | 							"validation_invalid_unique_system_field_index", | ||||||
| 							fmt.Sprintf("Unique index definition on system fields (%q) is invalid or missing.", f.GetName()), | 							"Unique index definition on system fields ({{.fieldName}}) is invalid or missing.", | ||||||
| 						).SetParams(map[string]any{"fieldName": f.GetName()}) | 						).SetParams(map[string]any{"fieldName": f.GetName()}) | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
|  | @ -669,7 +669,7 @@ func (cv *collectionValidator) checkIndexes(value any) error { | ||||||
| 			if !dbutils.HasSingleColumnUniqueIndex(name, indexes) { | 			if !dbutils.HasSingleColumnUniqueIndex(name, indexes) { | ||||||
| 				return validation.NewError( | 				return validation.NewError( | ||||||
| 					"validation_missing_required_unique_index", | 					"validation_missing_required_unique_index", | ||||||
| 					`Missing required unique index for field "`+name+`".`, | 					`Missing required unique index for field "{{.fieldName}}".`, | ||||||
| 				).SetParams(map[string]any{"fieldName": name}) | 				).SetParams(map[string]any{"fieldName": name}) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -464,7 +464,7 @@ func validateCollectionId(app App, optTypes ...string) validation.RuleFunc { | ||||||
| 			return validation.NewError( | 			return validation.NewError( | ||||||
| 				"validation_invalid_collection_type", | 				"validation_invalid_collection_type", | ||||||
| 				fmt.Sprintf("Invalid collection type - must be %s.", strings.Join(optTypes, ", ")), | 				fmt.Sprintf("Invalid collection type - must be %s.", strings.Join(optTypes, ", ")), | ||||||
| 			).SetParams(map[string]any{"types": optTypes}) | 			) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		return nil | 		return nil | ||||||
|  |  | ||||||
|  | @ -2,7 +2,6 @@ package core | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"fmt" |  | ||||||
| 
 | 
 | ||||||
| 	validation "github.com/go-ozzo/ozzo-validation/v4" | 	validation "github.com/go-ozzo/ozzo-validation/v4" | ||||||
| 	"github.com/pocketbase/pocketbase/core/validators" | 	"github.com/pocketbase/pocketbase/core/validators" | ||||||
|  | @ -137,7 +136,7 @@ func (f *EditorField) ValidateValue(ctx context.Context, app App, record *Record | ||||||
| 	if int64(len(val)) > maxSize { | 	if int64(len(val)) > maxSize { | ||||||
| 		return validation.NewError( | 		return validation.NewError( | ||||||
| 			"validation_content_size_limit", | 			"validation_content_size_limit", | ||||||
| 			fmt.Sprintf("The maximum allowed content size is %v bytes", maxSize), | 			"The maximum allowed content size is {{.maxSize}} bytes", | ||||||
| 		).SetParams(map[string]any{"maxSize": maxSize}) | 		).SetParams(map[string]any{"maxSize": maxSize}) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -250,13 +250,22 @@ func (f *FileField) ValidateValue(ctx context.Context, app App, record *Record) | ||||||
| 	addedStrings := f.excludeFiles(existingStrings, oldExistingStrings) | 	addedStrings := f.excludeFiles(existingStrings, oldExistingStrings) | ||||||
| 
 | 
 | ||||||
| 	if len(addedStrings) > 0 { | 	if len(addedStrings) > 0 { | ||||||
| 		return validation.NewError("validation_invalid_file", "Invalid files:"+strings.Join(cast.ToStringSlice(addedStrings), ", ")). | 		invalidFiles := make([]string, len(addedStrings)) | ||||||
| 			SetParams(map[string]any{"invalidFiles": addedStrings}) | 		for i, invalid := range addedStrings { | ||||||
|  | 			invalidStr := cast.ToString(invalid) | ||||||
|  | 			if len(invalidStr) > 250 { | ||||||
|  | 				invalidStr = invalidStr[:250] | ||||||
|  | 			} | ||||||
|  | 			invalidFiles[i] = invalidStr | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return validation.NewError("validation_invalid_file", "Invalid new files: {{.invalidFiles}}."). | ||||||
|  | 			SetParams(map[string]any{"invalidFiles": invalidFiles}) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	maxSelect := f.maxSelect() | 	maxSelect := f.maxSelect() | ||||||
| 	if len(files) > maxSelect { | 	if len(files) > maxSelect { | ||||||
| 		return validation.NewError("validation_too_many_files", fmt.Sprintf("The maximum allowed files is %d", maxSelect)). | 		return validation.NewError("validation_too_many_files", "The maximum allowed files is {{.maxSelect}}"). | ||||||
| 			SetParams(map[string]any{"maxSelect": maxSelect}) | 			SetParams(map[string]any{"maxSelect": maxSelect}) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -2,7 +2,6 @@ package core | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"fmt" |  | ||||||
| 	"slices" | 	"slices" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"strings" | 	"strings" | ||||||
|  | @ -160,7 +159,7 @@ func (f *JSONField) ValidateValue(ctx context.Context, app App, record *Record) | ||||||
| 	if int64(len(raw)) > maxSize { | 	if int64(len(raw)) > maxSize { | ||||||
| 		return validation.NewError( | 		return validation.NewError( | ||||||
| 			"validation_json_size_limit", | 			"validation_json_size_limit", | ||||||
| 			fmt.Sprintf("The maximum allowed JSON size is %v bytes", maxSize), | 			"The maximum allowed JSON size is {{.maxSize}} bytes", | ||||||
| 		).SetParams(map[string]any{"maxSize": maxSize}) | 		).SetParams(map[string]any{"maxSize": maxSize}) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3,7 +3,6 @@ package core | ||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"database/sql/driver" | 	"database/sql/driver" | ||||||
| 	"fmt" |  | ||||||
| 
 | 
 | ||||||
| 	validation "github.com/go-ozzo/ozzo-validation/v4" | 	validation "github.com/go-ozzo/ozzo-validation/v4" | ||||||
| 	"github.com/pocketbase/dbx" | 	"github.com/pocketbase/dbx" | ||||||
|  | @ -202,13 +201,13 @@ func (f *RelationField) ValidateValue(ctx context.Context, app App, record *Reco | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if f.MinSelect > 0 && len(ids) < f.MinSelect { | 	if f.MinSelect > 0 && len(ids) < f.MinSelect { | ||||||
| 		return validation.NewError("validation_not_enough_values", fmt.Sprintf("Select at least %d", f.MinSelect)). | 		return validation.NewError("validation_not_enough_values", "Select at least {{.minSelect}}"). | ||||||
| 			SetParams(map[string]any{"minSelect": f.MinSelect}) | 			SetParams(map[string]any{"minSelect": f.MinSelect}) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	maxSelect := max(f.MaxSelect, 1) | 	maxSelect := max(f.MaxSelect, 1) | ||||||
| 	if len(ids) > maxSelect { | 	if len(ids) > maxSelect { | ||||||
| 		return validation.NewError("validation_too_many_values", fmt.Sprintf("Select no more than %d", maxSelect)). | 		return validation.NewError("validation_too_many_values", "Select no more than {{.maxSelect}}"). | ||||||
| 			SetParams(map[string]any{"maxSelect": maxSelect}) | 			SetParams(map[string]any{"maxSelect": maxSelect}) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3,7 +3,6 @@ package core | ||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"database/sql/driver" | 	"database/sql/driver" | ||||||
| 	"fmt" |  | ||||||
| 	"slices" | 	"slices" | ||||||
| 
 | 
 | ||||||
| 	validation "github.com/go-ozzo/ozzo-validation/v4" | 	validation "github.com/go-ozzo/ozzo-validation/v4" | ||||||
|  | @ -192,14 +191,14 @@ func (f *SelectField) ValidateValue(ctx context.Context, app App, record *Record | ||||||
| 
 | 
 | ||||||
| 	// check max selected items
 | 	// check max selected items
 | ||||||
| 	if len(normalizedVal) > maxSelect { | 	if len(normalizedVal) > maxSelect { | ||||||
| 		return validation.NewError("validation_too_many_values", fmt.Sprintf("Select no more than %d", maxSelect)). | 		return validation.NewError("validation_too_many_values", "Select no more than {{.maxSelect}}"). | ||||||
| 			SetParams(map[string]any{"maxSelect": maxSelect}) | 			SetParams(map[string]any{"maxSelect": maxSelect}) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// check against the allowed values
 | 	// check against the allowed values
 | ||||||
| 	for _, val := range normalizedVal { | 	for _, val := range normalizedVal { | ||||||
| 		if !slices.Contains(f.Values, val) { | 		if !slices.Contains(f.Values, val) { | ||||||
| 			return validation.NewError("validation_invalid_value", "Invalid value "+val). | 			return validation.NewError("validation_invalid_value", "Invalid value {{.value}}"). | ||||||
| 				SetParams(map[string]any{"value": val}) | 				SetParams(map[string]any{"value": val}) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -222,7 +222,7 @@ func (f *TextField) ValidatePlainValue(value string) error { | ||||||
| 	length := len([]rune(value)) | 	length := len([]rune(value)) | ||||||
| 
 | 
 | ||||||
| 	if f.Min > 0 && length < f.Min { | 	if f.Min > 0 && length < f.Min { | ||||||
| 		return validation.NewError("validation_min_text_constraint", fmt.Sprintf("Must be at least %d character(s)", f.Min)). | 		return validation.NewError("validation_min_text_constraint", "Must be at least {{.min}} character(s)"). | ||||||
| 			SetParams(map[string]any{"min": f.Min}) | 			SetParams(map[string]any{"min": f.Min}) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -232,7 +232,7 @@ func (f *TextField) ValidatePlainValue(value string) error { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if max > 0 && length > max { | 	if max > 0 && length > max { | ||||||
| 		return validation.NewError("validation_max_text_constraint", fmt.Sprintf("Must be less than %d character(s)", max)). | 		return validation.NewError("validation_max_text_constraint", "Must be less than {{.max}} character(s)"). | ||||||
| 			SetParams(map[string]any{"max": f.Max}) | 			SetParams(map[string]any{"max": f.Max}) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -639,7 +639,7 @@ func checkUniqueRuleLabel(value any) error { | ||||||
| 		if conflicts { | 		if conflicts { | ||||||
| 			return validation.Errors{ | 			return validation.Errors{ | ||||||
| 				strconv.Itoa(i): validation.Errors{ | 				strconv.Itoa(i): validation.Errors{ | ||||||
| 					"label": validation.NewError("validation_conflicting_rate_limit_rule", "Rate limit rule configuration with label "+rule.Label+" already exists or conflicts with another rule."). | 					"label": validation.NewError("validation_conflicting_rate_limit_rule", "Rate limit rule configuration with label {{.label}} already exists or conflicts with another rule."). | ||||||
| 						SetParams(map[string]any{"label": rule.Label}), | 						SetParams(map[string]any{"label": rule.Label}), | ||||||
| 				}, | 				}, | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | @ -29,7 +29,7 @@ func UploadedFileSize(maxBytes int64) validation.RuleFunc { | ||||||
| 		if v.Size > maxBytes { | 		if v.Size > maxBytes { | ||||||
| 			return validation.NewError( | 			return validation.NewError( | ||||||
| 				"validation_file_size_limit", | 				"validation_file_size_limit", | ||||||
| 				fmt.Sprintf("Failed to upload %q - the maximum allowed file size is %v bytes.", v.OriginalName, maxBytes), | 				"Failed to upload {{.file}} - the maximum allowed file size is {{.maxSize}} bytes.", | ||||||
| 			).SetParams(map[string]any{ | 			).SetParams(map[string]any{ | ||||||
| 				"file":    v.OriginalName, | 				"file":    v.OriginalName, | ||||||
| 				"maxSize": maxBytes, | 				"maxSize": maxBytes, | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue