From 236e97ebc1a53dbd89eda1d613a5634226d651bf Mon Sep 17 00:00:00 2001 From: Sean Chittenden Date: Tue, 28 Jan 2020 08:29:45 -0800 Subject: [PATCH] auditlogs: fix GetOrganizationAuditLogs() (#415) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * auditlogs: fix GetOrganizationAuditLogs() Move to using stdlib strategies for encoding URL parameters. * Fix tests * Update godoc * auditlogs: use /accounts/${account_id}/audit_logs for audit logs `/organizations` has been deprecated. Pointed out by: @jacobbednarz * Update auditlogs_test.go Co-authored-by: Patryk Szczygłowski --- auditlogs.go | 58 ++++++++++++++++++++++++++--------------------- auditlogs_test.go | 44 +++++++++++++++++------------------ 2 files changed, 54 insertions(+), 48 deletions(-) diff --git a/auditlogs.go b/auditlogs.go index 8cb8eab6910..3bd26941b7b 100644 --- a/auditlogs.go +++ b/auditlogs.go @@ -1,9 +1,10 @@ package cloudflare import ( - "encoding/base64" "encoding/json" - "fmt" + "net/url" + "path" + "strconv" "time" ) @@ -65,39 +66,41 @@ type AuditLogFilter struct { Page int } -// String turns an audit log filter in to an HTTP Query Param -// list. It will not inclue empty members of the struct in the -// query parameters. -func (a AuditLogFilter) String() string { - params := "?" +// ToQuery turns an audit log filter in to an HTTP Query Param +// list, suitable for use in a url.URL.RawQuery. It will not inclue empty +// members of the struct in the query parameters. +func (a AuditLogFilter) ToQuery() url.Values { + v := url.Values{} + if a.ID != "" { - params += "&id=" + a.ID + v.Add("id", a.ID) } if a.ActorIP != "" { - params += "&actor.ip=" + a.ActorIP + v.Add("actor.ip", a.ActorIP) } if a.ActorEmail != "" { - params += "&actor.email=" + a.ActorEmail + v.Add("actor.email", a.ActorEmail) } if a.ZoneName != "" { - params += "&zone.name=" + a.ZoneName + v.Add("zone.name", a.ZoneName) } if a.Direction != "" { - params += "&direction=" + a.Direction + v.Add("direction", a.Direction) } if a.Since != "" { - params += "&since=" + a.Since + v.Add("since", a.Since) } if a.Before != "" { - params += "&before=" + a.Before + v.Add("before", a.Before) } if a.PerPage > 0 { - params += "&per_page=" + fmt.Sprintf("%d", a.PerPage) + v.Add("per_page", strconv.Itoa(a.PerPage)) } if a.Page > 0 { - params += "&page=" + fmt.Sprintf("%d", a.Page) + v.Add("page", strconv.Itoa(a.Page)) } - return params + + return v } // GetOrganizationAuditLogs will return the audit logs of a specific @@ -106,17 +109,16 @@ func (a AuditLogFilter) String() string { // // API Reference: https://api.cloudflare.com/#audit-logs-list-organization-audit-logs func (api *API) GetOrganizationAuditLogs(organizationID string, a AuditLogFilter) (AuditLogResponse, error) { - uri := "/organizations/" + organizationID + "/audit_logs" + fmt.Sprintf("%s", a) - - res, err := api.makeRequest("GET", uri, nil) - if err != nil { - return AuditLogResponse{}, err + uri := url.URL{ + Path: path.Join("/accounts", organizationID, "audit_logs"), + ForceQuery: true, + RawQuery: a.ToQuery().Encode(), } - buf, err := base64.RawStdEncoding.DecodeString(string(res)) + res, err := api.makeRequest("GET", uri.String(), nil) if err != nil { return AuditLogResponse{}, err } - return unmarshalReturn(buf) + return unmarshalReturn(res) } // unmarshalReturn will unmarshal bytes and return an auditlogresponse @@ -134,8 +136,12 @@ func unmarshalReturn(res []byte) (AuditLogResponse, error) { // // API Reference: https://api.cloudflare.com/#audit-logs-list-user-audit-logs func (api *API) GetUserAuditLogs(a AuditLogFilter) (AuditLogResponse, error) { - uri := "/user/audit_logs" + fmt.Sprintf("%s", a) - res, err := api.makeRequest("GET", uri, nil) + uri := url.URL{ + Path: path.Join("/user", "audit_logs"), + ForceQuery: true, + RawQuery: a.ToQuery().Encode(), + } + res, err := api.makeRequest("GET", uri.String(), nil) if err != nil { return AuditLogResponse{}, err } diff --git a/auditlogs_test.go b/auditlogs_test.go index 02bed4d7e8d..d8d288992ae 100644 --- a/auditlogs_test.go +++ b/auditlogs_test.go @@ -5,51 +5,51 @@ import ( "testing" ) -func TestAuditLogFilterStringify(t *testing.T) { +func TestAuditLogFilterToQuery(t *testing.T) { filter := AuditLogFilter{ ID: "aaaa", } - if !strings.Contains(filter.String(), "&id=aaaa") { - t.Fatalf("Did not properly stringify the id field: %s", filter.String()) + if !strings.Contains(filter.ToQuery().Encode(), "id=aaaa") { + t.Fatalf("Did not properly stringify the id field: %s", filter.ToQuery().Encode()) } - filter.ActorIP = "1.1.1.1" - if !strings.Contains(filter.String(), "&actor.ip=1.1.1.1") { - t.Fatalf("Did not properly stringify the actorip field: %s", filter.String()) + filter.ActorEmail = "admin@example.com" + if !strings.Contains(filter.ToQuery().Encode(), "actor.email=admin%40example.com") { + t.Fatalf("Did not properly stringify the actor.email field: %s", filter.ToQuery().Encode()) } - filter.ZoneName = "ejj.io" - if !strings.Contains(filter.String(), "&zone.name=ejj.io") { - t.Fatalf("Did not properly stringify the zone.name field: %s", filter.String()) + filter.ActorIP = "192.0.2.0" + if !strings.Contains(filter.ToQuery().Encode(), "&actor.ip=192.0.2.0") { + t.Fatalf("Did not properly stringify the actorip field: %s", filter.ToQuery().Encode()) } - filter.ActorEmail = "admin@admin.com" - if !strings.Contains(filter.String(), "&actor.email=admin@admin.com") { - t.Fatalf("Did not properly stringify the actor.email field: %s", filter.String()) + filter.ZoneName = "example.com" + if !strings.Contains(filter.ToQuery().Encode(), "&zone.name=example.com") { + t.Fatalf("Did not properly stringify the zone.name field: %s", filter.ToQuery().Encode()) } filter.Direction = "direction" - if !strings.Contains(filter.String(), "&direction=direction") { - t.Fatalf("Did not properly stringify the direction field: %s", filter.String()) + if !strings.Contains(filter.ToQuery().Encode(), "&direction=direction") { + t.Fatalf("Did not properly stringify the direction field: %s", filter.ToQuery().Encode()) } filter.Since = "10-2-2018" - if !strings.Contains(filter.String(), "&since=10-2-2018") { - t.Fatalf("Did not properly stringify the since field: %s", filter.String()) + if !strings.Contains(filter.ToQuery().Encode(), "&since=10-2-2018") { + t.Fatalf("Did not properly stringify the since field: %s", filter.ToQuery().Encode()) } filter.Before = "10-2-2018" - if !strings.Contains(filter.String(), "&before=10-2-2018") { - t.Fatalf("Did not properly stringify the before field: %s", filter.String()) + if !strings.Contains(filter.ToQuery().Encode(), "&before=10-2-2018") { + t.Fatalf("Did not properly stringify the before field: %s", filter.ToQuery().Encode()) } filter.PerPage = 10000 - if !strings.Contains(filter.String(), "&per_page=10000") { - t.Fatalf("Did not properly stringify the per_page field: %s", filter.String()) + if !strings.Contains(filter.ToQuery().Encode(), "&per_page=10000") { + t.Fatalf("Did not properly stringify the per_page field: %s", filter.ToQuery().Encode()) } filter.Page = 3 - if !strings.Contains(filter.String(), "&page=3") { - t.Fatalf("Did not properly stringify the page field: %s", filter.String()) + if !strings.Contains(filter.ToQuery().Encode(), "&page=3") { + t.Fatalf("Did not properly stringify the page field: %s", filter.ToQuery().Encode()) } }