package cloudflare import ( "context" "net/http" "net/url" "path" "strconv" "time" "github.com/goccy/go-json" ) // AuditLogAction is a member of AuditLog, the action that was taken. type AuditLogAction struct { Result bool `json:"result"` Type string `json:"type"` } // AuditLogActor is a member of AuditLog, who performed the action. type AuditLogActor struct { Email string `json:"email"` ID string `json:"id"` IP string `json:"ip"` Type string `json:"type"` } // AuditLogOwner is a member of AuditLog, who owns this audit log. type AuditLogOwner struct { ID string `json:"id"` } // AuditLogResource is a member of AuditLog, what was the action performed on. type AuditLogResource struct { ID string `json:"id"` Type string `json:"type"` } // AuditLog is an resource that represents an update in the cloudflare dash. type AuditLog struct { Action AuditLogAction `json:"action"` Actor AuditLogActor `json:"actor"` ID string `json:"id"` Metadata map[string]interface{} `json:"metadata"` NewValue string `json:"newValue"` NewValueJSON map[string]interface{} `json:"newValueJson"` OldValue string `json:"oldValue"` OldValueJSON map[string]interface{} `json:"oldValueJson"` Owner AuditLogOwner `json:"owner"` Resource AuditLogResource `json:"resource"` When time.Time `json:"when"` } // AuditLogResponse is the response returned from the cloudflare v4 api. type AuditLogResponse struct { Response Response Result []AuditLog `json:"result"` ResultInfo `json:"result_info"` } // AuditLogFilter is an object for filtering the audit log response from the api. type AuditLogFilter struct { ID string ActorIP string ActorEmail string HideUserLogs bool Direction string ZoneName string Since string Before string PerPage int Page int } // ToQuery turns an audit log filter in to an HTTP Query Param // list, suitable for use in a url.URL.RawQuery. It will not include empty // members of the struct in the query parameters. func (a AuditLogFilter) ToQuery() url.Values { v := url.Values{} if a.ID != "" { v.Add("id", a.ID) } if a.ActorIP != "" { v.Add("actor.ip", a.ActorIP) } if a.ActorEmail != "" { v.Add("actor.email", a.ActorEmail) } if a.HideUserLogs { v.Add("hide_user_logs", "true") } if a.ZoneName != "" { v.Add("zone.name", a.ZoneName) } if a.Direction != "" { v.Add("direction", a.Direction) } if a.Since != "" { v.Add("since", a.Since) } if a.Before != "" { v.Add("before", a.Before) } if a.PerPage > 0 { v.Add("per_page", strconv.Itoa(a.PerPage)) } if a.Page > 0 { v.Add("page", strconv.Itoa(a.Page)) } return v } // GetOrganizationAuditLogs will return the audit logs of a specific // organization, based on the ID passed in. The audit logs can be // filtered based on any argument in the AuditLogFilter. // // API Reference: https://api.cloudflare.com/#audit-logs-list-organization-audit-logs func (api *API) GetOrganizationAuditLogs(ctx context.Context, organizationID string, a AuditLogFilter) (AuditLogResponse, error) { uri := url.URL{ Path: path.Join("/accounts", organizationID, "audit_logs"), ForceQuery: true, RawQuery: a.ToQuery().Encode(), } res, err := api.makeRequestContext(ctx, http.MethodGet, uri.String(), nil) if err != nil { return AuditLogResponse{}, err } return unmarshalReturn(res) } // unmarshalReturn will unmarshal bytes and return an auditlogresponse. func unmarshalReturn(res []byte) (AuditLogResponse, error) { var auditResponse AuditLogResponse err := json.Unmarshal(res, &auditResponse) if err != nil { return auditResponse, err } return auditResponse, nil } // GetUserAuditLogs will return your user's audit logs. The audit logs can be // filtered based on any argument in the AuditLogFilter. // // API Reference: https://api.cloudflare.com/#audit-logs-list-user-audit-logs func (api *API) GetUserAuditLogs(ctx context.Context, a AuditLogFilter) (AuditLogResponse, error) { uri := url.URL{ Path: path.Join("/user", "audit_logs"), ForceQuery: true, RawQuery: a.ToQuery().Encode(), } res, err := api.makeRequestContext(ctx, http.MethodGet, uri.String(), nil) if err != nil { return AuditLogResponse{}, err } return unmarshalReturn(res) }