Skip to content

Commit 3cc86cf

Browse files
authored
chore: implement sane default pagination limit for audit logs (coder#13676)
* chore: implement sane default pagination limit for audit logs
1 parent 1a87771 commit 3cc86cf

File tree

10 files changed

+78
-45
lines changed

10 files changed

+78
-45
lines changed

coderd/audit.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ func (api *API) auditLogs(rw http.ResponseWriter, r *http.Request) {
5353
})
5454
return
5555
}
56-
filter.Offset = int32(page.Offset)
57-
filter.Limit = int32(page.Limit)
56+
filter.OffsetOpt = int32(page.Offset)
57+
filter.LimitOpt = int32(page.Limit)
5858

5959
if filter.Username == "me" {
6060
filter.UserID = apiKey.UserID

coderd/audit_test.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -343,9 +343,6 @@ func TestAuditLogsFilter(t *testing.T) {
343343
t.Parallel()
344344
auditLogs, err := client.AuditLogs(ctx, codersdk.AuditLogsRequest{
345345
SearchQuery: testCase.SearchQuery,
346-
Pagination: codersdk.Pagination{
347-
Limit: 25,
348-
},
349346
})
350347
if testCase.ExpectedError {
351348
require.Error(t, err, "expected error")

coderd/database/dbauthz/dbauthz_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ func (s *MethodTestSuite) TestAuditLogs() {
263263
_ = dbgen.AuditLog(s.T(), db, database.AuditLog{})
264264
_ = dbgen.AuditLog(s.T(), db, database.AuditLog{})
265265
check.Args(database.GetAuditLogsOffsetParams{
266-
Limit: 10,
266+
LimitOpt: 10,
267267
}).Asserts(rbac.ResourceAuditLog, policy.ActionRead)
268268
}))
269269
}

coderd/database/dbgen/dbgen_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ func TestGenerator(t *testing.T) {
1919
t.Parallel()
2020
db := dbmem.New()
2121
_ = dbgen.AuditLog(t, db, database.AuditLog{})
22-
logs := must(db.GetAuditLogsOffset(context.Background(), database.GetAuditLogsOffsetParams{Limit: 1}))
22+
logs := must(db.GetAuditLogsOffset(context.Background(), database.GetAuditLogsOffsetParams{LimitOpt: 1}))
2323
require.Len(t, logs, 1)
2424
})
2525

coderd/database/dbmem/dbmem.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1965,12 +1965,17 @@ func (q *FakeQuerier) GetAuditLogsOffset(_ context.Context, arg database.GetAudi
19651965
q.mutex.RLock()
19661966
defer q.mutex.RUnlock()
19671967

1968-
logs := make([]database.GetAuditLogsOffsetRow, 0, arg.Limit)
1968+
if arg.LimitOpt == 0 {
1969+
// Default to 100 is set in the SQL query.
1970+
arg.LimitOpt = 100
1971+
}
1972+
1973+
logs := make([]database.GetAuditLogsOffsetRow, 0, arg.LimitOpt)
19691974

19701975
// q.auditLogs are already sorted by time DESC, so no need to sort after the fact.
19711976
for _, alog := range q.auditLogs {
1972-
if arg.Offset > 0 {
1973-
arg.Offset--
1977+
if arg.OffsetOpt > 0 {
1978+
arg.OffsetOpt--
19741979
continue
19751980
}
19761981
if arg.OrganizationID != uuid.Nil && arg.OrganizationID != alog.OrganizationID {
@@ -2047,7 +2052,7 @@ func (q *FakeQuerier) GetAuditLogsOffset(_ context.Context, arg database.GetAudi
20472052
Count: 0,
20482053
})
20492054

2050-
if len(logs) >= int(arg.Limit) {
2055+
if len(logs) >= int(arg.LimitOpt) {
20512056
break
20522057
}
20532058
}

coderd/database/querier_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,29 @@ func TestDefaultOrg(t *testing.T) {
516516
require.True(t, all[0].IsDefault, "first org should always be default")
517517
}
518518

519+
func TestAuditLogDefaultLimit(t *testing.T) {
520+
t.Parallel()
521+
if testing.Short() {
522+
t.SkipNow()
523+
}
524+
525+
sqlDB := testSQLDB(t)
526+
err := migrations.Up(sqlDB)
527+
require.NoError(t, err)
528+
db := database.New(sqlDB)
529+
530+
for i := 0; i < 110; i++ {
531+
dbgen.AuditLog(t, db, database.AuditLog{})
532+
}
533+
534+
ctx := testutil.Context(t, testutil.WaitShort)
535+
rows, err := db.GetAuditLogsOffset(ctx, database.GetAuditLogsOffsetParams{})
536+
require.NoError(t, err)
537+
// The length should match the default limit of the SQL query.
538+
// Updating the sql query requires changing the number below to match.
539+
require.Len(t, rows, 100)
540+
}
541+
519542
// TestReadCustomRoles tests the input params returns the correct set of roles.
520543
func TestReadCustomRoles(t *testing.T) {
521544
t.Parallel()

coderd/database/queries.sql.go

Lines changed: 31 additions & 28 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: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,12 @@ WHERE
116116
ORDER BY
117117
"time" DESC
118118
LIMIT
119-
$1
119+
-- a limit of 0 means "no limit". The audit log table is unbounded
120+
-- in size, and is expected to be quite large. Implement a default
121+
-- limit of 100 to prevent accidental excessively large queries.
122+
COALESCE(NULLIF(@limit_opt :: int, 0), 100)
120123
OFFSET
121-
$2;
124+
@offset_opt;
122125

123126
-- name: InsertAuditLog :one
124127
INSERT INTO

coderd/pagination.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ func parsePagination(w http.ResponseWriter, r *http.Request) (p codersdk.Paginat
1717
parser := httpapi.NewQueryParamParser()
1818
params := codersdk.Pagination{
1919
AfterID: parser.UUID(queryParams, uuid.Nil, "after_id"),
20-
Limit: int(parser.PositiveInt32(queryParams, 0, "limit")),
21-
Offset: int(parser.PositiveInt32(queryParams, 0, "offset")),
20+
// A limit of 0 should be interpreted by the SQL query as "null" or
21+
// "no limit". Do not make this value anything besides 0.
22+
Limit: int(parser.PositiveInt32(queryParams, 0, "limit")),
23+
Offset: int(parser.PositiveInt32(queryParams, 0, "offset")),
2224
}
2325
if len(parser.Errors) > 0 {
2426
httpapi.Write(ctx, w, http.StatusBadRequest, codersdk.Response{

enterprise/audit/backends/postgres_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ func TestPostgresBackend(t *testing.T) {
3030
require.NoError(t, err)
3131

3232
got, err := db.GetAuditLogsOffset(ctx, database.GetAuditLogsOffsetParams{
33-
Offset: 0,
34-
Limit: 1,
33+
OffsetOpt: 0,
34+
LimitOpt: 1,
3535
})
3636
require.NoError(t, err)
3737
require.Len(t, got, 1)

0 commit comments

Comments
 (0)