From 4eb01e62d3258cb90933360087d13808adee6303 Mon Sep 17 00:00:00 2001 From: nicholassully Date: Wed, 28 Aug 2024 14:29:53 +0100 Subject: [PATCH] pfs-117 moving logic from the api layer --- internal/api/api_client.go | 16 -------- internal/api/upload.go | 25 ++---------- internal/api/upload_test.go | 31 ++++++++------- internal/model/upload.go | 22 +++++++++++ internal/model/upload_test.go | 69 ++++++++++++++++++++++++++++++++++ internal/model/upload_type.go | 32 ++++++++++++++++ internal/server/server.go | 2 +- internal/server/server_test.go | 2 +- internal/server/upload.go | 7 +++- 9 files changed, 150 insertions(+), 56 deletions(-) create mode 100644 internal/model/upload_test.go diff --git a/internal/api/api_client.go b/internal/api/api_client.go index 1637e22..63e7949 100644 --- a/internal/api/api_client.go +++ b/internal/api/api_client.go @@ -69,22 +69,6 @@ func (c *Client) newBackendRequest(ctx Context, method, path string, body io.Rea return req, err } -func (c *Client) newSiriusRequest(ctx Context, method, path string, body io.Reader) (*http.Request, error) { - req, err := http.NewRequestWithContext(ctx.Context, method, c.siriusURL+"/supervision-api/v1"+path, body) - if err != nil { - return nil, err - } - - for _, c := range ctx.Cookies { - req.AddCookie(c) - } - - req.Header.Add("OPG-Bypass-Membrane", "1") - req.Header.Add("X-XSRF-TOKEN", ctx.XSRFToken) - - return req, err -} - func newStatusError(resp *http.Response) StatusError { return StatusError{ Code: resp.StatusCode, diff --git a/internal/api/upload.go b/internal/api/upload.go index 1b61d1a..37b5530 100644 --- a/internal/api/upload.go +++ b/internal/api/upload.go @@ -4,33 +4,18 @@ import ( "bytes" "encoding/json" "github.com/opg-sirius-finance-admin/internal/model" - "io" "net/http" ) -func (c *Client) Upload(ctx Context, reportUploadType string, uploadDate string, email string, file io.Reader) error { +func (c *Client) Upload(ctx Context, data model.Upload) error { var body bytes.Buffer - var uploadDateTransformed *model.Date - var req *http.Request - if uploadDate != "" { - uploadDateFormatted := model.NewDate(uploadDate) - uploadDateTransformed = &uploadDateFormatted - } - - fileTransformed, err := io.ReadAll(file) - - err = json.NewEncoder(&body).Encode(model.Upload{ - ReportUploadType: reportUploadType, - UploadDate: uploadDateTransformed, - Email: email, - File: fileTransformed, - }) + err := json.NewEncoder(&body).Encode(data) if err != nil { return err } - req, err = c.newBackendRequest(ctx, http.MethodPost, "/uploads", &body) + req, err := c.newBackendRequest(ctx, http.MethodPost, "/uploads", &body) if err != nil { return err @@ -64,9 +49,7 @@ func (c *Client) Upload(ctx Context, reportUploadType string, uploadDate string, validationErrors := model.ValidationErrors{} for _, reason := range badRequests.Reasons { - innerMap := make(map[string]string) - innerMap[reason] = reason - validationErrors[reason] = innerMap + validationErrors[reason] = map[string]string{reason: reason} } return model.ValidationError{Errors: validationErrors} diff --git a/internal/api/upload_test.go b/internal/api/upload_test.go index c4b44b8..eb3c43f 100644 --- a/internal/api/upload_test.go +++ b/internal/api/upload_test.go @@ -4,36 +4,35 @@ import ( "bytes" "encoding/json" "github.com/opg-sirius-finance-admin/internal/model" + "github.com/stretchr/testify/assert" "io" "net/http" "net/http/httptest" - "net/url" - "strings" "testing" - - "github.com/stretchr/testify/assert" ) func TestUploadUrlSwitching(t *testing.T) { mockClient := &MockClient{} client, _ := NewClient(mockClient, "http://localhost:3000", "") - - // Write some content to the temp file - content := strings.NewReader("something here") - - var capturedURL *url.URL + uploadDate := model.NewDate("2025-06-15") + content := []byte("file content") + + data := model.Upload{ + ReportUploadType: "reportUploadType", + UploadDate: &uploadDate, + Email: "Something@example.com", + File: content, + } GetDoFunc = func(req *http.Request) (*http.Response, error) { - capturedURL = req.URL return &http.Response{ StatusCode: http.StatusCreated, Body: io.NopCloser(bytes.NewReader([]byte{})), }, nil } - err := client.Upload(getContext(nil), "", "", "", content) + err := client.Upload(getContext(nil), data) assert.NoError(t, err) - assert.Equal(t, "/uploads", capturedURL.String()) } func TestSubmitUploadUnauthorised(t *testing.T) { @@ -44,7 +43,7 @@ func TestSubmitUploadUnauthorised(t *testing.T) { client, _ := NewClient(http.DefaultClient, svr.URL, svr.URL) - err := client.Upload(getContext(nil), "", "", "", nil) + err := client.Upload(getContext(nil), model.Upload{}) assert.Equal(t, ErrUnauthorized.Error(), err.Error()) } @@ -57,7 +56,7 @@ func TestSubmitUploadReturns500Error(t *testing.T) { client, _ := NewClient(http.DefaultClient, svr.URL, svr.URL) - err := client.Upload(getContext(nil), "", "", "", nil) + err := client.Upload(getContext(nil), model.Upload{}) assert.Equal(t, StatusError{ Code: http.StatusInternalServerError, @@ -83,7 +82,7 @@ func TestSubmitUploadReturnsBadRequestError(t *testing.T) { }, nil } - err := client.Upload(getContext(nil), "", "", "", nil) + err := client.Upload(getContext(nil), model.Upload{}) expectedError := model.ValidationError{Message: "", Errors: model.ValidationErrors{"EndDate": map[string]string{"EndDate": "EndDate"}, "StartDate": map[string]string{"StartDate": "StartDate"}}} assert.Equal(t, expectedError, err) @@ -107,7 +106,7 @@ func TestSubmitUploadReturnsValidationError(t *testing.T) { client, _ := NewClient(http.DefaultClient, svr.URL, svr.URL) - err := client.Upload(getContext(nil), "", "", "", nil) + err := client.Upload(getContext(nil), model.Upload{}) expectedError := model.ValidationError{Message: "", Errors: model.ValidationErrors{"ReportUploadType": map[string]string{"required": "Please select a report type"}}} assert.Equal(t, expectedError, err.(model.ValidationError)) } diff --git a/internal/model/upload.go b/internal/model/upload.go index b228e67..6509acb 100644 --- a/internal/model/upload.go +++ b/internal/model/upload.go @@ -1,8 +1,30 @@ package model +import "io" + type Upload struct { ReportUploadType string `json:"reportUploadType"` UploadDate *Date `json:"uploadDate"` Email string `json:"email"` File []byte `json:"file"` } + +func NewUpload(reportUploadType string, uploadDate string, email string, file io.Reader) (Upload, error) { + fileTransformed, err := io.ReadAll(file) + if err != nil { + return Upload{}, err + } + + upload := Upload{ + ReportUploadType: reportUploadType, + Email: email, + File: fileTransformed, + } + + if uploadDate != "" { + uploadDateFormatted := NewDate(uploadDate) + upload.UploadDate = &uploadDateFormatted + } + + return upload, nil +} diff --git a/internal/model/upload_test.go b/internal/model/upload_test.go new file mode 100644 index 0000000..5c1478e --- /dev/null +++ b/internal/model/upload_test.go @@ -0,0 +1,69 @@ +package model + +import ( + "bytes" + "github.com/stretchr/testify/assert" + "io" + "testing" +) + +type errorReader struct{} + +func (e *errorReader) Read(_ []byte) (int, error) { + return 0, io.ErrUnexpectedEOF +} + +func TestNewUploadReturnsCorrectly(t *testing.T) { + reportUploadType := "SomeReportType" + email := "test@example.com" + uploadDate := "11/05/2024" + fileContent := []byte("file content") + fileReader := bytes.NewReader(fileContent) + + // Expected result + expectedDate := NewDate(uploadDate) + expectedUpload := Upload{ + ReportUploadType: reportUploadType, + Email: email, + File: fileContent, + UploadDate: &expectedDate, + } + + upload, err := NewUpload(reportUploadType, uploadDate, email, fileReader) + + assert.NoError(t, err) + assert.Equal(t, expectedUpload, upload) +} + +func TestNewUploadWithNoFileReturnsCorrectly(t *testing.T) { + reportUploadType := "SomeReportType" + email := "test@example.com" + uploadDate := "" + fileContent := []byte("file content") + fileReader := bytes.NewReader(fileContent) + + expectedUpload := Upload{ + ReportUploadType: reportUploadType, + Email: email, + File: fileContent, + UploadDate: nil, + } + + upload, err := NewUpload(reportUploadType, uploadDate, email, fileReader) + + assert.NoError(t, err) + assert.Equal(t, expectedUpload, upload) +} + +func TestNewUpload_ReturnsError(t *testing.T) { + // Prepare input with an errorReader that always fails + reportUploadType := "SomeReportType" + email := "test@example.com" + uploadDate := "11/05/2024" + reader := &errorReader{} + + upload, err := NewUpload(reportUploadType, uploadDate, email, reader) + + assert.ErrorIs(t, err, io.ErrUnexpectedEOF) + assert.Empty(t, upload.File) +} diff --git a/internal/model/upload_type.go b/internal/model/upload_type.go index d11ea66..1ccd509 100644 --- a/internal/model/upload_type.go +++ b/internal/model/upload_type.go @@ -1,5 +1,7 @@ package model +import "encoding/json" + var ReportUploadTypes = []ReportUploadType{ ReportTypeUploadPaymentsMOTOCard, ReportTypeUploadPaymentsOnlineCard, @@ -21,6 +23,15 @@ const ( ReportTypeUploadDeputySchedule ) +var reportTypeUploadMap = map[string]ReportUploadType{ + "PaymentsMOTOCard": ReportTypeUploadPaymentsMOTOCard, + "PaymentsOnlineCard": ReportTypeUploadPaymentsOnlineCard, + "PaymentsOPGBACS": ReportTypeUploadPaymentsOPGBACS, + "PaymentsSupervisionBACS": ReportTypeUploadPaymentsSupervisionBACS, + "DebtChase": ReportTypeUploadDebtChase, + "DeputySchedule": ReportTypeUploadDeputySchedule, +} + func (i ReportUploadType) String() string { return i.Key() } @@ -63,6 +74,27 @@ func (i ReportUploadType) Key() string { } } +func ParseReportUploadType(s string) ReportUploadType { + value, ok := reportTypeUploadMap[s] + if !ok { + return ReportUploadType(0) + } + return value +} + func (i ReportUploadType) Valid() bool { return i != ReportTypeUploadUnknown } + +func (i ReportUploadType) MarshalJSON() ([]byte, error) { + return json.Marshal(i.Key()) +} + +func (i *ReportUploadType) UnmarshalJSON(data []byte) (err error) { + var s string + if err := json.Unmarshal(data, &s); err != nil { + return err + } + *i = ParseReportUploadType(s) + return nil +} diff --git a/internal/server/server.go b/internal/server/server.go index 1ccc3e5..8156b0f 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -15,7 +15,7 @@ import ( type ApiClient interface { Download(api.Context, model.Download) error - Upload(api.Context, string, string, string, io.Reader) error + Upload(api.Context, model.Upload) error } type router interface { diff --git a/internal/server/server_test.go b/internal/server/server_test.go index 3e03b46..f134750 100644 --- a/internal/server/server_test.go +++ b/internal/server/server_test.go @@ -52,7 +52,7 @@ type mockApiClient struct { error error //nolint:golint,unused } -func (m mockApiClient) Upload(context api.Context, s string, s2 string, s3 string, file io.Reader) error { +func (m mockApiClient) Upload(context api.Context, data model.Upload) error { return m.error } diff --git a/internal/server/upload.go b/internal/server/upload.go index 278a4d0..e2074c2 100644 --- a/internal/server/upload.go +++ b/internal/server/upload.go @@ -52,8 +52,13 @@ func (h *UploadHandler) render(v AppVars, w http.ResponseWriter, r *http.Request return err } + data, err := model.NewUpload(reportUploadType, uploadDate, email, file) + if err != nil { + return h.handleError(w, r, "Failed to read file", http.StatusBadRequest) + } + // Upload the file - if err := h.Client().Upload(ctx, reportUploadType, uploadDate, email, file); err != nil { + if err := h.Client().Upload(ctx, data); err != nil { return h.handleUploadError(w, r, err) }