From cacfae2c6539abc7cdf75a1cf531fdc3c01d658c Mon Sep 17 00:00:00 2001 From: Preslav Gerchev Date: Wed, 11 Oct 2023 14:19:39 +0300 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Fix=20retrieval=20of=20report=20?= =?UTF-8?q?usage=20by=20going=20back=20a=20week.=20Use=20time.DateOnly=20f?= =?UTF-8?q?or=20date=20formatting.=20(#2112)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../google-workspace/resources/reports.go | 71 ++++++++++++------- providers/google-workspace/resources/users.go | 4 +- 2 files changed, 48 insertions(+), 27 deletions(-) diff --git a/providers/google-workspace/resources/reports.go b/providers/google-workspace/resources/reports.go index d2cf69803f..9ae1eee794 100644 --- a/providers/google-workspace/resources/reports.go +++ b/providers/google-workspace/resources/reports.go @@ -6,6 +6,7 @@ package resources import ( "errors" "strconv" + "strings" "time" "go.mondoo.com/cnquery/v9/llx" @@ -41,9 +42,6 @@ const ( appKeep = "keep" ) -// ISO8601 is a date format required by Google Workspace Reports API -const ISO8601 = "2006-01-02" // yyyy-mm-dd - func (g *mqlGoogleworkspaceReportApps) id() (string, error) { return "googleworkspace.report.apps", nil } @@ -125,46 +123,69 @@ func (g *mqlGoogleworkspaceReportUsers) list() ([]interface{}, error) { res := []interface{}{} date := time.Now() - usageReports, err := reportsService.UserUsageReport.Get("all", date.Format(ISO8601)).CustomerId(conn.CustomerID()).Do() - if err != nil { + expectedErr := "googleapi: Error 400: Data for dates later than" + + usageReports, err := fetchReportUsage(g.MqlRuntime, reportsService, conn.CustomerID(), date.Format(time.DateOnly)) + // we expect this error if there is no data for the current day, so we continue + if err != nil && !strings.HasPrefix(err.Error(), expectedErr) { return nil, err } - for { - if len(usageReports.UsageReports) == 0 { + + if len(usageReports) == 0 { + // try and fetch usage for each of the past 7 days + attempts := 7 + for attempts > 0 { date = date.Add(-24 * time.Hour) - // try fetching from a day before - usageReports, err = reportsService.UserUsageReport.Get("all", date.Format(ISO8601)).CustomerId(conn.CustomerID()).Do() - if err != nil { + reports, err := fetchReportUsage(g.MqlRuntime, reportsService, conn.CustomerID(), date.Format(time.DateOnly)) + // we expect this error if there is no data for the current day, so we continue + if err != nil && !strings.HasPrefix(err.Error(), expectedErr) { return nil, err } - continue - } - - for i := range usageReports.UsageReports { - r, err := newMqlGoogleWorkspaceUsageReport(g.MqlRuntime, usageReports.UsageReports[i]) - if err != nil { - return nil, err + if len(reports) > 0 { + res = append(res, reports...) + break } - res = append(res, r) + attempts-- } + } - if usageReports.NextPageToken == "" { - break - } + return res, nil +} + +func fetchReportUsage(runtime *plugin.Runtime, service *reports.Service, customerId, date string) ([]interface{}, error) { + res := []interface{}{} - usageReports, err = reportsService.UserUsageReport.Get("all", date.Format(ISO8601)).CustomerId(conn.CustomerID()). - PageToken(usageReports.NextPageToken).Do() + usageReports, err := service.UserUsageReport.Get("all", date).CustomerId(customerId).Do() + if err != nil { + return nil, err + } + for _, u := range usageReports.UsageReports { + r, err := newMqlGoogleWorkspaceUsageReport(runtime, u) if err != nil { return nil, err } + res = append(res, r) } + for usageReports != nil && usageReports.NextPageToken != "" { + usageReports, err := service.UserUsageReport.Get("all", date).CustomerId(customerId).PageToken(usageReports.NextPageToken).Do() + if err != nil { + return nil, err + } + for _, u := range usageReports.UsageReports { + r, err := newMqlGoogleWorkspaceUsageReport(runtime, u) + if err != nil { + return nil, err + } + res = append(res, r) + } + } return res, nil } func newMqlGoogleWorkspaceUsageReport(runtime *plugin.Runtime, entry *reports.UsageReport) (*mqlGoogleworkspaceReportUsage, error) { var date *time.Time - parsedDate, err := time.Parse(ISO8601, entry.Date) + parsedDate, err := time.Parse(time.DateOnly, entry.Date) if err == nil { date = &parsedDate } @@ -220,7 +241,7 @@ func (g *mqlGoogleworkspaceReportUsage) id() (string, error) { } date := g.Date.Data - return "googleworkspace.report.usage/" + customerId + "/" + profileId + "/" + date.Format(ISO8601), nil + return "googleworkspace.report.usage/" + customerId + "/" + profileId + "/" + date.Format(time.DateOnly), nil } type userReport struct { diff --git a/providers/google-workspace/resources/users.go b/providers/google-workspace/resources/users.go index c12d86a6a7..4379e3d660 100644 --- a/providers/google-workspace/resources/users.go +++ b/providers/google-workspace/resources/users.go @@ -104,7 +104,7 @@ func (g *mqlGoogleworkspaceUser) usageReport() (*mqlGoogleworkspaceReportUsage, primaryEmail := g.PrimaryEmail.Data date := time.Now() - report, err := reportsService.UserUsageReport.Get(primaryEmail, date.Format(ISO8601)).CustomerId(conn.CustomerID()).Do() + report, err := reportsService.UserUsageReport.Get(primaryEmail, date.Format(time.DateOnly)).CustomerId(conn.CustomerID()).Do() if err != nil { return nil, err } @@ -118,7 +118,7 @@ func (g *mqlGoogleworkspaceUser) usageReport() (*mqlGoogleworkspaceReportUsage, if len(report.UsageReports) == 0 { date = date.Add(-24 * time.Hour) // try fetching from a day before - report, err = reportsService.UserUsageReport.Get(primaryEmail, date.Format(ISO8601)).CustomerId(conn.CustomerID()).Do() + report, err = reportsService.UserUsageReport.Get(primaryEmail, date.Format(time.DateOnly)).CustomerId(conn.CustomerID()).Do() if err != nil { return nil, err }