From 1f0cb46fa43ddf50cbf4d0a869f5ae5449cc0a87 Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Fri, 28 Oct 2022 22:00:04 +0000 Subject: [PATCH 01/10] sql query --- coderd/audit.go | 10 ++++++++++ coderd/database/queries.sql.go | 10 +++++++++- coderd/database/queries/auditlogs.sql | 8 +++++++- enterprise/audit/table.go | 5 +++-- site/src/api/api.ts | 2 ++ 5 files changed, 31 insertions(+), 4 deletions(-) diff --git a/coderd/audit.go b/coderd/audit.go index ba845c8b048b0..5a2d587ec228a 100644 --- a/coderd/audit.go +++ b/coderd/audit.go @@ -34,6 +34,8 @@ func (api *API) auditLogs(rw http.ResponseWriter, r *http.Request) { queryStr := r.URL.Query().Get("q") filter, errs := auditSearchQuery(queryStr) + fmt.Println("BLOOP FILTER", filter) + if len(errs) > 0 { httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ Message: "Invalid audit search query.", @@ -50,6 +52,7 @@ func (api *API) auditLogs(rw http.ResponseWriter, r *http.Request) { Action: filter.Action, Username: filter.Username, Email: filter.Email, + TimeFrom: filter.TimeFrom, }) if err != nil { httpapi.InternalServerError(rw, err) @@ -257,12 +260,17 @@ func auditSearchQuery(query string) (database.GetAuditLogsOffsetParams, []coders return database.GetAuditLogsOffsetParams{}, nil } query = strings.ToLower(query) + fmt.Println("KIRA query", query) // Because we do this in 2 passes, we want to maintain quotes on the first // pass.Further splitting occurs on the second pass and quotes will be // dropped. elements := splitQueryParameterByDelimiter(query, ' ', true) + fmt.Println("MARGE elements", elements) + for _, element := range elements { parts := splitQueryParameterByDelimiter(element, ':', false) + fmt.Println("MARGOT parts", parts) + switch len(parts) { case 1: // No key:value pair. @@ -285,6 +293,8 @@ func auditSearchQuery(query string) (database.GetAuditLogsOffsetParams, []coders Action: actionFromString(parser.String(searchParams, "", "action")), Username: parser.String(searchParams, "", "username"), Email: parser.String(searchParams, "", "email"), + TimeFrom: time.Date( + 2022, 10, 27, 00, 00, 00, 000000000, time.UTC), } return filter, parser.Errors diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go index b99d651016fb3..56e6d9f83b891 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -441,7 +441,7 @@ SELECT users.avatar_url AS user_avatar_url FROM audit_logs -LEFT JOIN +LEFT JOIN users ON audit_logs.user_id = users.id WHERE -- Filter resource_type @@ -480,6 +480,12 @@ WHERE users.email = $8 ELSE true END + -- Filter by time_from + AND CASE + WHEN $9 :: timestamp with time zone != '0001-01-01 00:00:00' THEN + "time" > $9 + ELSE true + END ORDER BY "time" DESC LIMIT @@ -497,6 +503,7 @@ type GetAuditLogsOffsetParams struct { Action string `db:"action" json:"action"` Username string `db:"username" json:"username"` Email string `db:"email" json:"email"` + TimeFrom time.Time `db:"time_from" json:"time_from"` } type GetAuditLogsOffsetRow struct { @@ -535,6 +542,7 @@ func (q *sqlQuerier) GetAuditLogsOffset(ctx context.Context, arg GetAuditLogsOff arg.Action, arg.Username, arg.Email, + arg.TimeFrom, ) if err != nil { return nil, err diff --git a/coderd/database/queries/auditlogs.sql b/coderd/database/queries/auditlogs.sql index 5cb8e93db4876..973006bf3191d 100644 --- a/coderd/database/queries/auditlogs.sql +++ b/coderd/database/queries/auditlogs.sql @@ -11,7 +11,7 @@ SELECT users.avatar_url AS user_avatar_url FROM audit_logs -LEFT JOIN +LEFT JOIN users ON audit_logs.user_id = users.id WHERE -- Filter resource_type @@ -50,6 +50,12 @@ WHERE users.email = @email ELSE true END + -- Filter by time_from + AND CASE + WHEN @time_from :: timestamp with time zone != '0001-01-01 00:00:00' THEN + "time" > @time_from + ELSE true + END ORDER BY "time" DESC LIMIT diff --git a/enterprise/audit/table.go b/enterprise/audit/table.go index 241f53b024c4b..2578ae7437844 100644 --- a/enterprise/audit/table.go +++ b/enterprise/audit/table.go @@ -109,13 +109,14 @@ var AuditableResources = auditMap(map[any]map[string]Action{ "organization_id": ActionIgnore, // Never changes. "avatar_url": ActionTrack, }, - // We don't show any diff for the WorkspaceBuild resource + // We don't show any diff for the WorkspaceBuild resource, + // save for the template_version_id &database.WorkspaceBuild{}: { "id": ActionIgnore, "created_at": ActionIgnore, "updated_at": ActionIgnore, "workspace_id": ActionIgnore, - "template_version_id": ActionIgnore, + "template_version_id": ActionTrack, "build_number": ActionIgnore, "transition": ActionIgnore, "initiator_id": ActionIgnore, diff --git a/site/src/api/api.ts b/site/src/api/api.ts index 8bb9303f97fa2..9d104c7f0da5a 100644 --- a/site/src/api/api.ts +++ b/site/src/api/api.ts @@ -563,8 +563,10 @@ export const getAuditLogs = async ( searchParams.set("offset", options.offset.toString()) } if (options.q) { + console.log('q', options.q) searchParams.set("q", options.q) } + console.log('searchParams', searchParams) const response = await axios.get(`/api/v2/audit?${searchParams.toString()}`) return response.data From 4886a91179b84db1d3e8207f130878e2001963c3 Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Fri, 28 Oct 2022 23:40:28 +0000 Subject: [PATCH 02/10] added time_to --- coderd/audit.go | 32 +++++++++++++++++---------- coderd/database/queries.sql.go | 10 ++++++++- coderd/database/queries/auditlogs.sql | 8 ++++++- 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/coderd/audit.go b/coderd/audit.go index 5a2d587ec228a..5f70a83fe3797 100644 --- a/coderd/audit.go +++ b/coderd/audit.go @@ -260,16 +260,13 @@ func auditSearchQuery(query string) (database.GetAuditLogsOffsetParams, []coders return database.GetAuditLogsOffsetParams{}, nil } query = strings.ToLower(query) - fmt.Println("KIRA query", query) // Because we do this in 2 passes, we want to maintain quotes on the first // pass.Further splitting occurs on the second pass and quotes will be // dropped. elements := splitQueryParameterByDelimiter(query, ' ', true) - fmt.Println("MARGE elements", elements) for _, element := range elements { parts := splitQueryParameterByDelimiter(element, ':', false) - fmt.Println("MARGOT parts", parts) switch len(parts) { case 1: @@ -287,15 +284,26 @@ func auditSearchQuery(query string) (database.GetAuditLogsOffsetParams, []coders // Using the query param parser here just returns consistent errors with // other parsing. parser := httpapi.NewQueryParamParser() - filter := database.GetAuditLogsOffsetParams{ - ResourceType: resourceTypeFromString(parser.String(searchParams, "", "resource_type")), - ResourceID: parser.UUID(searchParams, uuid.Nil, "resource_id"), - Action: actionFromString(parser.String(searchParams, "", "action")), - Username: parser.String(searchParams, "", "username"), - Email: parser.String(searchParams, "", "email"), - TimeFrom: time.Date( - 2022, 10, 27, 00, 00, 00, 000000000, time.UTC), - } + const layout = "2006-01-02" + + var ( + timeFromString = parser.String(searchParams, "", "time_from") + timeToString = parser.String(searchParams, "", "time_to") + parsedTimeFrom, _ = time.Parse(layout, timeFromString) + parsedTimeTo, _ = time.Parse(layout, timeToString) + filter = database.GetAuditLogsOffsetParams{ + ResourceType: resourceTypeFromString(parser.String(searchParams, "", "resource_type")), + ResourceID: parser.UUID(searchParams, uuid.Nil, "resource_id"), + Action: actionFromString(parser.String(searchParams, "", "action")), + Username: parser.String(searchParams, "", "username"), + Email: parser.String(searchParams, "", "email"), + TimeFrom: parsedTimeFrom, + TimeTo: parsedTimeTo, + } + ) + + fmt.Println("FROM!", parsedTimeFrom) + fmt.Println("TO!", parsedTimeTo) return filter, parser.Errors } diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go index 56e6d9f83b891..0e4d2a7b615e7 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -483,7 +483,13 @@ WHERE -- Filter by time_from AND CASE WHEN $9 :: timestamp with time zone != '0001-01-01 00:00:00' THEN - "time" > $9 + "time" >= $9 + ELSE true + END + -- Filter by time_to + AND CASE + WHEN $10 :: timestamp with time zone != '0001-01-01 00:00:00' THEN + "time" <= $10 ELSE true END ORDER BY @@ -504,6 +510,7 @@ type GetAuditLogsOffsetParams struct { Username string `db:"username" json:"username"` Email string `db:"email" json:"email"` TimeFrom time.Time `db:"time_from" json:"time_from"` + TimeTo time.Time `db:"time_to" json:"time_to"` } type GetAuditLogsOffsetRow struct { @@ -543,6 +550,7 @@ func (q *sqlQuerier) GetAuditLogsOffset(ctx context.Context, arg GetAuditLogsOff arg.Username, arg.Email, arg.TimeFrom, + arg.TimeTo, ) if err != nil { return nil, err diff --git a/coderd/database/queries/auditlogs.sql b/coderd/database/queries/auditlogs.sql index 973006bf3191d..6da3ce48093a8 100644 --- a/coderd/database/queries/auditlogs.sql +++ b/coderd/database/queries/auditlogs.sql @@ -53,7 +53,13 @@ WHERE -- Filter by time_from AND CASE WHEN @time_from :: timestamp with time zone != '0001-01-01 00:00:00' THEN - "time" > @time_from + "time" >= @time_from + ELSE true + END + -- Filter by time_to + AND CASE + WHEN @time_to :: timestamp with time zone != '0001-01-01 00:00:00' THEN + "time" <= @time_to ELSE true END ORDER BY From 22b53ef3729f67b418500e70eeba3536873adec7 Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Mon, 31 Oct 2022 18:03:58 +0000 Subject: [PATCH 03/10] added validation error --- coderd/audit.go | 36 ++++++++++++++++++--------- coderd/database/queries.sql.go | 12 ++++----- coderd/database/queries/auditlogs.sql | 12 ++++----- site/src/api/api.ts | 2 -- 4 files changed, 36 insertions(+), 26 deletions(-) diff --git a/coderd/audit.go b/coderd/audit.go index 5f70a83fe3797..d89c1f6b1f626 100644 --- a/coderd/audit.go +++ b/coderd/audit.go @@ -34,7 +34,8 @@ func (api *API) auditLogs(rw http.ResponseWriter, r *http.Request) { queryStr := r.URL.Query().Get("q") filter, errs := auditSearchQuery(queryStr) - fmt.Println("BLOOP FILTER", filter) + fmt.Println("FILTER", filter.DateFrom) + fmt.Println("FILTER", filter.DateTo) if len(errs) > 0 { httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ @@ -52,7 +53,8 @@ func (api *API) auditLogs(rw http.ResponseWriter, r *http.Request) { Action: filter.Action, Username: filter.Username, Email: filter.Email, - TimeFrom: filter.TimeFrom, + DateFrom: filter.DateFrom, + DateTo: filter.DateTo, }) if err != nil { httpapi.InternalServerError(rw, err) @@ -287,24 +289,34 @@ func auditSearchQuery(query string) (database.GetAuditLogsOffsetParams, []coders const layout = "2006-01-02" var ( - timeFromString = parser.String(searchParams, "", "time_from") - timeToString = parser.String(searchParams, "", "time_to") - parsedTimeFrom, _ = time.Parse(layout, timeFromString) - parsedTimeTo, _ = time.Parse(layout, timeToString) - filter = database.GetAuditLogsOffsetParams{ + dateFromString = parser.String(searchParams, "", "date_from") + dateToString = parser.String(searchParams, "", "date_to") + parsedDateFrom, _ = time.Parse(layout, dateFromString) + parsedDateTo, _ = time.Parse(layout, dateToString) + ) + + if dateToString != "" { + parsedDateTo = parsedDateTo.Add(23*time.Hour + 59*time.Minute + 59*time.Second) // parsedDateTo goes to 23:59 + } + + if dateToString != "" && parsedDateTo.Before(parsedDateFrom) { + return database.GetAuditLogsOffsetParams{}, []codersdk.ValidationError{ + {Field: "q", Detail: fmt.Sprintf("DateTo value %q cannot be before than DateFrom", parsedDateTo)}, + } + } + + var ( + filter = database.GetAuditLogsOffsetParams{ ResourceType: resourceTypeFromString(parser.String(searchParams, "", "resource_type")), ResourceID: parser.UUID(searchParams, uuid.Nil, "resource_id"), Action: actionFromString(parser.String(searchParams, "", "action")), Username: parser.String(searchParams, "", "username"), Email: parser.String(searchParams, "", "email"), - TimeFrom: parsedTimeFrom, - TimeTo: parsedTimeTo, + DateFrom: parsedDateFrom, + DateTo: parsedDateTo, } ) - fmt.Println("FROM!", parsedTimeFrom) - fmt.Println("TO!", parsedTimeTo) - return filter, parser.Errors } diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go index 0e4d2a7b615e7..bf414db88da0c 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -480,13 +480,13 @@ WHERE users.email = $8 ELSE true END - -- Filter by time_from + -- Filter by date_from AND CASE WHEN $9 :: timestamp with time zone != '0001-01-01 00:00:00' THEN "time" >= $9 ELSE true END - -- Filter by time_to + -- Filter by date_to AND CASE WHEN $10 :: timestamp with time zone != '0001-01-01 00:00:00' THEN "time" <= $10 @@ -509,8 +509,8 @@ type GetAuditLogsOffsetParams struct { Action string `db:"action" json:"action"` Username string `db:"username" json:"username"` Email string `db:"email" json:"email"` - TimeFrom time.Time `db:"time_from" json:"time_from"` - TimeTo time.Time `db:"time_to" json:"time_to"` + DateFrom time.Time `db:"date_from" json:"date_from"` + DateTo time.Time `db:"date_to" json:"date_to"` } type GetAuditLogsOffsetRow struct { @@ -549,8 +549,8 @@ func (q *sqlQuerier) GetAuditLogsOffset(ctx context.Context, arg GetAuditLogsOff arg.Action, arg.Username, arg.Email, - arg.TimeFrom, - arg.TimeTo, + arg.DateFrom, + arg.DateTo, ) if err != nil { return nil, err diff --git a/coderd/database/queries/auditlogs.sql b/coderd/database/queries/auditlogs.sql index 6da3ce48093a8..db87ab3309b65 100644 --- a/coderd/database/queries/auditlogs.sql +++ b/coderd/database/queries/auditlogs.sql @@ -50,16 +50,16 @@ WHERE users.email = @email ELSE true END - -- Filter by time_from + -- Filter by date_from AND CASE - WHEN @time_from :: timestamp with time zone != '0001-01-01 00:00:00' THEN - "time" >= @time_from + WHEN @date_from :: timestamp with time zone != '0001-01-01 00:00:00' THEN + "time" >= @date_from ELSE true END - -- Filter by time_to + -- Filter by date_to AND CASE - WHEN @time_to :: timestamp with time zone != '0001-01-01 00:00:00' THEN - "time" <= @time_to + WHEN @date_to :: timestamp with time zone != '0001-01-01 00:00:00' THEN + "time" <= @date_to ELSE true END ORDER BY diff --git a/site/src/api/api.ts b/site/src/api/api.ts index 9d104c7f0da5a..8bb9303f97fa2 100644 --- a/site/src/api/api.ts +++ b/site/src/api/api.ts @@ -563,10 +563,8 @@ export const getAuditLogs = async ( searchParams.set("offset", options.offset.toString()) } if (options.q) { - console.log('q', options.q) searchParams.set("q", options.q) } - console.log('searchParams', searchParams) const response = await axios.get(`/api/v2/audit?${searchParams.toString()}`) return response.data From 090490283d433e8454d009b325b95fdaa259db6f Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Tue, 1 Nov 2022 17:25:21 +0000 Subject: [PATCH 04/10] documentation --- coderd/audit.go | 2 -- docs/admin/audit-logs.md | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/coderd/audit.go b/coderd/audit.go index d89c1f6b1f626..75328584e93dd 100644 --- a/coderd/audit.go +++ b/coderd/audit.go @@ -34,8 +34,6 @@ func (api *API) auditLogs(rw http.ResponseWriter, r *http.Request) { queryStr := r.URL.Query().Get("q") filter, errs := auditSearchQuery(queryStr) - fmt.Println("FILTER", filter.DateFrom) - fmt.Println("FILTER", filter.DateTo) if len(errs) > 0 { httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ diff --git a/docs/admin/audit-logs.md b/docs/admin/audit-logs.md index d7179c7ee590c..a0b35e3f0e552 100644 --- a/docs/admin/audit-logs.md +++ b/docs/admin/audit-logs.md @@ -29,6 +29,8 @@ The supported filters are: - `action`- The action applied to a resource. You can [find here](https://pkg.go.dev/github.com/coder/coder@main/codersdk#AuditAction) all the actions that are supported. - `username` - The username of the user who triggered the action. - `email` - The email of the user who triggered the action. +- `date_from` - The inclusive start date with format `YYYY-MM-DD`. +- `date_to ` - the inclusive end date with format `YYYY-MM-DD`. ## Enabling this feature From c3f04f5be91ce51e909242528779b995409b7bb4 Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Tue, 1 Nov 2022 19:36:49 +0000 Subject: [PATCH 05/10] attempt to add test --- coderd/audit.go | 5 ++++- coderd/audit_test.go | 8 ++++++++ codersdk/audit.go | 1 + 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/coderd/audit.go b/coderd/audit.go index fc85e31636aca..a432b8fd2a7a3 100644 --- a/coderd/audit.go +++ b/coderd/audit.go @@ -145,10 +145,13 @@ func (api *API) generateFakeAuditLog(rw http.ResponseWriter, r *http.Request) { if params.ResourceID == uuid.Nil { params.ResourceID = uuid.New() } + if params.Time.IsZero() { + params.Time = time.Now() + } _, err = api.Database.InsertAuditLog(ctx, database.InsertAuditLogParams{ ID: uuid.New(), - Time: time.Now(), + Time: params.Time, UserID: user.ID, Ip: ipNet, UserAgent: r.UserAgent(), diff --git a/coderd/audit_test.go b/coderd/audit_test.go index d281a6a97fdac..47c6743503dbf 100644 --- a/coderd/audit_test.go +++ b/coderd/audit_test.go @@ -3,6 +3,7 @@ package coderd_test import ( "context" "testing" + "time" "github.com/google/uuid" "github.com/stretchr/testify/require" @@ -54,12 +55,14 @@ func TestAuditLogsFilter(t *testing.T) { err := client.CreateTestAuditLog(ctx, codersdk.CreateTestAuditLogRequest{ Action: codersdk.AuditActionCreate, ResourceType: codersdk.ResourceTypeTemplate, + Time: time.Date(2022, 8, 15, 14, 30, 45, 100, time.UTC), // 2022-8-15 14:30:45 }) require.NoError(t, err) err = client.CreateTestAuditLog(ctx, codersdk.CreateTestAuditLogRequest{ Action: codersdk.AuditActionCreate, ResourceType: codersdk.ResourceTypeUser, ResourceID: userResourceID, + Time: time.Date(2022, 8, 16, 14, 30, 45, 100, time.UTC), // 2022-8-16 14:30:45 }) require.NoError(t, err) @@ -127,6 +130,11 @@ func TestAuditLogsFilter(t *testing.T) { SearchQuery: "action:invalid", ExpectedResult: 3, }, + { + Name: "FilterWithDateFrom", + SearchQuery: "action:create date_from:2022-08-15 date_to:2022-08-15", + ExpectedResult: 1, + }, } for _, testCase := range testCases { diff --git a/codersdk/audit.go b/codersdk/audit.go index 0fc10f27f05a4..8e77c875aeca5 100644 --- a/codersdk/audit.go +++ b/codersdk/audit.go @@ -127,6 +127,7 @@ type CreateTestAuditLogRequest struct { Action AuditAction `json:"action,omitempty"` ResourceType ResourceType `json:"resource_type,omitempty"` ResourceID uuid.UUID `json:"resource_id,omitempty"` + Time time.Time `json:"time,omitempty"` } // AuditLogs retrieves audit logs from the given page. From 27f04e1eca1e07b06fd3abd9ff4550ecabf490a8 Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Tue, 1 Nov 2022 19:50:45 +0000 Subject: [PATCH 06/10] removed whiitespace --- coderd/audit.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/coderd/audit.go b/coderd/audit.go index a432b8fd2a7a3..71b9b23302d71 100644 --- a/coderd/audit.go +++ b/coderd/audit.go @@ -34,7 +34,6 @@ func (api *API) auditLogs(rw http.ResponseWriter, r *http.Request) { queryStr := r.URL.Query().Get("q") filter, errs := auditSearchQuery(queryStr) - if len(errs) > 0 { httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ Message: "Invalid audit search query.", @@ -261,10 +260,8 @@ func auditSearchQuery(query string) (database.GetAuditLogsOffsetParams, []coders // pass.Further splitting occurs on the second pass and quotes will be // dropped. elements := splitQueryParameterByDelimiter(query, ' ', true) - for _, element := range elements { parts := splitQueryParameterByDelimiter(element, ':', false) - switch len(parts) { case 1: // No key:value pair. From d9eab84cf91879a18f03daa471391dd054d886cc Mon Sep 17 00:00:00 2001 From: Dean Sheather Date: Wed, 2 Nov 2022 14:07:15 +0000 Subject: [PATCH 07/10] fix: ensure date_from and date_to are applied correct audit logs --- coderd/audit.go | 2 ++ coderd/database/databasefake/databasefake.go | 20 ++++++++++++++++++++ coderd/database/queries.sql.go | 18 +++++++++++++++++- coderd/database/queries/auditlogs.sql | 14 +++++++++++++- 4 files changed, 52 insertions(+), 2 deletions(-) diff --git a/coderd/audit.go b/coderd/audit.go index 71b9b23302d71..a974b8854194c 100644 --- a/coderd/audit.go +++ b/coderd/audit.go @@ -86,6 +86,8 @@ func (api *API) auditLogCount(rw http.ResponseWriter, r *http.Request) { Action: filter.Action, Username: filter.Username, Email: filter.Email, + DateFrom: filter.DateFrom, + DateTo: filter.DateTo, }) if err != nil { httpapi.InternalServerError(rw, err) diff --git a/coderd/database/databasefake/databasefake.go b/coderd/database/databasefake/databasefake.go index c6900c316ec1d..c83091fa3e82a 100644 --- a/coderd/database/databasefake/databasefake.go +++ b/coderd/database/databasefake/databasefake.go @@ -2995,6 +2995,16 @@ func (q *fakeQuerier) GetAuditLogsOffset(ctx context.Context, arg database.GetAu continue } } + if arg.DateFrom != (time.Time{}) { + if alog.Time.Before(arg.DateFrom) { + continue + } + } + if arg.DateTo != (time.Time{}) { + if alog.Time.After(arg.DateTo) { + continue + } + } user, err := q.GetUserByID(ctx, alog.UserID) userValid := err == nil @@ -3057,6 +3067,16 @@ func (q *fakeQuerier) GetAuditLogCount(_ context.Context, arg database.GetAuditL continue } } + if arg.DateFrom != (time.Time{}) { + if alog.Time.Before(arg.DateFrom) { + continue + } + } + if arg.DateTo != (time.Time{}) { + if alog.Time.After(arg.DateTo) { + continue + } + } logs = append(logs, alog) } diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go index 854b764f70ec9..2a2cc3cf09936 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -405,6 +405,18 @@ WHERE user_id = (SELECT id from users WHERE users.email = $6 ) ELSE true END + -- Filter by date_from + AND CASE + WHEN $7 :: timestamp with time zone != '0001-01-01 00:00:00' THEN + "time" >= $7 + ELSE true + END + -- Filter by date_to + AND CASE + WHEN $8 :: timestamp with time zone != '0001-01-01 00:00:00' THEN + "time" <= $8 + ELSE true + END ` type GetAuditLogCountParams struct { @@ -414,6 +426,8 @@ type GetAuditLogCountParams struct { Action string `db:"action" json:"action"` Username string `db:"username" json:"username"` Email string `db:"email" json:"email"` + DateFrom time.Time `db:"date_from" json:"date_from"` + DateTo time.Time `db:"date_to" json:"date_to"` } func (q *sqlQuerier) GetAuditLogCount(ctx context.Context, arg GetAuditLogCountParams) (int64, error) { @@ -424,6 +438,8 @@ func (q *sqlQuerier) GetAuditLogCount(ctx context.Context, arg GetAuditLogCountP arg.Action, arg.Username, arg.Email, + arg.DateFrom, + arg.DateTo, ) var count int64 err := row.Scan(&count) @@ -441,7 +457,7 @@ SELECT users.avatar_url AS user_avatar_url FROM audit_logs -LEFT JOIN +LEFT JOIN users ON audit_logs.user_id = users.id WHERE -- Filter resource_type diff --git a/coderd/database/queries/auditlogs.sql b/coderd/database/queries/auditlogs.sql index db87ab3309b65..b9219b264e670 100644 --- a/coderd/database/queries/auditlogs.sql +++ b/coderd/database/queries/auditlogs.sql @@ -11,7 +11,7 @@ SELECT users.avatar_url AS user_avatar_url FROM audit_logs -LEFT JOIN +LEFT JOIN users ON audit_logs.user_id = users.id WHERE -- Filter resource_type @@ -110,6 +110,18 @@ WHERE WHEN @email :: text != '' THEN user_id = (SELECT id from users WHERE users.email = @email ) ELSE true + END + -- Filter by date_from + AND CASE + WHEN @date_from :: timestamp with time zone != '0001-01-01 00:00:00' THEN + "time" >= @date_from + ELSE true + END + -- Filter by date_to + AND CASE + WHEN @date_to :: timestamp with time zone != '0001-01-01 00:00:00' THEN + "time" <= @date_to + ELSE true END; -- name: InsertAuditLog :one From 3fa3a9ac6a7b7e202387f56d32821a00800e5307 Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Wed, 2 Nov 2022 14:44:16 +0000 Subject: [PATCH 08/10] added more tests --- coderd/audit_test.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/coderd/audit_test.go b/coderd/audit_test.go index 47c6743503dbf..13c90bcceb08a 100644 --- a/coderd/audit_test.go +++ b/coderd/audit_test.go @@ -71,6 +71,7 @@ func TestAuditLogsFilter(t *testing.T) { Action: codersdk.AuditActionDelete, ResourceType: codersdk.ResourceTypeUser, ResourceID: userResourceID, + Time: time.Date(2022, 8, 15, 14, 30, 45, 100, time.UTC), // 2022-8-15 14:30:45 }) require.NoError(t, err) @@ -131,10 +132,20 @@ func TestAuditLogsFilter(t *testing.T) { ExpectedResult: 3, }, { - Name: "FilterWithDateFrom", + Name: "FilterOnCreateSingleDay", SearchQuery: "action:create date_from:2022-08-15 date_to:2022-08-15", ExpectedResult: 1, }, + { + Name: "FilterOnCreateDateFrom", + SearchQuery: "action:create date_from:2022-08-15", + ExpectedResult: 2, + }, + { + Name: "FilterOnCreateDateTo", + SearchQuery: "action:create date_to:2022-08-15", + ExpectedResult: 1, + }, } for _, testCase := range testCases { From 9acef91b419f4839a90de515434a0f08e0007b47 Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Wed, 2 Nov 2022 14:45:02 +0000 Subject: [PATCH 09/10] ran make gen --- site/src/api/typesGenerated.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 2c704b1988e85..764aab5c6e761 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -204,6 +204,7 @@ export interface CreateTestAuditLogRequest { readonly action?: AuditAction readonly resource_type?: ResourceType readonly resource_id?: string + readonly time?: string } // From codersdk/apikey.go From 492ec38707e3019ffa4b06e0287ade842e83565d Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Thu, 3 Nov 2022 14:19:21 +0000 Subject: [PATCH 10/10] PR feedback --- coderd/audit.go | 20 +++++++++----------- coderd/database/databasefake/databasefake.go | 8 ++++---- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/coderd/audit.go b/coderd/audit.go index a974b8854194c..d43f804e6a52d 100644 --- a/coderd/audit.go +++ b/coderd/audit.go @@ -299,17 +299,15 @@ func auditSearchQuery(query string) (database.GetAuditLogsOffsetParams, []coders } } - var ( - filter = database.GetAuditLogsOffsetParams{ - ResourceType: resourceTypeFromString(parser.String(searchParams, "", "resource_type")), - ResourceID: parser.UUID(searchParams, uuid.Nil, "resource_id"), - Action: actionFromString(parser.String(searchParams, "", "action")), - Username: parser.String(searchParams, "", "username"), - Email: parser.String(searchParams, "", "email"), - DateFrom: parsedDateFrom, - DateTo: parsedDateTo, - } - ) + filter := database.GetAuditLogsOffsetParams{ + ResourceType: resourceTypeFromString(parser.String(searchParams, "", "resource_type")), + ResourceID: parser.UUID(searchParams, uuid.Nil, "resource_id"), + Action: actionFromString(parser.String(searchParams, "", "action")), + Username: parser.String(searchParams, "", "username"), + Email: parser.String(searchParams, "", "email"), + DateFrom: parsedDateFrom, + DateTo: parsedDateTo, + } return filter, parser.Errors } diff --git a/coderd/database/databasefake/databasefake.go b/coderd/database/databasefake/databasefake.go index c83091fa3e82a..a9117f2b2efca 100644 --- a/coderd/database/databasefake/databasefake.go +++ b/coderd/database/databasefake/databasefake.go @@ -2995,12 +2995,12 @@ func (q *fakeQuerier) GetAuditLogsOffset(ctx context.Context, arg database.GetAu continue } } - if arg.DateFrom != (time.Time{}) { + if !arg.DateFrom.IsZero() { if alog.Time.Before(arg.DateFrom) { continue } } - if arg.DateTo != (time.Time{}) { + if !arg.DateTo.IsZero() { if alog.Time.After(arg.DateTo) { continue } @@ -3067,12 +3067,12 @@ func (q *fakeQuerier) GetAuditLogCount(_ context.Context, arg database.GetAuditL continue } } - if arg.DateFrom != (time.Time{}) { + if !arg.DateFrom.IsZero() { if alog.Time.Before(arg.DateFrom) { continue } } - if arg.DateTo != (time.Time{}) { + if !arg.DateTo.IsZero() { if alog.Time.After(arg.DateTo) { continue }