abstract rest.UploadedFile to allow loading local files
This commit is contained in:
+10
-9
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/pocketbase/pocketbase/forms/validators"
|
||||
"github.com/pocketbase/pocketbase/models"
|
||||
"github.com/pocketbase/pocketbase/models/schema"
|
||||
"github.com/pocketbase/pocketbase/tools/filesystem"
|
||||
"github.com/pocketbase/pocketbase/tools/list"
|
||||
"github.com/pocketbase/pocketbase/tools/rest"
|
||||
"github.com/pocketbase/pocketbase/tools/security"
|
||||
@@ -34,7 +35,7 @@ type RecordUpsert struct {
|
||||
manageAccess bool
|
||||
record *models.Record
|
||||
|
||||
filesToUpload map[string][]*rest.UploadedFile
|
||||
filesToUpload map[string][]*filesystem.File
|
||||
filesToDelete []string // names list
|
||||
|
||||
// base model fields
|
||||
@@ -66,7 +67,7 @@ func NewRecordUpsert(app core.App, record *models.Record) *RecordUpsert {
|
||||
dao: app.Dao(),
|
||||
record: record,
|
||||
filesToDelete: []string{},
|
||||
filesToUpload: map[string][]*rest.UploadedFile{},
|
||||
filesToUpload: map[string][]*filesystem.File{},
|
||||
}
|
||||
|
||||
form.loadFormDefaults()
|
||||
@@ -153,7 +154,7 @@ func (form *RecordUpsert) extractMultipartFormData(r *http.Request, keyPrefix st
|
||||
|
||||
arrayValueSupportTypes := schema.ArraybleFieldTypes()
|
||||
|
||||
form.filesToUpload = map[string][]*rest.UploadedFile{}
|
||||
form.filesToUpload = map[string][]*filesystem.File{}
|
||||
|
||||
for fullKey, values := range r.PostForm {
|
||||
key := fullKey
|
||||
@@ -202,7 +203,7 @@ func (form *RecordUpsert) extractMultipartFormData(r *http.Request, keyPrefix st
|
||||
}
|
||||
|
||||
if form.filesToUpload[key] == nil {
|
||||
form.filesToUpload[key] = []*rest.UploadedFile{}
|
||||
form.filesToUpload[key] = []*filesystem.File{}
|
||||
}
|
||||
|
||||
if options.MaxSelect == 1 {
|
||||
@@ -363,11 +364,11 @@ func (form *RecordUpsert) LoadData(requestData map[string]any) error {
|
||||
if len(oldNames) > 0 {
|
||||
form.filesToDelete = list.ToUniqueStringSlice(append(form.filesToDelete, oldNames...))
|
||||
}
|
||||
form.Data[key] = form.filesToUpload[key][0].Name()
|
||||
form.Data[key] = form.filesToUpload[key][0].Name
|
||||
} else if options.MaxSelect > 1 {
|
||||
// append the id of each uploaded file instance
|
||||
for _, file := range form.filesToUpload[key] {
|
||||
oldNames = append(oldNames, file.Name())
|
||||
oldNames = append(oldNames, file.Name)
|
||||
}
|
||||
form.Data[key] = oldNames
|
||||
}
|
||||
@@ -685,7 +686,7 @@ func (form *RecordUpsert) getFilesToUploadNames() []string {
|
||||
|
||||
for fieldKey := range form.filesToUpload {
|
||||
for _, file := range form.filesToUpload[fieldKey] {
|
||||
names = append(names, file.Name())
|
||||
names = append(names, file.Name)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -712,8 +713,8 @@ func (form *RecordUpsert) processFilesToUpload() error {
|
||||
|
||||
for fieldKey := range form.filesToUpload {
|
||||
for i, file := range form.filesToUpload[fieldKey] {
|
||||
path := form.record.BaseFilesPath() + "/" + file.Name()
|
||||
if err := fs.UploadMultipart(file.Header(), path); err == nil {
|
||||
path := form.record.BaseFilesPath() + "/" + file.Name
|
||||
if err := fs.UploadFile(file, path); err == nil {
|
||||
// keep track of the already uploaded file
|
||||
uploaded = append(uploaded, path)
|
||||
} else {
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
|
||||
"github.com/gabriel-vasile/mimetype"
|
||||
validation "github.com/go-ozzo/ozzo-validation/v4"
|
||||
"github.com/pocketbase/pocketbase/tools/rest"
|
||||
"github.com/pocketbase/pocketbase/tools/filesystem"
|
||||
)
|
||||
|
||||
// UploadedFileSize checks whether the validated `rest.UploadedFile`
|
||||
@@ -16,12 +16,12 @@ import (
|
||||
// validation.Field(&form.File, validation.By(validators.UploadedFileSize(1000)))
|
||||
func UploadedFileSize(maxBytes int) validation.RuleFunc {
|
||||
return func(value any) error {
|
||||
v, _ := value.(*rest.UploadedFile)
|
||||
v, _ := value.(*filesystem.File)
|
||||
if v == nil {
|
||||
return nil // nothing to validate
|
||||
}
|
||||
|
||||
if int(v.Header().Size) > maxBytes {
|
||||
if int(v.Size) > maxBytes {
|
||||
return validation.NewError("validation_file_size_limit", fmt.Sprintf("Maximum allowed file size is %v bytes.", maxBytes))
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ func UploadedFileSize(maxBytes int) validation.RuleFunc {
|
||||
// validation.Field(&form.File, validation.By(validators.UploadedFileMimeType(validMimeTypes)))
|
||||
func UploadedFileMimeType(validTypes []string) validation.RuleFunc {
|
||||
return func(value any) error {
|
||||
v, _ := value.(*rest.UploadedFile)
|
||||
v, _ := value.(*filesystem.File)
|
||||
if v == nil {
|
||||
return nil // nothing to validate
|
||||
}
|
||||
@@ -46,7 +46,7 @@ func UploadedFileMimeType(validTypes []string) validation.RuleFunc {
|
||||
return validation.NewError("validation_invalid_mime_type", "Unsupported file type.")
|
||||
}
|
||||
|
||||
f, err := v.Header().Open()
|
||||
f, err := v.Reader.Open()
|
||||
if err != nil {
|
||||
return validation.NewError("validation_invalid_mime_type", "Unsupported file type.")
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/pocketbase/pocketbase/forms/validators"
|
||||
"github.com/pocketbase/pocketbase/tests"
|
||||
"github.com/pocketbase/pocketbase/tools/filesystem"
|
||||
"github.com/pocketbase/pocketbase/tools/rest"
|
||||
)
|
||||
|
||||
@@ -30,7 +31,7 @@ func TestUploadedFileSize(t *testing.T) {
|
||||
|
||||
scenarios := []struct {
|
||||
maxBytes int
|
||||
file *rest.UploadedFile
|
||||
file *filesystem.File
|
||||
expectError bool
|
||||
}{
|
||||
{0, nil, false},
|
||||
@@ -70,7 +71,7 @@ func TestUploadedFileMimeType(t *testing.T) {
|
||||
|
||||
scenarios := []struct {
|
||||
types []string
|
||||
file *rest.UploadedFile
|
||||
file *filesystem.File
|
||||
expectError bool
|
||||
}{
|
||||
{nil, nil, false},
|
||||
|
||||
@@ -12,8 +12,8 @@ import (
|
||||
"github.com/pocketbase/pocketbase/daos"
|
||||
"github.com/pocketbase/pocketbase/models"
|
||||
"github.com/pocketbase/pocketbase/models/schema"
|
||||
"github.com/pocketbase/pocketbase/tools/filesystem"
|
||||
"github.com/pocketbase/pocketbase/tools/list"
|
||||
"github.com/pocketbase/pocketbase/tools/rest"
|
||||
"github.com/pocketbase/pocketbase/tools/types"
|
||||
)
|
||||
|
||||
@@ -28,7 +28,7 @@ var requiredErr = validation.NewError("validation_required", "Missing required v
|
||||
func NewRecordDataValidator(
|
||||
dao *daos.Dao,
|
||||
record *models.Record,
|
||||
uploadedFiles map[string][]*rest.UploadedFile,
|
||||
uploadedFiles map[string][]*filesystem.File,
|
||||
) *RecordDataValidator {
|
||||
return &RecordDataValidator{
|
||||
dao: dao,
|
||||
@@ -42,7 +42,7 @@ func NewRecordDataValidator(
|
||||
type RecordDataValidator struct {
|
||||
dao *daos.Dao
|
||||
record *models.Record
|
||||
uploadedFiles map[string][]*rest.UploadedFile
|
||||
uploadedFiles map[string][]*filesystem.File
|
||||
}
|
||||
|
||||
// Validate validates the provided `data` by checking it against
|
||||
@@ -314,9 +314,9 @@ func (validator *RecordDataValidator) checkFileValue(field *schema.SchemaField,
|
||||
}
|
||||
|
||||
// extract the uploaded files
|
||||
files := make([]*rest.UploadedFile, 0, len(validator.uploadedFiles[field.Name]))
|
||||
files := make([]*filesystem.File, 0, len(validator.uploadedFiles[field.Name]))
|
||||
for _, file := range validator.uploadedFiles[field.Name] {
|
||||
if list.ExistInSlice(file.Name(), names) {
|
||||
if list.ExistInSlice(file.Name, names) {
|
||||
files = append(files, file)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/pocketbase/pocketbase/models"
|
||||
"github.com/pocketbase/pocketbase/models/schema"
|
||||
"github.com/pocketbase/pocketbase/tests"
|
||||
"github.com/pocketbase/pocketbase/tools/filesystem"
|
||||
"github.com/pocketbase/pocketbase/tools/rest"
|
||||
"github.com/pocketbase/pocketbase/tools/types"
|
||||
)
|
||||
@@ -20,7 +21,7 @@ import (
|
||||
type testDataFieldScenario struct {
|
||||
name string
|
||||
data map[string]any
|
||||
files map[string][]*rest.UploadedFile
|
||||
files map[string][]*filesystem.File
|
||||
expectedErrors []string
|
||||
}
|
||||
|
||||
@@ -1086,10 +1087,10 @@ func TestRecordDataValidatorValidateFile(t *testing.T) {
|
||||
"check MaxSelect constraint",
|
||||
map[string]any{
|
||||
"field1": "test1",
|
||||
"field2": []string{"test1", testFiles[0].Name(), testFiles[3].Name()},
|
||||
"field2": []string{"test1", testFiles[0].Name, testFiles[3].Name},
|
||||
"field3": []string{"test1", "test2", "test3", "test4"},
|
||||
},
|
||||
map[string][]*rest.UploadedFile{
|
||||
map[string][]*filesystem.File{
|
||||
"field2": {testFiles[0], testFiles[3]},
|
||||
},
|
||||
[]string{"field2", "field3"},
|
||||
@@ -1097,11 +1098,11 @@ func TestRecordDataValidatorValidateFile(t *testing.T) {
|
||||
{
|
||||
"check MaxSize constraint",
|
||||
map[string]any{
|
||||
"field1": testFiles[0].Name(),
|
||||
"field2": []string{"test1", testFiles[0].Name()},
|
||||
"field1": testFiles[0].Name,
|
||||
"field2": []string{"test1", testFiles[0].Name},
|
||||
"field3": []string{"test1", "test2", "test3"},
|
||||
},
|
||||
map[string][]*rest.UploadedFile{
|
||||
map[string][]*filesystem.File{
|
||||
"field1": {testFiles[0]},
|
||||
"field2": {testFiles[0]},
|
||||
},
|
||||
@@ -1111,10 +1112,10 @@ func TestRecordDataValidatorValidateFile(t *testing.T) {
|
||||
"check MimeTypes constraint",
|
||||
map[string]any{
|
||||
"field1": "test1",
|
||||
"field2": []string{"test1", testFiles[0].Name()},
|
||||
"field3": []string{testFiles[1].Name(), testFiles[2].Name()},
|
||||
"field2": []string{"test1", testFiles[0].Name},
|
||||
"field3": []string{testFiles[1].Name, testFiles[2].Name},
|
||||
},
|
||||
map[string][]*rest.UploadedFile{
|
||||
map[string][]*filesystem.File{
|
||||
"field2": {testFiles[0], testFiles[1], testFiles[2]},
|
||||
"field3": {testFiles[1], testFiles[2]},
|
||||
},
|
||||
@@ -1134,10 +1135,10 @@ func TestRecordDataValidatorValidateFile(t *testing.T) {
|
||||
"valid data - just new files",
|
||||
map[string]any{
|
||||
"field1": nil,
|
||||
"field2": []string{testFiles[0].Name(), testFiles[1].Name()},
|
||||
"field2": []string{testFiles[0].Name, testFiles[1].Name},
|
||||
"field3": nil,
|
||||
},
|
||||
map[string][]*rest.UploadedFile{
|
||||
map[string][]*filesystem.File{
|
||||
"field2": {testFiles[0], testFiles[1]},
|
||||
},
|
||||
[]string{},
|
||||
@@ -1146,10 +1147,10 @@ func TestRecordDataValidatorValidateFile(t *testing.T) {
|
||||
"valid data - mixed existing and new files",
|
||||
map[string]any{
|
||||
"field1": "test1",
|
||||
"field2": []string{"test1", testFiles[0].Name()},
|
||||
"field2": []string{"test1", testFiles[0].Name},
|
||||
"field3": "test1", // will be casted
|
||||
},
|
||||
map[string][]*rest.UploadedFile{
|
||||
map[string][]*filesystem.File{
|
||||
"field2": {testFiles[0], testFiles[1], testFiles[2]},
|
||||
},
|
||||
[]string{},
|
||||
|
||||
Reference in New Issue
Block a user