@@ -207,32 +207,84 @@ func (api *API) convertAuditLog(ctx context.Context, dblog database.GetAuditLogs
207
207
208
208
type AdditionalFields struct {
209
209
WorkspaceName string
210
+ WorkspaceID string
210
211
BuildNumber string
211
212
}
212
213
214
+ func (api * API ) auditLogIsResourceDeleted (ctx context.Context , alog database.GetAuditLogsOffsetRow ) bool {
215
+ switch alog .ResourceType {
216
+ case database .ResourceTypeTemplate :
217
+ template , err := api .Database .GetTemplateByID (ctx , alog .ResourceID )
218
+ if err != nil {
219
+ api .Logger .Error (ctx , "could not get template" , slog .Error (err ))
220
+ }
221
+ return template .Deleted
222
+ case database .ResourceTypeUser :
223
+ user , err := api .Database .GetUserByID (ctx , alog .ResourceID )
224
+ if err != nil {
225
+ api .Logger .Error (ctx , "could not get user" , slog .Error (err ))
226
+ }
227
+ return user .Deleted
228
+ case database .ResourceTypeWorkspace :
229
+ workspace , err := api .Database .GetWorkspaceByID (ctx , alog .ResourceID )
230
+ if err != nil {
231
+ api .Logger .Error (ctx , "could not get workspace" , slog .Error (err ))
232
+ }
233
+ return workspace .Deleted
234
+ case database .ResourceTypeWorkspaceBuild :
235
+ additionalFieldsBytes := []byte (alog .AdditionalFields )
236
+ var additionalFields AdditionalFields
237
+ err := json .Unmarshal (additionalFieldsBytes , & additionalFields )
238
+ if err != nil {
239
+ api .Logger .Error (ctx , "could not unmarshal workspace ID" , slog .Error (err ))
240
+ }
241
+ // if we don't have a WorkspaceID, we return true so as to hide the link in the UI
242
+ if len (additionalFields .WorkspaceID ) < 1 {
243
+ return true
244
+ }
245
+ // We use workspace as a proxy for workspace build here
246
+ workspace , err := api .Database .GetWorkspaceByID (ctx , uuid .MustParse (additionalFields .WorkspaceID ))
247
+ if err != nil {
248
+ api .Logger .Error (ctx , "could not get workspace" , slog .Error (err ))
249
+ }
250
+ return workspace .Deleted
251
+ default :
252
+ return false
253
+ }
254
+ }
255
+
213
256
func (api * API ) auditLogResourceLink (ctx context.Context , alog database.GetAuditLogsOffsetRow ) string {
214
257
switch alog .ResourceType {
215
258
case database .ResourceTypeTemplate :
259
+ if api .auditLogIsResourceDeleted (ctx , alog ) {
260
+ return ""
261
+ }
216
262
return fmt .Sprintf ("/templates/%s" ,
217
263
alog .ResourceTarget )
218
264
case database .ResourceTypeUser :
265
+ if api .auditLogIsResourceDeleted (ctx , alog ) {
266
+ return ""
267
+ }
219
268
return fmt .Sprintf ("/users?filter=%s" ,
220
269
alog .ResourceTarget )
221
270
case database .ResourceTypeWorkspace :
271
+ if api .auditLogIsResourceDeleted (ctx , alog ) {
272
+ return ""
273
+ }
222
274
return fmt .Sprintf ("/@%s/%s" ,
223
275
alog .UserUsername .String , alog .ResourceTarget )
224
276
case database .ResourceTypeWorkspaceBuild :
277
+ if api .auditLogIsResourceDeleted (ctx , alog ) {
278
+ return ""
279
+ }
225
280
additionalFieldsBytes := []byte (alog .AdditionalFields )
226
281
var additionalFields AdditionalFields
227
282
err := json .Unmarshal (additionalFieldsBytes , & additionalFields )
228
283
if err != nil {
229
- api .Logger .Error (ctx , "could not unmarshal workspace name for friendly string " , slog .Error (err ))
284
+ api .Logger .Error (ctx , "could not unmarshal workspace name" , slog .Error (err ))
230
285
}
231
286
return fmt .Sprintf ("/@%s/%s/builds/%s" ,
232
287
alog .UserUsername .String , additionalFields .WorkspaceName , additionalFields .BuildNumber )
233
- case database .ResourceTypeGroup :
234
- return fmt .Sprintf ("/groups/%s" ,
235
- alog .ResourceID )
236
288
default :
237
289
return ""
238
290
}
@@ -243,21 +295,27 @@ func auditLogDescription(alog database.GetAuditLogsOffsetRow) string {
243
295
codersdk .AuditAction (alog .Action ).FriendlyString (),
244
296
)
245
297
246
- // Strings for workspace_builds follow the below format:
247
- // "{user} started workspace build for {target}"
248
- // where target is a workspace instead of the workspace build,
298
+ // Strings for starting/stopping workspace builds follow the below format:
299
+ // "{user} started build for workspace {target}"
300
+ // where target is a workspace instead of a workspace build
249
301
// passed in on the FE via AuditLog.AdditionalFields rather than derived in request.go:35
250
- if alog .ResourceType != database .ResourceTypeWorkspaceBuild {
251
- str += fmt .Sprintf (" %s" ,
252
- codersdk .ResourceType (alog .ResourceType ).FriendlyString ())
302
+ if alog .ResourceType == database .ResourceTypeWorkspaceBuild && alog .Action != database .AuditActionDelete {
303
+ str += " build for"
253
304
}
254
305
255
- // We don't display the name for git ssh keys. It's fairly long and doesn't
306
+ // We don't display the name (target) for git ssh keys. It's fairly long and doesn't
256
307
// make too much sense to display.
257
- if alog .ResourceType != database .ResourceTypeGitSshKey {
258
- str += " {target}"
308
+ if alog .ResourceType == database .ResourceTypeGitSshKey {
309
+ str += fmt .Sprintf (" the %s" ,
310
+ codersdk .ResourceType (alog .ResourceType ).FriendlyString ())
311
+ return str
259
312
}
260
313
314
+ str += fmt .Sprintf (" %s" ,
315
+ codersdk .ResourceType (alog .ResourceType ).FriendlyString ())
316
+
317
+ str += " {target}"
318
+
261
319
return str
262
320
}
263
321
0 commit comments