diff --git a/pkg/probo/audit_service.go b/pkg/probo/audit_service.go index 2dd8fda83..c8d7bede6 100644 --- a/pkg/probo/audit_service.go +++ b/pkg/probo/audit_service.go @@ -19,9 +19,12 @@ import ( "fmt" "time" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/getprobo/probo/pkg/coredata" "github.com/getprobo/probo/pkg/gid" "github.com/getprobo/probo/pkg/page" + "go.gearno.de/crypto/uuid" "go.gearno.de/kit/pg" ) @@ -283,9 +286,41 @@ func (s AuditService) UploadReport( return fmt.Errorf("cannot load audit: %w", err) } - report, err := s.svc.Reports.Create(ctx, req.File) + reportID := gid.New(s.svc.scope.GetTenantID(), coredata.ReportEntityType) + now := time.Now() + + objectKey, err := uuid.NewV7() if err != nil { - return fmt.Errorf("cannot create report: %w", err) + return fmt.Errorf("cannot generate object key: %w", err) + } + + _, err = s.svc.s3.PutObject(ctx, &s3.PutObjectInput{ + Bucket: aws.String(s.svc.bucket), + Key: aws.String(objectKey.String()), + Body: req.File.Content, + ContentType: aws.String(req.File.ContentType), + Metadata: map[string]string{ + "type": "report", + "report-id": reportID.String(), + "organization-id": audit.OrganizationID.String(), + }, + }) + if err != nil { + return fmt.Errorf("cannot upload report to S3: %w", err) + } + + report := &coredata.Report{ + ID: reportID, + ObjectKey: objectKey.String(), + MimeType: req.File.ContentType, + Filename: req.File.Filename, + Size: req.File.Size, + CreatedAt: now, + UpdatedAt: now, + } + + if err := report.Insert(ctx, conn, s.svc.scope); err != nil { + return fmt.Errorf("cannot insert report: %w", err) } audit.ReportID = &report.ID diff --git a/pkg/probo/document_service.go b/pkg/probo/document_service.go index 393e5278e..c37f7ca42 100644 --- a/pkg/probo/document_service.go +++ b/pkg/probo/document_service.go @@ -1226,6 +1226,17 @@ func (s *DocumentService) BuildAndUploadExport(ctx context.Context, exportJobID return fmt.Errorf("cannot get document IDs: %w", err) } + if len(documentIDs) == 0 { + return fmt.Errorf("no document IDs found") + } + + var organizationID gid.GID + firstDocument := &coredata.Document{} + if err := firstDocument.LoadByID(ctx, tx, s.svc.scope, documentIDs[0]); err != nil { + return fmt.Errorf("cannot load document for organization ID: %w", err) + } + organizationID = firstDocument.OrganizationID + tempDir := os.TempDir() tempFile, err := os.CreateTemp(tempDir, "probo-document-export-*.zip") if err != nil { @@ -1273,8 +1284,9 @@ func (s *DocumentService) BuildAndUploadExport(ctx context.Context, exportJobID ContentLength: ref.Ref(fileInfo.Size()), ContentType: ref.Ref("application/zip"), Metadata: map[string]string{ - "type": "document-export", - "export-job-id": exportJob.ID.String(), + "type": "document-export", + "export-job-id": exportJob.ID.String(), + "organization-id": organizationID.String(), }, }, ) diff --git a/pkg/probo/evidence_service.go b/pkg/probo/evidence_service.go index 9bc121dae..70a68ee50 100644 --- a/pkg/probo/evidence_service.go +++ b/pkg/probo/evidence_service.go @@ -155,6 +155,11 @@ func (s EvidenceService) Fulfill( return fmt.Errorf("cannot load evidence: %w", err) } + measure := &coredata.Measure{} + if err := measure.LoadByID(ctx, conn, s.svc.scope, evidence.MeasureID); err != nil { + return fmt.Errorf("cannot load measure: %w", err) + } + evidence.State = coredata.EvidenceStateFulfilled if req.File != nil { @@ -206,6 +211,11 @@ func (s EvidenceService) Fulfill( Key: aws.String(objectKey.String()), Body: fileContent, ContentType: aws.String(contentType), + Metadata: map[string]string{ + "type": "evidence", + "evidence-id": req.EvidenceID.String(), + "organization-id": measure.OrganizationID.String(), + }, }) if err != nil { return fmt.Errorf("cannot upload file to S3: %w", err) @@ -271,27 +281,7 @@ func (s EvidenceService) UploadTaskEvidence( return nil, err } - objectKey, err := uuid.NewV7() - if err != nil { - return nil, fmt.Errorf("cannot generate object key: %w", err) - } - - _, err = s.svc.s3.PutObject( - ctx, - &s3.PutObjectInput{ - Bucket: aws.String(s.svc.bucket), - Key: aws.String(objectKey.String()), - Body: req.File.Content, - ContentType: aws.String(req.File.ContentType), - }, - ) - if err != nil { - return nil, fmt.Errorf("cannot upload file to S3: %w", err) - } - - evidence.ObjectKey = objectKey.String() - evidence.MimeType = req.File.ContentType - evidence.Size = uint64(req.File.Size) + var measureOrganizationID gid.GID err = s.svc.pg.WithTx( ctx, @@ -306,6 +296,38 @@ func (s EvidenceService) UploadTaskEvidence( return fmt.Errorf("task %q has no measure", req.TaskID) } + measure := &coredata.Measure{} + if err := measure.LoadByID(ctx, conn, s.svc.scope, *task.MeasureID); err != nil { + return fmt.Errorf("cannot load measure: %w", err) + } + measureOrganizationID = measure.OrganizationID + + objectKey, err := uuid.NewV7() + if err != nil { + return fmt.Errorf("cannot generate object key: %w", err) + } + + _, err = s.svc.s3.PutObject( + ctx, + &s3.PutObjectInput{ + Bucket: aws.String(s.svc.bucket), + Key: aws.String(objectKey.String()), + Body: req.File.Content, + ContentType: aws.String(req.File.ContentType), + Metadata: map[string]string{ + "type": "evidence", + "evidence-id": evidenceID.String(), + "organization-id": measureOrganizationID.String(), + }, + }, + ) + if err != nil { + return fmt.Errorf("cannot upload file to S3: %w", err) + } + + evidence.ObjectKey = objectKey.String() + evidence.MimeType = req.File.ContentType + evidence.Size = uint64(req.File.Size) evidence.MeasureID = *task.MeasureID if err := evidence.Insert(ctx, conn, s.svc.scope); err != nil { @@ -355,37 +377,40 @@ func (s EvidenceService) UploadMeasureEvidence( return nil, err } - objectKey, err := uuid.NewV7() - if err != nil { - return nil, fmt.Errorf("cannot generate object key: %w", err) - } - - _, err = s.svc.s3.PutObject( - ctx, - &s3.PutObjectInput{ - Bucket: aws.String(s.svc.bucket), - Key: aws.String(objectKey.String()), - Body: req.File.Content, - ContentType: aws.String(req.File.ContentType), - }, - ) - if err != nil { - return nil, fmt.Errorf("cannot upload file to S3: %w", err) - } - - evidence.ObjectKey = objectKey.String() - evidence.MimeType = req.File.ContentType - evidence.Size = uint64(req.File.Size) - err = s.svc.pg.WithTx( ctx, func(conn pg.Conn) error { measure := &coredata.Measure{} - if err := measure.LoadByID(ctx, conn, s.svc.scope, req.MeasureID); err != nil { return fmt.Errorf("cannot load measure %q: %w", req.MeasureID, err) } + objectKey, err := uuid.NewV7() + if err != nil { + return fmt.Errorf("cannot generate object key: %w", err) + } + + _, err = s.svc.s3.PutObject( + ctx, + &s3.PutObjectInput{ + Bucket: aws.String(s.svc.bucket), + Key: aws.String(objectKey.String()), + Body: req.File.Content, + ContentType: aws.String(req.File.ContentType), + Metadata: map[string]string{ + "type": "evidence", + "evidence-id": evidenceID.String(), + "organization-id": measure.OrganizationID.String(), + }, + }, + ) + if err != nil { + return fmt.Errorf("cannot upload file to S3: %w", err) + } + + evidence.ObjectKey = objectKey.String() + evidence.MimeType = req.File.ContentType + evidence.Size = uint64(req.File.Size) evidence.MeasureID = req.MeasureID if err := evidence.Insert(ctx, conn, s.svc.scope); err != nil { diff --git a/pkg/probo/framework_service.go b/pkg/probo/framework_service.go index a691786d7..227d425f1 100644 --- a/pkg/probo/framework_service.go +++ b/pkg/probo/framework_service.go @@ -807,8 +807,9 @@ func (s *FrameworkService) BuildAndUploadExport(ctx context.Context, exportJobID ContentLength: ref.Ref(fileInfo.Size()), ContentType: ref.Ref("application/zip"), Metadata: map[string]string{ - "type": "framework-export", - "export-job-id": exportJob.ID.String(), + "type": "framework-export", + "export-job-id": exportJob.ID.String(), + "organization-id": framework.OrganizationID.String(), }, }, ) diff --git a/pkg/probo/organization_service.go b/pkg/probo/organization_service.go index b007570a6..f2579d1e2 100644 --- a/pkg/probo/organization_service.go +++ b/pkg/probo/organization_service.go @@ -248,6 +248,10 @@ func (s OrganizationService) Update( Key: aws.String(objectKey.String()), Body: fileContent, ContentType: aws.String(contentType), + Metadata: map[string]string{ + "type": "organization-logo", + "organization-id": organization.ID.String(), + }, }) if err != nil { diff --git a/pkg/probo/report_service.go b/pkg/probo/report_service.go index a68a94511..388e365c5 100644 --- a/pkg/probo/report_service.go +++ b/pkg/probo/report_service.go @@ -23,7 +23,6 @@ import ( "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/getprobo/probo/pkg/coredata" "github.com/getprobo/probo/pkg/gid" - "go.gearno.de/crypto/uuid" "go.gearno.de/kit/pg" ) @@ -56,57 +55,6 @@ func (s ReportService) Get( return report, nil } -func (s ReportService) Create( - ctx context.Context, - file File, -) (*coredata.Report, error) { - reportID := gid.New(s.svc.scope.GetTenantID(), coredata.ReportEntityType) - now := time.Now() - - objectKey, err := uuid.NewV7() - if err != nil { - return nil, fmt.Errorf("cannot generate object key: %w", err) - } - - _, err = s.svc.s3.PutObject(ctx, &s3.PutObjectInput{ - Bucket: aws.String(s.svc.bucket), - Key: aws.String(objectKey.String()), - Body: file.Content, - ContentType: aws.String(file.ContentType), - Metadata: map[string]string{ - "report-id": reportID.String(), - }, - }) - if err != nil { - return nil, fmt.Errorf("cannot upload report to S3: %w", err) - } - - report := &coredata.Report{ - ID: reportID, - ObjectKey: objectKey.String(), - MimeType: file.ContentType, - Filename: file.Filename, - Size: file.Size, - CreatedAt: now, - UpdatedAt: now, - } - - err = s.svc.pg.WithConn(ctx, func(conn pg.Conn) error { - err := report.Insert(ctx, conn, s.svc.scope) - if err != nil { - return fmt.Errorf("cannot insert report: %w", err) - } - - return nil - }) - - if err != nil { - return nil, err - } - - return report, nil -} - func (s ReportService) Delete( ctx context.Context, reportID gid.GID, diff --git a/pkg/probo/trust_center_reference_service.go b/pkg/probo/trust_center_reference_service.go index d65247a5f..ee49def89 100644 --- a/pkg/probo/trust_center_reference_service.go +++ b/pkg/probo/trust_center_reference_service.go @@ -148,7 +148,7 @@ func (s TrustCenterReferenceService) Create( var logoKey string err := s.svc.pg.WithTx(ctx, func(tx pg.Conn) error { - fileID, s3Key, err := s.uploadLogoFile(ctx, tx, req.LogoFile, referenceID, now) + fileID, s3Key, err := s.uploadLogoFile(ctx, tx, req.LogoFile, referenceID, req.TrustCenterID, now) if err != nil { return fmt.Errorf("cannot upload logo file: %w", err) } @@ -200,8 +200,14 @@ func (s TrustCenterReferenceService) Update( var logoKey string err := s.svc.pg.WithTx(ctx, func(tx pg.Conn) error { + reference = &coredata.TrustCenterReference{} + + if err := reference.LoadByID(ctx, tx, s.svc.scope, req.ID); err != nil { + return fmt.Errorf("cannot load trust center reference: %w", err) + } + if req.LogoFile != nil { - fileID, s3Key, err := s.uploadLogoFile(ctx, tx, *req.LogoFile, req.ID, now) + fileID, s3Key, err := s.uploadLogoFile(ctx, tx, *req.LogoFile, req.ID, reference.TrustCenterID, now) if err != nil { return fmt.Errorf("cannot upload logo file: %w", err) } @@ -209,12 +215,6 @@ func (s TrustCenterReferenceService) Update( logoKey = s3Key } - reference = &coredata.TrustCenterReference{} - - if err := reference.LoadByID(ctx, tx, s.svc.scope, req.ID); err != nil { - return fmt.Errorf("cannot load trust center reference: %w", err) - } - if req.Name != nil { reference.Name = *req.Name } @@ -316,6 +316,7 @@ func (s TrustCenterReferenceService) uploadLogoFile( tx pg.Conn, file File, referenceID gid.GID, + trustCenterID gid.GID, now time.Time, ) (gid.GID, string, error) { fileID := gid.New(s.svc.scope.GetTenantID(), coredata.FileEntityType) @@ -325,6 +326,11 @@ func (s TrustCenterReferenceService) uploadLogoFile( return gid.GID{}, "", fmt.Errorf("cannot generate object key: %w", err) } + trustCenter := &coredata.TrustCenter{} + if err := trustCenter.LoadByID(ctx, tx, s.svc.scope, trustCenterID); err != nil { + return gid.GID{}, "", fmt.Errorf("cannot load trust center: %w", err) + } + var fileSize int64 var fileContent io.ReadSeeker filename := file.Filename @@ -372,6 +378,7 @@ func (s TrustCenterReferenceService) uploadLogoFile( Metadata: map[string]string{ "type": "trust-center-reference-logo", "trust-center-reference-id": referenceID.String(), + "organization-id": trustCenter.OrganizationID.String(), }, }) if err != nil { diff --git a/pkg/probo/trust_center_service.go b/pkg/probo/trust_center_service.go index 85da4c5a0..d5f0220e2 100644 --- a/pkg/probo/trust_center_service.go +++ b/pkg/probo/trust_center_service.go @@ -175,34 +175,6 @@ func (s TrustCenterService) UploadNDA( return nil, nil, fmt.Errorf("cannot generate object key: %w", err) } - mimeType := mime.TypeByExtension(filepath.Ext(req.FileName)) - - _, err = s.svc.s3.PutObject(ctx, &s3.PutObjectInput{ - Bucket: &s.svc.bucket, - Key: aws.String(objectKey.String()), - Body: req.File, - ContentType: &mimeType, - Metadata: map[string]string{ - "type": "trust-center-nda", - "trust-center-id": req.TrustCenterID.String(), - }, - }) - if err != nil { - return nil, nil, fmt.Errorf("cannot upload file to S3: %w", err) - } - - headOutput, err := s.svc.s3.HeadObject(ctx, &s3.HeadObjectInput{ - Bucket: aws.String(s.svc.bucket), - Key: aws.String(objectKey.String()), - }) - if err != nil { - return nil, nil, fmt.Errorf("cannot get object metadata: %w", err) - } - - now := time.Now() - - fileID := gid.New(s.svc.scope.GetTenantID(), coredata.FileEntityType) - var trustCenter *coredata.TrustCenter var file *coredata.File @@ -214,6 +186,34 @@ func (s TrustCenterService) UploadNDA( return fmt.Errorf("cannot load trust center: %w", err) } + mimeType := mime.TypeByExtension(filepath.Ext(req.FileName)) + + _, err := s.svc.s3.PutObject(ctx, &s3.PutObjectInput{ + Bucket: &s.svc.bucket, + Key: aws.String(objectKey.String()), + Body: req.File, + ContentType: &mimeType, + Metadata: map[string]string{ + "type": "trust-center-nda", + "trust-center-id": req.TrustCenterID.String(), + "organization-id": trustCenter.OrganizationID.String(), + }, + }) + if err != nil { + return fmt.Errorf("cannot upload file to S3: %w", err) + } + + headOutput, err := s.svc.s3.HeadObject(ctx, &s3.HeadObjectInput{ + Bucket: aws.String(s.svc.bucket), + Key: aws.String(objectKey.String()), + }) + if err != nil { + return fmt.Errorf("cannot get object metadata: %w", err) + } + + now := time.Now() + fileID := gid.New(s.svc.scope.GetTenantID(), coredata.FileEntityType) + file = &coredata.File{ ID: fileID, BucketName: s.svc.bucket, diff --git a/pkg/probo/vendor_business_associate_agreement_service.go b/pkg/probo/vendor_business_associate_agreement_service.go index 86b36c72d..c3cab8ce8 100644 --- a/pkg/probo/vendor_business_associate_agreement_service.go +++ b/pkg/probo/vendor_business_associate_agreement_service.go @@ -90,31 +90,6 @@ func (s VendorBusinessAssociateAgreementService) Upload( return nil, nil, fmt.Errorf("cannot generate object key: %w", err) } - mimeType := mime.TypeByExtension(filepath.Ext(req.FileName)) - - _, err = s.svc.s3.PutObject(ctx, &s3.PutObjectInput{ - Bucket: &s.svc.bucket, - Key: aws.String(objectKey.String()), - Body: req.File, - ContentType: &mimeType, - }) - if err != nil { - return nil, nil, fmt.Errorf("cannot upload file to S3: %w", err) - } - - headOutput, err := s.svc.s3.HeadObject(ctx, &s3.HeadObjectInput{ - Bucket: aws.String(s.svc.bucket), - Key: aws.String(objectKey.String()), - }) - if err != nil { - return nil, nil, fmt.Errorf("cannot get object metadata: %w", err) - } - - now := time.Now() - - fileID := gid.New(s.svc.scope.GetTenantID(), coredata.FileEntityType) - vendorBusinessAssociateAgreementID := gid.New(s.svc.scope.GetTenantID(), coredata.VendorBusinessAssociateAgreementEntityType) - var vendorBusinessAssociateAgreement *coredata.VendorBusinessAssociateAgreement var file *coredata.File @@ -126,6 +101,35 @@ func (s VendorBusinessAssociateAgreementService) Upload( return fmt.Errorf("cannot load vendor: %w", err) } + mimeType := mime.TypeByExtension(filepath.Ext(req.FileName)) + + _, err := s.svc.s3.PutObject(ctx, &s3.PutObjectInput{ + Bucket: &s.svc.bucket, + Key: aws.String(objectKey.String()), + Body: req.File, + ContentType: &mimeType, + Metadata: map[string]string{ + "type": "vendor-business-associate-agreement", + "vendor-id": vendorID.String(), + "organization-id": vendor.OrganizationID.String(), + }, + }) + if err != nil { + return fmt.Errorf("cannot upload file to S3: %w", err) + } + + headOutput, err := s.svc.s3.HeadObject(ctx, &s3.HeadObjectInput{ + Bucket: aws.String(s.svc.bucket), + Key: aws.String(objectKey.String()), + }) + if err != nil { + return fmt.Errorf("cannot get object metadata: %w", err) + } + + now := time.Now() + fileID := gid.New(s.svc.scope.GetTenantID(), coredata.FileEntityType) + vendorBusinessAssociateAgreementID := gid.New(s.svc.scope.GetTenantID(), coredata.VendorBusinessAssociateAgreementEntityType) + file = &coredata.File{ ID: fileID, BucketName: s.svc.bucket, diff --git a/pkg/probo/vendor_compliance_report_service.go b/pkg/probo/vendor_compliance_report_service.go index a72ee0196..e58c4fcbd 100644 --- a/pkg/probo/vendor_compliance_report_service.go +++ b/pkg/probo/vendor_compliance_report_service.go @@ -76,45 +76,56 @@ func (s VendorComplianceReportService) Upload( return nil, fmt.Errorf("cannot generate object key: %w", err) } - mimeType := mime.TypeByExtension(filepath.Ext(req.ReportName)) + var vendorComplianceReport *coredata.VendorComplianceReport - _, err = s.svc.s3.PutObject(ctx, &s3.PutObjectInput{ - Bucket: &s.svc.bucket, - Key: aws.String(objectKey.String()), - Body: req.File, - ContentType: &mimeType, - }) - if err != nil { - return nil, fmt.Errorf("cannot upload file to S3: %w", err) - } - - headOutput, err := s.svc.s3.HeadObject(ctx, &s3.HeadObjectInput{ - Bucket: aws.String(s.svc.bucket), - Key: aws.String(objectKey.String()), - }) - if err != nil { - return nil, fmt.Errorf("cannot get object metadata: %w", err) - } - - now := time.Now() - - vendorComplianceReportID := gid.New(s.svc.scope.GetTenantID(), coredata.VendorComplianceReportEntityType) - - vendorComplianceReport := &coredata.VendorComplianceReport{ - ID: vendorComplianceReportID, - VendorID: vendorID, - ReportDate: req.ReportDate, - ValidUntil: req.ValidUntil, - ReportName: req.ReportName, - FileKey: objectKey.String(), - FileSize: *headOutput.ContentLength, - CreatedAt: now, - UpdatedAt: now, - } - - err = s.svc.pg.WithConn( + err = s.svc.pg.WithTx( ctx, func(conn pg.Conn) error { + vendor := &coredata.Vendor{} + if err := vendor.LoadByID(ctx, conn, s.svc.scope, vendorID); err != nil { + return fmt.Errorf("cannot load vendor: %w", err) + } + + mimeType := mime.TypeByExtension(filepath.Ext(req.ReportName)) + + _, err := s.svc.s3.PutObject(ctx, &s3.PutObjectInput{ + Bucket: &s.svc.bucket, + Key: aws.String(objectKey.String()), + Body: req.File, + ContentType: &mimeType, + Metadata: map[string]string{ + "type": "vendor-compliance-report", + "vendor-id": vendorID.String(), + "organization-id": vendor.OrganizationID.String(), + }, + }) + if err != nil { + return fmt.Errorf("cannot upload file to S3: %w", err) + } + + headOutput, err := s.svc.s3.HeadObject(ctx, &s3.HeadObjectInput{ + Bucket: aws.String(s.svc.bucket), + Key: aws.String(objectKey.String()), + }) + if err != nil { + return fmt.Errorf("cannot get object metadata: %w", err) + } + + now := time.Now() + vendorComplianceReportID := gid.New(s.svc.scope.GetTenantID(), coredata.VendorComplianceReportEntityType) + + vendorComplianceReport = &coredata.VendorComplianceReport{ + ID: vendorComplianceReportID, + VendorID: vendorID, + ReportDate: req.ReportDate, + ValidUntil: req.ValidUntil, + ReportName: req.ReportName, + FileKey: objectKey.String(), + FileSize: *headOutput.ContentLength, + CreatedAt: now, + UpdatedAt: now, + } + return vendorComplianceReport.Insert(ctx, conn, s.svc.scope) }, ) diff --git a/pkg/probo/vendor_data_privacy_agreement_service.go b/pkg/probo/vendor_data_privacy_agreement_service.go index 5deef29f8..56e202f4a 100644 --- a/pkg/probo/vendor_data_privacy_agreement_service.go +++ b/pkg/probo/vendor_data_privacy_agreement_service.go @@ -90,42 +90,44 @@ func (s VendorDataPrivacyAgreementService) Upload( return nil, nil, fmt.Errorf("cannot generate object key: %w", err) } - mimeType := mime.TypeByExtension(filepath.Ext(req.FileName)) - - _, err = s.svc.s3.PutObject(ctx, &s3.PutObjectInput{ - Bucket: &s.svc.bucket, - Key: aws.String(objectKey.String()), - Body: req.File, - ContentType: &mimeType, - }) - if err != nil { - return nil, nil, fmt.Errorf("cannot upload file to S3: %w", err) - } - - headOutput, err := s.svc.s3.HeadObject(ctx, &s3.HeadObjectInput{ - Bucket: aws.String(s.svc.bucket), - Key: aws.String(objectKey.String()), - }) - if err != nil { - return nil, nil, fmt.Errorf("cannot get object metadata: %w", err) - } - - now := time.Now() - - fileID := gid.New(s.svc.scope.GetTenantID(), coredata.FileEntityType) - vendorDataPrivacyAgreementID := gid.New(s.svc.scope.GetTenantID(), coredata.VendorDataPrivacyAgreementEntityType) - var vendorDataPrivacyAgreement *coredata.VendorDataPrivacyAgreement var file *coredata.File + var vendor *coredata.Vendor err = s.svc.pg.WithTx( ctx, func(conn pg.Conn) error { - vendor := &coredata.Vendor{} + vendor = &coredata.Vendor{} if err := vendor.LoadByID(ctx, conn, s.svc.scope, vendorID); err != nil { return fmt.Errorf("cannot load vendor: %w", err) } + mimeType := mime.TypeByExtension(filepath.Ext(req.FileName)) + _, err := s.svc.s3.PutObject(ctx, &s3.PutObjectInput{ + Bucket: &s.svc.bucket, + Key: aws.String(objectKey.String()), + Body: req.File, + ContentType: &mimeType, + Metadata: map[string]string{ + "type": "vendor-data-privacy-agreement", + "vendor-id": vendorID.String(), + "organization-id": vendor.OrganizationID.String(), + }, + }) + if err != nil { + return fmt.Errorf("cannot upload file to S3: %w", err) + } + headOutput, err := s.svc.s3.HeadObject(ctx, &s3.HeadObjectInput{ + Bucket: aws.String(s.svc.bucket), + Key: aws.String(objectKey.String()), + }) + if err != nil { + return fmt.Errorf("cannot get object metadata: %w", err) + } + + now := time.Now() + fileID := gid.New(s.svc.scope.GetTenantID(), coredata.FileEntityType) + vendorDataPrivacyAgreementID := gid.New(s.svc.scope.GetTenantID(), coredata.VendorDataPrivacyAgreementEntityType) file = &coredata.File{ ID: fileID, BucketName: s.svc.bucket,