mirror of https://github.com/coder/coder.git
feat: amending audit string to show workspace owner (#5364)
* resolves #5269 * clean up * fixed audit link
This commit is contained in:
parent
66ec98f647
commit
c6ae151f49
|
@ -161,8 +161,9 @@ func (api *API) convertAuditLogs(ctx context.Context, dblogs []database.GetAudit
|
|||
}
|
||||
|
||||
type AdditionalFields struct {
|
||||
WorkspaceName string
|
||||
BuildNumber string
|
||||
WorkspaceName string
|
||||
BuildNumber string
|
||||
WorkspaceOwner string
|
||||
}
|
||||
|
||||
func (api *API) convertAuditLog(ctx context.Context, dblog database.GetAuditLogsOffsetRow) codersdk.AuditLog {
|
||||
|
@ -198,8 +199,9 @@ func (api *API) convertAuditLog(ctx context.Context, dblog database.GetAuditLogs
|
|||
if err != nil {
|
||||
api.Logger.Error(ctx, "unmarshal additional fields", slog.Error(err))
|
||||
resourceInfo := map[string]string{
|
||||
"workspaceName": "unknown",
|
||||
"buildNumber": "unknown",
|
||||
"workspaceName": "unknown",
|
||||
"buildNumber": "unknown",
|
||||
"workspaceOwner": "unknown",
|
||||
}
|
||||
dblog.AdditionalFields, err = json.Marshal(resourceInfo)
|
||||
api.Logger.Error(ctx, "marshal additional fields", slog.Error(err))
|
||||
|
@ -331,8 +333,12 @@ func auditLogResourceLink(alog database.GetAuditLogsOffsetRow, additionalFields
|
|||
return fmt.Sprintf("/users?filter=%s",
|
||||
alog.ResourceTarget)
|
||||
case database.ResourceTypeWorkspace:
|
||||
workspaceOwner := alog.UserUsername.String
|
||||
if len(additionalFields.WorkspaceOwner) != 0 && additionalFields.WorkspaceOwner != "unknown" {
|
||||
workspaceOwner = additionalFields.WorkspaceOwner
|
||||
}
|
||||
return fmt.Sprintf("/@%s/%s",
|
||||
alog.UserUsername.String, alog.ResourceTarget)
|
||||
workspaceOwner, alog.ResourceTarget)
|
||||
case database.ResourceTypeWorkspaceBuild:
|
||||
if len(additionalFields.WorkspaceName) == 0 || len(additionalFields.BuildNumber) == 0 {
|
||||
return ""
|
||||
|
|
|
@ -237,18 +237,27 @@ func (api *API) workspaceByOwnerAndName(rw http.ResponseWriter, r *http.Request)
|
|||
// Create a new workspace for the currently authenticated user.
|
||||
func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Request) {
|
||||
var (
|
||||
ctx = r.Context()
|
||||
organization = httpmw.OrganizationParam(r)
|
||||
apiKey = httpmw.APIKey(r)
|
||||
auditor = api.Auditor.Load()
|
||||
user = httpmw.UserParam(r)
|
||||
aReq, commitAudit = audit.InitRequest[database.Workspace](rw, &audit.RequestParams{
|
||||
Audit: *auditor,
|
||||
Log: api.Logger,
|
||||
Request: r,
|
||||
Action: database.AuditActionCreate,
|
||||
})
|
||||
ctx = r.Context()
|
||||
organization = httpmw.OrganizationParam(r)
|
||||
apiKey = httpmw.APIKey(r)
|
||||
auditor = api.Auditor.Load()
|
||||
user = httpmw.UserParam(r)
|
||||
workspaceResourceInfo = map[string]string{
|
||||
"workspaceOwner": user.Username,
|
||||
}
|
||||
)
|
||||
wriBytes, err := json.Marshal(workspaceResourceInfo)
|
||||
if err != nil {
|
||||
api.Logger.Warn(ctx, "marshal workspace owner name")
|
||||
}
|
||||
|
||||
aReq, commitAudit := audit.InitRequest[database.Workspace](rw, &audit.RequestParams{
|
||||
Audit: *auditor,
|
||||
Log: api.Logger,
|
||||
Request: r,
|
||||
Action: database.AuditActionCreate,
|
||||
AdditionalFields: wriBytes,
|
||||
})
|
||||
defer commitAudit()
|
||||
|
||||
if !api.Authorize(r, rbac.ActionCreate,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import {
|
||||
MockAuditLog,
|
||||
MockAuditLogWithWorkspaceBuild,
|
||||
MockWorkspaceCreateAuditLogForDifferentOwner,
|
||||
} from "testHelpers/entities"
|
||||
import { AuditLogDescription } from "./AuditLogDescription"
|
||||
import { render } from "../../testHelpers/renderHelpers"
|
||||
|
@ -46,4 +47,16 @@ describe("AuditLogDescription", () => {
|
|||
getByTextContent("TestUser stopped build for workspace workspace"),
|
||||
).toBeDefined()
|
||||
})
|
||||
it("renders the correct string for a workspace created for a different owner", async () => {
|
||||
render(
|
||||
<AuditLogDescription
|
||||
auditLog={MockWorkspaceCreateAuditLogForDifferentOwner}
|
||||
/>,
|
||||
)
|
||||
expect(
|
||||
getByTextContent(
|
||||
`TestUser created workspace bruno-dev on behalf of ${MockWorkspaceCreateAuditLogForDifferentOwner.additional_fields.workspaceOwner}`,
|
||||
),
|
||||
).toBeDefined()
|
||||
})
|
||||
})
|
||||
|
|
|
@ -45,9 +45,20 @@ export const AuditLogDescription: FC<{ auditLog: AuditLog }> = ({
|
|||
)}
|
||||
{auditLog.is_deleted && (
|
||||
<span className={classes.deletedLabel}>
|
||||
<> {t("auditLog:table.logRow.deletedLabel")}</>
|
||||
<>{t("auditLog:table.logRow.deletedLabel")}</>
|
||||
</span>
|
||||
)}
|
||||
{/* logs for workspaces created on behalf of other users indicate ownership in the description */}
|
||||
{auditLog.additional_fields.workspaceOwner &&
|
||||
auditLog.additional_fields.workspaceOwner !== "unknown" && (
|
||||
<span>
|
||||
<>
|
||||
{t("auditLog:table.logRow.onBehalfOf", {
|
||||
owner: auditLog.additional_fields.workspaceOwner,
|
||||
})}
|
||||
</>
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -8,11 +8,12 @@
|
|||
"emptyPage": "No audit logs available on this page",
|
||||
"noLogs": "No audit logs available",
|
||||
"logRow": {
|
||||
"deletedLabel": "(deleted)",
|
||||
"deletedLabel": " (deleted)",
|
||||
"ip": "IP: ",
|
||||
"os": "OS: ",
|
||||
"browser": "Browser: ",
|
||||
"notAvailable": "Not available"
|
||||
"notAvailable": "Not available",
|
||||
"onBehalfOf": " on behalf of {{owner}}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1020,6 +1020,13 @@ export const MockAuditLog2: TypesGen.AuditLog = {
|
|||
},
|
||||
}
|
||||
|
||||
export const MockWorkspaceCreateAuditLogForDifferentOwner = {
|
||||
...MockAuditLog,
|
||||
additional_fields: {
|
||||
workspaceOwner: "Member",
|
||||
},
|
||||
}
|
||||
|
||||
export const MockAuditLogWithWorkspaceBuild: TypesGen.AuditLog = {
|
||||
...MockAuditLog,
|
||||
id: "f90995bf-4a2b-4089-b597-e66e025e523e",
|
||||
|
|
Loading…
Reference in New Issue