diff --git a/appknox/reports.go b/appknox/reports.go index deb0960..532822f 100644 --- a/appknox/reports.go +++ b/appknox/reports.go @@ -4,139 +4,67 @@ import ( "context" "errors" "fmt" - "io" - "net/http" - "os" - "path/filepath" - "strings" + "strconv" + "time" ) type ReportsService service -type Report struct { - URL string `json:"url"` +type HIPAAPreferences struct { + ShowHIPPA bool `json:"value"` + IsInherited bool `json:"is_inherited"` } - -type ReportResult struct { - ID int `json:"id"` - GeneratedOn string `json:"generated_on"` - Language string `json:"language"` - Progress int `json:"progress"` - Rating string `json:"rating"` +type PCIDSSPreferences struct { + ShowPCIDSS bool `json:"value"` + IsInherited bool `json:"is_inherited"` } -// GenerateReport generates a report for the specified file. -func (s *ReportsService) GenerateReport(ctx context.Context, fileID int) (*ReportResult, error) { - url := fmt.Sprintf("api/v2/files/%d/reports", fileID) - req, err := s.client.NewRequest("POST", url, nil) - if err != nil { - return nil, err - } - - var resp ReportResult - - res, err := s.client.Do(ctx, req, &resp) - if err != nil { - if res.StatusCode == 400 { - return nil, errors.New("A report is already being generated or scan is in progress. Please wait.") - } - if res.StatusCode == 404 { - return nil, errors.New("File not found") - } - return nil, err - } - - return &resp, nil +type ReportPreferences struct { + ShowAPIScan bool `json:"show_api_scan"` + ShowManualScan bool `json:"show_manual_scan"` + ShowStaticScan bool `json:"show_static_scan"` + ShowDynamicScan bool `json:"show_dynamic_scan"` + ShowIgnoredAnalyses bool `json:"show_ignored_analyses"` + PCIDSSPreferences PCIDSSPreferences `json:"show_hipaa"` + HIPAAPreferences HIPAAPreferences `json:"show_pcidss"` } -// FetchReportResult it will fetch report result by result id. -func (s *ReportsService) FetchReportResult(ctx context.Context, reportID int) (*ReportResult, error) { - url := fmt.Sprintf("api/v2/reports/%d", reportID) - req, err := s.client.NewRequest("GET", url, nil) - if err != nil { - return nil, err - } - - var resp ReportResult - - _, err = s.client.Do(ctx, req, &resp) - if err != nil { - return nil, err - } +type ReportResult struct { + ID int `json:"id"` + GeneratedOn *time.Time `json:"generated_on"` + Language string `json:"language"` + Progress int `json:"progress"` + Rating string `json:"rating"` + ReportPreferences ReportPreferences `json:"preferences"` +} - return &resp, nil +type DRFResponseReport struct { + Count int `json:"count,omitempty"` + Next string `json:"next,omitempty"` + Previous string `json:"previous,omitempty"` + Results []*ReportResult `json:"results"` } -// FetchLastReportResult it will return last report result, report list api is responding in decending order. -func (s *ReportsService) FetchLastReportResult(ctx context.Context, fileID int) (*ReportResult, error) { +func (s *ReportsService) List(ctx context.Context, fileID int) ([]*ReportResult, error) { url := fmt.Sprintf("api/v2/files/%d/reports", fileID) - req, err := s.client.NewRequest("GET", url, nil) + request, err := s.client.NewRequest("GET", url, nil) if err != nil { return nil, err } - type ReportResultList struct { - Results []*ReportResult `json:"results"` - } - - var resp ReportResultList - - _, err = s.client.Do(ctx, req, &resp) - if err != nil { - return nil, err - } + var drfResponseReport DRFResponseReport - if len(resp.Results) > 0 { - return resp.Results[0], nil - } - return nil, errors.New("No report results found") -} - -// GetReportURL returns the url of the report file to download. -func (s *ReportsService) GetReportURL(ctx context.Context, reportID int) (*Report, error) { - u := fmt.Sprintf("api/v2/reports/%d/pdf", reportID) - req, err := s.client.NewRequest("GET", u, nil) - if err != nil { - return nil, err + resp, err := s.client.Do(ctx, request, &drfResponseReport) + if resp != nil && resp.StatusCode == 404 { + id := strconv.Itoa(fileID) + return nil, errors.New("Reports for fileID " + id + " doesn't exist. Are you sure " + id + " is a fileID?") } - - var reportResponse Report - - _, err = s.client.Do(ctx, req, &reportResponse) if err != nil { return nil, err } - return &reportResponse, nil -} - -// DownloadFile downloads the report file to the specified directory. -func (s *ReportsService) DownloadFile(ctx context.Context, url string, outputDir string) (string, error) { - - // Generating filename from download url - filename := strings.Split(strings.Split(url, "?")[0], "/")[len(strings.Split(url, "/"))-1] - - outputPath := filepath.Join(outputDir, filename) - - // Creating output file from output path - out, err := os.Create(outputPath) - if err != nil { - return "", err - } - defer out.Close() - - // Downloading file - resp, err := http.Get(url) - if err != nil || resp.StatusCode != 200 { - if resp.StatusCode != 200 { - err = errors.New(`resource not found`) - } - return "", err - } - defer resp.Body.Close() + return drfResponseReport.Results, nil - // Writing file to output file - _, err = io.Copy(out, resp.Body) + // return drfResponse.Results, &resp, nil - return outputPath, err } diff --git a/appknox/reports_test.go b/appknox/reports_test.go index 365a2b6..5d29919 100644 --- a/appknox/reports_test.go +++ b/appknox/reports_test.go @@ -4,349 +4,43 @@ import ( "context" "fmt" "net/http" - "os" "reflect" - "strings" "testing" - - "github.com/magiconair/properties/assert" ) -func TestReportsService_GenerateReport_Success(t *testing.T) { - client, mux, _, teardown := setup() - defer teardown() - - // Starting fake server to accept request - mux.HandleFunc("/api/v2/files/1/reports", func(w http.ResponseWriter, r *http.Request) { - testMethod(t, r, "POST") - resp := fmt.Sprintf(`{ - "id": %d, - "language": "en", - "progress": 50, - "rating": "20.73" - }`, 1) - fmt.Fprint(w, resp) - }) - - report, err := client.Reports.GenerateReport(context.Background(), 1) - - if err != nil { - t.Errorf("Reports.GenerateReport returned error: %v", err) - } - - want := &ReportResult{ - ID: 1, - Language: "en", - Progress: 50, - Rating: "20.73", - } - if !reflect.DeepEqual(report, want) { - t.Errorf("Reports.GenerateReport returned %+v, want %+v", report, want) - } -} - -func TestReportsService_GenerateReport_IfAPIFails_Should_Fail(t *testing.T) { - client, mux, _, teardown := setup() - defer teardown() - - // Starting fake server to accept request - mux.HandleFunc("/api/v2/files/1/reports", func(w http.ResponseWriter, r *http.Request) { - testMethod(t, r, "POST") - w.WriteHeader(http.StatusNotFound) - }) - - report, err := client.Reports.GenerateReport(context.Background(), 1) - - assert.Equal(t, true, err != nil) - assert.Equal(t, true, report == nil) -} - -func TestReportsService_GenerateReport_IfBaseURL_Should_Fail(t *testing.T) { - client, _, _, teardown := setup() - defer teardown() - // Setting invalid schame name to fail in `client.NewRequest` - client.BaseURL.Scheme = "" - client.BaseURL.Host = "localhost/" - - report, err := client.Reports.GenerateReport(context.Background(), 1) - - assert.Equal(t, true, err != nil) - assert.Equal(t, true, report == nil) -} - -func TestReportsService_FetchReportResult_Success(t *testing.T) { - client, mux, _, teardown := setup() - defer teardown() - - // Starting fake server to accept request - mux.HandleFunc("/api/v2/reports/1", func(w http.ResponseWriter, r *http.Request) { - testMethod(t, r, "GET") - resp := fmt.Sprintf(`{ - "id": %d, - "language": "en", - "progress": 100, - "rating": "20.73" - }`, 1) - fmt.Fprint(w, resp) - }) - - report, err := client.Reports.FetchReportResult(context.Background(), 1) - - if err != nil { - t.Errorf("Reports.FetchReportResult returned error: %v", err) - } - - want := &ReportResult{ - ID: 1, - Language: "en", - Progress: 100, - Rating: "20.73", - } - if !reflect.DeepEqual(report, want) { - t.Errorf("Reports.FetchReportResult returned %+v, want %+v", report, want) - } -} - -func TestReportsService_FetchReportResult_IfAPIFails_Should_Fail(t *testing.T) { +func TestReportService_ListByFile(t *testing.T) { client, mux, _, teardown := setup() defer teardown() - - // Starting fake server to accept request - mux.HandleFunc("/api/v2/reports/1", func(w http.ResponseWriter, r *http.Request) { - testMethod(t, r, "GET") - w.WriteHeader(http.StatusNotFound) - }) - - report, err := client.Reports.FetchReportResult(context.Background(), 1) - - assert.Equal(t, true, err != nil) - assert.Equal(t, true, report == nil) -} - -func TestReportsService_FetchReportResult_IfBaseURL_Should_Fail(t *testing.T) { - client, _, _, teardown := setup() - defer teardown() - // Setting invalid schame name to fail in `client.NewRequest` - client.BaseURL.Scheme = "" - client.BaseURL.Host = "localhost/" - - report, err := client.Reports.FetchReportResult(context.Background(), 1) - - assert.Equal(t, true, err != nil) - assert.Equal(t, true, report == nil) -} - -func TestReportsService_FetchLastReportResult_Success(t *testing.T) { - client, mux, _, teardown := setup() - defer teardown() - - // Starting fake server to accept request mux.HandleFunc("/api/v2/files/1/reports", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") - resp := fmt.Sprintf(`{ - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": %d, - "language": "en", - "progress": 100, - "rating": "20.73" - } - ] - }`, 1) - fmt.Fprint(w, resp) + fmt.Fprint(w, `{"count": 1, "results": [{"id": 1}]}`) }) - report, err := client.Reports.FetchLastReportResult(context.Background(), 1) - + reports, err := client.Reports.List(context.Background(), 1) if err != nil { - t.Errorf("Reports.FetchLastReportResult returned error: %v", err) + t.Errorf("Reports.List returned error: %v", err) } - - want := &ReportResult{ - ID: 1, - Language: "en", - Progress: 100, - Rating: "20.73", + want := []*ReportResult{{ID: 1}} + if !reflect.DeepEqual(reports, want) { + t.Errorf("Reports.List returned %+v, want %+v", reports, want) } - if !reflect.DeepEqual(report, want) { - t.Errorf("Reports.FetchLastReportResult returned %+v, want %+v", report, want) - } } -func TestReportsService_FetchLastReportResult_IfEmptyReport_Should_Fail(t *testing.T) { +func TestReportService_InvalidFileID(t *testing.T) { client, mux, _, teardown := setup() defer teardown() - - // Starting fake server to accept request - mux.HandleFunc("/api/v2/files/1/reports", func(w http.ResponseWriter, r *http.Request) { - testMethod(t, r, "GET") - resp := fmt.Sprintf(`{ - "count": 1, - "next": null, - "previous": null, - "results": [] - }`) - fmt.Fprint(w, resp) - }) - - report, err := client.Reports.FetchLastReportResult(context.Background(), 1) - - assert.Equal(t, true, err != nil) - assert.Equal(t, err.Error(), "No report results found") - assert.Equal(t, true, report == nil) -} - -func TestReportsService_FetchLastReportResult_IfAPIFails_Should_Fail(t *testing.T) { - client, mux, _, teardown := setup() - defer teardown() - - // Starting fake server to accept request - mux.HandleFunc("/api/v2/files/1/reports", func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc("/api/v2/files/999/reports", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") w.WriteHeader(http.StatusNotFound) + fmt.Fprint(w, `{"detail":"Not found."}`) }) - - report, err := client.Reports.FetchLastReportResult(context.Background(), 1) - - assert.Equal(t, true, err != nil) - assert.Equal(t, true, report == nil) -} - -func TestReportsService_FetchLastReportResult_IfBaseURL_Should_Fail(t *testing.T) { - client, _, _, teardown := setup() - defer teardown() - // Setting invalid schame name to fail in `client.NewRequest` - client.BaseURL.Scheme = "" - client.BaseURL.Host = "localhost/" - - report, err := client.Reports.FetchLastReportResult(context.Background(), 1) - - assert.Equal(t, true, err != nil) - assert.Equal(t, true, report == nil) -} - -func TestReportsService_GetReportURL_Success(t *testing.T) { - client, mux, _, teardown := setup() - defer teardown() - - // Starting fake server to accept request - mux.HandleFunc("/api/v2/reports/1/pdf", func(w http.ResponseWriter, r *http.Request) { - testMethod(t, r, "GET") - fmt.Fprint(w, `{"url":"http://example.com"}`) - }) - - report, err := client.Reports.GetReportURL(context.Background(), 1) - - if err != nil { - t.Errorf("Reports.GetReportURL returned error: %v", err) + resp, err := client.Reports.List(context.Background(), 999) + if resp != nil { + t.Errorf("ReportREsult should be nil for invalid fileID") } - - want := &Report{URL: "http://example.com"} - if !reflect.DeepEqual(report, want) { - t.Errorf("Reports.GetReportURL returned %+v, want %+v", report, want) + if err.Error() != "Reports for fileID 999 doesn't exist. Are you sure 999 is a fileID?" { + t.Errorf("Error message should be displayed for invalid fileID") } -} - -func TestReportsService_GetReportURL_IFAPINotWorking_ShuldFail(t *testing.T) { - client, mux, _, teardown := setup() - defer teardown() - - // Starting fake server to accept request - mux.HandleFunc("/api/v2/reports/1/pdf", func(w http.ResponseWriter, r *http.Request) { - testMethod(t, r, "GET") - w.WriteHeader(http.StatusInternalServerError) - }) - - _, err := client.Reports.GetReportURL(context.Background(), 1) - - // Assert http response code - assert.Equal(t, strings.TrimSpace(strings.Split(err.Error(), ":")[3]), "500") -} - -func TestReportsService_GetReportURL_IFBaseURL_ShuldFail(t *testing.T) { - client, mux, _, teardown := setup() - defer teardown() - - // Starting fake server to accept request - mux.HandleFunc("/api/v2/reports/1/pdf", func(w http.ResponseWriter, r *http.Request) { - testMethod(t, r, "GET") - w.WriteHeader(http.StatusInternalServerError) - }) - - // Setting invalid schame name to fail in `client.NewRequest` - client.BaseURL.Scheme = "" - client.BaseURL.Host = "localhost/" - - _, err := client.Reports.GetReportURL(context.Background(), 1) - assert.Equal(t, true, err != nil) -} - -func TestReportsService_DownloadFile_Success(t *testing.T) { - client, mux, serverURL, teardown := setup() - defer teardown() - - // Starting fake server to accept download request - mux.HandleFunc("/aws_fake_signed_url.txt", func(w http.ResponseWriter, r *http.Request) { - testMethod(t, r, "GET") - fmt.Fprint(w, `Fake_File_Content`) - }) - - outputDir := ".." - report, err := client.Reports.DownloadFile(context.Background(), serverURL+"/aws_fake_signed_url.txt?signature=fake_signature_hash", outputDir) - - if err != nil { - t.Errorf("Reports.DownloadFile returned error: %v", err) - } - - want := "../aws_fake_signed_url.txt" - if !reflect.DeepEqual(report, want) { - t.Errorf("Reports.DownloadFile returned %+v, want %+v", report, want) - } - - // remove files after test - err = os.Remove(want) - assert.Equal(t, nil, err) -} - -func TestReportsService_DownloadFile_IfWrongURL_Should_Fail(t *testing.T) { - client, mux, serverURL, teardown := setup() - defer teardown() - - // Starting fake server to accept request - mux.HandleFunc("/aws_fake_signed_url.txt", func(w http.ResponseWriter, r *http.Request) { - testMethod(t, r, "GET") - w.WriteHeader(http.StatusNotFound) - }) - - outputDir := t.TempDir() - report, err := client.Reports.DownloadFile(context.Background(), serverURL+"/aws_fake_signed_url.txt?signature=fake_signature_hash", outputDir) - assert.Equal(t, true, err != nil) - assert.Equal(t, true, len(report) == 0) -} - -func TestReportsService_DownloadFile_IfInvalidURL_Should_Fail(t *testing.T) { - client, _, _, teardown := setup() - defer teardown() - - outputDir := t.TempDir() - report, err := client.Reports.DownloadFile(context.Background(), "", outputDir) - assert.Equal(t, true, err != nil) - assert.Equal(t, true, len(report) == 0) -} - -func TestReportsService_DownloadFile_IfBaseURL_Should_Fail(t *testing.T) { - client, _, _, teardown := setup() - defer teardown() - // Setting invalid schame name to fail in `client.NewRequest` - client.BaseURL.Scheme = "" - client.BaseURL.Host = "localhost/" - outputDir := t.TempDir() - report, err := client.Reports.DownloadFile(context.Background(), "", outputDir) - assert.Equal(t, true, err != nil) - assert.Equal(t, true, len(report) == 0) } diff --git a/cmd/reports.go b/cmd/reports.go index 6229c13..ad41c0a 100644 --- a/cmd/reports.go +++ b/cmd/reports.go @@ -2,7 +2,6 @@ package cmd import ( "errors" - "os" "strconv" "github.com/appknox/appknox-go/helper" @@ -12,8 +11,13 @@ import ( // reportsCmd is the command to generate reports var reportsCmd = &cobra.Command{ Use: "reports", - Short: "Download reports for vulnerabilities check.", - Long: `Download reports for all the vulnerabilities check to local system.`, + Short: "Vulnerability Analysis Reports", + Long: `List or create reports for the file ID. Download reports using report ID`, +} + +var reportsListCmd = &cobra.Command{ + Use: "list", + Short: "List Vulnerability Analysis Reports", Args: func(cmd *cobra.Command, args []string) error { if len(args) < 1 { return errors.New("file id is required") @@ -21,28 +25,19 @@ var reportsCmd = &cobra.Command{ return nil }, Run: func(cmd *cobra.Command, args []string) { - // Collecting arguments fileID, err := strconv.Atoi(args[0]) if err != nil { err := errors.New("Valid file id is required") helper.PrintError(err) - os.Exit(1) } - // Collecting flags - allowExperimentalFeatures, _ := cmd.Flags().GetBool("allow-experimental-features") - outputDir, _ := cmd.Flags().GetString("output") - generate, _ := cmd.Flags().GetBool("generate") - // Performing download reports - ok, err := helper.ProcessDownloadReports(fileID, allowExperimentalFeatures, generate, outputDir) - if err != nil || !ok { - os.Exit(1) + err = helper.ProcessListReports(fileID) + if err != nil { + helper.PrintError(err) } }, } func init() { + reportsCmd.AddCommand(reportsListCmd) RootCmd.AddCommand(reportsCmd) - reportsCmd.Flags().StringP("output", "o", ".", "Output directory to save reports") - reportsCmd.Flags().Bool("generate", false, "Generate reports") - reportsCmd.Flags().Bool("allow-experimental-features", false, "Allow experimental features to download reports") } diff --git a/helper/reports.go b/helper/reports.go index f5db3b9..9826c00 100644 --- a/helper/reports.go +++ b/helper/reports.go @@ -2,68 +2,56 @@ package helper import ( "context" - "errors" - "fmt" "time" -) - -func ProcessDownloadReports(fileID int, allowExperimentalFeatures bool, generate bool, output string) (bool, error) { - var reportID int - if !allowExperimentalFeatures { - fmt.Println("Downloading PDF reports is not a fully supported/experimental feature. Please opt-in by specifying --allow-experimental-features in the command.") - return false, errors.New("Downloading PDF reports is not a fully supported/experimental feature. Please opt-in by specifying --allow-experimental-features in the command.") - } + "github.com/cheynewallace/tabby" +) +func ProcessListReports(fileID int) error { ctx := context.Background() client := getClient() - - if generate { - // This part of code is to generate reports - fmt.Println("Generating reports...") - report, err := client.Reports.GenerateReport(ctx, fileID) - if err != nil { - PrintError(err) - return false, err - } - - // Assigning result id for later use in download report section - reportID = report.ID - for report.Progress < 100 { - time.Sleep(100 * time.Millisecond) - report, err = client.Reports.FetchReportResult(ctx, reportID) - if err != nil { - PrintError(errors.New("Faild to fetch report result")) - return false, err - } - fmt.Printf("\rGeneration progress: %d%%", report.Progress) - } - fmt.Println("\nReport generated successfully.") - } else { - // This part of code will be executed when user want to download report which is already generated. - fmt.Println("Fetching reports...") - report, err := client.Reports.FetchLastReportResult(ctx, fileID) - if err != nil { - PrintError(errors.New("No report generated for this file.")) - return false, err - } - // Assigning result id for later use in download report section - reportID = report.ID - } - - report, err := client.Reports.GetReportURL(ctx, reportID) + reports, err := client.Reports.List(ctx, fileID) if err != nil { - PrintError(err) - return false, err + return err } - - out, err := client.Reports.DownloadFile(ctx, report.URL, output) - if err != nil { - PrintError(err) - return false, err + t := tabby.New() + header := []interface{}{ + "ID", + "Generated On", + "Language", + "Progress", + "Rating", + "Show API Scan", + "Show Manual Scan", + "Show Static Scan", + "Show Dynamic Scan", + "Show Ignored Analyses Scan", + "Show HIPAA", + "Is HIPAA Inherited", + "Show PCIDSS", + "Is PCIDSS Inherited", + } + t.AddHeader(header...) + for i := 0; i < len(reports); i++ { + row := []interface{}{ + reports[i].ID, + reports[i].GeneratedOn.Format(time.RFC1123), + reports[i].Language, + reports[i].Progress, + reports[i].Rating, + reports[i].ReportPreferences.ShowAPIScan, + reports[i].ReportPreferences.ShowManualScan, + reports[i].ReportPreferences.ShowStaticScan, + reports[i].ReportPreferences.ShowDynamicScan, + reports[i].ReportPreferences.ShowIgnoredAnalyses, + reports[i].ReportPreferences.HIPAAPreferences.ShowHIPPA, + reports[i].ReportPreferences.HIPAAPreferences.IsInherited, + reports[i].ReportPreferences.PCIDSSPreferences.ShowPCIDSS, + reports[i].ReportPreferences.PCIDSSPreferences.IsInherited, + } + t.AddLine(row...) } + t.Print() + return nil - fmt.Println("Report downloaded successfully.") - fmt.Println("Report saved to: ", out) - return true, nil } diff --git a/helper/reports_test.go b/helper/reports_test.go deleted file mode 100644 index d5a2238..0000000 --- a/helper/reports_test.go +++ /dev/null @@ -1,325 +0,0 @@ -package helper - -import ( - "fmt" - "net/http" - "net/http/httptest" - "net/url" - "os" - "path/filepath" - "testing" - - "github.com/appknox/appknox-go/appknox" - "github.com/magiconair/properties/assert" - "github.com/spf13/viper" -) - -func setup() (client *appknox.Client, mux *http.ServeMux, serverURL string, teardown func()) { - // mux is the HTTP request multiplexer used with the test server. - mux = http.NewServeMux() - - // We want to ensure that tests catch mistakes where the endpoint URL is - // specified as absolute rather than relative. It only makes a difference - // when there's a non-empty base URL path. So, use that. See issue #752. - apiHandler := http.NewServeMux() - apiHandler.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { - fmt.Fprintln(os.Stderr, "FAIL: Client.BaseURL path prefix is not preserved in the request URL:\t"+req.URL.String()) - fmt.Fprintln(os.Stderr, "\tDid you accidentally use an absolute endpoint URL rather than relative?") - http.Error(w, "Client.BaseURL path prefix is not preserved in the request URL.", http.StatusInternalServerError) - }) - - // server is a test HTTP server used to provide mock API responses. - server := httptest.NewServer(apiHandler) - - // client is the appknox client being tested and is - // configured to use test server. - - client, err := appknox.NewClient("token") - if err != nil { - fmt.Println(err) - os.Exit(1) - } - url, _ := url.Parse(server.URL + "/") - client.BaseURL = url - return client, apiHandler, server.URL, server.Close -} - -func TestHelper_ProcessDownloadReports_WithValidData_Success(t *testing.T) { - _, mux, serverURL, teardown := setup() - defer teardown() - - // Setting up environment variable to use fake server in this api tests - viper.Set("host", serverURL+"/") - viper.Set("insecure", true) - viper.Set("access-token", "token") - - // Starting fake server to accept request - mux.HandleFunc("/api/v2/files/1/reports", func(w http.ResponseWriter, r *http.Request) { - resp := fmt.Sprintf(`{ - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": %d, - "language": "en", - "progress": 100, - "rating": "20.73" - } - ] - }`, 1) - fmt.Fprint(w, resp) - }) - - // Starting fake server to accept request - mux.HandleFunc("/api/v2/reports/1/pdf", func(w http.ResponseWriter, r *http.Request) { - resp := fmt.Sprintf(`{"url":"%s/aws_fake_signed_url1.txt?signature=fake_signature_hash"}`, serverURL) - fmt.Fprint(w, resp) - }) - - // Starting fake server to accept download request - mux.HandleFunc("/aws_fake_signed_url1.txt", func(w http.ResponseWriter, r *http.Request) { - fmt.Fprint(w, `Fake_File_Content`) - }) - - tmpDir := t.TempDir() - - ok, err := ProcessDownloadReports(1, true, false, tmpDir) - assert.Equal(t, true, ok) - assert.Equal(t, nil, err) - - // remove files after test - err = os.Remove(filepath.Join(tmpDir, "aws_fake_signed_url1.txt")) - assert.Equal(t, nil, err) -} - -func TestHelper_ProcessDownloadReports_With_Generate_No_IfFetchLastReportResult_Fail_ShouldFail(t *testing.T) { - _, mux, serverURL, teardown := setup() - defer teardown() - - // Starting fake server to accept request - mux.HandleFunc("/api/v2/files/1/reports", func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusNotFound) - }) - - // Setting up environment variable to use fake server in this api tests - viper.Set("host", serverURL+"/") - viper.Set("insecure", true) - viper.Set("access-token", "token") - - ok, err := ProcessDownloadReports(1, true, false, t.TempDir()) - assert.Equal(t, false, ok) - assert.Equal(t, false, err == nil) -} - -func TestHelper_ProcessDownloadReports_With_Generate_No_IfGetReportURL_Fail_ShouldFail(t *testing.T) { - _, mux, serverURL, teardown := setup() - defer teardown() - - // Setting up environment variable to use fake server in this api tests - viper.Set("host", serverURL+"/") - viper.Set("insecure", true) - viper.Set("access-token", "token") - - // Starting fake server to accept request - mux.HandleFunc("/api/v2/files/1/reports", func(w http.ResponseWriter, r *http.Request) { - resp := fmt.Sprintf(`{ - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": %d, - "language": "en", - "progress": 100, - "rating": "20.73" - } - ] - }`, 1) - fmt.Fprint(w, resp) - }) - - // Starting fake server to accept request - mux.HandleFunc("/api/v2/reports/1/pdf", func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusNotFound) - }) - - ok, err := ProcessDownloadReports(1, true, false, t.TempDir()) - assert.Equal(t, false, ok) - assert.Equal(t, false, err == nil) -} - -func TestHelper_ProcessDownloadReports_With_Generate_No_IfDownloadFile_Fail_ShouldFail(t *testing.T) { - _, mux, serverURL, teardown := setup() - defer teardown() - - // Setting up environment variable to use fake server in this api tests - viper.Set("host", serverURL+"/") - viper.Set("insecure", true) - viper.Set("access-token", "token") - - // Starting fake server to accept request - mux.HandleFunc("/api/v2/files/1/reports", func(w http.ResponseWriter, r *http.Request) { - resp := fmt.Sprintf(`{ - "count": 1, - "next": null, - "previous": null, - "results": [ - { - "id": %d, - "language": "en", - "progress": 100, - "rating": "20.73" - } - ] - }`, 1) - fmt.Fprint(w, resp) - }) - - // Starting fake server to accept request - mux.HandleFunc("/api/v2/reports/1/pdf", func(w http.ResponseWriter, r *http.Request) { - resp := fmt.Sprintf(`{"url":"%s/aws_fake_signed_url1.txt?signature=fake_signature_hash"}`, serverURL) - fmt.Fprint(w, resp) - }) - - // Starting fake server to accept request - mux.HandleFunc("/aws_fake_signed_url1.txt", func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusNotFound) - }) - - tmpDir := t.TempDir() - - ok, err := ProcessDownloadReports(1, true, false, tmpDir) - assert.Equal(t, false, ok) - assert.Equal(t, false, err == nil) - - // remove files after test - err = os.Remove(filepath.Join(tmpDir, "aws_fake_signed_url1.txt")) - assert.Equal(t, nil, err) -} - -func TestHelper_ProcessDownloadReports_With_Generate_Yes_Success(t *testing.T) { - _, mux, serverURL, teardown := setup() - defer teardown() - - // Setting up environment variable to use fake server in this api tests - viper.Set("host", serverURL+"/") - viper.Set("insecure", true) - viper.Set("access-token", "token") - - // Starting fake server to accept request for generate reports - mux.HandleFunc("/api/v2/files/1/reports", func(w http.ResponseWriter, r *http.Request) { - resp := fmt.Sprintf(`{ - "id": %d, - "language": "en", - "progress": 50, - "rating": "20.73" - }`, 1) - fmt.Fprint(w, resp) - }) - - // Starting fake server to accept request - mux.HandleFunc("/api/v2/reports/1", func(w http.ResponseWriter, r *http.Request) { - resp := fmt.Sprintf(`{ - "id": %d, - "language": "en", - "progress": 100, - "rating": "20.73" - }`, 1) - fmt.Fprint(w, resp) - }) - - // Starting fake server to accept request - mux.HandleFunc("/api/v2/reports/1/pdf", func(w http.ResponseWriter, r *http.Request) { - resp := fmt.Sprintf(`{"url":"%s/aws_fake_signed_url1.txt?signature=fake_signature_hash"}`, serverURL) - fmt.Fprint(w, resp) - }) - - // Starting fake server to accept download request - mux.HandleFunc("/aws_fake_signed_url1.txt", func(w http.ResponseWriter, r *http.Request) { - fmt.Fprint(w, `Fake_File_Content`) - }) - - tmpDir := t.TempDir() - - ok, err := ProcessDownloadReports(1, true, true, tmpDir) - assert.Equal(t, true, ok) - assert.Equal(t, nil, err) - - // remove files after test - // remove files after test - err = os.Remove(filepath.Join(tmpDir, "aws_fake_signed_url1.txt")) - assert.Equal(t, nil, err) -} -func TestHelper_ProcessDownloadReports_With_Generate_Yes_IfAPIFails_Should_Fail(t *testing.T) { - _, mux, serverURL, teardown := setup() - defer teardown() - - // Starting fake server to accept download request - mux.HandleFunc("/api/v2/files/1/reports", func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusNotFound) - }) - - // Setting up environment variable to use fake server in this api tests - viper.Set("host", serverURL+"/") - viper.Set("insecure", true) - viper.Set("access-token", "token") - - ok, err := ProcessDownloadReports(1, true, true, t.TempDir()) - assert.Equal(t, false, ok) - assert.Equal(t, false, err == nil) -} -func TestHelper_ProcessDownloadReports_With_Generate_Yes_and_Generate_Report_Fails_Should_Fail(t *testing.T) { - _, mux, serverURL, teardown := setup() - defer teardown() - - // Setting up environment variable to use fake server in this api tests - viper.Set("host", serverURL+"/") - viper.Set("insecure", true) - viper.Set("access-token", "token") - - // Starting fake server to accept request - mux.HandleFunc("/api/v2/files/1/reports", func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusBadRequest) - }) - - ok, err := ProcessDownloadReports(1, true, true, t.TempDir()) - assert.Equal(t, false, ok) - assert.Equal(t, "A report is already being generated or scan is in progress. Please wait.", err.Error()) -} - -func TestHelper_ProcessDownloadReports_WithInvalidData_Fail(t *testing.T) { - ok, err := ProcessDownloadReports(1, false, false, t.TempDir()) - assert.Equal(t, false, ok) - assert.Equal(t, "Downloading PDF reports is not a fully supported/experimental feature. Please opt-in by specifying --allow-experimental-features in the command.", err.Error()) -} - -func TestHelper_ProcessDownloadReports_With_Generate_Yes_FetchReportResultFail_ShouldFail(t *testing.T) { - _, mux, serverURL, teardown := setup() - defer teardown() - - // Setting up environment variable to use fake server in this api tests - viper.Set("host", serverURL+"/") - viper.Set("insecure", true) - viper.Set("access-token", "token") - - // Starting fake server to accept request for generate reports - mux.HandleFunc("/api/v2/files/1/reports", func(w http.ResponseWriter, r *http.Request) { - resp := fmt.Sprintf(`{ - "id": %d, - "language": "en", - "progress": 50, - "rating": "20.73" - }`, 1) - fmt.Fprint(w, resp) - }) - - // Starting fake server to accept download request - mux.HandleFunc("/api/v2/reports/1", func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusNotFound) - }) - - ok, err := ProcessDownloadReports(1, true, true, t.TempDir()) - assert.Equal(t, false, ok) - assert.Equal(t, false, err == nil) -}