diff --git a/apps/console/src/pages/organizations/audits/AuditDetailsPage.tsx b/apps/console/src/pages/organizations/audits/AuditDetailsPage.tsx index d5851967d..56648e3d1 100644 --- a/apps/console/src/pages/organizations/audits/AuditDetailsPage.tsx +++ b/apps/console/src/pages/organizations/audits/AuditDetailsPage.tsx @@ -296,8 +296,9 @@ export default function AuditDetailsPage(props: Props) { onDrop={files => void handleUploadFile(files)} accept={{ "application/pdf": [".pdf"], - "application/vnd.openxmlformats-officedocument.wordprocessingml.document": - [".docx"], + "application/msword": [".doc"], + "application/vnd.openxmlformats-officedocument.wordprocessingml.document": [".docx"], + "application/vnd.oasis.opendocument.text": [".odt"], }} maxSize={25} /> diff --git a/e2e/console/audit_test.go b/e2e/console/audit_test.go index 569a86485..e60febea5 100644 --- a/e2e/console/audit_test.go +++ b/e2e/console/audit_test.go @@ -1597,7 +1597,7 @@ func TestAudit_UploadReport_Validation(t *testing.T) { frameworkID := factory.NewFramework(owner).WithName("Framework for Upload Validation").Create() - t.Run("reject non-PDF file", func(t *testing.T) { + t.Run("reject non document file", func(t *testing.T) { auditID := factory.NewAudit(owner, frameworkID).WithName("Invalid File Test").Create() query := ` @@ -1611,7 +1611,7 @@ func TestAudit_UploadReport_Validation(t *testing.T) { ` // Try to upload a text file - textContent := []byte("This is not a PDF file") + textContent := []byte("This is not a document file") err := owner.ExecuteWithFile(query, map[string]any{ "input": map[string]any{ @@ -1619,14 +1619,14 @@ func TestAudit_UploadReport_Validation(t *testing.T) { "file": nil, }, }, "input.file", testutil.UploadFile{ - Filename: "not-a-pdf.txt", + Filename: "not-a-document.txt", ContentType: "text/plain", Content: textContent, }, nil) - require.Error(t, err, "Should reject non-PDF file") + require.Error(t, err, "Should reject non-document file") }) - t.Run("reject file with wrong extension but PDF content-type", func(t *testing.T) { + t.Run("reject file with wrong extension but document content-type", func(t *testing.T) { auditID := factory.NewAudit(owner, frameworkID).WithName("Wrong Extension Test").Create() query := ` @@ -1640,7 +1640,7 @@ func TestAudit_UploadReport_Validation(t *testing.T) { ` // Try to upload with wrong extension - textContent := []byte("Not a real PDF") + textContent := []byte("Not a real document") err := owner.ExecuteWithFile(query, map[string]any{ "input": map[string]any{ diff --git a/pkg/filevalidation/validator.go b/pkg/filevalidation/validator.go index c69dc302a..61734b24f 100644 --- a/pkg/filevalidation/validator.go +++ b/pkg/filevalidation/validator.go @@ -17,6 +17,7 @@ package filevalidation import ( "fmt" "path/filepath" + "slices" "strings" ) @@ -162,6 +163,10 @@ func (v *FileValidator) WithMaxFileSize(maxSize int64) *FileValidator { // Validate validates that the file meets the configured requirements func (v *FileValidator) Validate(filename string, contentType string, size int64) error { + if size == 0 { + return fmt.Errorf("file can't be empty") + } + if size > v.MaxFileSize { return fmt.Errorf("file size exceeds maximum allowed size of %d bytes", v.MaxFileSize) } @@ -180,13 +185,7 @@ func (v *FileValidator) Validate(filename string, contentType string, size int64 return fmt.Errorf("file extension %q is not allowed", ext) } - validType := false - for _, allowedType := range allowedTypes { - if contentType == allowedType { - validType = true - break - } - } + validType := slices.Contains(allowedTypes, contentType) if !validType { return fmt.Errorf("content type %q does not match extension %q", contentType, ext) diff --git a/pkg/probo/audit_service.go b/pkg/probo/audit_service.go index 4467a451c..50805b09c 100644 --- a/pkg/probo/audit_service.go +++ b/pkg/probo/audit_service.go @@ -24,6 +24,7 @@ import ( "go.gearno.de/crypto/uuid" "go.gearno.de/kit/pg" "go.probo.inc/probo/pkg/coredata" + "go.probo.inc/probo/pkg/filevalidation" "go.probo.inc/probo/pkg/gid" "go.probo.inc/probo/pkg/page" "go.probo.inc/probo/pkg/validator" @@ -88,8 +89,19 @@ func (uarr *UploadAuditReportRequest) Validate() error { v := validator.New() v.Check(uarr.AuditID, "audit_id", validator.Required(), validator.GID(coredata.AuditEntityType)) + if err := v.Error(); err != nil { + return err + } - return v.Error() + fv := filevalidation.NewValidator( + filevalidation.WithCategories(filevalidation.CategoryDocument), + filevalidation.WithMaxFileSize(25*1024*1024), + ) + if err := fv.Validate(uarr.File.Filename, uarr.File.ContentType, uarr.File.Size); err != nil { + return fmt.Errorf("invalid audit report file: %w", err) + } + + return nil } func (s AuditService) Get( @@ -313,6 +325,10 @@ func (s AuditService) UploadReport( ctx context.Context, req UploadAuditReportRequest, ) (*coredata.Audit, error) { + if err := req.Validate(); err != nil { + return nil, fmt.Errorf("invalid request: %w", err) + } + audit := &coredata.Audit{} err := s.svc.pg.WithTx(