diff --git a/core/resource/service.go b/core/resource/service.go index 5a0be64976..6d78b7ec6e 100644 --- a/core/resource/service.go +++ b/core/resource/service.go @@ -152,6 +152,10 @@ func (s Service) Create(ctx context.Context, res Resource) (Resource, error) { } func (s Service) createAuditRecord(ctx context.Context, event pkgauditrecord.Event, res Resource, proj project.Project) { + targetName := res.Title + if targetName == "" { + targetName = res.Name + } if _, err := s.auditRecordRepository.Create(ctx, auditmodels.AuditRecord{ Event: event, Resource: auditmodels.Resource{ @@ -162,7 +166,7 @@ func (s Service) createAuditRecord(ctx context.Context, event pkgauditrecord.Eve Target: &auditmodels.Target{ ID: res.ID, Type: pkgauditrecord.EntityType(res.NamespaceID), - Name: res.Name, + Name: targetName, }, OrgID: proj.Organization.ID, OrgName: proj.Organization.Title, diff --git a/core/resource/service_test.go b/core/resource/service_test.go index 0ec4a3cc89..90a8606d9d 100644 --- a/core/resource/service_test.go +++ b/core/resource/service_test.go @@ -420,6 +420,56 @@ func TestCreate(t *testing.T) { assert.Equal(t, schema.UserPrincipal, got.PrincipalType) }) + t.Run("audit record target name uses title when set", func(t *testing.T) { + repo, relationSvc, _, projectSvc, _, _, auditRepo, _, svc := newTestService(t) + userID := uuid.New().String() + + projectSvc.EXPECT().Get(mock.Anything, testProject.ID).Return(testProject, nil) + + repo.EXPECT().Create(mock.Anything, mock.Anything).Return(resource.Resource{ + ID: uuid.New().String(), Name: "aoi-uuid-1", Title: "My AOI", NamespaceID: "resource/item", + ProjectID: testProject.ID, PrincipalID: userID, PrincipalType: schema.UserPrincipal, + }, nil) + + relationSvc.EXPECT().Delete(mock.Anything, mock.Anything).Return(nil) + relationSvc.EXPECT().Create(mock.Anything, mock.Anything).Return(relation.Relation{}, nil).Times(2) + + auditRepo.EXPECT().Create(mock.Anything, mock.MatchedBy(func(r auditmodels.AuditRecord) bool { + return r.Target != nil && r.Target.Name == "My AOI" + })).Return(auditmodels.AuditRecord{}, nil) + + _, err := svc.Create(ctx, resource.Resource{ + Name: "aoi-uuid-1", Title: "My AOI", NamespaceID: "resource/item", ProjectID: testProject.ID, + PrincipalID: userID, PrincipalType: schema.UserPrincipal, + }) + assert.NoError(t, err) + }) + + t.Run("audit record target name falls back to name when title empty", func(t *testing.T) { + repo, relationSvc, _, projectSvc, _, _, auditRepo, _, svc := newTestService(t) + userID := uuid.New().String() + + projectSvc.EXPECT().Get(mock.Anything, testProject.ID).Return(testProject, nil) + + repo.EXPECT().Create(mock.Anything, mock.Anything).Return(resource.Resource{ + ID: uuid.New().String(), Name: "res-slug", NamespaceID: "resource/item", + ProjectID: testProject.ID, PrincipalID: userID, PrincipalType: schema.UserPrincipal, + }, nil) + + relationSvc.EXPECT().Delete(mock.Anything, mock.Anything).Return(nil) + relationSvc.EXPECT().Create(mock.Anything, mock.Anything).Return(relation.Relation{}, nil).Times(2) + + auditRepo.EXPECT().Create(mock.Anything, mock.MatchedBy(func(r auditmodels.AuditRecord) bool { + return r.Target != nil && r.Target.Name == "res-slug" + })).Return(auditmodels.AuditRecord{}, nil) + + _, err := svc.Create(ctx, resource.Resource{ + Name: "res-slug", NamespaceID: "resource/item", ProjectID: testProject.ID, + PrincipalID: userID, PrincipalType: schema.UserPrincipal, + }) + assert.NoError(t, err) + }) + t.Run("explicit principal skips authn lookup", func(t *testing.T) { repo, relationSvc, _, projectSvc, _, _, auditRepo, _, svc := newTestService(t) userID := uuid.New().String()