diff --git a/docker-compose.yml b/docker-compose.yml index 95cc80c..60519ad 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -32,6 +32,7 @@ services: AWS_S3_ENDPOINT: http://localstack:4566 AWS_ACCESS_KEY_ID: localstack AWS_SECRET_ACCESS_KEY: localstack + S3_ENCRYPTION_KEY: alias/aws/s3 healthcheck: test: wget -O /dev/null -S 'http://localhost:8080/health-check' 2>&1 | grep 'HTTP/1.1 200 OK' || exit 1 interval: 15s diff --git a/finance-admin-api/api/upload.go b/finance-admin-api/api/upload.go index 03c3d6a..0a0c527 100644 --- a/finance-admin-api/api/upload.go +++ b/finance-admin-api/api/upload.go @@ -95,9 +95,10 @@ func (s *Server) upload(w http.ResponseWriter, r *http.Request) error { _, err = s.awsClient.PutObject(ctx, &s3.PutObjectInput{ Bucket: aws.String(os.Getenv("ASYNC_S3_BUCKET")), - Key: aws.String(fmt.Sprintf("%s/%s", "finance-admin", upload.Filename)), + Key: aws.String(fmt.Sprintf("%s/%s", upload.ReportUploadType.S3Directory(), upload.Filename)), Body: bytes.NewReader(upload.File), - ServerSideEncryption: "AES256", + ServerSideEncryption: "aws:kms", + SSEKMSKeyId: aws.String(os.Getenv("S3_ENCRYPTION_KEY")), }) if err != nil { diff --git a/finance-admin/internal/server/post_upload.go b/finance-admin/internal/server/post_upload.go index 3e75b00..e6de506 100644 --- a/finance-admin/internal/server/post_upload.go +++ b/finance-admin/internal/server/post_upload.go @@ -7,6 +7,7 @@ import ( "github.com/opg-sirius-finance-admin/finance-admin/internal/model" "github.com/opg-sirius-finance-admin/shared" "net/http" + "strings" ) type UploadFormHandler struct { @@ -16,7 +17,7 @@ type UploadFormHandler struct { func (h *UploadFormHandler) render(v AppVars, w http.ResponseWriter, r *http.Request) error { ctx := getContext(r) - reportUploadType := r.PostFormValue("reportUploadType") + reportUploadType := shared.ParseReportUploadType(r.PostFormValue("reportUploadType")) uploadDate := r.PostFormValue("uploadDate") email := r.PostFormValue("email") @@ -27,7 +28,17 @@ func (h *UploadFormHandler) render(v AppVars, w http.ResponseWriter, r *http.Req } defer file.Close() - data, err := shared.NewUpload(shared.ParseReportUploadType(reportUploadType), uploadDate, email, file, handler.Filename) + expectedFilename, err := reportUploadType.Filename(uploadDate) + if err != nil { + return h.handleError(w, r, "Could not parse upload date", http.StatusBadRequest) + } + + if handler.Filename != expectedFilename && expectedFilename != "" { + expectedFilename := strings.Replace(expectedFilename, ":", "/", -1) + return h.handleError(w, r, fmt.Sprintf("Filename should be named \"%s\"", expectedFilename), http.StatusBadRequest) + } + + data, err := shared.NewUpload(reportUploadType, uploadDate, email, file, handler.Filename) if err != nil { return h.handleError(w, r, "Failed to read file", http.StatusBadRequest) } diff --git a/shared/upload_type.go b/shared/upload_type.go index d7df5c2..6eb92d0 100644 --- a/shared/upload_type.go +++ b/shared/upload_type.go @@ -1,6 +1,10 @@ package shared -import "encoding/json" +import ( + "encoding/json" + "fmt" + "time" +) var ReportUploadTypes = []ReportUploadType{ ReportTypeUploadPaymentsMOTOCard, @@ -76,6 +80,8 @@ func (i ReportUploadType) Key() string { func (i ReportUploadType) CSVHeaders() []string { switch i { + case ReportTypeUploadPaymentsMOTOCard: + return []string{"Ordercode", "Date", "Amount"} case ReportTypeUploadDeputySchedule: return []string{"Deputy number", "Deputy name", "Case number", "Client forename", "Client surname", "Do not invoice", "Total outstanding"} case ReportTypeUploadDebtChase: @@ -87,6 +93,28 @@ func (i ReportUploadType) CSVHeaders() []string { } } +func (i ReportUploadType) S3Directory() string { + switch i { + case ReportTypeUploadPaymentsMOTOCard: + return "moto-card-payments" + default: + return "finance-admin" + } +} + +func (i ReportUploadType) Filename(date string) (string, error) { + switch i { + case ReportTypeUploadPaymentsMOTOCard: + parsedDate, err := time.Parse("2006-01-02", date) + if err != nil { + return "", err + } + return fmt.Sprintf("feemoto_%snormal.csv", parsedDate.Format("02:01:2006")), nil + default: + return "", nil + } +} + func ParseReportUploadType(s string) ReportUploadType { value, ok := reportTypeUploadMap[s] if !ok { diff --git a/shared/upload_type_test.go b/shared/upload_type_test.go new file mode 100644 index 0000000..93bc6b2 --- /dev/null +++ b/shared/upload_type_test.go @@ -0,0 +1,49 @@ +package shared + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestReportUploadType_Filename(t *testing.T) { + tests := []struct { + name string + uploadType ReportUploadType + dateString string + wantErr bool + wantFilename string + }{ + { + name: "Non-moto card payments report type", + uploadType: ReportTypeUploadDeputySchedule, + dateString: "02/01/2020", + wantErr: false, + wantFilename: "", + }, + { + name: "Moto card payments report type", + uploadType: ReportTypeUploadPaymentsMOTOCard, + dateString: "02/01/2020", + wantErr: false, + wantFilename: "", + }, + { + name: "Invalid date", + uploadType: ReportTypeUploadPaymentsMOTOCard, + dateString: "hehe", + wantErr: true, + wantFilename: "", + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + filename, err := test.uploadType.Filename(test.dateString) + + assert.Equal(t, test.wantFilename, filename) + + if test.wantErr { + assert.Error(t, err) + } + }) + } +}