diff --git a/Makefile b/Makefile index f7a8c74..5f641c4 100644 --- a/Makefile +++ b/Makefile @@ -33,3 +33,4 @@ generatemocks: @mkdir "mocks" cd $(CURDIR)/pkg/google/googleDrive && minimock -i GoogleDriveActions -s _mock.go -o $(CURDIR)/mocks cd $(CURDIR)/pkg/conference && minimock -i ICalendarActions -s _mock.go -o $(CURDIR)/mocks + cd $(CURDIR)/pkg/rest/ && minimock -i ClientActions -s _mock.go -o $(CURDIR)/mocks diff --git a/common/util/constant.go b/common/util/constant.go index 6abf4cd..9a4bc53 100644 --- a/common/util/constant.go +++ b/common/util/constant.go @@ -53,3 +53,21 @@ const ( const ( ConferenceMessage = "To discuss, use this *<%s|Meet link>*" ) + +type DocumentServiceFileTypeKeys string + +type ContentType string + +const ( + ContentTypeJSON = "application/json" +) + +const ( + DocumentServiceFlowId = "HOUSTON_KRAKATOA_GRAFANA_IMAGE" +) + +const ( + DocumentServicePNGFileType = "PNG" + DocumentServiceDOCFileType = "DOC" + DocumentServiceDOCXFileType = "DOCX" +) diff --git a/config/local.env b/config/local.env index 0e7c7bc..fb6fc2f 100644 --- a/config/local.env +++ b/config/local.env @@ -21,4 +21,3 @@ CRON_JOB_NAME=cron #incidents INCIDENTS_SHOW_LIMIT=10 - diff --git a/model/document_service.go b/model/document_service.go new file mode 100644 index 0000000..1919231 --- /dev/null +++ b/model/document_service.go @@ -0,0 +1,35 @@ +package model + +type FileDownloadPreSignedURLRequest struct { + FlowId string `json:"flowId"` + IdentifierKey string `json:"identifierKey"` +} + +type FileUploadURLRequest struct { + CustomerId string `json:"customerId"` + FileType string `json:"fileType"` + FlowId string `json:"flowId"` +} + +type FileUploadURLGeneratorResponse struct { + FormData FormData `json:"formData"` + Url string `json:"url"` +} + +type FormData struct { + Policy string `json:"Policy"` + XAmzAlgorithm string `json:"X-Amz-Algorithm"` + XAmzCredential string `json:"X-Amz-Credential"` + XAmzDate string `json:"X-Amz-Date"` + XAmzSecurityToken string `json:"X-Amz-Security-Token"` + XAmzSignature string `json:"X-Amz-Signature"` + Bucket string `json:"bucket"` + Key string `json:"key"` +} +type FileDownloadURLResponse struct { + Data struct { + Url string `json:"url"` + } `json:"data"` + Errors []interface{} `json:"errors"` + StatusCode int `json:"statusCode"` +} diff --git a/pkg/documentService/document_service_interface.go b/pkg/documentService/document_service_interface.go new file mode 100644 index 0000000..de9b2b0 --- /dev/null +++ b/pkg/documentService/document_service_interface.go @@ -0,0 +1,14 @@ +package documentService + +import ( + "houston/model" + "io" +) + +type ServiceActions interface { + GeneratePreSignedURL(fileType string, flowId string) (*model.FileUploadURLGeneratorResponse, error) + UploadFileWithPreSignedURL(fileUploadResponse *model.FileUploadURLGeneratorResponse, + fileName string, file io.Reader, contentType string) + FileDownloadPreSignedURL(fileDownloadPreSignedURLRequest model. + FileDownloadPreSignedURLRequest) (string, error) +} diff --git a/pkg/rest/rest_client.go b/pkg/rest/rest_client.go new file mode 100644 index 0000000..e0551e6 --- /dev/null +++ b/pkg/rest/rest_client.go @@ -0,0 +1,143 @@ +package rest + +import ( + "bytes" + "context" + "fmt" + "github.com/spf13/viper" + "houston/common/util" + "houston/logger" + "io" + "mime/multipart" + "net/http" + "net/url" + "time" +) + +type ClientActions interface { + PostWithoutTimeout(url string, body bytes.Buffer, headers map[string]string, + formData map[string]interface{}) (*http.Response, error) + PostWithTimeout(url string, body bytes.Buffer, headers map[string]string, timeout time.Duration, + formData map[string]interface{}) (*http.Response, error) + GetWithoutTimeout(url string, urlParams map[string]string, headers map[string]string, encodedURL bool) (*http.Response, error) + GetWithTimeout(url string, urlParams map[string]string, headers map[string]string, timeout time.Duration, encodedURL bool) (*http.Response, error) +} + +type ClientActionsImpl struct { + DefaultTimeout time.Duration +} + +func NewClientActionsImpl() *ClientActionsImpl { + return &ClientActionsImpl{ + DefaultTimeout: viper.GetDuration("DEFAULT_HTTP_REQUEST_TIMEOUT"), + } +} + +func (client *ClientActionsImpl) PostWithoutTimeout(url string, body bytes.Buffer, headers map[string]string, + formData map[string]interface{}) (*http.Response, error) { + return client.PostWithTimeout(url, body, headers, client.DefaultTimeout, formData) +} +func (client *ClientActionsImpl) PostWithTimeout(url string, body bytes.Buffer, headers map[string]string, + timeout time.Duration, formData map[string]interface{}) (*http.Response, error) { + requestContext, cancelFunc := context.WithTimeout(context.Background(), timeout) + defer cancelFunc() + contentType := util.ContentTypeJSON + restClient := &http.Client{ + Timeout: timeout, + } + if formData != nil { + var err error + body, contentType, err = constructFormFields(formData) + if err != nil { + return nil, err + } + } + var request, _ = http.NewRequest("POST", url, &body) + request.WithContext(requestContext) + request.Header.Set("Content-Type", contentType) + for key, value := range headers { + request.Header.Set(key, value) + } + return restClient.Do(request) +} + +func (client *ClientActionsImpl) GetWithoutTimeout(url string, urlParams map[string]string, headers map[string]string, + encodedURL bool) (*http.Response, error) { + return client.GetWithTimeout(url, urlParams, headers, client.DefaultTimeout, encodedURL) +} + +func (client *ClientActionsImpl) GetWithTimeout(url string, urlParams map[string]string, headers map[string]string, + timeout time.Duration, encodedURL bool) (*http.Response, error) { + requestContext, cancelFunc := context.WithTimeout(context.Background(), timeout) + defer cancelFunc() + restClient := &http.Client{ + Timeout: timeout, + } + url += urlFromParams(urlParams, encodedURL) + var request, _ = http.NewRequest("GET", url, nil) + request.WithContext(requestContext) + for key, value := range headers { + request.Header.Set(key, value) + } + return restClient.Do(request) +} + +func urlFromParams(urlParams map[string]string, encode bool) string { + if len(urlParams) != 0 { + if encode { + values := url.Values{} + for key, value := range urlParams { + values.Add(key, value) + } + return values.Encode() + } else { + result := "?" + for key, value := range urlParams { + if result == "" { + result = key + "=" + value + } else { + result += "&" + key + "=" + value + } + } + return result + } + } + return "" +} + +func constructFormFields(formData map[string]interface{}) (bytes.Buffer, string, error) { + body := &bytes.Buffer{} + writer := multipart.NewWriter(body) + + // Iterate through the map and add all non file fields to the form + for key, value := range formData { + switch value.(type) { + case string: + if key != "filename" { + _ = writer.WriteField(key, value.(string)) + } + } + } + // Parse the file field and add it to the form to ensure that file is at the end of the form + if formData["file"] != nil { + file := formData["file"].(io.Reader) + fileName := formData["filename"].(string) + part, err := writer.CreateFormFile("file", fileName) + if err != nil { + logger.Error(fmt.Sprintf("error creating form file: %v", err)) + return bytes.Buffer{}, "", err + } + _, err = io.Copy(part, file) + if err != nil { + logger.Error(fmt.Sprintf("error copying file data: %v", err)) + return bytes.Buffer{}, "", err + } + } + err := writer.Close() + contentType := writer.FormDataContentType() + if err != nil { + logger.Error(fmt.Sprintf("error closing multipart writer: %v", err)) + return bytes.Buffer{}, "", err + } + return *body, contentType, nil +} diff --git a/service/documentService/document_service.go b/service/documentService/document_service.go new file mode 100644 index 0000000..f982548 --- /dev/null +++ b/service/documentService/document_service.go @@ -0,0 +1,161 @@ +package documentService + +import ( + "bytes" + "encoding/json" + "errors" + "github.com/spf13/viper" + "go.uber.org/zap" + "houston/common/util" + "houston/model" + "houston/pkg/rest" + "io" + "net/http" + "time" +) + +type ActionsImpl struct { + BaseURL string + CustomerId string + DownloadPreSignedURLGeneratorPath string + UploadPreSignedURLGeneratorPath string + ServiceToken string + Logger *zap.Logger + Client rest.ClientActions + DefaultTimeout time.Duration +} + +func NewActionsImpl(logger *zap.Logger, client rest.ClientActions) *ActionsImpl { + return &ActionsImpl{ + Logger: logger, + Client: client, + BaseURL: viper.GetString("DOCUMENT_SERVICE_BASEURL"), + CustomerId: viper.GetString("DOCUMENT_SERVICE_CUSTOMER_ID"), + ServiceToken: viper.GetString("DOCUMENT_SERVICE_TOKEN"), + DownloadPreSignedURLGeneratorPath: viper.GetString("DOCUMENT_SERVICE_DOWNLOAD_PRE_SIGNED_URL_GENERATOR_PATH"), + UploadPreSignedURLGeneratorPath: viper.GetString("DOCUMENT_SERVICE_UPLOAD_PRE_SIGNED_URL_GENERATOR_PATH"), + DefaultTimeout: viper.GetDuration("DEFAULT_DOCUMENT_SERVICE_TIMEOUT"), + } +} + +func (documentService *ActionsImpl) GenerateFileUploadPreSignedURL(fileType string, flowId string) (*model.FileUploadURLGeneratorResponse, error) { + fullURL := documentService.BaseURL + documentService.UploadPreSignedURLGeneratorPath + fileUploadURLRequestPayload := model.FileUploadURLRequest{ + CustomerId: documentService.CustomerId, + FileType: fileType, + FlowId: flowId, + } + payload, err := json.Marshal(fileUploadURLRequestPayload) + requestHeaders := map[string]string{ + "Authorization": "Basic " + documentService.ServiceToken, + "X-Service": "houston", + "X-Source": "HOUSTON", + "Content-Type": util.ContentTypeJSON, + } + response, err := documentService.Client.PostWithTimeout(fullURL, *bytes.NewBuffer(payload), requestHeaders, + documentService.DefaultTimeout, nil) + if err != nil { + documentService.Logger.Error("Error while generating pre-signed url", zap.Error(err)) + return nil, err + } + if response.StatusCode == http.StatusOK { + documentService.Logger.Info("File upload URL generated successfully.") + } else { + documentService.Logger.Error("File upload URL generation failed with status code:", zap.Int("status_code", response.StatusCode)) + } + if response.Body == nil { + documentService.Logger.Error("response body is nil") + return nil, errors.New("response body is nil") + } + responseBody, err := io.ReadAll(response.Body) + if err != nil { + documentService.Logger.Error("Error while reading response body", zap.Error(err)) + return nil, err + } + var fileUploadURLGeneratorResponse *model.FileUploadURLGeneratorResponse + err = json.Unmarshal(responseBody, &fileUploadURLGeneratorResponse) + if err != nil { + documentService.Logger.Error("error while unmarshalling response body", zap.Error(err)) + return nil, err + } + if fileUploadURLGeneratorResponse.Url == "" { + documentService.Logger.Error("file upload URL is empty") + return nil, errors.New("file upload URL is empty") + } + return fileUploadURLGeneratorResponse, nil +} + +func (documentService *ActionsImpl) UploadFileWithPreSignedURL( + fileUploadResponse *model.FileUploadURLGeneratorResponse, fileName string, file io.Reader, contentType string) error { + + formData := map[string]interface{}{ + "Policy": fileUploadResponse.FormData.Policy, + "X-Amz-Algorithm": fileUploadResponse.FormData.XAmzAlgorithm, + "X-Amz-Credential": fileUploadResponse.FormData.XAmzCredential, + "X-Amz-Date": fileUploadResponse.FormData.XAmzDate, + "X-Amz-Security-Token": fileUploadResponse.FormData.XAmzSecurityToken, + "X-Amz-Signature": fileUploadResponse.FormData.XAmzSignature, + "bucket": fileUploadResponse.FormData.Bucket, + "key": fileUploadResponse.FormData.Key, + "Content-type": contentType, + "file": file, + "filename": fileName, + } + + resp, err := documentService.Client.PostWithTimeout(fileUploadResponse.Url, bytes.Buffer{}, nil, + documentService.DefaultTimeout, formData) + if err != nil { + documentService.Logger.Error("Error while uploading file", zap.Error(err)) + return err + } + // Check the response status code + if resp.StatusCode == http.StatusNoContent { + documentService.Logger.Info("File uploaded successfully.") + } else { + documentService.Logger.Error("File upload failed with status code:", zap.Int("status_code", resp.StatusCode)) + return errors.New("file upload failed") + } + return nil +} + +func (documentService *ActionsImpl) GenerateFileDownloadPreSignedURL(fileDownloadPreSignedURLRequest model.FileDownloadPreSignedURLRequest) (string, error) { + documentDownloadURL := documentService.BaseURL + documentService.DownloadPreSignedURLGeneratorPath + params := map[string]string{ + "customerId": documentService.CustomerId, + "flowId": fileDownloadPreSignedURLRequest.FlowId, + "identifierKey": fileDownloadPreSignedURLRequest.IdentifierKey, + } + + requestHeaders := map[string]string{ + "Authorization": "Basic " + documentService.ServiceToken, + "X-Service": "houston", + "X-Source": "HOUSTON", + "Content-Type": util.ContentTypeJSON, + } + response, err := documentService.Client.GetWithTimeout(documentDownloadURL, params, requestHeaders, documentService.DefaultTimeout, false) + if err != nil { + documentService.Logger.Error("Error while generating pre-signed url", zap.Error(err)) + return "", err + } + if response.StatusCode == http.StatusOK { + documentService.Logger.Info("File download URL generated successfully.") + } else { + documentService.Logger.Error("File download URL generation failed with status code:", zap.Int("status_code", response.StatusCode)) + } + responseBody, err := io.ReadAll(response.Body) + if err != nil { + documentService.Logger.Error("Error while reading response body", zap.Error(err)) + return "", err + } + var fileDownloadURLResponse *model.FileDownloadURLResponse + err = json.Unmarshal(responseBody, &fileDownloadURLResponse) + if err != nil { + documentService.Logger.Error("Error while unmarshalling response body", zap.Error(err)) + return "", err + } + if fileDownloadURLResponse.StatusCode != 200 || fileDownloadURLResponse.Data.Url == "" { + documentService.Logger.Error("file download URL generation failed") + return "", errors.New("file download URL generation failed") + } + return fileDownloadURLResponse.Data.Url, nil +} diff --git a/service/documentService/document_service_client_test.go b/service/documentService/document_service_client_test.go new file mode 100644 index 0000000..16b2c77 --- /dev/null +++ b/service/documentService/document_service_client_test.go @@ -0,0 +1,296 @@ +package documentService + +import ( + "bytes" + "encoding/json" + "errors" + "github.com/gojuno/minimock/v3" + "github.com/google/uuid" + "github.com/spf13/viper" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" + "houston/common/util" + "houston/logger" + "houston/mocks" + "houston/model" + "io" + "net/http" + "testing" + "time" +) + +type DocumentServiceClientSuite struct { + suite.Suite + baseURL string + customerId string + serviceToken string + downloadPreSignedURLGeneratorPath string + uploadPreSignedURLGeneratorPath string + defaultTimeout time.Duration +} + +func (suite *DocumentServiceClientSuite) SetupSuite() { + logger.InitLogger() + viper.Set("DOCUMENT_SERVICE_BASEURL", "https://qa-document-service.np.navi-sa.in") + viper.Set("DOCUMENT_SERVICE_CUSTOMER_ID", uuid.NewString()) + viper.Set("DOCUMENT_SERVICE_TOKEN", "TOKEN") + viper.Set("DOCUMENT_SERVICE_DOWNLOAD_PRE_SIGNED_URL_GENERATOR_PATH", "/document-service/s3/presigned-url") + viper.Set("DOCUMENT_SERVICE_UPLOAD_PRE_SIGNED_URL_GENERATOR_PATH", "/document-service/s3/generate-presigned-url") + viper.Set("DEFAULT_DOCUMENT_SERVICE_TIMEOUT", 10*time.Second) + suite.baseURL = viper.GetString("DOCUMENT_SERVICE_BASEURL") + suite.customerId = viper.GetString("DOCUMENT_SERVICE_CUSTOMER_ID") + suite.serviceToken = viper.GetString("DOCUMENT_SERVICE_TOKEN") + suite.downloadPreSignedURLGeneratorPath = viper.GetString("DOCUMENT_SERVICE_DOWNLOAD_PRE_SIGNED_URL_GENERATOR_PATH") + suite.uploadPreSignedURLGeneratorPath = viper.GetString("DOCUMENT_SERVICE_UPLOAD_PRE_SIGNED_URL_GENERATOR_PATH") + suite.defaultTimeout = viper.GetDuration("DEFAULT_DOCUMENT_SERVICE_TIMEOUT") +} + +func TestDocumentService(t *testing.T) { + suite.Run(t, new(DocumentServiceClientSuite)) +} + +func (suite *DocumentServiceClientSuite) Test_GenerateFileUploadPreSignedURL_FailureCase() { + controller := minimock.NewController(suite.T()) + suite.T().Cleanup(controller.Finish) + restActions := mocks.NewClientActionsMock(controller) + headers := map[string]string{ + "Authorization": "Basic " + suite.serviceToken, + "X-Service": "houston", + "X-Source": "HOUSTON", + "Content-Type": util.ContentTypeJSON, + } + + documentDownloadURL := suite.baseURL + suite.uploadPreSignedURLGeneratorPath + + fileUploadURLRequestPayload := model.FileUploadURLRequest{ + CustomerId: suite.customerId, + FileType: "fileType", + FlowId: "flowId", + } + payload, err := json.Marshal(fileUploadURLRequestPayload) + restActions.PostWithTimeoutMock.When(documentDownloadURL, *bytes.NewBuffer(payload), headers, + suite.defaultTimeout, nil). + Then(nil, errors.New("error while generating pre-signed url")) + + documentServiceImpl := NewActionsImpl(logger.GetLogger(), restActions) + + _, err = documentServiceImpl.GenerateFileUploadPreSignedURL("fileType", "flowId") + suite.Equal("error while generating pre-signed url", err.Error()) +} + +func (suite *DocumentServiceClientSuite) Test_GenerateFileUploadPreSignedURL_NilBodyCase() { + controller := minimock.NewController(suite.T()) + suite.T().Cleanup(controller.Finish) + restActions := mocks.NewClientActionsMock(controller) + headers := map[string]string{ + "Authorization": "Basic " + suite.serviceToken, + "X-Service": "houston", + "X-Source": "HOUSTON", + "Content-Type": util.ContentTypeJSON, + } + + documentDownloadURL := suite.baseURL + suite.uploadPreSignedURLGeneratorPath + + fileUploadURLRequestPayload := model.FileUploadURLRequest{ + CustomerId: suite.customerId, + FileType: "fileType", + FlowId: "flowId", + } + payload, err := json.Marshal(fileUploadURLRequestPayload) + + restActions.PostWithTimeoutMock.When(documentDownloadURL, *bytes.NewBuffer(payload), headers, + suite.defaultTimeout, nil). + Then(&http.Response{StatusCode: http.StatusOK, Body: nil}, nil) + + documentServiceImpl := NewActionsImpl(logger.GetLogger(), restActions) + + fileUploadResponse, err := documentServiceImpl.GenerateFileUploadPreSignedURL("fileType", "flowId") + assert.Nil(suite.T(), fileUploadResponse) + assert.Equal(suite.T(), err.Error(), "response body is nil") +} + +func (suite *DocumentServiceClientSuite) Test_GenerateFileUploadPreSignedURL_ResponseBodyUnmarshalErrorCase() { + controller := minimock.NewController(suite.T()) + suite.T().Cleanup(controller.Finish) + restActions := mocks.NewClientActionsMock(controller) + headers := map[string]string{ + "Authorization": "Basic " + suite.serviceToken, + "X-Service": "houston", + "X-Source": "HOUSTON", + "Content-Type": util.ContentTypeJSON, + } + + documentDownloadURL := suite.baseURL + suite.uploadPreSignedURLGeneratorPath + + fileUploadURLRequestPayload := model.FileUploadURLRequest{ + CustomerId: suite.customerId, + FileType: "fileType", + FlowId: "flowId", + } + payload, err := json.Marshal(fileUploadURLRequestPayload) + responseBody, _ := json.Marshal(fileUploadURLRequestPayload) + + restActions.PostWithTimeoutMock.When(documentDownloadURL, *bytes.NewBuffer(payload), headers, + suite.defaultTimeout, nil).Then(&http.Response{ + StatusCode: http.StatusOK, + Body: io.NopCloser(bytes.NewBufferString(string(responseBody))), + }, nil) + + documentServiceImpl := NewActionsImpl(logger.GetLogger(), restActions) + + fileUploadResponse, err := documentServiceImpl.GenerateFileUploadPreSignedURL("fileType", "flowId") + assert.Nil(suite.T(), fileUploadResponse) + assert.Equal(suite.T(), err.Error(), "file upload URL is empty") +} + +func (suite *DocumentServiceClientSuite) Test_GenerateFileUploadPreSignedURL_SuccessCase() { + controller := minimock.NewController(suite.T()) + suite.T().Cleanup(controller.Finish) + restActions := mocks.NewClientActionsMock(controller) + headers := map[string]string{ + "Authorization": "Basic " + suite.serviceToken, + "X-Service": "houston", + "X-Source": "HOUSTON", + "Content-Type": util.ContentTypeJSON, + } + + documentDownloadURL := suite.baseURL + suite.uploadPreSignedURLGeneratorPath + + fileUploadURLRequestPayload := model.FileUploadURLRequest{ + CustomerId: suite.customerId, + FileType: "fileType", + FlowId: "flowId", + } + payload, err := json.Marshal(fileUploadURLRequestPayload) + response := &model.FileUploadURLGeneratorResponse{ + Url: "https://s3.ap-south-1.amazonaws.com/navi-qa-document-service-android-file-upload", + FormData: model.FormData{ + Bucket: "bucket", + Policy: "policy", + XAmzDate: "date", + XAmzAlgorithm: "algorithm", + XAmzSignature: "signature", + XAmzCredential: "credential", + Key: "key", + XAmzSecurityToken: "token", + }, + } + responseBody, _ := json.Marshal(response) + + restActions.PostWithTimeoutMock.When(documentDownloadURL, *bytes.NewBuffer(payload), headers, suite. + defaultTimeout, nil).Then(&http.Response{ + StatusCode: http.StatusOK, + Body: io.NopCloser(bytes.NewBufferString(string(responseBody))), + }, nil) + + documentServiceImpl := NewActionsImpl(logger.GetLogger(), restActions) + + fileUploadResponse, err := documentServiceImpl.GenerateFileUploadPreSignedURL("fileType", "flowId") + assert.Nil(suite.T(), err) + assert.Equal(suite.T(), fileUploadResponse, response) +} + +func (suite *DocumentServiceClientSuite) Test_GenerateFileDownloadPreSignedURL_FailureCase() { + controller := minimock.NewController(suite.T()) + suite.T().Cleanup(controller.Finish) + restActions := mocks.NewClientActionsMock(controller) + fileDownloadPreSignedURLRequest := model.FileDownloadPreSignedURLRequest{ + FlowId: "flowId", + IdentifierKey: "identifierKey", + } + headers := map[string]string{ + "Authorization": "Basic " + suite.serviceToken, + "X-Service": "houston", + "X-Source": "HOUSTON", + "Content-Type": util.ContentTypeJSON, + } + params := map[string]string{ + "customerId": suite.customerId, + "flowId": fileDownloadPreSignedURLRequest.FlowId, + "identifierKey": fileDownloadPreSignedURLRequest.IdentifierKey, + } + + documentDownloadURL := suite.baseURL + suite.downloadPreSignedURLGeneratorPath + restActions.GetWithTimeoutMock.When(documentDownloadURL, params, headers, suite.defaultTimeout, false). + Then(nil, errors.New("error while generating pre-signed url")) + documentServiceImpl := NewActionsImpl(logger.GetLogger(), restActions) + resp, err := documentServiceImpl.GenerateFileDownloadPreSignedURL(fileDownloadPreSignedURLRequest) + suite.Equal("error while generating pre-signed url", err.Error()) + suite.Equal(resp, "") +} + +func (suite *DocumentServiceClientSuite) Test_GenerateFileDownloadPreSignedURL_EmptyURLCase() { + controller := minimock.NewController(suite.T()) + suite.T().Cleanup(controller.Finish) + restActions := mocks.NewClientActionsMock(controller) + fileDownloadPreSignedURLRequest := model.FileDownloadPreSignedURLRequest{ + FlowId: "flowId", + IdentifierKey: "identifierKey", + } + headers := map[string]string{ + "Authorization": "Basic " + suite.serviceToken, + "X-Service": "houston", + "X-Source": "HOUSTON", + "Content-Type": util.ContentTypeJSON, + } + params := map[string]string{ + "customerId": suite.customerId, + "flowId": fileDownloadPreSignedURLRequest.FlowId, + "identifierKey": fileDownloadPreSignedURLRequest.IdentifierKey, + } + var response model.FileDownloadURLResponse + response.Data.Url = "" + response.Errors = nil + response.StatusCode = 200 + responseBody, _ := json.Marshal(response) + finalResponse := http.Response{ + StatusCode: 200, + Body: io.NopCloser(bytes.NewBufferString(string(responseBody))), + } + + documentDownloadURL := suite.baseURL + suite.downloadPreSignedURLGeneratorPath + restActions.GetWithTimeoutMock.When(documentDownloadURL, params, headers, suite.defaultTimeout, false). + Then(&finalResponse, nil) + documentServiceImpl := NewActionsImpl(logger.GetLogger(), restActions) + resp, err := documentServiceImpl.GenerateFileDownloadPreSignedURL(fileDownloadPreSignedURLRequest) + suite.Equal("file download URL generation failed", err.Error()) + suite.Equal(resp, "") +} + +func (suite *DocumentServiceClientSuite) Test_GenerateFileDownloadPreSignedURL_Non200Case() { + controller := minimock.NewController(suite.T()) + suite.T().Cleanup(controller.Finish) + restActions := mocks.NewClientActionsMock(controller) + fileDownloadPreSignedURLRequest := model.FileDownloadPreSignedURLRequest{ + FlowId: "flowId", + IdentifierKey: "identifierKey", + } + headers := map[string]string{ + "Authorization": "Basic " + suite.serviceToken, + "X-Service": "houston", + "X-Source": "HOUSTON", + "Content-Type": util.ContentTypeJSON, + } + params := map[string]string{ + "customerId": suite.customerId, + "flowId": fileDownloadPreSignedURLRequest.FlowId, + "identifierKey": fileDownloadPreSignedURLRequest.IdentifierKey, + } + var response model.FileDownloadURLResponse + response.Data.Url = "" + response.Errors = nil + response.StatusCode = 500 + responseBody, _ := json.Marshal(response) + finalResponse := http.Response{ + StatusCode: 500, + Body: io.NopCloser(bytes.NewBufferString(string(responseBody))), + } + + documentDownloadURL := suite.baseURL + suite.downloadPreSignedURLGeneratorPath + restActions.GetWithTimeoutMock.When(documentDownloadURL, params, headers, suite.defaultTimeout, false). + Then(&finalResponse, nil) + documentServiceImpl := NewActionsImpl(logger.GetLogger(), restActions) + resp, err := documentServiceImpl.GenerateFileDownloadPreSignedURL(fileDownloadPreSignedURLRequest) + suite.Equal("file download URL generation failed", err.Error()) + suite.Equal(resp, "") +} diff --git a/service/team_service.go b/service/team_service.go index 59946b4..d3bb7d2 100644 --- a/service/team_service.go +++ b/service/team_service.go @@ -10,7 +10,7 @@ import ( "go.uber.org/zap" "gorm.io/gorm" commonutil "houston/common/util" - logger "houston/logger" + "houston/logger" "houston/model/log" "houston/model/team" "houston/pkg/slackbot"