diff --git a/descope/internal/mgmt/audit.go b/descope/internal/mgmt/audit.go index 83c0621e..ad985eb2 100644 --- a/descope/internal/mgmt/audit.go +++ b/descope/internal/mgmt/audit.go @@ -17,7 +17,7 @@ type audit struct { var _ sdk.Audit = &audit{} -func (a *audit) Search(ctx context.Context, options *descope.AuditSearchOptions) ([]*descope.AuditRecord, error) { +func (a *audit) SearchAll(ctx context.Context, options *descope.AuditSearchOptions) ([]*descope.AuditRecord, int, error) { body := map[string]any{ "userIds": options.UserIDs, "actions": options.Actions, @@ -32,16 +32,22 @@ func (a *audit) Search(ctx context.Context, options *descope.AuditSearchOptions) "tenants": options.Tenants, "noTenants": options.NoTenants, "text": options.Text, - "size": options.Size, + "size": options.Limit, "page": options.Page, } res, err := a.client.DoPostRequest(ctx, api.Routes.ManagementAuditSearch(), body, nil, a.conf.ManagementKey) if err != nil { - return nil, err + return nil, 0, err } return unmarshalAuditRecords(res) } +// Deprecated: replaced by audit.SearchAll +func (a *audit) Search(ctx context.Context, options *descope.AuditSearchOptions) ([]*descope.AuditRecord, error) { + records, _, err := a.SearchAll(ctx, options) + return records, err +} + func (a *audit) CreateEvent(ctx context.Context, options *descope.AuditCreateOptions) error { if options.Action == "" { return utils.NewInvalidArgumentError("Action") @@ -88,20 +94,21 @@ type apiAuditRecord struct { type apiSearchAuditResponse struct { Audits []*apiAuditRecord + Total int } -func unmarshalAuditRecords(res *api.HTTPResponse) ([]*descope.AuditRecord, error) { +func unmarshalAuditRecords(res *api.HTTPResponse) ([]*descope.AuditRecord, int, error) { var auditRes *apiSearchAuditResponse err := utils.Unmarshal([]byte(res.BodyStr), &auditRes) if err != nil { // notest - return nil, err + return nil, 0, err } var records []*descope.AuditRecord for _, rec := range auditRes.Audits { occurred, err := strconv.ParseInt(rec.Occurred, 10, 64) if err != nil { - return nil, err + return nil, 0, err } records = append(records, &descope.AuditRecord{ ProjectID: rec.ProjectID, @@ -119,5 +126,5 @@ func unmarshalAuditRecords(res *api.HTTPResponse) ([]*descope.AuditRecord, error Type: rec.Type, }) } - return records, nil + return records, auditRes.Total, nil } diff --git a/descope/internal/mgmt/audit_test.go b/descope/internal/mgmt/audit_test.go index 3b53d1f2..eff4c0b3 100644 --- a/descope/internal/mgmt/audit_test.go +++ b/descope/internal/mgmt/audit_test.go @@ -42,7 +42,9 @@ func TestAuditSearch(t *testing.T) { Tenants: []string{"t1"}, Data: map[string]interface{}{"x": "y1", "z": 2}, }, - }} + }, + Total: 2, + } searchOptions := &descope.AuditSearchOptions{ UserIDs: []string{"u1", "u2"}, Actions: []string{"a1", "a2"}, @@ -56,7 +58,7 @@ func TestAuditSearch(t *testing.T) { Tenants: []string{"t1"}, NoTenants: true, Text: "kuku", - Size: 10, + Limit: 10, Page: 1, } mgmt := newTestMgmt(nil, helpers.DoOkWithBody(func(r *http.Request) { @@ -77,24 +79,32 @@ func TestAuditSearch(t *testing.T) { require.EqualValues(t, []interface{}{searchOptions.Tenants[0]}, req["tenants"]) require.EqualValues(t, searchOptions.NoTenants, req["noTenants"]) require.EqualValues(t, searchOptions.Text, req["text"]) - require.EqualValues(t, searchOptions.Size, req["size"]) + require.EqualValues(t, searchOptions.Limit, req["size"]) require.EqualValues(t, searchOptions.Page, req["page"]) }, response)) + doAsserts := func(res []*descope.AuditRecord, err error) { + require.NoError(t, err) + require.Len(t, res, 2) + assert.Equal(t, response.Audits[0].ProjectID, res[0].ProjectID) + assert.Equal(t, response.Audits[0].UserID, res[0].UserID) + assert.Equal(t, response.Audits[0].Action, res[0].Action) + assert.Equal(t, response.Audits[0].Occurred, strconv.FormatInt(res[0].Occurred.UnixMilli(), 10)) + assert.Equal(t, response.Audits[0].Device, res[0].Device) + assert.Equal(t, response.Audits[0].Method, res[0].Method) + assert.Equal(t, response.Audits[0].Geo, res[0].Geo) + assert.Equal(t, response.Audits[0].RemoteAddress, res[0].RemoteAddress) + assert.EqualValues(t, response.Audits[0].ExternalIDs, res[0].LoginIDs) + assert.EqualValues(t, response.Audits[0].Tenants, res[0].Tenants) + assert.EqualValues(t, response.Audits[0].Data["x"], res[0].Data["x"]) + assert.True(t, called) + } + //run test for Deprecated Search API res, err := mgmt.Audit().Search(context.Background(), searchOptions) - require.NoError(t, err) - require.Len(t, res, 2) - assert.Equal(t, response.Audits[0].ProjectID, res[0].ProjectID) - assert.Equal(t, response.Audits[0].UserID, res[0].UserID) - assert.Equal(t, response.Audits[0].Action, res[0].Action) - assert.Equal(t, response.Audits[0].Occurred, strconv.FormatInt(res[0].Occurred.UnixMilli(), 10)) - assert.Equal(t, response.Audits[0].Device, res[0].Device) - assert.Equal(t, response.Audits[0].Method, res[0].Method) - assert.Equal(t, response.Audits[0].Geo, res[0].Geo) - assert.Equal(t, response.Audits[0].RemoteAddress, res[0].RemoteAddress) - assert.EqualValues(t, response.Audits[0].ExternalIDs, res[0].LoginIDs) - assert.EqualValues(t, response.Audits[0].Tenants, res[0].Tenants) - assert.EqualValues(t, response.Audits[0].Data["x"], res[0].Data["x"]) - assert.True(t, called) + doAsserts(res, err) + //run test for SearchAll API, and also assert the value of the "total" return value + res, total, err := mgmt.Audit().SearchAll(context.Background(), searchOptions) + doAsserts(res, err) + assert.Equal(t, 2, total) } func TestAuditCreate(t *testing.T) { diff --git a/descope/sdk/mgmt.go b/descope/sdk/mgmt.go index c0924fbf..671b5e47 100644 --- a/descope/sdk/mgmt.go +++ b/descope/sdk/mgmt.go @@ -742,7 +742,8 @@ type Project interface { // Provides search project audit trail type Audit interface { - Search(ctx context.Context, options *descope.AuditSearchOptions) ([]*descope.AuditRecord, error) + Search(ctx context.Context, options *descope.AuditSearchOptions) ([]*descope.AuditRecord, error) // Deprecated: replaced by Audit.SearchAll + SearchAll(ctx context.Context, options *descope.AuditSearchOptions) ([]*descope.AuditRecord, int, error) CreateEvent(ctx context.Context, options *descope.AuditCreateOptions) error } diff --git a/descope/tests/mocks/mgmt/managementmock.go b/descope/tests/mocks/mgmt/managementmock.go index bf99334b..b5288c51 100644 --- a/descope/tests/mocks/mgmt/managementmock.go +++ b/descope/tests/mocks/mgmt/managementmock.go @@ -1290,6 +1290,7 @@ func (m *MockProject) ListProjects(_ context.Context) ([]*descope.Project, error type MockAudit struct { SearchAssert func(*descope.AuditSearchOptions) SearchResponse []*descope.AuditRecord + SearchTotal int SearchError error CreateEventAssert func(*descope.AuditCreateOptions) @@ -1303,6 +1304,13 @@ func (m *MockAudit) Search(_ context.Context, options *descope.AuditSearchOption return m.SearchResponse, m.SearchError } +func (m *MockAudit) SearchAll(_ context.Context, options *descope.AuditSearchOptions) ([]*descope.AuditRecord, int, error) { + if m.SearchAssert != nil { + m.SearchAssert(options) + } + return m.SearchResponse, m.SearchTotal, m.SearchError +} + func (m *MockAudit) CreateEvent(_ context.Context, options *descope.AuditCreateOptions) error { if m.CreateEventAssert != nil { m.CreateEventAssert(options) diff --git a/descope/types.go b/descope/types.go index c39cc450..c4651921 100644 --- a/descope/types.go +++ b/descope/types.go @@ -870,7 +870,7 @@ type AuditSearchOptions struct { Tenants []string `json:"tenants"` // List of tenants to filter by NoTenants bool `json:"noTenants"` // Should audits without any tenants always be included Text string `json:"text"` // Free text search across all fields - Size int32 `json:"size,omitempty"` // Number of results to include per retrived page. Current default, and max value, is 1000. + Limit int32 `json:"limit,omitempty"` // Number of results to include per retrieved page. Current default, and max value, is 1000 Page int32 `json:"page,omitempty"` // Page number of results to retrieve, zero-based. Default is 0. } diff --git a/examples/webapp/main.go b/examples/webapp/main.go index aa8c53bc..f02b84d9 100644 --- a/examples/webapp/main.go +++ b/examples/webapp/main.go @@ -565,11 +565,11 @@ func handleStepupStepupVerify(w http.ResponseWriter, r *http.Request) { func handleAuditSearch(w http.ResponseWriter, r *http.Request) { searchOptions := &descope.AuditSearchOptions{} - auditSearchRes, err := descopeClient.Management.Audit().Search(r.Context(), searchOptions) + auditSearchRes, total, err := descopeClient.Management.Audit().SearchAll(r.Context(), searchOptions) if err != nil { setError(w, err.Error()) } else { - helpTxt := fmt.Sprintf("Audit Search Results (%d Results Returned):\n", len(auditSearchRes)) + helpTxt := fmt.Sprintf("Audit Search Results (%d Results Returned, %d Total):\n", len(auditSearchRes), total) mr, _ := json.MarshalIndent(auditSearchRes, "", "\t") helpTxt += string(mr) + "\n" setResponse(w, http.StatusOK, helpTxt) diff --git a/scripts/lint/gitleaks.toml b/scripts/lint/gitleaks.toml index d16088a4..6c7b757e 100644 --- a/scripts/lint/gitleaks.toml +++ b/scripts/lint/gitleaks.toml @@ -651,4 +651,6 @@ paths = [ '''(.*?)(jpg|gif|doc|pdf|bin|svg|socket)$''', '''(go.mod|go.sum)$''', "vendor/", + "examples/key.pem", + "examples/cert.pem", ]