Skip to content

Commit adad347

Browse files
refactor: Refactor audit logs count to support filtering (#4113)
1 parent 6f82ad0 commit adad347

File tree

9 files changed

+164
-13
lines changed

9 files changed

+164
-13
lines changed

coderd/audit.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,20 @@ func (api *API) auditLogCount(rw http.ResponseWriter, r *http.Request) {
6565
return
6666
}
6767

68-
count, err := api.Database.GetAuditLogCount(ctx)
68+
queryStr := r.URL.Query().Get("q")
69+
filter, errs := auditSearchQuery(queryStr)
70+
if len(errs) > 0 {
71+
httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
72+
Message: "Invalid audit search query.",
73+
Validations: errs,
74+
})
75+
return
76+
}
77+
78+
count, err := api.Database.GetAuditLogCount(ctx, database.GetAuditLogCountParams{
79+
ResourceType: filter.ResourceType,
80+
Action: filter.Action,
81+
})
6982
if err != nil {
7083
httpapi.InternalServerError(rw, err)
7184
return

coderd/audit_test.go

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func TestAuditLogs(t *testing.T) {
2323
err := client.CreateTestAuditLog(ctx, codersdk.CreateTestAuditLogRequest{})
2424
require.NoError(t, err)
2525

26-
count, err := client.AuditLogCount(ctx)
26+
count, err := client.AuditLogCount(ctx, codersdk.AuditLogCountRequest{})
2727
require.NoError(t, err)
2828

2929
alogs, err := client.AuditLogs(ctx, codersdk.AuditLogsRequest{
@@ -41,7 +41,7 @@ func TestAuditLogs(t *testing.T) {
4141
func TestAuditLogsFilter(t *testing.T) {
4242
t.Parallel()
4343

44-
t.Run("FilterByResourceType", func(t *testing.T) {
44+
t.Run("Filter", func(t *testing.T) {
4545
t.Parallel()
4646

4747
ctx := context.Background()
@@ -110,3 +110,73 @@ func TestAuditLogsFilter(t *testing.T) {
110110
}
111111
})
112112
}
113+
114+
func TestAuditLogCountFilter(t *testing.T) {
115+
t.Parallel()
116+
117+
t.Run("Filter", func(t *testing.T) {
118+
t.Parallel()
119+
120+
ctx := context.Background()
121+
client := coderdtest.New(t, nil)
122+
_ = coderdtest.CreateFirstUser(t, client)
123+
124+
// Create two logs with "Create"
125+
err := client.CreateTestAuditLog(ctx, codersdk.CreateTestAuditLogRequest{
126+
Action: codersdk.AuditActionCreate,
127+
ResourceType: codersdk.ResourceTypeTemplate,
128+
})
129+
require.NoError(t, err)
130+
err = client.CreateTestAuditLog(ctx, codersdk.CreateTestAuditLogRequest{
131+
Action: codersdk.AuditActionCreate,
132+
ResourceType: codersdk.ResourceTypeUser,
133+
})
134+
require.NoError(t, err)
135+
136+
// Create one log with "Delete"
137+
err = client.CreateTestAuditLog(ctx, codersdk.CreateTestAuditLogRequest{
138+
Action: codersdk.AuditActionDelete,
139+
ResourceType: codersdk.ResourceTypeUser,
140+
})
141+
require.NoError(t, err)
142+
143+
// Test cases
144+
testCases := []struct {
145+
Name string
146+
SearchQuery string
147+
ExpectedResult int64
148+
}{
149+
{
150+
Name: "FilterByCreateAction",
151+
SearchQuery: "action:create",
152+
ExpectedResult: 2,
153+
},
154+
{
155+
Name: "FilterByDeleteAction",
156+
SearchQuery: "action:delete",
157+
ExpectedResult: 1,
158+
},
159+
{
160+
Name: "FilterByUserResourceType",
161+
SearchQuery: "resource_type:user",
162+
ExpectedResult: 2,
163+
},
164+
{
165+
Name: "FilterByTemplateResourceType",
166+
SearchQuery: "resource_type:template",
167+
ExpectedResult: 1,
168+
},
169+
}
170+
171+
for _, testCase := range testCases {
172+
t.Run(testCase.Name, func(t *testing.T) {
173+
t.Parallel()
174+
response, err := client.AuditLogCount(ctx, codersdk.AuditLogCountRequest{
175+
SearchQuery: testCase.SearchQuery,
176+
})
177+
require.NoError(t, err, "fetch audit logs count")
178+
require.Equal(t, response.Count, testCase.ExpectedResult, "expected audit logs count returned")
179+
})
180+
}
181+
})
182+
}

coderd/database/databasefake/databasefake.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2402,11 +2402,25 @@ func (q *fakeQuerier) GetAuditLogsOffset(ctx context.Context, arg database.GetAu
24022402
return logs, nil
24032403
}
24042404

2405-
func (q *fakeQuerier) GetAuditLogCount(_ context.Context) (int64, error) {
2405+
func (q *fakeQuerier) GetAuditLogCount(_ context.Context, arg database.GetAuditLogCountParams) (int64, error) {
24062406
q.mutex.RLock()
24072407
defer q.mutex.RUnlock()
24082408

2409-
return int64(len(q.auditLogs)), nil
2409+
logs := make([]database.AuditLog, 0)
2410+
2411+
for _, alog := range q.auditLogs {
2412+
if arg.Action != "" && !strings.Contains(string(alog.Action), arg.Action) {
2413+
continue
2414+
}
2415+
2416+
if arg.ResourceType != "" && !strings.Contains(string(alog.ResourceType), arg.ResourceType) {
2417+
continue
2418+
}
2419+
2420+
logs = append(logs, alog)
2421+
}
2422+
2423+
return int64(len(logs)), nil
24102424
}
24112425

24122426
func (q *fakeQuerier) InsertAuditLog(_ context.Context, arg database.InsertAuditLogParams) (database.AuditLog, error) {

coderd/database/querier.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries.sql.go

Lines changed: 20 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries/auditlogs.sql

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,20 @@ OFFSET
3737
SELECT
3838
COUNT(*) as count
3939
FROM
40-
audit_logs;
40+
audit_logs
41+
WHERE
42+
-- Filter resource_type
43+
CASE
44+
WHEN @resource_type :: text != '' THEN
45+
resource_type = @resource_type :: resource_type
46+
ELSE true
47+
END
48+
-- Filter action
49+
AND CASE
50+
WHEN @action :: text != '' THEN
51+
action = @action :: audit_action
52+
ELSE true
53+
END;
4154

4255
-- name: InsertAuditLog :one
4356
INSERT INTO

codersdk/audit.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ type AuditLogResponse struct {
103103
AuditLogs []AuditLog `json:"audit_logs"`
104104
}
105105

106+
type AuditLogCountRequest struct {
107+
SearchQuery string `json:"q,omitempty"`
108+
}
109+
106110
type AuditLogCountResponse struct {
107111
Count int64 `json:"count"`
108112
}
@@ -142,8 +146,16 @@ func (c *Client) AuditLogs(ctx context.Context, req AuditLogsRequest) (AuditLogR
142146
}
143147

144148
// AuditLogCount returns the count of all audit logs in the product.
145-
func (c *Client) AuditLogCount(ctx context.Context) (AuditLogCountResponse, error) {
146-
res, err := c.Request(ctx, http.MethodGet, "/api/v2/audit/count", nil)
149+
func (c *Client) AuditLogCount(ctx context.Context, req AuditLogCountRequest) (AuditLogCountResponse, error) {
150+
res, err := c.Request(ctx, http.MethodGet, "/api/v2/audit/count", nil, func(r *http.Request) {
151+
q := r.URL.Query()
152+
var params []string
153+
if req.SearchQuery != "" {
154+
params = append(params, req.SearchQuery)
155+
}
156+
q.Set("q", strings.Join(params, " "))
157+
r.URL.RawQuery = q.Encode()
158+
})
147159
if err != nil {
148160
return AuditLogCountResponse{}, err
149161
}

site/src/api/api.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -446,8 +446,14 @@ export const getAuditLogs = async (
446446
return response.data
447447
}
448448

449-
export const getAuditLogsCount = async (): Promise<TypesGen.AuditLogCountResponse> => {
450-
const response = await axios.get(`/api/v2/audit/count`)
449+
export const getAuditLogsCount = async (
450+
options: TypesGen.AuditLogCountRequest = {},
451+
): Promise<TypesGen.AuditLogCountResponse> => {
452+
const searchParams = new URLSearchParams()
453+
if (options.q) {
454+
searchParams.set("q", options.q)
455+
}
456+
const response = await axios.get(`/api/v2/audit/count?${searchParams.toString()}`)
451457
return response.data
452458
}
453459

site/src/api/typesGenerated.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ export interface AuditLog {
7676
readonly user?: User
7777
}
7878

79+
// From codersdk/audit.go
80+
export interface AuditLogCountRequest {
81+
readonly q?: string
82+
}
83+
7984
// From codersdk/audit.go
8085
export interface AuditLogCountResponse {
8186
readonly count: number

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy