From acf1ad3bfd513b389a4e519cdd47d951aa22501d Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Mon, 24 Oct 2022 22:58:06 +0000 Subject: [PATCH 1/8] added test for stopping a workspace build --- coderd/workspacebuilds_test.go | 4 ++++ docs/admin/audit-logs.md | 1 + 2 files changed, 5 insertions(+) diff --git a/coderd/workspacebuilds_test.go b/coderd/workspacebuilds_test.go index 983063a1907bc..1c7f2abf1f141 100644 --- a/coderd/workspacebuilds_test.go +++ b/coderd/workspacebuilds_test.go @@ -561,6 +561,10 @@ func TestWorkspaceBuildStatus(t *testing.T) { require.NoError(t, err) require.EqualValues(t, codersdk.WorkspaceStatusStopped, workspace.LatestBuild.Status) + // assert an audit log has been created for workspace stopping + require.Len(t, auditor.AuditLogs, 5) + assert.Equal(t, database.AuditActionStop, auditor.AuditLogs[4].Action) + _ = closeDaemon.Close() // after successful cancel is "canceled" build = coderdtest.CreateWorkspaceBuild(t, client, workspace, database.WorkspaceTransitionStart) diff --git a/docs/admin/audit-logs.md b/docs/admin/audit-logs.md index d7179c7ee590c..7ecd5142cb660 100644 --- a/docs/admin/audit-logs.md +++ b/docs/admin/audit-logs.md @@ -11,6 +11,7 @@ We track **create, update and delete** events for the following resources: - Template - TemplateVersion - Workspace +- Workspace start/stop - User - Group From c50db185f03253ab43d78c242e3fecf67da42f1d Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Wed, 26 Oct 2022 15:26:43 +0000 Subject: [PATCH 2/8] formatted sfriendly string; added tests --- coderd/audit.go | 4 +++- coderd/audit/request.go | 2 +- coderd/workspacebuilds_test.go | 23 +++++++++++++++---- .../AuditLogRow/AuditLogRow.stories.tsx | 11 ++++++++- .../components/AuditLogRow/AuditLogRow.tsx | 8 +++++++ site/src/testHelpers/entities.ts | 9 ++++++++ 6 files changed, 50 insertions(+), 7 deletions(-) diff --git a/coderd/audit.go b/coderd/audit.go index ba845c8b048b0..4f2c28aff4912 100644 --- a/coderd/audit.go +++ b/coderd/audit.go @@ -241,7 +241,9 @@ func auditLogDescription(alog database.GetAuditLogsOffsetRow) string { // We don't display the name for git ssh keys. It's fairly long and doesn't // make too much sense to display. - if alog.ResourceType != database.ResourceTypeGitSshKey { + + // The UI-visible target for workspace builds is workspace (see above block) so we don't add it to the friendly string + if alog.ResourceType != database.ResourceTypeGitSshKey && alog.ResourceType != database.ResourceTypeWorkspaceBuild { str += " {target}" } diff --git a/coderd/audit/request.go b/coderd/audit/request.go index efba7ebb4304b..ef15611fa8de2 100644 --- a/coderd/audit/request.go +++ b/coderd/audit/request.go @@ -46,7 +46,7 @@ func ResourceTarget[T Auditable](tgt T) string { return typed.Name case database.WorkspaceBuild: // this isn't used - return string(typed.BuildNumber) + return "" case database.GitSSHKey: return typed.PublicKey case database.Group: diff --git a/coderd/workspacebuilds_test.go b/coderd/workspacebuilds_test.go index a758bb712ce24..3d152932bf866 100644 --- a/coderd/workspacebuilds_test.go +++ b/coderd/workspacebuilds_test.go @@ -536,13 +536,20 @@ func TestWorkspaceBuildStatus(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong) defer cancel() auditor := audit.NewMock() + numLogs := len(auditor.AuditLogs) client, closeDaemon, api := coderdtest.NewWithAPI(t, &coderdtest.Options{IncludeProvisionerDaemon: true, Auditor: auditor}) user := coderdtest.CreateFirstUser(t, client) + numLogs++ // add an audit log for user version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil) + numLogs++ // add an audit log for template version + coderdtest.AwaitTemplateVersionJob(t, client, version.ID) closeDaemon.Close() template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) + numLogs++ // add an audit log for template creation + workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) + numLogs++ // add an audit log for workspace creation // initial returned state is "pending" require.EqualValues(t, codersdk.WorkspaceStatusPending, workspace.LatestBuild.Status) @@ -562,14 +569,21 @@ func TestWorkspaceBuildStatus(t *testing.T) { require.EqualValues(t, codersdk.WorkspaceStatusStopped, workspace.LatestBuild.Status) // assert an audit log has been created for workspace stopping - require.Len(t, auditor.AuditLogs, 5) - assert.Equal(t, database.AuditActionStop, auditor.AuditLogs[4].Action) + numLogs++ // add an audit log for workspace_build stop + require.Len(t, auditor.AuditLogs, numLogs) + require.Equal(t, database.AuditActionStop, auditor.AuditLogs[numLogs-1].Action) _ = closeDaemon.Close() // after successful cancel is "canceled" build = coderdtest.CreateWorkspaceBuild(t, client, workspace, database.WorkspaceTransitionStart) err = client.CancelWorkspaceBuild(ctx, build.ID) require.NoError(t, err) + + numLogs++ // add an audit log for workspace build start + // assert an audit log has been created workspace starting + require.Len(t, auditor.AuditLogs, numLogs) + require.Equal(t, database.AuditActionStart, auditor.AuditLogs[numLogs-1].Action) + workspace, err = client.Workspace(ctx, workspace.ID) require.NoError(t, err) require.EqualValues(t, codersdk.WorkspaceStatusCanceled, workspace.LatestBuild.Status) @@ -581,8 +595,9 @@ func TestWorkspaceBuildStatus(t *testing.T) { workspace, err = client.DeletedWorkspace(ctx, workspace.ID) require.NoError(t, err) require.EqualValues(t, codersdk.WorkspaceStatusDeleted, workspace.LatestBuild.Status) + numLogs++ // add an audit log for workspace build deletion // assert an audit log has been created for deletion - require.Len(t, auditor.AuditLogs, 7) - assert.Equal(t, database.AuditActionDelete, auditor.AuditLogs[6].Action) + require.Len(t, auditor.AuditLogs, numLogs) + require.Equal(t, database.AuditActionDelete, auditor.AuditLogs[numLogs-1].Action) } diff --git a/site/src/components/AuditLogRow/AuditLogRow.stories.tsx b/site/src/components/AuditLogRow/AuditLogRow.stories.tsx index b552b868ac240..9b1239ebe7b82 100644 --- a/site/src/components/AuditLogRow/AuditLogRow.stories.tsx +++ b/site/src/components/AuditLogRow/AuditLogRow.stories.tsx @@ -5,7 +5,11 @@ import TableContainer from "@material-ui/core/TableContainer" import TableHead from "@material-ui/core/TableHead" import TableRow from "@material-ui/core/TableRow" import { ComponentMeta, Story } from "@storybook/react" -import { MockAuditLog, MockAuditLog2 } from "testHelpers/entities" +import { + MockAuditLog, + MockAuditLog2, + MockAuditLogWithWorkspaceBuild, +} from "testHelpers/entities" import { AuditLogRow, AuditLogRowProps } from "./AuditLogRow" export default { @@ -38,3 +42,8 @@ WithDiff.args = { auditLog: MockAuditLog2, defaultIsDiffOpen: true, } + +export const WithWorkspaceBuild = Template.bind({}) +WithWorkspaceBuild.args = { + auditLog: MockAuditLogWithWorkspaceBuild, +} diff --git a/site/src/components/AuditLogRow/AuditLogRow.tsx b/site/src/components/AuditLogRow/AuditLogRow.tsx index 478c01e05aa19..e330ecfc8da8a 100644 --- a/site/src/components/AuditLogRow/AuditLogRow.tsx +++ b/site/src/components/AuditLogRow/AuditLogRow.tsx @@ -31,6 +31,14 @@ const pillTypeByHttpStatus = ( } const readableActionMessage = (auditLog: AuditLog) => { + // workspace builds audit logs don't have targets; therefore format them differently + if (auditLog.resource_type === "workspace_build") { + const substr = auditLog.description.trim().split(" ").pop() ?? "" + return auditLog.description + .replace("{user}", `${auditLog.user?.username}`) + .replace(substr, `${substr}`) + } + return auditLog.description .replace("{user}", `${auditLog.user?.username}`) .replace("{target}", `${auditLog.resource_target}`) diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts index d02f8bfd5b60f..a910f7b51c916 100644 --- a/site/src/testHelpers/entities.ts +++ b/site/src/testHelpers/entities.ts @@ -949,6 +949,15 @@ export const MockAuditLog2: TypesGen.AuditLog = { }, } +export const MockAuditLogWithWorkspaceBuild: TypesGen.AuditLog = { + ...MockAuditLog, + id: "f90995bf-4a2b-4089-b597-e66e025e523e", + request_id: "61555889-2875-475c-8494-f7693dd5d75b", + action: "stop", + resource_type: "workspace_build", + description: "{user} stopped workspace build for workspace test2", +} + export const MockWorkspaceQuota: TypesGen.WorkspaceQuota = { user_workspace_count: 0, user_workspace_limit: 100, From fdc94d8295d0f6786f286c6a972be525c0170434 Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Wed, 26 Oct 2022 15:50:51 +0000 Subject: [PATCH 3/8] logging unmarshal error in auditLogDescription --- coderd/audit.go | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/coderd/audit.go b/coderd/audit.go index 4f2c28aff4912..b1e399f6a9149 100644 --- a/coderd/audit.go +++ b/coderd/audit.go @@ -1,6 +1,7 @@ package coderd import ( + "context" "encoding/json" "fmt" "net" @@ -13,6 +14,7 @@ import ( "github.com/google/uuid" "github.com/tabbed/pqtype" + "cdr.dev/slog" "github.com/coder/coder/coderd/database" "github.com/coder/coder/coderd/httpapi" "github.com/coder/coder/coderd/httpmw" @@ -57,7 +59,7 @@ func (api *API) auditLogs(rw http.ResponseWriter, r *http.Request) { } httpapi.Write(ctx, rw, http.StatusOK, codersdk.AuditLogResponse{ - AuditLogs: convertAuditLogs(dblogs), + AuditLogs: api.convertAuditLogs(ctx, dblogs), }) } @@ -165,17 +167,17 @@ func (api *API) generateFakeAuditLog(rw http.ResponseWriter, r *http.Request) { rw.WriteHeader(http.StatusNoContent) } -func convertAuditLogs(dblogs []database.GetAuditLogsOffsetRow) []codersdk.AuditLog { +func (api *API) convertAuditLogs(ctx context.Context, dblogs []database.GetAuditLogsOffsetRow) []codersdk.AuditLog { alogs := make([]codersdk.AuditLog, 0, len(dblogs)) for _, dblog := range dblogs { - alogs = append(alogs, convertAuditLog(dblog)) + alogs = append(alogs, api.convertAuditLog(ctx, dblog)) } return alogs } -func convertAuditLog(dblog database.GetAuditLogsOffsetRow) codersdk.AuditLog { +func (api *API) convertAuditLog(ctx context.Context, dblog database.GetAuditLogsOffsetRow) codersdk.AuditLog { ip, _ := netip.AddrFromSlice(dblog.Ip.IPNet.IP) diff := codersdk.AuditDiff{} @@ -214,7 +216,7 @@ func convertAuditLog(dblog database.GetAuditLogsOffsetRow) codersdk.AuditLog { Diff: diff, StatusCode: dblog.StatusCode, AdditionalFields: dblog.AdditionalFields, - Description: auditLogDescription(dblog), + Description: api.auditLogDescription(ctx, dblog), User: user, } } @@ -223,7 +225,7 @@ type WorkspaceResourceInfo struct { WorkspaceName string } -func auditLogDescription(alog database.GetAuditLogsOffsetRow) string { +func (api *API) auditLogDescription(ctx context.Context, alog database.GetAuditLogsOffsetRow) string { str := fmt.Sprintf("{user} %s %s", codersdk.AuditAction(alog.Action).FriendlyString(), codersdk.ResourceType(alog.ResourceType).FriendlyString(), @@ -235,7 +237,10 @@ func auditLogDescription(alog database.GetAuditLogsOffsetRow) string { if alog.ResourceType == database.ResourceTypeWorkspaceBuild { workspaceBytes := []byte(alog.AdditionalFields) var workspaceResourceInfo WorkspaceResourceInfo - _ = json.Unmarshal(workspaceBytes, &workspaceResourceInfo) + err := json.Unmarshal(workspaceBytes, &workspaceResourceInfo) + if err != nil { + api.Logger.Error(ctx, "could not unmarshal workspace name for friendly string", slog.Error(err)) + } str += " for workspace " + workspaceResourceInfo.WorkspaceName } From 93aedaff54805ed761e0293419270644ce15d2af Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Wed, 26 Oct 2022 15:57:50 +0000 Subject: [PATCH 4/8] prettier --- site/src/testHelpers/entities.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts index a910f7b51c916..62e9c7804313f 100644 --- a/site/src/testHelpers/entities.ts +++ b/site/src/testHelpers/entities.ts @@ -950,12 +950,12 @@ export const MockAuditLog2: TypesGen.AuditLog = { } export const MockAuditLogWithWorkspaceBuild: TypesGen.AuditLog = { - ...MockAuditLog, - id: "f90995bf-4a2b-4089-b597-e66e025e523e", - request_id: "61555889-2875-475c-8494-f7693dd5d75b", - action: "stop", - resource_type: "workspace_build", - description: "{user} stopped workspace build for workspace test2", + ...MockAuditLog, + id: "f90995bf-4a2b-4089-b597-e66e025e523e", + request_id: "61555889-2875-475c-8494-f7693dd5d75b", + action: "stop", + resource_type: "workspace_build", + description: "{user} stopped workspace build for workspace test2", } export const MockWorkspaceQuota: TypesGen.WorkspaceQuota = { From 1a9936f03717c6a97b65c0aa87682b458335ef5e Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Wed, 26 Oct 2022 16:35:17 +0000 Subject: [PATCH 5/8] got rid of extra workspace word --- coderd/audit.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/coderd/audit.go b/coderd/audit.go index b1e399f6a9149..e90d78f6e27a3 100644 --- a/coderd/audit.go +++ b/coderd/audit.go @@ -232,7 +232,7 @@ func (api *API) auditLogDescription(ctx context.Context, alog database.GetAuditL ) // Strings for build updates follow the below format: - // "{user} started workspace build for workspace {target}" + // "{user} started workspace build for {target}" // where target is a workspace instead of the workspace build if alog.ResourceType == database.ResourceTypeWorkspaceBuild { workspaceBytes := []byte(alog.AdditionalFields) @@ -241,7 +241,7 @@ func (api *API) auditLogDescription(ctx context.Context, alog database.GetAuditL if err != nil { api.Logger.Error(ctx, "could not unmarshal workspace name for friendly string", slog.Error(err)) } - str += " for workspace " + workspaceResourceInfo.WorkspaceName + str += " for " + workspaceResourceInfo.WorkspaceName } // We don't display the name for git ssh keys. It's fairly long and doesn't From 3e4cb891fd0ee99293dd676fb71c0ab86435f075 Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Thu, 27 Oct 2022 15:13:59 +0000 Subject: [PATCH 6/8] PR feedback --- coderd/audit.go | 3 ++- .../components/AuditLogRow/AuditLogRow.tsx | 25 +++++++++++++++---- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/coderd/audit.go b/coderd/audit.go index e90d78f6e27a3..3e011dc6616ae 100644 --- a/coderd/audit.go +++ b/coderd/audit.go @@ -233,7 +233,8 @@ func (api *API) auditLogDescription(ctx context.Context, alog database.GetAuditL // Strings for build updates follow the below format: // "{user} started workspace build for {target}" - // where target is a workspace instead of the workspace build + // where target is a workspace instead of the workspace build. + // Note the workspace name will be bolded on the FE. if alog.ResourceType == database.ResourceTypeWorkspaceBuild { workspaceBytes := []byte(alog.AdditionalFields) var workspaceResourceInfo WorkspaceResourceInfo diff --git a/site/src/components/AuditLogRow/AuditLogRow.tsx b/site/src/components/AuditLogRow/AuditLogRow.tsx index e330ecfc8da8a..3452222cf969b 100644 --- a/site/src/components/AuditLogRow/AuditLogRow.tsx +++ b/site/src/components/AuditLogRow/AuditLogRow.tsx @@ -30,13 +30,26 @@ const pillTypeByHttpStatus = ( return "success" } -const readableActionMessage = (auditLog: AuditLog) => { +// the BE returns additional_field as a string, since it's stored as JSON but +// technically, it's a map, so we adjust the type here. +type ExtendedAuditLog = Omit & { + additional_fields: Record +} + +const readableActionMessage = (auditLog: ExtendedAuditLog) => { // workspace builds audit logs don't have targets; therefore format them differently if (auditLog.resource_type === "workspace_build") { - const substr = auditLog.description.trim().split(" ").pop() ?? "" - return auditLog.description + // remove the "{target}" identifier in the string description as we don't use it + const amendedDescription = auditLog.description.substring( + 0, + auditLog.description.lastIndexOf(" "), + ) + return amendedDescription .replace("{user}", `${auditLog.user?.username}`) - .replace(substr, `${substr}`) + .replace( + auditLog.additional_fields.workspaceName, + `${auditLog.additional_fields.workspaceName}`, + ) } return auditLog.description @@ -101,7 +114,9 @@ export const AuditLogRow: React.FC = ({ From dc7e4a969395fecfc0ab8e3f560d4dcf465d7ea1 Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Thu, 27 Oct 2022 18:46:01 +0000 Subject: [PATCH 7/8] fixed mistake; wrote tests in penance --- site/src/api/typesGenerated.ts | 3 +- .../AuditLogRow/AuditLogRow.test.tsx | 41 +++++++++++++++++++ .../components/AuditLogRow/AuditLogRow.tsx | 28 +++---------- site/src/testHelpers/entities.ts | 7 +++- 4 files changed, 53 insertions(+), 26 deletions(-) create mode 100644 site/src/components/AuditLogRow/AuditLogRow.test.tsx diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index c006c13928eef..7a3bf62d1c6af 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -65,8 +65,7 @@ export interface AuditLog { readonly action: AuditAction readonly diff: AuditDiff readonly status_code: number - // This is likely an enum in an external package ("encoding/json.RawMessage") - readonly additional_fields: string + readonly additional_fields: Record readonly description: string readonly user?: User } diff --git a/site/src/components/AuditLogRow/AuditLogRow.test.tsx b/site/src/components/AuditLogRow/AuditLogRow.test.tsx new file mode 100644 index 0000000000000..3ee13f46e4bc0 --- /dev/null +++ b/site/src/components/AuditLogRow/AuditLogRow.test.tsx @@ -0,0 +1,41 @@ +import { readableActionMessage } from "./AuditLogRow" +import { + MockAuditLog, + MockAuditLogWithWorkspaceBuild, +} from "testHelpers/entities" + +describe("readableActionMessage()", () => { + it("renders the correct string for a workspaceBuild audit log", async () => { + // When + const friendlyString = readableActionMessage(MockAuditLogWithWorkspaceBuild) + + // Then + expect(friendlyString).toBe( + "TestUser stopped workspace build for test2", + ) + }) + it("renders the correct string for a workspaceBuild audit log with a duplicate word", async () => { + // When + const AuditLogWithRepeat = { + ...MockAuditLogWithWorkspaceBuild, + additional_fields: { + workspaceName: "workspace", + }, + } + const friendlyString = readableActionMessage(AuditLogWithRepeat) + + // Then + expect(friendlyString).toBe( + "TestUser stopped workspace build for workspace", + ) + }) + it("renders the correct string for a workspace audit log", async () => { + // When + const friendlyString = readableActionMessage(MockAuditLog) + + // Then + expect(friendlyString).toBe( + "TestUser updated workspace bruno-dev", + ) + }) +}) diff --git a/site/src/components/AuditLogRow/AuditLogRow.tsx b/site/src/components/AuditLogRow/AuditLogRow.tsx index 8bd27fa4bbeb5..c00d1564d5c95 100644 --- a/site/src/components/AuditLogRow/AuditLogRow.tsx +++ b/site/src/components/AuditLogRow/AuditLogRow.tsx @@ -16,31 +16,17 @@ import userAgentParser from "ua-parser-js" import { combineClasses } from "util/combineClasses" import { AuditLogDiff } from "./AuditLogDiff" -// the BE returns additional_field as a string, since it's stored as JSON but -// technically, it's a map, so we adjust the type here. -type ExtendedAuditLog = Omit & { - additional_fields: Record -} +export const readableActionMessage = (auditLog: AuditLog): string => { + let target = auditLog.resource_target.trim() -const readableActionMessage = (auditLog: ExtendedAuditLog) => { - // workspace builds audit logs don't have targets; therefore format them differently + // audit logs with a resource_type of workspace build use workspace name as a target if (auditLog.resource_type === "workspace_build") { - // remove the "{target}" identifier in the string description as we don't use it - const amendedDescription = auditLog.description.substring( - 0, - auditLog.description.lastIndexOf(" "), - ) - return amendedDescription - .replace("{user}", `${auditLog.user?.username}`) - .replace( - auditLog.additional_fields.workspaceName, - `${auditLog.additional_fields.workspaceName}`, - ) + target = auditLog.additional_fields.workspaceName.trim() } return auditLog.description .replace("{user}", `${auditLog.user?.username.trim()}`) - .replace("{target}", `${auditLog.resource_target.trim()}`) + .replace("{target}", `${target}`) } const httpStatusColor = (httpStatus: number): PaletteIndex => { @@ -132,9 +118,7 @@ export const AuditLogRow: React.FC = ({ > diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts index 62e9c7804313f..704871496c79c 100644 --- a/site/src/testHelpers/entities.ts +++ b/site/src/testHelpers/entities.ts @@ -916,7 +916,7 @@ export const MockAuditLog: TypesGen.AuditLog = { }, }, status_code: 200, - additional_fields: "", + additional_fields: {}, description: "{user} updated workspace {target}", user: MockUser, } @@ -955,7 +955,10 @@ export const MockAuditLogWithWorkspaceBuild: TypesGen.AuditLog = { request_id: "61555889-2875-475c-8494-f7693dd5d75b", action: "stop", resource_type: "workspace_build", - description: "{user} stopped workspace build for workspace test2", + description: "{user} stopped workspace build for {target}", + additional_fields: { + "workspaceName": "test2" + }, } export const MockWorkspaceQuota: TypesGen.WorkspaceQuota = { From ac68b3cb150dc2424ef5129965070bce8d247f6d Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Thu, 27 Oct 2022 18:50:00 +0000 Subject: [PATCH 8/8] fix be --- coderd/audit.go | 36 ++++++++++---------------------- scripts/apitypings/main.go | 2 ++ site/src/testHelpers/entities.ts | 2 +- 3 files changed, 14 insertions(+), 26 deletions(-) diff --git a/coderd/audit.go b/coderd/audit.go index 3e011dc6616ae..1a8f0e79b8b8e 100644 --- a/coderd/audit.go +++ b/coderd/audit.go @@ -1,7 +1,6 @@ package coderd import ( - "context" "encoding/json" "fmt" "net" @@ -14,7 +13,6 @@ import ( "github.com/google/uuid" "github.com/tabbed/pqtype" - "cdr.dev/slog" "github.com/coder/coder/coderd/database" "github.com/coder/coder/coderd/httpapi" "github.com/coder/coder/coderd/httpmw" @@ -59,7 +57,7 @@ func (api *API) auditLogs(rw http.ResponseWriter, r *http.Request) { } httpapi.Write(ctx, rw, http.StatusOK, codersdk.AuditLogResponse{ - AuditLogs: api.convertAuditLogs(ctx, dblogs), + AuditLogs: convertAuditLogs(dblogs), }) } @@ -167,17 +165,17 @@ func (api *API) generateFakeAuditLog(rw http.ResponseWriter, r *http.Request) { rw.WriteHeader(http.StatusNoContent) } -func (api *API) convertAuditLogs(ctx context.Context, dblogs []database.GetAuditLogsOffsetRow) []codersdk.AuditLog { +func convertAuditLogs(dblogs []database.GetAuditLogsOffsetRow) []codersdk.AuditLog { alogs := make([]codersdk.AuditLog, 0, len(dblogs)) for _, dblog := range dblogs { - alogs = append(alogs, api.convertAuditLog(ctx, dblog)) + alogs = append(alogs, convertAuditLog(dblog)) } return alogs } -func (api *API) convertAuditLog(ctx context.Context, dblog database.GetAuditLogsOffsetRow) codersdk.AuditLog { +func convertAuditLog(dblog database.GetAuditLogsOffsetRow) codersdk.AuditLog { ip, _ := netip.AddrFromSlice(dblog.Ip.IPNet.IP) diff := codersdk.AuditDiff{} @@ -216,40 +214,28 @@ func (api *API) convertAuditLog(ctx context.Context, dblog database.GetAuditLogs Diff: diff, StatusCode: dblog.StatusCode, AdditionalFields: dblog.AdditionalFields, - Description: api.auditLogDescription(ctx, dblog), + Description: auditLogDescription(dblog), User: user, } } -type WorkspaceResourceInfo struct { - WorkspaceName string -} - -func (api *API) auditLogDescription(ctx context.Context, alog database.GetAuditLogsOffsetRow) string { +func auditLogDescription(alog database.GetAuditLogsOffsetRow) string { str := fmt.Sprintf("{user} %s %s", codersdk.AuditAction(alog.Action).FriendlyString(), codersdk.ResourceType(alog.ResourceType).FriendlyString(), ) - // Strings for build updates follow the below format: + // Strings for workspace_builds follow the below format: // "{user} started workspace build for {target}" - // where target is a workspace instead of the workspace build. - // Note the workspace name will be bolded on the FE. + // where target is a workspace instead of the workspace build, + // passed in on the FE via AuditLog.AdditionalFields rather than derived in request.go:35 if alog.ResourceType == database.ResourceTypeWorkspaceBuild { - workspaceBytes := []byte(alog.AdditionalFields) - var workspaceResourceInfo WorkspaceResourceInfo - err := json.Unmarshal(workspaceBytes, &workspaceResourceInfo) - if err != nil { - api.Logger.Error(ctx, "could not unmarshal workspace name for friendly string", slog.Error(err)) - } - str += " for " + workspaceResourceInfo.WorkspaceName + str += " for" } // We don't display the name for git ssh keys. It's fairly long and doesn't // make too much sense to display. - - // The UI-visible target for workspace builds is workspace (see above block) so we don't add it to the friendly string - if alog.ResourceType != database.ResourceTypeGitSshKey && alog.ResourceType != database.ResourceTypeWorkspaceBuild { + if alog.ResourceType != database.ResourceTypeGitSshKey { str += " {target}" } diff --git a/scripts/apitypings/main.go b/scripts/apitypings/main.go index 20ff1ba1f8250..5d27695fc6d43 100644 --- a/scripts/apitypings/main.go +++ b/scripts/apitypings/main.go @@ -688,6 +688,8 @@ func (g *Generator) typescriptType(ty types.Type) (TypescriptType, error) { return TypescriptType{ValueType: "string", Optional: true}, nil case "github.com/google/uuid.UUID": return TypescriptType{ValueType: "string"}, nil + case "encoding/json.RawMessage": + return TypescriptType{ValueType: "Record"}, nil } // Then see if the type is defined elsewhere. If it is, we can just diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts index 704871496c79c..d4670f66baead 100644 --- a/site/src/testHelpers/entities.ts +++ b/site/src/testHelpers/entities.ts @@ -957,7 +957,7 @@ export const MockAuditLogWithWorkspaceBuild: TypesGen.AuditLog = { resource_type: "workspace_build", description: "{user} stopped workspace build for {target}", additional_fields: { - "workspaceName": "test2" + workspaceName: "test2", }, }