github.com/companieshouse/insolvency-api@v0.0.0-20231024103413-440c973d9e9b/service/attachment.go (about)

     1  package service
     2  
     3  import (
     4  	"fmt"
     5  	"mime/multipart"
     6  	"net/http"
     7  	"strings"
     8  
     9  	"github.com/companieshouse/chs.go/log"
    10  	"github.com/companieshouse/go-sdk-manager/manager"
    11  	"github.com/companieshouse/insolvency-api/constants"
    12  	"github.com/companieshouse/insolvency-api/dao"
    13  	"github.com/companieshouse/insolvency-api/models"
    14  )
    15  
    16  const maxFileSize = 1048576 * 4 // 4MB
    17  
    18  // UploadAttachment sends a file to be uploaded to the File Transfer API and returns the ID
    19  func UploadAttachment(file multipart.File, header *multipart.FileHeader, req *http.Request) (string, ResponseType, error) {
    20  	// Create SDK session
    21  	api, err := manager.GetSDK(req)
    22  	if err != nil {
    23  		err = fmt.Errorf("error creating SDK to upload attachment: [%v]", err)
    24  		log.ErrorR(req, err)
    25  		return "", Error, err
    26  	}
    27  
    28  	uploadedFileResponse, err := api.FileTransfer.UploadFile(file, header).Do()
    29  	if err != nil {
    30  		err = fmt.Errorf(constants.MsgErrorCommsFileTransferAPI, err)
    31  		log.ErrorR(req, err)
    32  		return "", Error, err
    33  	}
    34  	if uploadedFileResponse == nil {
    35  		err = fmt.Errorf("error uploading file: [%v]", err)
    36  		log.ErrorR(req, err)
    37  		return "", Error, err
    38  	}
    39  	return uploadedFileResponse.Id, Success, nil
    40  }
    41  
    42  // ValidateAttachmentDetails checks that the incoming attachment details are valid
    43  func ValidateAttachmentDetails(svc dao.Service, transactionID string, attachmentType string, header *multipart.FileHeader) (string, error) {
    44  	var errs []string
    45  
    46  	// Check attachment is of valid type
    47  	if !constants.IsAttachmentTypeValid(attachmentType) {
    48  		errs = append(errs, "attachment_type is invalid")
    49  	}
    50  
    51  	// Check if attachment has already been filed
    52  	attachments, err := svc.GetAttachmentResources(transactionID)
    53  	if err != nil {
    54  		return "", err
    55  	}
    56  	if len(attachments) > 0 {
    57  		if attachmentType == constants.StatementOfAffairsLiquidator.String() {
    58  			errs = append(errs, fmt.Sprintf("attachment of type [%s] cannot be filed for insolvency case with transaction ID [%s] - other attachments have already been filed for this case", attachmentType, transactionID))
    59  		} else {
    60  			for _, a := range attachments {
    61  				if a.Type == constants.StatementOfAffairsLiquidator.String() {
    62  					errs = append(errs, fmt.Sprintf("attachment of type [%s] has been filed for insolvency case with transaction ID [%s] - no other attachments can be filed for this case", a.Type, transactionID))
    63  					break
    64  				}
    65  				if a.Type == attachmentType {
    66  					errs = append(errs, fmt.Sprintf("attachment of type [%s] has already been filed for insolvency case with transaction ID [%s]", attachmentType, transactionID))
    67  					break
    68  				}
    69  			}
    70  		}
    71  	}
    72  
    73  	// Check file type is PDF
    74  	fileType := header.Header.Get("Content-Type")
    75  	if fileType != "application/pdf" && header.Filename[len(header.Filename)-3:] != "pdf" {
    76  		errs = append(errs, "attachment file format should be pdf")
    77  	}
    78  
    79  	// Check if attachment size is less than maxFileSize
    80  	if header.Size > maxFileSize {
    81  		errs = append(errs, "attachment file size is too large to be processed")
    82  	}
    83  
    84  	return strings.Join(errs, ", "), nil
    85  }
    86  
    87  // GetAttachmentDetails gets attachment details from File Transfer API
    88  func GetAttachmentDetails(id string, req *http.Request) (*models.AttachmentFile, ResponseType, error) {
    89  	// Create SDK session
    90  	api, err := manager.GetSDK(req)
    91  	if err != nil {
    92  		err = fmt.Errorf("error creating SDK to get attachment details: [%v]", err)
    93  		log.ErrorR(req, err)
    94  		return nil, Error, err
    95  	}
    96  
    97  	response, err := api.FileTransfer.GetFile(id).Do()
    98  
    99  	if err != nil {
   100  		err = fmt.Errorf(constants.MsgErrorCommsFileTransferAPI, err)
   101  		log.ErrorR(req, err)
   102  		return nil, Error, err
   103  	}
   104  	// Add relevant file transfer attachment details to response
   105  	GetFileResponse := models.AttachmentFile{
   106  		Name:        response.Name,
   107  		Size:        response.Size,
   108  		ContentType: response.ContentType,
   109  		AVStatus:    response.AvStatus,
   110  	}
   111  
   112  	if (models.AttachmentFile{}) == GetFileResponse {
   113  		err = fmt.Errorf("error getting file: [%v]", err)
   114  		log.ErrorR(req, err)
   115  		return nil, Error, err
   116  	}
   117  
   118  	return &GetFileResponse, Success, nil
   119  }
   120  
   121  // DownloadAttachment downloads a file from the File Transfer API writes it to a ResponseWriter
   122  func DownloadAttachment(attachmentID string, req *http.Request, w http.ResponseWriter) (ResponseType, error) {
   123  
   124  	// Create SDK session
   125  	api, err := manager.GetSDK(req)
   126  	if err != nil {
   127  		err = fmt.Errorf("error creating SDK to upload attachment: [%v]", err)
   128  		log.ErrorR(req, err)
   129  		return Error, err
   130  	}
   131  
   132  	downloadedFileResponse, err := api.FileTransfer.DownloadFile(attachmentID, w).Do()
   133  	if err != nil {
   134  		err = fmt.Errorf(constants.MsgErrorCommsFileTransferAPI, err)
   135  		log.ErrorR(req, err)
   136  		return Error, err
   137  	}
   138  
   139  	if downloadedFileResponse == nil {
   140  		err = fmt.Errorf("error downloading file: [%v]", err)
   141  		log.ErrorR(req, err)
   142  		return Error, err
   143  	}
   144  	return Success, nil
   145  }
   146  
   147  // DeleteAttachment deletes an attachment via the File Transfer API
   148  func DeleteAttachment(id string, req *http.Request) (ResponseType, error) {
   149  	// Create SDK session
   150  	api, err := manager.GetSDK(req)
   151  	if err != nil {
   152  		err = fmt.Errorf("error creating SDK to get attachment details: [%v]", err)
   153  		log.ErrorR(req, err)
   154  		return Error, err
   155  	}
   156  
   157  	response, err := api.FileTransfer.DeleteFile(id).Do()
   158  
   159  	if err != nil {
   160  		err = fmt.Errorf(constants.MsgErrorCommsFileTransferAPI, err)
   161  		log.ErrorR(req, err)
   162  		return Error, err
   163  	}
   164  
   165  	if response == nil {
   166  		err = fmt.Errorf("error deleting file: [%v]", err)
   167  		log.ErrorR(req, err)
   168  		return Error, err
   169  	}
   170  
   171  	return Success, nil
   172  }