package codersdk import ( "context" "encoding/json" "net/http" "net/netip" "time" "github.com/google/uuid" ) type ResourceType string const ( ResourceTypeOrganization ResourceType = "organization" ResourceTypeTemplate ResourceType = "template" ResourceTypeTemplateVersion ResourceType = "template_version" ResourceTypeUser ResourceType = "user" ResourceTypeWorkspace ResourceType = "workspace" ResourceTypeGitSSHKey ResourceType = "git_ssh_key" ResourceTypeAPIKey ResourceType = "api_key" ) func (r ResourceType) FriendlyString() string { switch r { case ResourceTypeOrganization: return "organization" case ResourceTypeTemplate: return "template" case ResourceTypeTemplateVersion: return "template version" case ResourceTypeUser: return "user" case ResourceTypeWorkspace: return "workspace" case ResourceTypeGitSSHKey: return "git ssh key" case ResourceTypeAPIKey: return "api key" default: return "unknown" } } type AuditAction string const ( AuditActionCreate AuditAction = "create" AuditActionWrite AuditAction = "write" AuditActionDelete AuditAction = "delete" ) func (a AuditAction) FriendlyString() string { switch a { case AuditActionCreate: return "created" case AuditActionWrite: return "updated" case AuditActionDelete: return "deleted" default: return "unknown" } } type AuditDiff map[string]AuditDiffField type AuditDiffField struct { Old any `json:"old,omitempty"` New any `json:"new,omitempty"` Secret bool `json:"secret"` } type AuditLog struct { ID uuid.UUID `json:"id"` RequestID uuid.UUID `json:"request_id"` Time time.Time `json:"time"` OrganizationID uuid.UUID `json:"organization_id"` IP netip.Addr `json:"ip"` UserAgent string `json:"user_agent"` ResourceType ResourceType `json:"resource_type"` ResourceID uuid.UUID `json:"resource_id"` // ResourceTarget is the name of the resource. ResourceTarget string `json:"resource_target"` ResourceIcon string `json:"resource_icon"` Action AuditAction `json:"action"` Diff AuditDiff `json:"diff"` StatusCode int32 `json:"status_code"` AdditionalFields json.RawMessage `json:"additional_fields"` Description string `json:"description"` User *User `json:"user"` } type AuditLogResponse struct { AuditLogs []AuditLog `json:"audit_logs"` } type AuditLogCountResponse struct { Count int64 `json:"count"` } // AuditLogs retrieves audit logs from the given page. func (c *Client) AuditLogs(ctx context.Context, page Pagination) (AuditLogResponse, error) { res, err := c.Request(ctx, http.MethodGet, "/api/v2/audit", nil, page.asRequestOption()) if err != nil { return AuditLogResponse{}, err } defer res.Body.Close() if res.StatusCode != http.StatusOK { return AuditLogResponse{}, readBodyAsError(res) } var logRes AuditLogResponse err = json.NewDecoder(res.Body).Decode(&logRes) if err != nil { return AuditLogResponse{}, err } return logRes, nil } // AuditLogCount returns the count of all audit logs in the product. func (c *Client) AuditLogCount(ctx context.Context) (AuditLogCountResponse, error) { res, err := c.Request(ctx, http.MethodGet, "/api/v2/audit/count", nil) if err != nil { return AuditLogCountResponse{}, err } defer res.Body.Close() if res.StatusCode != http.StatusOK { return AuditLogCountResponse{}, readBodyAsError(res) } var logRes AuditLogCountResponse err = json.NewDecoder(res.Body).Decode(&logRes) if err != nil { return AuditLogCountResponse{}, err } return logRes, nil } func (c *Client) CreateTestAuditLog(ctx context.Context) error { res, err := c.Request(ctx, http.MethodPost, "/api/v2/audit/testgenerate", nil) if err != nil { return err } defer res.Body.Close() if res.StatusCode != http.StatusNoContent { return err } return nil }