diff --git a/internal/api/graphql/graph/baseResolver/activity.go b/internal/api/graphql/graph/baseResolver/activity.go index ce2a17ad..f1aa850b 100644 --- a/internal/api/graphql/graph/baseResolver/activity.go +++ b/internal/api/graphql/graph/baseResolver/activity.go @@ -93,6 +93,7 @@ func ActivityBaseResolver(app app.Heureka, ctx context.Context, filter *model.Ac ServiceCCRN: filter.ServiceCcrn, ServiceId: sId, IssueId: issueId, + State: entity.GetStateFilterType(filter.State), } opt := GetListOptions(requestedFields) diff --git a/internal/api/graphql/graph/baseResolver/component.go b/internal/api/graphql/graph/baseResolver/component.go index 91cedbc1..28130213 100644 --- a/internal/api/graphql/graph/baseResolver/component.go +++ b/internal/api/graphql/graph/baseResolver/component.go @@ -72,6 +72,7 @@ func ComponentBaseResolver(app app.Heureka, ctx context.Context, filter *model.C f := &entity.ComponentFilter{ Paginated: entity.Paginated{First: first, After: afterId}, CCRN: filter.ComponentCcrn, + State: entity.GetStateFilterType(filter.State), } opt := GetListOptions(requestedFields) diff --git a/internal/api/graphql/graph/baseResolver/component_instance.go b/internal/api/graphql/graph/baseResolver/component_instance.go index 6c35cafe..cf9d6157 100644 --- a/internal/api/graphql/graph/baseResolver/component_instance.go +++ b/internal/api/graphql/graph/baseResolver/component_instance.go @@ -98,6 +98,7 @@ func ComponentInstanceBaseResolver(app app.Heureka, ctx context.Context, filter ServiceCcrn: filter.ServiceCcrn, ComponentVersionId: copmonentVersionId, Search: filter.Search, + State: entity.GetStateFilterType(filter.State), } opt := GetListOptions(requestedFields) @@ -146,6 +147,7 @@ func CcrnBaseResolver(app app.Heureka, ctx context.Context, filter *model.Compon f := &entity.ComponentInstanceFilter{ CCRN: filter.Ccrn, Search: filter.Search, + State: entity.GetStateFilterType(filter.State), } opt := GetListOptions(requestedFields) diff --git a/internal/api/graphql/graph/baseResolver/component_version.go b/internal/api/graphql/graph/baseResolver/component_version.go index 040ad90e..ec202243 100644 --- a/internal/api/graphql/graph/baseResolver/component_version.go +++ b/internal/api/graphql/graph/baseResolver/component_version.go @@ -100,6 +100,7 @@ func ComponentVersionBaseResolver(app app.Heureka, ctx context.Context, filter * ComponentId: componentId, ComponentCCRN: filter.ComponentCcrn, Version: filter.Version, + State: entity.GetStateFilterType(filter.State), } opt := GetListOptions(requestedFields) diff --git a/internal/api/graphql/graph/baseResolver/evidence.go b/internal/api/graphql/graph/baseResolver/evidence.go index 3bc0b2bf..345b9108 100644 --- a/internal/api/graphql/graph/baseResolver/evidence.go +++ b/internal/api/graphql/graph/baseResolver/evidence.go @@ -51,6 +51,7 @@ func EvidenceBaseResolver(app app.Heureka, ctx context.Context, filter *model.Ev Paginated: entity.Paginated{First: first, After: afterId}, ActivityId: activityId, IssueMatchId: imId, + State: entity.GetStateFilterType(filter.State), } opt := GetListOptions(requestedFields) diff --git a/internal/api/graphql/graph/baseResolver/issue.go b/internal/api/graphql/graph/baseResolver/issue.go index 065db6df..25f4805a 100644 --- a/internal/api/graphql/graph/baseResolver/issue.go +++ b/internal/api/graphql/graph/baseResolver/issue.go @@ -110,6 +110,7 @@ func IssueBaseResolver(app app.Heureka, ctx context.Context, filter *model.Issue IssueMatchStatus: nil, //@todo Implement IssueMatchDiscoveryDate: nil, //@todo Implement IssueMatchTargetRemediationDate: nil, //@todo Implement + State: entity.GetStateFilterType(filter.State), } opt := GetIssueListOptions(requestedFields) @@ -177,6 +178,7 @@ func IssueNameBaseResolver(app app.Heureka, ctx context.Context, filter *model.I IssueMatchStatus: nil, //@todo Implement IssueMatchDiscoveryDate: nil, //@todo Implement IssueMatchTargetRemediationDate: nil, //@todo Implement + State: entity.GetStateFilterType(filter.State), } opt := GetListOptions(requestedFields) diff --git a/internal/api/graphql/graph/baseResolver/issue_match.go b/internal/api/graphql/graph/baseResolver/issue_match.go index 5ae2aa9f..4591de29 100644 --- a/internal/api/graphql/graph/baseResolver/issue_match.go +++ b/internal/api/graphql/graph/baseResolver/issue_match.go @@ -116,6 +116,7 @@ func IssueMatchBaseResolver(app app.Heureka, ctx context.Context, filter *model. ComponentCCRN: filter.ComponentCcrn, PrimaryName: filter.PrimaryName, IssueType: lo.Map(filter.IssueType, func(item *model.IssueTypes, _ int) *string { return pointer.String(item.String()) }), + State: entity.GetStateFilterType(filter.State), } opt := GetListOptions(requestedFields) diff --git a/internal/api/graphql/graph/baseResolver/issue_match_change.go b/internal/api/graphql/graph/baseResolver/issue_match_change.go index 9e97c867..8e26df31 100644 --- a/internal/api/graphql/graph/baseResolver/issue_match_change.go +++ b/internal/api/graphql/graph/baseResolver/issue_match_change.go @@ -54,6 +54,7 @@ func IssueMatchChangeBaseResolver(app app.Heureka, ctx context.Context, filter * Action: lo.Map(filter.Action, func(item *model.IssueMatchChangeActions, _ int) *string { return pointer.String(item.String()) }), ActivityId: aId, IssueMatchId: imId, + State: entity.GetStateFilterType(filter.State), } opt := GetListOptions(requestedFields) diff --git a/internal/api/graphql/graph/baseResolver/issue_repository.go b/internal/api/graphql/graph/baseResolver/issue_repository.go index 8f571b0d..092800c3 100644 --- a/internal/api/graphql/graph/baseResolver/issue_repository.go +++ b/internal/api/graphql/graph/baseResolver/issue_repository.go @@ -90,6 +90,7 @@ func IssueRepositoryBaseResolver(app app.Heureka, ctx context.Context, filter *m ServiceId: serviceId, Name: filter.Name, ServiceCCRN: filter.ServiceCcrn, + State: entity.GetStateFilterType(filter.State), } opt := GetListOptions(requestedFields) diff --git a/internal/api/graphql/graph/baseResolver/issue_variant.go b/internal/api/graphql/graph/baseResolver/issue_variant.go index aed2c741..395e8a87 100644 --- a/internal/api/graphql/graph/baseResolver/issue_variant.go +++ b/internal/api/graphql/graph/baseResolver/issue_variant.go @@ -93,6 +93,7 @@ func IssueVariantBaseResolver(app app.Heureka, ctx context.Context, filter *mode IssueId: issueId, IssueRepositoryId: irId, SecondaryName: filter.SecondaryName, + State: entity.GetStateFilterType(filter.State), } opt := GetListOptions(requestedFields) @@ -163,6 +164,7 @@ func EffectiveIssueVariantBaseResolver(app app.Heureka, ctx context.Context, fil f := &entity.IssueVariantFilter{ Paginated: entity.Paginated{First: first, After: afterId}, IssueMatchId: imId, + State: entity.GetStateFilterType(filter.State), } opt := GetListOptions(requestedFields) diff --git a/internal/api/graphql/graph/baseResolver/service.go b/internal/api/graphql/graph/baseResolver/service.go index a9d1ab90..66969e53 100644 --- a/internal/api/graphql/graph/baseResolver/service.go +++ b/internal/api/graphql/graph/baseResolver/service.go @@ -104,6 +104,7 @@ func ServiceBaseResolver(app app.Heureka, ctx context.Context, filter *model.Ser IssueRepositoryId: irId, SupportGroupId: sgId, Search: filter.Search, + State: entity.GetStateFilterType(filter.State), } opt := GetListOptions(requestedFields) @@ -159,6 +160,7 @@ func ServiceCcrnBaseResolver(app app.Heureka, ctx context.Context, filter *model SupportGroupCCRN: filter.SupportGroupCcrn, CCRN: filter.ServiceCcrn, OwnerName: filter.UserName, + State: entity.GetStateFilterType(filter.State), } opt := GetListOptions(requestedFields) diff --git a/internal/api/graphql/graph/baseResolver/support_group.go b/internal/api/graphql/graph/baseResolver/support_group.go index 8a174e67..3bd47a9b 100644 --- a/internal/api/graphql/graph/baseResolver/support_group.go +++ b/internal/api/graphql/graph/baseResolver/support_group.go @@ -53,6 +53,7 @@ func SupportGroupBaseResolver(app app.Heureka, ctx context.Context, filter *mode ServiceId: serviceId, UserId: userId, CCRN: filter.SupportGroupCcrn, + State: entity.GetStateFilterType(filter.State), } opt := GetListOptions(requestedFields) @@ -112,6 +113,7 @@ func SupportGroupCcrnBaseResolver(app app.Heureka, ctx context.Context, filter * Paginated: entity.Paginated{}, UserId: userIds, CCRN: filter.SupportGroupCcrn, + State: entity.GetStateFilterType(filter.State), } opt := GetListOptions(requestedFields) diff --git a/internal/api/graphql/graph/baseResolver/user.go b/internal/api/graphql/graph/baseResolver/user.go index 09079a38..402e1a1f 100644 --- a/internal/api/graphql/graph/baseResolver/user.go +++ b/internal/api/graphql/graph/baseResolver/user.go @@ -93,6 +93,7 @@ func UserBaseResolver(app app.Heureka, ctx context.Context, filter *model.UserFi ServiceId: serviceId, Name: filter.UserName, UniqueUserID: filter.UniqueUserID, + State: entity.GetStateFilterType(filter.State), } opt := GetListOptions(requestedFields) @@ -140,6 +141,7 @@ func UserNameBaseResolver(app app.Heureka, ctx context.Context, filter *model.Us Paginated: entity.Paginated{}, Name: filter.UserName, UniqueUserID: filter.UniqueUserID, + State: entity.GetStateFilterType(filter.State), } opt := GetListOptions(requestedFields) @@ -178,6 +180,7 @@ func UniqueUserIDBaseResolver(app app.Heureka, ctx context.Context, filter *mode Paginated: entity.Paginated{}, UniqueUserID: filter.UniqueUserID, Name: filter.UserName, + State: entity.GetStateFilterType(filter.State), } opt := GetListOptions(requestedFields) diff --git a/internal/api/graphql/graph/schema/activity.graphqls b/internal/api/graphql/graph/schema/activity.graphqls index c7029148..912454e0 100644 --- a/internal/api/graphql/graph/schema/activity.graphqls +++ b/internal/api/graphql/graph/schema/activity.graphqls @@ -30,6 +30,7 @@ type ActivityEdge implements Edge { input ActivityFilter { serviceCcrn: [String] status: [ActivityStatusValues] + state: Int } enum ActivityStatusValues { diff --git a/internal/api/graphql/graph/schema/component.graphqls b/internal/api/graphql/graph/schema/component.graphqls index 302322da..b0df1510 100644 --- a/internal/api/graphql/graph/schema/component.graphqls +++ b/internal/api/graphql/graph/schema/component.graphqls @@ -22,6 +22,7 @@ enum ComponentTypeValues { input ComponentFilter { componentCcrn: [String] + state: Int } type ComponentConnection implements Connection { diff --git a/internal/api/graphql/graph/schema/component_instance.graphqls b/internal/api/graphql/graph/schema/component_instance.graphqls index 3d909907..a0a9a614 100644 --- a/internal/api/graphql/graph/schema/component_instance.graphqls +++ b/internal/api/graphql/graph/schema/component_instance.graphqls @@ -36,4 +36,5 @@ input ComponentInstanceFilter { ccrn: [String], supportGroup: [String], search:[String], + state: Int, } diff --git a/internal/api/graphql/graph/schema/component_version.graphqls b/internal/api/graphql/graph/schema/component_version.graphqls index 36fe0026..ea0d1f40 100644 --- a/internal/api/graphql/graph/schema/component_version.graphqls +++ b/internal/api/graphql/graph/schema/component_version.graphqls @@ -32,4 +32,5 @@ input ComponentVersionFilter { componentCcrn: [String] issueId: [String] version: [String] + state: Int } diff --git a/internal/api/graphql/graph/schema/evidence.graphqls b/internal/api/graphql/graph/schema/evidence.graphqls index faee3485..16ac2e9a 100644 --- a/internal/api/graphql/graph/schema/evidence.graphqls +++ b/internal/api/graphql/graph/schema/evidence.graphqls @@ -38,4 +38,5 @@ type EvidenceEdge implements Edge { input EvidenceFilter { placeholder: [Boolean] + state: Int } diff --git a/internal/api/graphql/graph/schema/issue.graphqls b/internal/api/graphql/graph/schema/issue.graphqls index 370f5a80..0846bba1 100644 --- a/internal/api/graphql/graph/schema/issue.graphqls +++ b/internal/api/graphql/graph/schema/issue.graphqls @@ -59,6 +59,7 @@ input IssueFilter { primaryName: [String], issueMatchStatus: [IssueMatchStatusValues], issueType: [IssueTypes], + state: Int, componentVersionId: [String], diff --git a/internal/api/graphql/graph/schema/issue_match.graphqls b/internal/api/graphql/graph/schema/issue_match.graphqls index 70108ed7..ef45356f 100644 --- a/internal/api/graphql/graph/schema/issue_match.graphqls +++ b/internal/api/graphql/graph/schema/issue_match.graphqls @@ -40,6 +40,7 @@ input IssueMatchFilter { severity: [SeverityValues] affectedService: [String] supportGroupCcrn: [String] + state: Int } #type CCloudSeverity { diff --git a/internal/api/graphql/graph/schema/issue_match_change.graphqls b/internal/api/graphql/graph/schema/issue_match_change.graphqls index 65385d01..485e11e8 100644 --- a/internal/api/graphql/graph/schema/issue_match_change.graphqls +++ b/internal/api/graphql/graph/schema/issue_match_change.graphqls @@ -20,6 +20,7 @@ input IssueMatchChangeInput { input IssueMatchChangeFilter { action: [IssueMatchChangeActions] + state: Int } type IssueMatchChangeConnection implements Connection { diff --git a/internal/api/graphql/graph/schema/issue_match_filter_value.graphqls b/internal/api/graphql/graph/schema/issue_match_filter_value.graphqls index b44a0589..cfabe57a 100644 --- a/internal/api/graphql/graph/schema/issue_match_filter_value.graphqls +++ b/internal/api/graphql/graph/schema/issue_match_filter_value.graphqls @@ -9,4 +9,4 @@ type IssueMatchFilterValue { affectedService(filter: ServiceFilter): FilterItem componentCcrn(filter: ComponentFilter): FilterItem supportGroupCcrn(filter: SupportGroupFilter): FilterItem -} \ No newline at end of file +} diff --git a/internal/api/graphql/graph/schema/issue_repository.graphqls b/internal/api/graphql/graph/schema/issue_repository.graphqls index eb4cae34..da20b728 100644 --- a/internal/api/graphql/graph/schema/issue_repository.graphqls +++ b/internal/api/graphql/graph/schema/issue_repository.graphqls @@ -32,4 +32,5 @@ input IssueRepositoryFilter { serviceCcrn: [String] serviceId: [String] name: [String] + state: Int } diff --git a/internal/api/graphql/graph/schema/issue_variant.graphqls b/internal/api/graphql/graph/schema/issue_variant.graphqls index 8f688f65..ba8584b1 100644 --- a/internal/api/graphql/graph/schema/issue_variant.graphqls +++ b/internal/api/graphql/graph/schema/issue_variant.graphqls @@ -35,4 +35,5 @@ type IssueVariantEdge implements Edge { input IssueVariantFilter { secondaryName: [String] + state: Int } diff --git a/internal/api/graphql/graph/schema/service.graphqls b/internal/api/graphql/graph/schema/service.graphqls index 2a36af8c..80c09b9c 100644 --- a/internal/api/graphql/graph/schema/service.graphqls +++ b/internal/api/graphql/graph/schema/service.graphqls @@ -42,4 +42,5 @@ input ServiceFilter { userName: [String] supportGroupCcrn: [String] search: [String] + state: Int } diff --git a/internal/api/graphql/graph/schema/support_group.graphqls b/internal/api/graphql/graph/schema/support_group.graphqls index b66d4e0f..897bc7c4 100644 --- a/internal/api/graphql/graph/schema/support_group.graphqls +++ b/internal/api/graphql/graph/schema/support_group.graphqls @@ -27,4 +27,5 @@ type SupportGroupEdge implements Edge { input SupportGroupFilter { supportGroupCcrn: [String], userIds: [String], + state: Int, } diff --git a/internal/api/graphql/graph/schema/user.graphqls b/internal/api/graphql/graph/schema/user.graphqls index 2cd19c19..04923e3b 100644 --- a/internal/api/graphql/graph/schema/user.graphqls +++ b/internal/api/graphql/graph/schema/user.graphqls @@ -32,4 +32,5 @@ input UserFilter { userName: [String], supportGroupIds: [String], uniqueUserId: [String], + state: Int, } diff --git a/internal/app/activity/activity_handler.go b/internal/app/activity/activity_handler.go index 2b10dd52..c1482a80 100644 --- a/internal/app/activity/activity_handler.go +++ b/internal/app/activity/activity_handler.go @@ -192,7 +192,13 @@ func (a *activityHandler) DeleteActivity(id int64) error { "id": id, }) - err := a.database.DeleteActivity(id) + userId, err := common.GetCurrentUserId(a.database) + if err != nil { + l.Error(err) + return NewActivityHandlerError("Internal error while deleting activity (GetUserId).") + } + + err = a.database.DeleteActivity(id, userId) if err != nil { l.Error(err) diff --git a/internal/app/activity/activity_handler_test.go b/internal/app/activity/activity_handler_test.go index f768d6fe..ea3f920c 100644 --- a/internal/app/activity/activity_handler_test.go +++ b/internal/app/activity/activity_handler_test.go @@ -190,7 +190,8 @@ var _ = Describe("When deleting Activity", Label("app", "DeleteActivity"), func( }) It("deletes activity", func() { - db.On("DeleteActivity", id).Return(nil) + db.On("GetAllUserIds", mock.Anything).Return([]int64{}, nil) + db.On("DeleteActivity", id, mock.Anything).Return(nil) activityHandler = a.NewActivityHandler(db, er) db.On("GetActivities", filter).Return([]entity.Activity{}, nil) err := activityHandler.DeleteActivity(id) diff --git a/internal/app/common/user_id.go b/internal/app/common/user_id.go index 173dd0ba..b9d2f041 100644 --- a/internal/app/common/user_id.go +++ b/internal/app/common/user_id.go @@ -10,17 +10,20 @@ import ( "github.com/cloudoperators/heureka/internal/entity" ) +const systemUserUniqueUserId = "S0000000" +const unknownUser = int64(0) + func GetCurrentUserId(db database.Database) (int64, error) { - return getUserIdFromDb(db, "S0000000") + return getUserIdFromDb(db, systemUserUniqueUserId) } func getUserIdFromDb(db database.Database, uniqueUserId string) (int64, error) { filter := &entity.UserFilter{UniqueUserID: []*string{&uniqueUserId}} ids, err := db.GetAllUserIds(filter) if err != nil { - return 0, fmt.Errorf("Unable to get user ids %w", err) + return unknownUser, fmt.Errorf("Unable to get user ids %w", err) } else if len(ids) < 1 { - return 0, nil + return unknownUser, nil } return ids[0], nil } diff --git a/internal/app/component/component_handler.go b/internal/app/component/component_handler.go index 4e917f98..620fea76 100644 --- a/internal/app/component/component_handler.go +++ b/internal/app/component/component_handler.go @@ -189,7 +189,13 @@ func (cs *componentHandler) DeleteComponent(id int64) error { "id": id, }) - err := cs.database.DeleteComponent(id) + userId, err := common.GetCurrentUserId(cs.database) + if err != nil { + l.Error(err) + return NewUserHandlerError("Internal error while deleting component (GetUserId).") + } + + err = cs.database.DeleteComponent(id, userId) if err != nil { l.Error(err) diff --git a/internal/app/component/component_handler_test.go b/internal/app/component/component_handler_test.go index 4dee1a12..b5db7c05 100644 --- a/internal/app/component/component_handler_test.go +++ b/internal/app/component/component_handler_test.go @@ -201,7 +201,8 @@ var _ = Describe("When deleting Component", Label("app", "DeleteComponent"), fun }) It("deletes component", func() { - db.On("DeleteComponent", id).Return(nil) + db.On("GetAllUserIds", mock.Anything).Return([]int64{}, nil) + db.On("DeleteComponent", id, mock.Anything).Return(nil) componentHandler = c.NewComponentHandler(db, er) db.On("GetComponents", filter).Return([]entity.Component{}, nil) err := componentHandler.DeleteComponent(id) diff --git a/internal/app/component_instance/component_instance_handler.go b/internal/app/component_instance/component_instance_handler.go index 1a9a624b..8521e4d7 100644 --- a/internal/app/component_instance/component_instance_handler.go +++ b/internal/app/component_instance/component_instance_handler.go @@ -183,7 +183,13 @@ func (ci *componentInstanceHandler) DeleteComponentInstance(id int64) error { "id": id, }) - err := ci.database.DeleteComponentInstance(id) + userId, err := common.GetCurrentUserId(ci.database) + if err != nil { + l.Error(err) + return NewComponentInstanceHandlerError("Internal error while deleting componentInstance (GetUserId).") + } + + err = ci.database.DeleteComponentInstance(id, userId) if err != nil { l.Error(err) diff --git a/internal/app/component_instance/component_instance_handler_test.go b/internal/app/component_instance/component_instance_handler_test.go index a5a1d470..37108da7 100644 --- a/internal/app/component_instance/component_instance_handler_test.go +++ b/internal/app/component_instance/component_instance_handler_test.go @@ -200,7 +200,8 @@ var _ = Describe("When deleting ComponentInstance", Label("app", "DeleteComponen }) It("deletes componentInstance", func() { - db.On("DeleteComponentInstance", id).Return(nil) + db.On("GetAllUserIds", mock.Anything).Return([]int64{}, nil) + db.On("DeleteComponentInstance", id, mock.Anything).Return(nil) componentInstanceHandler = ci.NewComponentInstanceHandler(db, er) db.On("GetComponentInstances", filter).Return([]entity.ComponentInstance{}, nil) err := componentInstanceHandler.DeleteComponentInstance(id) diff --git a/internal/app/component_version/component_version_handler.go b/internal/app/component_version/component_version_handler.go index 109918ed..14b59a12 100644 --- a/internal/app/component_version/component_version_handler.go +++ b/internal/app/component_version/component_version_handler.go @@ -185,7 +185,13 @@ func (cv *componentVersionHandler) DeleteComponentVersion(id int64) error { "id": id, }) - err := cv.database.DeleteComponentVersion(id) + userId, err := common.GetCurrentUserId(cv.database) + if err != nil { + l.Error(err) + return NewComponentVersionHandlerError("Internal error while deleting componentVersion (GetUserId).") + } + + err = cv.database.DeleteComponentVersion(id, userId) if err != nil { l.Error(err) diff --git a/internal/app/component_version/component_version_handler_test.go b/internal/app/component_version/component_version_handler_test.go index 71c948b3..2ebea839 100644 --- a/internal/app/component_version/component_version_handler_test.go +++ b/internal/app/component_version/component_version_handler_test.go @@ -186,7 +186,8 @@ var _ = Describe("When deleting ComponentVersion", Label("app", "DeleteComponent }) It("deletes componentVersion", func() { - db.On("DeleteComponentVersion", id).Return(nil) + db.On("GetAllUserIds", mock.Anything).Return([]int64{}, nil) + db.On("DeleteComponentVersion", id, mock.Anything).Return(nil) componenVersionService = cv.NewComponentVersionHandler(db, er) db.On("GetComponentVersions", filter).Return([]entity.ComponentVersion{}, nil) err := componenVersionService.DeleteComponentVersion(id) diff --git a/internal/app/evidence/evidence_handler.go b/internal/app/evidence/evidence_handler.go index 95297de4..33ad74a7 100644 --- a/internal/app/evidence/evidence_handler.go +++ b/internal/app/evidence/evidence_handler.go @@ -172,7 +172,13 @@ func (e *evidenceHandler) DeleteEvidence(id int64) error { "id": id, }) - err := e.database.DeleteEvidence(id) + userId, err := common.GetCurrentUserId(e.database) + if err != nil { + l.Error(err) + return NewEvidenceHandlerError("Internal error while deleting evidence (GetUserId).") + } + + err = e.database.DeleteEvidence(id, userId) if err != nil { l.Error(err) diff --git a/internal/app/evidence/evidence_handler_test.go b/internal/app/evidence/evidence_handler_test.go index 1c2c5dbd..c4744571 100644 --- a/internal/app/evidence/evidence_handler_test.go +++ b/internal/app/evidence/evidence_handler_test.go @@ -202,7 +202,8 @@ var _ = Describe("When deleting Evidence", Label("app", "DeleteEvidence"), func( }) It("deletes evidence", func() { - db.On("DeleteEvidence", id).Return(nil) + db.On("GetAllUserIds", mock.Anything).Return([]int64{}, nil) + db.On("DeleteEvidence", id, mock.Anything).Return(nil) evidenceHandler = es.NewEvidenceHandler(db, er) db.On("GetEvidences", filter).Return([]entity.Evidence{}, nil) err := evidenceHandler.DeleteEvidence(id) diff --git a/internal/app/issue/issue_handler.go b/internal/app/issue/issue_handler.go index fac11df9..78cd2bf9 100644 --- a/internal/app/issue/issue_handler.go +++ b/internal/app/issue/issue_handler.go @@ -242,7 +242,13 @@ func (is *issueHandler) DeleteIssue(id int64) error { "id": id, }) - err := is.database.DeleteIssue(id) + userId, err := common.GetCurrentUserId(is.database) + if err != nil { + l.Error(err) + return NewIssueHandlerError("Internal error while deleting issue (GetUserId).") + } + + err = is.database.DeleteIssue(id, userId) if err != nil { l.Error(err) diff --git a/internal/app/issue/issue_handler_test.go b/internal/app/issue/issue_handler_test.go index 76100094..388a96aa 100644 --- a/internal/app/issue/issue_handler_test.go +++ b/internal/app/issue/issue_handler_test.go @@ -316,7 +316,8 @@ var _ = Describe("When deleting Issue", Label("app", "DeleteIssue"), func() { }) It("deletes issue", func() { - db.On("DeleteIssue", id).Return(nil) + db.On("GetAllUserIds", mock.Anything).Return([]int64{}, nil) + db.On("DeleteIssue", id, mock.Anything).Return(nil) issueHandler = issue.NewIssueHandler(db, er) db.On("GetIssues", filter).Return([]entity.Issue{}, nil) err := issueHandler.DeleteIssue(id) diff --git a/internal/app/issue_match/issue_match_handler.go b/internal/app/issue_match/issue_match_handler.go index 6191b451..c17e81b5 100644 --- a/internal/app/issue_match/issue_match_handler.go +++ b/internal/app/issue_match/issue_match_handler.go @@ -145,7 +145,7 @@ func (im *issueMatchHandler) CreateIssueMatch(issueMatch *entity.IssueMatch) (*e issueMatch.CreatedBy, err = common.GetCurrentUserId(im.database) if err != nil { l.Error(err) - return nil, NewIssueMatchHandlerError("Internal error while retrieving effective severity (GetUserId).") + return nil, NewIssueMatchHandlerError("Internal error while creating issueMatch (GetUserId).") } issueMatch.UpdatedBy = issueMatch.CreatedBy @@ -187,7 +187,7 @@ func (im *issueMatchHandler) UpdateIssueMatch(issueMatch *entity.IssueMatch) (*e issueMatch.UpdatedBy, err = common.GetCurrentUserId(im.database) if err != nil { l.Error(err) - return nil, NewIssueMatchHandlerError("Internal error while retrieving effective severity (GetUserId).") + return nil, NewIssueMatchHandlerError("Internal error while updating issueMatch (GetUserId).") } err = im.database.UpdateIssueMatch(issueMatch) @@ -210,7 +210,13 @@ func (im *issueMatchHandler) DeleteIssueMatch(id int64) error { "id": id, }) - err := im.database.DeleteIssueMatch(id) + userId, err := common.GetCurrentUserId(im.database) + if err != nil { + l.Error(err) + return NewIssueMatchHandlerError("Internal error while deleting issueMatch (GetUserId).") + } + + err = im.database.DeleteIssueMatch(id, userId) if err != nil { l.Error(err) diff --git a/internal/app/issue_match/issue_match_handler_test.go b/internal/app/issue_match/issue_match_handler_test.go index 5155e289..3e83f188 100644 --- a/internal/app/issue_match/issue_match_handler_test.go +++ b/internal/app/issue_match/issue_match_handler_test.go @@ -290,7 +290,8 @@ var _ = Describe("When deleting IssueMatch", Label("app", "DeleteIssueMatch"), f }) It("deletes issueMatch", func() { - db.On("DeleteIssueMatch", id).Return(nil) + db.On("GetAllUserIds", mock.Anything).Return([]int64{}, nil) + db.On("DeleteIssueMatch", id, mock.Anything).Return(nil) issueMatchHandler = im.NewIssueMatchHandler(db, er, nil) db.On("GetIssueMatches", filter).Return([]entity.IssueMatch{}, nil) err := issueMatchHandler.DeleteIssueMatch(id) diff --git a/internal/app/issue_match_change/issue_match_change_handler.go b/internal/app/issue_match_change/issue_match_change_handler.go index 66c27cb9..8bcd3121 100644 --- a/internal/app/issue_match_change/issue_match_change_handler.go +++ b/internal/app/issue_match_change/issue_match_change_handler.go @@ -180,7 +180,13 @@ func (imc *issueMatchChangeHandler) DeleteIssueMatchChange(id int64) error { "id": id, }) - err := imc.database.DeleteIssueMatchChange(id) + userId, err := common.GetCurrentUserId(imc.database) + if err != nil { + l.Error(err) + return NewIssueMatchChangeHandlerError("Internal error while deleting issueMatchChange (GetUserId).") + } + + err = imc.database.DeleteIssueMatchChange(id, userId) if err != nil { l.Error(err) diff --git a/internal/app/issue_match_change/issue_match_change_handler_test.go b/internal/app/issue_match_change/issue_match_change_handler_test.go index 48ffc9a7..4a0ca93d 100644 --- a/internal/app/issue_match_change/issue_match_change_handler_test.go +++ b/internal/app/issue_match_change/issue_match_change_handler_test.go @@ -192,7 +192,8 @@ var _ = Describe("When deleting IssueMatchChange", Label("app", "DeleteIssueMatc }) It("deletes issueMatchChange", func() { - db.On("DeleteIssueMatchChange", id).Return(nil) + db.On("GetAllUserIds", mock.Anything).Return([]int64{}, nil) + db.On("DeleteIssueMatchChange", id, mock.Anything).Return(nil) issueMatchChangeHandler = imc.NewIssueMatchChangeHandler(db, er) db.On("GetIssueMatchChanges", filter).Return([]entity.IssueMatchChange{}, nil) err := issueMatchChangeHandler.DeleteIssueMatchChange(id) diff --git a/internal/app/issue_repository/issue_repository_handler.go b/internal/app/issue_repository/issue_repository_handler.go index fb1d1d51..b11fadbb 100644 --- a/internal/app/issue_repository/issue_repository_handler.go +++ b/internal/app/issue_repository/issue_repository_handler.go @@ -187,7 +187,13 @@ func (ir *issueRepositoryHandler) DeleteIssueRepository(id int64) error { "id": id, }) - err := ir.database.DeleteIssueRepository(id) + userId, err := common.GetCurrentUserId(ir.database) + if err != nil { + l.Error(err) + return NewIssueRepositoryHandlerError("Internal error while deleting issueRepository (GetUserId).") + } + + err = ir.database.DeleteIssueRepository(id, userId) if err != nil { l.Error(err) diff --git a/internal/app/issue_repository/issue_repository_handler_test.go b/internal/app/issue_repository/issue_repository_handler_test.go index 70e1cb60..42a3b8e6 100644 --- a/internal/app/issue_repository/issue_repository_handler_test.go +++ b/internal/app/issue_repository/issue_repository_handler_test.go @@ -231,7 +231,8 @@ var _ = Describe("When deleting IssueRepository", Label("app", "DeleteIssueRepos }) It("deletes issueRepository", func() { - db.On("DeleteIssueRepository", id).Return(nil) + db.On("GetAllUserIds", mock.Anything).Return([]int64{}, nil) + db.On("DeleteIssueRepository", id, mock.Anything).Return(nil) issueRepositoryHandler = ir.NewIssueRepositoryHandler(db, er) db.On("GetIssueRepositories", filter).Return([]entity.IssueRepository{}, nil) err := issueRepositoryHandler.DeleteIssueRepository(id) diff --git a/internal/app/issue_variant/issue_variant_handler.go b/internal/app/issue_variant/issue_variant_handler.go index d21752f4..9af8fbef 100644 --- a/internal/app/issue_variant/issue_variant_handler.go +++ b/internal/app/issue_variant/issue_variant_handler.go @@ -253,7 +253,13 @@ func (iv *issueVariantHandler) DeleteIssueVariant(id int64) error { "id": id, }) - err := iv.database.DeleteIssueVariant(id) + userId, err := common.GetCurrentUserId(iv.database) + if err != nil { + l.Error(err) + return NewIssueVariantHandlerError("Internal error while deleting issueVariant (GetUserId).") + } + + err = iv.database.DeleteIssueVariant(id, userId) if err != nil { l.Error(err) diff --git a/internal/app/issue_variant/issue_variant_handler_test.go b/internal/app/issue_variant/issue_variant_handler_test.go index 12190e1f..e80c25e8 100644 --- a/internal/app/issue_variant/issue_variant_handler_test.go +++ b/internal/app/issue_variant/issue_variant_handler_test.go @@ -320,7 +320,8 @@ var _ = Describe("When deleting IssueVariant", Label("app", "DeleteIssueVariant" }) It("deletes issueVariant", func() { - db.On("DeleteIssueVariant", id).Return(nil) + db.On("GetAllUserIds", mock.Anything).Return([]int64{}, nil) + db.On("DeleteIssueVariant", id, mock.Anything).Return(nil) issueVariantHandler = iv.NewIssueVariantHandler(db, er, rs) db.On("GetIssueVariants", filter).Return([]entity.IssueVariant{}, nil) err := issueVariantHandler.DeleteIssueVariant(id) diff --git a/internal/app/service/service_handler.go b/internal/app/service/service_handler.go index 10c21373..1aad26dd 100644 --- a/internal/app/service/service_handler.go +++ b/internal/app/service/service_handler.go @@ -226,7 +226,13 @@ func (s *serviceHandler) DeleteService(id int64) error { "id": id, }) - err := s.database.DeleteService(id) + userId, err := common.GetCurrentUserId(s.database) + if err != nil { + l.Error(err) + return NewServiceHandlerError("Internal error while deleting service (GetUserId).") + } + + err = s.database.DeleteService(id, userId) if err != nil { l.Error(err) diff --git a/internal/app/service/service_handler_test.go b/internal/app/service/service_handler_test.go index 74de1554..e7bba8d6 100644 --- a/internal/app/service/service_handler_test.go +++ b/internal/app/service/service_handler_test.go @@ -374,7 +374,8 @@ var _ = Describe("When deleting Service", Label("app", "DeleteService"), func() }) It("deletes service", func() { - db.On("DeleteService", id).Return(nil) + db.On("GetAllUserIds", mock.Anything).Return([]int64{}, nil) + db.On("DeleteService", id, mock.Anything).Return(nil) serviceHandler = s.NewServiceHandler(db, er) db.On("GetServices", filter).Return([]entity.Service{}, nil) err := serviceHandler.DeleteService(id) diff --git a/internal/app/support_group/support_group_handler.go b/internal/app/support_group/support_group_handler.go index f26ca922..756019eb 100644 --- a/internal/app/support_group/support_group_handler.go +++ b/internal/app/support_group/support_group_handler.go @@ -206,7 +206,13 @@ func (sg *supportGroupHandler) DeleteSupportGroup(id int64) error { "id": id, }) - err := sg.database.DeleteSupportGroup(id) + userId, err := common.GetCurrentUserId(sg.database) + if err != nil { + l.Error(err) + return NewSupportGroupHandlerError("Internal error while deleting supportGroup (GetUserId).") + } + + err = sg.database.DeleteSupportGroup(id, userId) if err != nil { l.Error(err) diff --git a/internal/app/support_group/support_group_handler_test.go b/internal/app/support_group/support_group_handler_test.go index 9c622bcc..cd0f271b 100644 --- a/internal/app/support_group/support_group_handler_test.go +++ b/internal/app/support_group/support_group_handler_test.go @@ -196,7 +196,8 @@ var _ = Describe("When deleting SupportGroup", Label("app", "DeleteSupportGroup" }) It("deletes supportGroup", func() { - db.On("DeleteSupportGroup", id).Return(nil) + db.On("GetAllUserIds", mock.Anything).Return([]int64{}, nil) + db.On("DeleteSupportGroup", id, mock.Anything).Return(nil) supportGroupHandler = sg.NewSupportGroupHandler(db, er) db.On("GetSupportGroups", filter).Return([]entity.SupportGroup{}, nil) err := supportGroupHandler.DeleteSupportGroup(id) diff --git a/internal/app/user/user_handler.go b/internal/app/user/user_handler.go index 51cb82b6..d3630bc6 100644 --- a/internal/app/user/user_handler.go +++ b/internal/app/user/user_handler.go @@ -186,7 +186,13 @@ func (u *userHandler) DeleteUser(id int64) error { "id": id, }) - err := u.database.DeleteUser(id) + userId, err := common.GetCurrentUserId(u.database) + if err != nil { + l.Error(err) + return NewUserHandlerError("Internal error while deleting user (GetUserId).") + } + + err = u.database.DeleteUser(id, userId) if err != nil { l.Error(err) diff --git a/internal/app/user/user_handler_test.go b/internal/app/user/user_handler_test.go index 106ff4cd..0053451b 100644 --- a/internal/app/user/user_handler_test.go +++ b/internal/app/user/user_handler_test.go @@ -201,7 +201,8 @@ var _ = Describe("When deleting User", Label("app", "DeleteUser"), func() { }) It("deletes user", func() { - db.On("DeleteUser", id).Return(nil) + db.On("GetAllUserIds", mock.Anything).Return([]int64{}, nil) + db.On("DeleteUser", id, mock.Anything).Return(nil) userHandler = u.NewUserHandler(db, er) db.On("GetUsers", filter).Return([]entity.User{}, nil) err := userHandler.DeleteUser(id) diff --git a/internal/database/interface.go b/internal/database/interface.go index 6bc94636..682a806f 100644 --- a/internal/database/interface.go +++ b/internal/database/interface.go @@ -13,7 +13,7 @@ type Database interface { GetAllIssueIds(*entity.IssueFilter) ([]int64, error) CreateIssue(*entity.Issue) (*entity.Issue, error) UpdateIssue(*entity.Issue) error - DeleteIssue(int64) error + DeleteIssue(int64, int64) error AddComponentVersionToIssue(int64, int64) error RemoveComponentVersionFromIssue(int64, int64) error GetIssueNames(*entity.IssueFilter) ([]string, error) @@ -24,14 +24,14 @@ type Database interface { CountIssueVariants(*entity.IssueVariantFilter) (int64, error) CreateIssueVariant(*entity.IssueVariant) (*entity.IssueVariant, error) UpdateIssueVariant(*entity.IssueVariant) error - DeleteIssueVariant(int64) error + DeleteIssueVariant(int64, int64) error GetIssueRepositories(*entity.IssueRepositoryFilter) ([]entity.IssueRepository, error) GetAllIssueRepositoryIds(*entity.IssueRepositoryFilter) ([]int64, error) CountIssueRepositories(*entity.IssueRepositoryFilter) (int64, error) CreateIssueRepository(*entity.IssueRepository) (*entity.IssueRepository, error) UpdateIssueRepository(*entity.IssueRepository) error - DeleteIssueRepository(int64) error + DeleteIssueRepository(int64, int64) error GetDefaultIssuePriority() int64 GetDefaultRepositoryName() string @@ -40,14 +40,14 @@ type Database interface { CountIssueMatches(filter *entity.IssueMatchFilter) (int64, error) CreateIssueMatch(*entity.IssueMatch) (*entity.IssueMatch, error) UpdateIssueMatch(*entity.IssueMatch) error - DeleteIssueMatch(int64) error + DeleteIssueMatch(int64, int64) error GetIssueMatchChanges(*entity.IssueMatchChangeFilter) ([]entity.IssueMatchChange, error) GetAllIssueMatchChangeIds(*entity.IssueMatchChangeFilter) ([]int64, error) CountIssueMatchChanges(filter *entity.IssueMatchChangeFilter) (int64, error) CreateIssueMatchChange(*entity.IssueMatchChange) (*entity.IssueMatchChange, error) UpdateIssueMatchChange(*entity.IssueMatchChange) error - DeleteIssueMatchChange(int64) error + DeleteIssueMatchChange(int64, int64) error AddEvidenceToIssueMatch(int64, int64) error RemoveEvidenceFromIssueMatch(int64, int64) error @@ -57,7 +57,7 @@ type Database interface { CountServices(*entity.ServiceFilter) (int64, error) CreateService(*entity.Service) (*entity.Service, error) UpdateService(*entity.Service) error - DeleteService(int64) error + DeleteService(int64, int64) error AddOwnerToService(int64, int64) error RemoveOwnerFromService(int64, int64) error AddIssueRepositoryToService(int64, int64, int64) error @@ -69,7 +69,7 @@ type Database interface { CountUsers(*entity.UserFilter) (int64, error) CreateUser(*entity.User) (*entity.User, error) UpdateUser(*entity.User) error - DeleteUser(int64) error + DeleteUser(int64, int64) error GetUserNames(*entity.UserFilter) ([]string, error) GetUniqueUserIDs(*entity.UserFilter) ([]string, error) @@ -78,7 +78,7 @@ type Database interface { CountSupportGroups(*entity.SupportGroupFilter) (int64, error) CreateSupportGroup(*entity.SupportGroup) (*entity.SupportGroup, error) UpdateSupportGroup(*entity.SupportGroup) error - DeleteSupportGroup(int64) error + DeleteSupportGroup(int64, int64) error AddServiceToSupportGroup(int64, int64) error RemoveServiceFromSupportGroup(int64, int64) error AddUserToSupportGroup(int64, int64) error @@ -90,7 +90,7 @@ type Database interface { CountComponentInstances(*entity.ComponentInstanceFilter) (int64, error) CreateComponentInstance(*entity.ComponentInstance) (*entity.ComponentInstance, error) UpdateComponentInstance(*entity.ComponentInstance) error - DeleteComponentInstance(int64) error + DeleteComponentInstance(int64, int64) error GetComponentCcrns(filter *entity.ComponentFilter) ([]string, error) GetCcrn(filter *entity.ComponentInstanceFilter) ([]string, error) @@ -99,7 +99,7 @@ type Database interface { CountActivities(*entity.ActivityFilter) (int64, error) CreateActivity(*entity.Activity) (*entity.Activity, error) UpdateActivity(*entity.Activity) error - DeleteActivity(int64) error + DeleteActivity(int64, int64) error AddServiceToActivity(int64, int64) error RemoveServiceFromActivity(int64, int64) error AddIssueToActivity(int64, int64) error @@ -110,21 +110,21 @@ type Database interface { CountEvidences(*entity.EvidenceFilter) (int64, error) CreateEvidence(*entity.Evidence) (*entity.Evidence, error) UpdateEvidence(*entity.Evidence) error - DeleteEvidence(int64) error + DeleteEvidence(int64, int64) error GetComponents(*entity.ComponentFilter) ([]entity.Component, error) GetAllComponentIds(*entity.ComponentFilter) ([]int64, error) CountComponents(*entity.ComponentFilter) (int64, error) CreateComponent(*entity.Component) (*entity.Component, error) UpdateComponent(*entity.Component) error - DeleteComponent(int64) error + DeleteComponent(int64, int64) error GetComponentVersions(*entity.ComponentVersionFilter) ([]entity.ComponentVersion, error) GetAllComponentVersionIds(*entity.ComponentVersionFilter) ([]int64, error) CountComponentVersions(*entity.ComponentVersionFilter) (int64, error) CreateComponentVersion(*entity.ComponentVersion) (*entity.ComponentVersion, error) UpdateComponentVersion(*entity.ComponentVersion) error - DeleteComponentVersion(int64) error + DeleteComponentVersion(int64, int64) error CloseConnection() error } diff --git a/internal/database/mariadb/activity.go b/internal/database/mariadb/activity.go index bec47c8c..5125da86 100644 --- a/internal/database/mariadb/activity.go +++ b/internal/database/mariadb/activity.go @@ -58,7 +58,7 @@ func (s *SqlDatabase) getActivityFilterString(filter *entity.ActivityFilter) str fl = append(fl, buildFilterQuery(filter.ServiceCCRN, "S.service_ccrn= ?", OP_OR)) fl = append(fl, buildFilterQuery(filter.EvidenceId, "E.evidence_id = ?", OP_OR)) fl = append(fl, buildFilterQuery(filter.IssueId, "AHI.activityhasissue_issue_id = ?", OP_OR)) - fl = append(fl, "A.activity_deleted_at IS NULL") + fl = appendStateFilterQuery(fl, "A.activity", filter.State) return combineFilterQueries(fl, OP_AND) } @@ -259,7 +259,7 @@ func (s *SqlDatabase) UpdateActivity(activity *entity.Activity) error { return err } -func (s *SqlDatabase) DeleteActivity(id int64) error { +func (s *SqlDatabase) DeleteActivity(id int64, userId int64) error { l := logrus.WithFields(logrus.Fields{ "id": id, "event": "database.DeleteActivity", @@ -267,12 +267,14 @@ func (s *SqlDatabase) DeleteActivity(id int64) error { query := ` UPDATE Activity SET - activity_deleted_at = NOW() + activity_deleted_at = NOW(), + activity_updated_by = :userId WHERE activity_id = :id ` args := map[string]interface{}{ - "id": id, + "userId": userId, + "id": id, } _, err := performExec(s, query, args, l) diff --git a/internal/database/mariadb/activity_test.go b/internal/database/mariadb/activity_test.go index 05238133..7c6c9472 100644 --- a/internal/database/mariadb/activity_test.go +++ b/internal/database/mariadb/activity_test.go @@ -487,7 +487,7 @@ var _ = Describe("Activity", Label("database", "Activity"), func() { It("can delete activity correctly", func() { activity := seedCollection.ActivityRows[0].AsActivity() - err := db.DeleteActivity(activity.Id) + err := db.DeleteActivity(activity.Id, systemUserId) By("throwing no error", func() { Expect(err).To(BeNil()) diff --git a/internal/database/mariadb/common_test.go b/internal/database/mariadb/common_test.go new file mode 100644 index 00000000..985febf3 --- /dev/null +++ b/internal/database/mariadb/common_test.go @@ -0,0 +1,6 @@ +// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Greenhouse contributors +// SPDX-License-Identifier: Apache-2.0 + +package mariadb_test + +const systemUserId = 1 diff --git a/internal/database/mariadb/component.go b/internal/database/mariadb/component.go index 5a52f00d..3489d441 100644 --- a/internal/database/mariadb/component.go +++ b/internal/database/mariadb/component.go @@ -17,7 +17,7 @@ func (s *SqlDatabase) getComponentFilterString(filter *entity.ComponentFilter) s fl = append(fl, buildFilterQuery(filter.CCRN, "C.component_ccrn = ?", OP_OR)) fl = append(fl, buildFilterQuery(filter.Id, "C.component_id = ?", OP_OR)) fl = append(fl, buildFilterQuery(filter.ComponentVersionId, "CV.componentversion_id = ?", OP_OR)) - fl = append(fl, "C.component_deleted_at IS NULL") + fl = appendStateFilterQuery(fl, "C.component", filter.State) return combineFilterQueries(fl, OP_AND) } @@ -254,7 +254,7 @@ func (s *SqlDatabase) UpdateComponent(component *entity.Component) error { return err } -func (s *SqlDatabase) DeleteComponent(id int64) error { +func (s *SqlDatabase) DeleteComponent(id int64, userId int64) error { l := logrus.WithFields(logrus.Fields{ "id": id, "event": "database.DeleteComponent", @@ -262,12 +262,14 @@ func (s *SqlDatabase) DeleteComponent(id int64) error { query := ` UPDATE Component SET - component_deleted_at = NOW() + component_deleted_at = NOW(), + component_updated_by = :userId WHERE component_id = :id ` args := map[string]interface{}{ - "id": id, + "userId": userId, + "id": id, } _, err := performExec(s, query, args, l) diff --git a/internal/database/mariadb/component_instance.go b/internal/database/mariadb/component_instance.go index c80c3af2..68aa9786 100644 --- a/internal/database/mariadb/component_instance.go +++ b/internal/database/mariadb/component_instance.go @@ -49,7 +49,7 @@ func (s *SqlDatabase) getComponentInstanceFilterString(filter *entity.ComponentI fl = append(fl, buildFilterQuery(filter.ComponentVersionId, "CI.componentinstance_component_version_id = ?", OP_OR)) fl = append(fl, buildFilterQuery(filter.CCRN, "CI.componentinstance_ccrn = ?", OP_OR)) fl = append(fl, buildFilterQuery(filter.Search, componentInstanceWildCardFilterQuery, OP_OR)) - fl = append(fl, "CI.componentinstance_deleted_at IS NULL") + fl = appendStateFilterQuery(fl, "CI.componentinstance", filter.State) filterStr := combineFilterQueries(fl, OP_AND) return filterStr @@ -278,7 +278,7 @@ func (s *SqlDatabase) UpdateComponentInstance(componentInstance *entity.Componen return err } -func (s *SqlDatabase) DeleteComponentInstance(id int64) error { +func (s *SqlDatabase) DeleteComponentInstance(id int64, userId int64) error { l := logrus.WithFields(logrus.Fields{ "id": id, "event": "database.DeleteComponentInstance", @@ -286,12 +286,14 @@ func (s *SqlDatabase) DeleteComponentInstance(id int64) error { query := ` UPDATE ComponentInstance SET - componentinstance_deleted_at = NOW() + componentinstance_deleted_at = NOW(), + componentinstance_updated_by = :userId WHERE componentinstance_id = :id ` args := map[string]interface{}{ - "id": id, + "userId": userId, + "id": id, } _, err := performExec(s, query, args, l) diff --git a/internal/database/mariadb/component_instance_test.go b/internal/database/mariadb/component_instance_test.go index e71511a5..4769f7b6 100644 --- a/internal/database/mariadb/component_instance_test.go +++ b/internal/database/mariadb/component_instance_test.go @@ -546,7 +546,7 @@ var _ = Describe("ComponentInstance - ", Label("database", "ComponentInstance"), It("can delete componentInstance correctly", func() { componentInstance := seedCollection.ComponentInstanceRows[0].AsComponentInstance() - err := db.DeleteComponentInstance(componentInstance.Id) + err := db.DeleteComponentInstance(componentInstance.Id, systemUserId) By("throwing no error", func() { Expect(err).To(BeNil()) diff --git a/internal/database/mariadb/component_test.go b/internal/database/mariadb/component_test.go index 30fe938a..87324c09 100644 --- a/internal/database/mariadb/component_test.go +++ b/internal/database/mariadb/component_test.go @@ -460,7 +460,7 @@ var _ = Describe("Component", Label("database", "Component"), func() { It("can delete component correctly", func() { component := seedCollection.ComponentRows[0].AsComponent() - err := db.DeleteComponent(component.Id) + err := db.DeleteComponent(component.Id, systemUserId) By("throwing no error", func() { Expect(err).To(BeNil()) diff --git a/internal/database/mariadb/component_version.go b/internal/database/mariadb/component_version.go index 41456747..aa7f0a73 100644 --- a/internal/database/mariadb/component_version.go +++ b/internal/database/mariadb/component_version.go @@ -70,7 +70,7 @@ func (s *SqlDatabase) getComponentVersionFilterString(filter *entity.ComponentVe fl = append(fl, buildFilterQuery(filter.ComponentId, "CV.componentversion_component_id = ?", OP_OR)) fl = append(fl, buildFilterQuery(filter.Version, "CV.componentversion_version = ?", OP_OR)) fl = append(fl, buildFilterQuery(filter.ComponentCCRN, "C.component_ccrn = ?", OP_OR)) - fl = append(fl, "CV.componentversion_deleted_at IS NULL") + fl = appendStateFilterQuery(fl, "CV.componentversion", filter.State) return combineFilterQueries(fl, OP_AND) } @@ -264,7 +264,7 @@ func (s *SqlDatabase) UpdateComponentVersion(componentVersion *entity.ComponentV return err } -func (s *SqlDatabase) DeleteComponentVersion(id int64) error { +func (s *SqlDatabase) DeleteComponentVersion(id int64, userId int64) error { l := logrus.WithFields(logrus.Fields{ "id": id, "event": "database.DeleteComponentVersion", @@ -272,12 +272,14 @@ func (s *SqlDatabase) DeleteComponentVersion(id int64) error { query := ` UPDATE ComponentVersion SET - componentversion_deleted_at = NOW() + componentversion_deleted_at = NOW(), + componentversion_updated_by = :userId WHERE componentversion_id = :id ` args := map[string]interface{}{ - "id": id, + "userId": userId, + "id": id, } _, err := performExec(s, query, args, l) diff --git a/internal/database/mariadb/database.go b/internal/database/mariadb/database.go index 55dd60a8..c16a7009 100644 --- a/internal/database/mariadb/database.go +++ b/internal/database/mariadb/database.go @@ -391,3 +391,12 @@ func getCursor(p entity.Paginated, filterStr string, stmt string) entity.Cursor Limit: limit, } } + +func appendStateFilterQuery(query []string, prefix string, state entity.StateFilterType) []string { + if state == entity.Active { + query = append(query, fmt.Sprintf("%s_deleted_at IS NULL", prefix)) + } else if state == entity.Deleted { + query = append(query, fmt.Sprintf("%s_deleted_at IS NOT NULL", prefix)) + } + return query +} diff --git a/internal/database/mariadb/evidence.go b/internal/database/mariadb/evidence.go index 89845f96..88e11535 100644 --- a/internal/database/mariadb/evidence.go +++ b/internal/database/mariadb/evidence.go @@ -48,7 +48,7 @@ func (s *SqlDatabase) getEvidenceFilterString(filter *entity.EvidenceFilter) str fl = append(fl, buildFilterQuery(filter.ActivityId, "E.evidence_activity_id = ?", OP_OR)) fl = append(fl, buildFilterQuery(filter.UserId, "E.author_id = ?", OP_OR)) fl = append(fl, buildFilterQuery(filter.IssueMatchId, "IME.issuematchevidence_issue_match_id = ?", OP_OR)) - fl = append(fl, "E.evidence_deleted_at IS NULL") + fl = appendStateFilterQuery(fl, "E.evidence", filter.State) return combineFilterQueries(fl, OP_AND) } @@ -277,7 +277,7 @@ func (s *SqlDatabase) UpdateEvidence(evidence *entity.Evidence) error { return err } -func (s *SqlDatabase) DeleteEvidence(id int64) error { +func (s *SqlDatabase) DeleteEvidence(id int64, userId int64) error { l := logrus.WithFields(logrus.Fields{ "id": id, "event": "database.DeleteEvidence", @@ -285,12 +285,14 @@ func (s *SqlDatabase) DeleteEvidence(id int64) error { query := ` UPDATE Evidence SET - evidence_deleted_at = NOW() + evidence_deleted_at = NOW(), + evidence_updated_by = :userId WHERE evidence_id = :id ` args := map[string]interface{}{ - "id": id, + "userId": userId, + "id": id, } _, err := performExec(s, query, args, l) diff --git a/internal/database/mariadb/evidence_test.go b/internal/database/mariadb/evidence_test.go index cb4099e8..5a1db9ac 100644 --- a/internal/database/mariadb/evidence_test.go +++ b/internal/database/mariadb/evidence_test.go @@ -417,7 +417,7 @@ var _ = Describe("Evidence", Label("database", "Evidence"), func() { It("can delete evidence correctly", func() { evidence := seedCollection.EvidenceRows[0].AsEvidence() - err := db.DeleteEvidence(evidence.Id) + err := db.DeleteEvidence(evidence.Id, systemUserId) By("throwing no error", func() { Expect(err).To(BeNil()) diff --git a/internal/database/mariadb/issue.go b/internal/database/mariadb/issue.go index a56b9ebc..98e090a1 100644 --- a/internal/database/mariadb/issue.go +++ b/internal/database/mariadb/issue.go @@ -51,7 +51,7 @@ func (s *SqlDatabase) getIssueFilterString(filter *entity.IssueFilter) string { fl = append(fl, buildFilterQuery(filter.Type, "I.issue_type = ?", OP_OR)) fl = append(fl, buildFilterQuery(filter.PrimaryName, "I.issue_primary_name = ?", OP_OR)) fl = append(fl, buildFilterQuery(filter.Search, wildCardFilterQuery, OP_OR)) - fl = append(fl, "I.issue_deleted_at IS NULL") + fl = appendStateFilterQuery(fl, "I.issue", filter.State) return combineFilterQueries(fl, OP_AND) } @@ -457,7 +457,7 @@ func (s *SqlDatabase) UpdateIssue(issue *entity.Issue) error { return err } -func (s *SqlDatabase) DeleteIssue(id int64) error { +func (s *SqlDatabase) DeleteIssue(id int64, userId int64) error { l := logrus.WithFields(logrus.Fields{ "id": id, "event": "database.DeleteIssue", @@ -465,12 +465,14 @@ func (s *SqlDatabase) DeleteIssue(id int64) error { query := ` UPDATE Issue SET - issue_deleted_at = NOW() + issue_deleted_at = NOW(), + issue_updated_by = :userId WHERE issue_id = :id ` args := map[string]interface{}{ - "id": id, + "userId": userId, + "id": id, } _, err := performExec(s, query, args, l) diff --git a/internal/database/mariadb/issue_match.go b/internal/database/mariadb/issue_match.go index 6ba5466a..a93dc247 100644 --- a/internal/database/mariadb/issue_match.go +++ b/internal/database/mariadb/issue_match.go @@ -42,7 +42,7 @@ func (s *SqlDatabase) getIssueMatchFilterString(filter *entity.IssueMatchFilter) fl = append(fl, buildFilterQuery(filter.ComponentCCRN, "C.component_ccrn = ?", OP_OR)) fl = append(fl, buildFilterQuery(filter.IssueType, "I.issue_type = ?", OP_OR)) fl = append(fl, buildFilterQuery(filter.Search, wildCardFilterQuery, OP_OR)) - fl = append(fl, "IM.issuematch_deleted_at IS NULL") + fl = appendStateFilterQuery(fl, "IM.issuematch", filter.State) return combineFilterQueries(fl, OP_AND) } @@ -328,7 +328,7 @@ func (s *SqlDatabase) UpdateIssueMatch(issueMatch *entity.IssueMatch) error { return err } -func (s *SqlDatabase) DeleteIssueMatch(id int64) error { +func (s *SqlDatabase) DeleteIssueMatch(id int64, userId int64) error { l := logrus.WithFields(logrus.Fields{ "id": id, "event": "database.DeleteIssueMatch", @@ -336,12 +336,14 @@ func (s *SqlDatabase) DeleteIssueMatch(id int64) error { query := ` UPDATE IssueMatch SET - issuematch_deleted_at = NOW() + issuematch_deleted_at = NOW(), + issuematch_updated_by = :userId WHERE issuematch_id = :id ` args := map[string]interface{}{ - "id": id, + "userId": userId, + "id": id, } _, err := performExec(s, query, args, l) diff --git a/internal/database/mariadb/issue_match_change.go b/internal/database/mariadb/issue_match_change.go index edd67daf..59b2ed2f 100644 --- a/internal/database/mariadb/issue_match_change.go +++ b/internal/database/mariadb/issue_match_change.go @@ -37,7 +37,7 @@ func (s *SqlDatabase) getIssueMatchChangeFilterString(filter *entity.IssueMatchC fl = append(fl, buildFilterQuery(filter.ActivityId, "IMC.issuematchchange_activity_id = ?", OP_OR)) fl = append(fl, buildFilterQuery(filter.IssueMatchId, "IMC.issuematchchange_issue_match_id = ?", OP_OR)) fl = append(fl, buildFilterQuery(filter.Action, "IMC.issuematchchange_action = ?", OP_OR)) - fl = append(fl, "IMC.issuematchchange_deleted_at IS NULL") + fl = appendStateFilterQuery(fl, "IMC.issuematchchange", filter.State) return combineFilterQueries(fl, OP_AND) } @@ -234,7 +234,7 @@ func (s *SqlDatabase) UpdateIssueMatchChange(imc *entity.IssueMatchChange) error return err } -func (s *SqlDatabase) DeleteIssueMatchChange(id int64) error { +func (s *SqlDatabase) DeleteIssueMatchChange(id int64, userId int64) error { l := logrus.WithFields(logrus.Fields{ "id": id, "event": "database.DeleteIssueMatchChange", @@ -242,12 +242,14 @@ func (s *SqlDatabase) DeleteIssueMatchChange(id int64) error { query := ` UPDATE IssueMatchChange SET - issuematchchange_deleted_at = NOW() + issuematchchange_deleted_at = NOW(), + issuematchchange_updated_by = :userId WHERE issuematchchange_id = :id ` args := map[string]interface{}{ - "id": id, + "userId": userId, + "id": id, } _, err := performExec(s, query, args, l) diff --git a/internal/database/mariadb/issue_match_change_test.go b/internal/database/mariadb/issue_match_change_test.go index d021dcad..09f870ee 100644 --- a/internal/database/mariadb/issue_match_change_test.go +++ b/internal/database/mariadb/issue_match_change_test.go @@ -451,7 +451,7 @@ var _ = Describe("IssueMatchChange", Label("database", "IssueMatchChange"), func It("can delete issueMatchChange correctly", func() { imc := seedCollection.IssueMatchChangeRows[0].AsIssueMatchChange() - err := db.DeleteIssueMatchChange(imc.Id) + err := db.DeleteIssueMatchChange(imc.Id, systemUserId) By("throwing no error", func() { Expect(err).To(BeNil()) diff --git a/internal/database/mariadb/issue_match_test.go b/internal/database/mariadb/issue_match_test.go index 46dfd8fa..dcbc0b40 100644 --- a/internal/database/mariadb/issue_match_test.go +++ b/internal/database/mariadb/issue_match_test.go @@ -546,7 +546,7 @@ var _ = Describe("IssueMatch", Label("database", "IssueMatch"), func() { It("can delete issueMatch correctly", func() { issueMatch := seedCollection.IssueMatchRows[0].AsIssueMatch() - err := db.DeleteIssueMatch(issueMatch.Id) + err := db.DeleteIssueMatch(issueMatch.Id, systemUserId) By("throwing no error", func() { Expect(err).To(BeNil()) diff --git a/internal/database/mariadb/issue_repository.go b/internal/database/mariadb/issue_repository.go index a86840e6..38862331 100644 --- a/internal/database/mariadb/issue_repository.go +++ b/internal/database/mariadb/issue_repository.go @@ -18,7 +18,7 @@ func (s *SqlDatabase) getIssueRepositoryFilterString(filter *entity.IssueReposit fl = append(fl, buildFilterQuery(filter.Id, "IR.issuerepository_id = ?", OP_OR)) fl = append(fl, buildFilterQuery(filter.ServiceCCRN, "S.service_ccrn = ?", OP_OR)) fl = append(fl, buildFilterQuery(filter.ServiceId, "IRS.issuerepositoryservice_service_id = ?", OP_OR)) - fl = append(fl, "IR.issuerepository_deleted_at IS NULL") + fl = appendStateFilterQuery(fl, "IR.issuerepository", filter.State) return combineFilterQueries(fl, OP_AND) } @@ -270,7 +270,7 @@ func (s *SqlDatabase) UpdateIssueRepository(issueRepository *entity.IssueReposit return err } -func (s *SqlDatabase) DeleteIssueRepository(id int64) error { +func (s *SqlDatabase) DeleteIssueRepository(id int64, userId int64) error { l := logrus.WithFields(logrus.Fields{ "id": id, "event": "database.DeleteIssueRepository", @@ -278,12 +278,14 @@ func (s *SqlDatabase) DeleteIssueRepository(id int64) error { query := ` UPDATE IssueRepository SET - issuerepository_deleted_at = NOW() + issuerepository_deleted_at = NOW(), + issuerepository_updated_by = :userId WHERE issuerepository_id = :id ` args := map[string]interface{}{ - "id": id, + "userId": userId, + "id": id, } _, err := performExec(s, query, args, l) diff --git a/internal/database/mariadb/issue_repository_test.go b/internal/database/mariadb/issue_repository_test.go index 5bd2c4c5..7a43f034 100644 --- a/internal/database/mariadb/issue_repository_test.go +++ b/internal/database/mariadb/issue_repository_test.go @@ -467,7 +467,7 @@ var _ = Describe("IssueRepository", Label("database", "IssueRepository"), func() It("can delete issueRepository correctly", func() { issueRepository := seedCollection.IssueRepositoryRows[0].AsIssueRepository() - err := db.DeleteIssueRepository(issueRepository.Id) + err := db.DeleteIssueRepository(issueRepository.Id, systemUserId) By("throwing no error", func() { Expect(err).To(BeNil()) diff --git a/internal/database/mariadb/issue_test.go b/internal/database/mariadb/issue_test.go index 20c98363..1645fc5c 100644 --- a/internal/database/mariadb/issue_test.go +++ b/internal/database/mariadb/issue_test.go @@ -678,7 +678,7 @@ var _ = Describe("Issue", Label("database", "Issue"), func() { It("can delete issue correctly", func() { issue := seedCollection.IssueRows[0].AsIssue() - err := db.DeleteIssue(issue.Id) + err := db.DeleteIssue(issue.Id, systemUserId) By("throwing no error", func() { Expect(err).To(BeNil()) diff --git a/internal/database/mariadb/issue_variant.go b/internal/database/mariadb/issue_variant.go index 400fc193..ace02f3e 100644 --- a/internal/database/mariadb/issue_variant.go +++ b/internal/database/mariadb/issue_variant.go @@ -71,7 +71,7 @@ func (s *SqlDatabase) getIssueVariantFilterString(filter *entity.IssueVariantFil fl = append(fl, buildFilterQuery(filter.IssueRepositoryId, "IV.issuevariant_repository_id = ?", OP_OR)) fl = append(fl, buildFilterQuery(filter.ServiceId, "IRS.issuerepositoryservice_service_id = ?", OP_OR)) fl = append(fl, buildFilterQuery(filter.IssueMatchId, "IM.issuematch_id = ?", OP_OR)) - fl = append(fl, "IV.issuevariant_deleted_at IS NULL") + fl = appendStateFilterQuery(fl, "IV.issuevariant", filter.State) return combineFilterQueries(fl, OP_AND) } @@ -299,7 +299,7 @@ func (s *SqlDatabase) UpdateIssueVariant(issueVariant *entity.IssueVariant) erro return err } -func (s *SqlDatabase) DeleteIssueVariant(id int64) error { +func (s *SqlDatabase) DeleteIssueVariant(id int64, userId int64) error { l := logrus.WithFields(logrus.Fields{ "id": id, "event": "database.DeleteIssueVariant", @@ -307,12 +307,14 @@ func (s *SqlDatabase) DeleteIssueVariant(id int64) error { query := ` UPDATE IssueVariant SET - issuevariant_deleted_at = NOW() + issuevariant_deleted_at = NOW(), + issuevariant_updated_by = :userId WHERE issuevariant_id = :id ` args := map[string]interface{}{ - "id": id, + "userId": userId, + "id": id, } _, err := performExec(s, query, args, l) diff --git a/internal/database/mariadb/issue_variant_test.go b/internal/database/mariadb/issue_variant_test.go index 3e622410..f1c5048b 100644 --- a/internal/database/mariadb/issue_variant_test.go +++ b/internal/database/mariadb/issue_variant_test.go @@ -551,7 +551,7 @@ var _ = Describe("IssueVariant - ", Label("database", "IssueVariant"), func() { ir := seedCollection.IssueRepositoryRows[0].AsIssueRepository() issueVariant := seedCollection.IssueVariantRows[0].AsIssueVariant(&ir) - err := db.DeleteIssueVariant(issueVariant.Id) + err := db.DeleteIssueVariant(issueVariant.Id, systemUserId) By("throwing no error", func() { Expect(err).To(BeNil()) diff --git a/internal/database/mariadb/service.go b/internal/database/mariadb/service.go index 5421679a..257d747a 100644 --- a/internal/database/mariadb/service.go +++ b/internal/database/mariadb/service.go @@ -47,7 +47,7 @@ func (s *SqlDatabase) getServiceFilterString(filter *entity.ServiceFilter) strin fl = append(fl, buildFilterQuery(filter.SupportGroupId, "SGS.supportgroupservice_support_group_id = ?", OP_OR)) fl = append(fl, buildFilterQuery(filter.OwnerId, "O.owner_user_id = ?", OP_OR)) fl = append(fl, buildFilterQuery(filter.Search, serviceWildCardFilterQuery, OP_OR)) - fl = append(fl, "S.service_deleted_at IS NULL") + fl = appendStateFilterQuery(fl, "S.service", filter.State) return combineFilterQueries(fl, OP_AND) } @@ -392,7 +392,7 @@ func (s *SqlDatabase) UpdateService(service *entity.Service) error { return err } -func (s *SqlDatabase) DeleteService(id int64) error { +func (s *SqlDatabase) DeleteService(id int64, userId int64) error { l := logrus.WithFields(logrus.Fields{ "id": id, "event": "database.DeleteService", @@ -400,12 +400,14 @@ func (s *SqlDatabase) DeleteService(id int64) error { query := ` UPDATE Service SET - service_deleted_at = NOW() + service_deleted_at = NOW(), + service_updated_by = :userId WHERE service_id = :id ` args := map[string]interface{}{ - "id": id, + "userId": userId, + "id": id, } _, err := performExec(s, query, args, l) diff --git a/internal/database/mariadb/service_issue_variant.go b/internal/database/mariadb/service_issue_variant.go index d35a0938..43aaf266 100644 --- a/internal/database/mariadb/service_issue_variant.go +++ b/internal/database/mariadb/service_issue_variant.go @@ -36,7 +36,7 @@ func (s *SqlDatabase) getServiceIssueVariantFilterString(filter *entity.ServiceI var fl []string fl = append(fl, buildFilterQuery(filter.ComponentInstanceId, "CI.componentinstance_id = ?", OP_OR)) fl = append(fl, buildFilterQuery(filter.IssueId, "I.issue_id = ?", OP_OR)) - fl = append(fl, "IV.issuevariant_deleted_at IS NULL") + fl = appendStateFilterQuery(fl, "IV.issuevariant", filter.State) return combineFilterQueries(fl, OP_AND) } diff --git a/internal/database/mariadb/service_test.go b/internal/database/mariadb/service_test.go index 4479f3a9..f6c0165e 100644 --- a/internal/database/mariadb/service_test.go +++ b/internal/database/mariadb/service_test.go @@ -679,7 +679,7 @@ var _ = Describe("Service", Label("database", "Service"), func() { It("can delete service correctly", func() { service := seedCollection.ServiceRows[0].AsService() - err := db.DeleteService(service.Id) + err := db.DeleteService(service.Id, systemUserId) By("throwing no error", func() { Expect(err).To(BeNil()) diff --git a/internal/database/mariadb/support_group.go b/internal/database/mariadb/support_group.go index e2c43dbb..fce40a2a 100644 --- a/internal/database/mariadb/support_group.go +++ b/internal/database/mariadb/support_group.go @@ -18,7 +18,7 @@ func (s *SqlDatabase) getSupportGroupFilterString(filter *entity.SupportGroupFil fl = append(fl, buildFilterQuery(filter.ServiceId, "SGS.supportgroupservice_service_id = ?", OP_OR)) fl = append(fl, buildFilterQuery(filter.CCRN, "SG.supportgroup_ccrn = ?", OP_OR)) fl = append(fl, buildFilterQuery(filter.UserId, "SGU.supportgroupuser_user_id = ?", OP_OR)) - fl = append(fl, "SG.supportgroup_deleted_at IS NULL") + fl = appendStateFilterQuery(fl, "SG.supportgroup", filter.State) return combineFilterQueries(fl, OP_AND) } @@ -257,7 +257,7 @@ func (s *SqlDatabase) UpdateSupportGroup(supportGroup *entity.SupportGroup) erro return err } -func (s *SqlDatabase) DeleteSupportGroup(id int64) error { +func (s *SqlDatabase) DeleteSupportGroup(id int64, userId int64) error { l := logrus.WithFields(logrus.Fields{ "id": id, "event": "database.DeleteSupportGroup", @@ -265,12 +265,14 @@ func (s *SqlDatabase) DeleteSupportGroup(id int64) error { query := ` UPDATE SupportGroup SET - supportgroup_deleted_at = NOW() + supportgroup_deleted_at = NOW(), + supportgroup_updated_by = :userId WHERE supportgroup_id = :id ` args := map[string]interface{}{ - "id": id, + "userId": userId, + "id": id, } _, err := performExec(s, query, args, l) diff --git a/internal/database/mariadb/support_group_test.go b/internal/database/mariadb/support_group_test.go index a94986ac..6314cfa6 100644 --- a/internal/database/mariadb/support_group_test.go +++ b/internal/database/mariadb/support_group_test.go @@ -388,7 +388,7 @@ var _ = Describe("SupportGroup", Label("database", "SupportGroup"), func() { It("can delete supportGroup correctly", func() { supportGroup := seedCollection.SupportGroupRows[0].AsSupportGroup() - err := db.DeleteSupportGroup(supportGroup.Id) + err := db.DeleteSupportGroup(supportGroup.Id, systemUserId) By("throwing no error", func() { Expect(err).To(BeNil()) diff --git a/internal/database/mariadb/user.go b/internal/database/mariadb/user.go index f4b916a8..96728d89 100644 --- a/internal/database/mariadb/user.go +++ b/internal/database/mariadb/user.go @@ -20,7 +20,7 @@ func (s *SqlDatabase) getUserFilterString(filter *entity.UserFilter) string { fl = append(fl, buildFilterQuery(filter.Type, "U.user_type = ?", OP_OR)) fl = append(fl, buildFilterQuery(filter.SupportGroupId, "SGU.supportgroupuser_support_group_id = ?", OP_OR)) fl = append(fl, buildFilterQuery(filter.ServiceId, "O.owner_service_id = ?", OP_OR)) - fl = append(fl, "U.user_deleted_at IS NULL") + fl = appendStateFilterQuery(fl, "U.user", filter.State) return combineFilterQueries(fl, OP_AND) } @@ -272,7 +272,7 @@ func (s *SqlDatabase) UpdateUser(user *entity.User) error { return err } -func (s *SqlDatabase) DeleteUser(id int64) error { +func (s *SqlDatabase) DeleteUser(id int64, userId int64) error { l := logrus.WithFields(logrus.Fields{ "id": id, "event": "database.DeleteUser", @@ -280,12 +280,14 @@ func (s *SqlDatabase) DeleteUser(id int64) error { query := ` UPDATE User SET - user_deleted_at = NOW() + user_deleted_at = NOW(), + user_updated_by = :userId WHERE user_id = :id ` args := map[string]interface{}{ - "id": id, + "userId": userId, + "id": id, } _, err := performExec(s, query, args, l) diff --git a/internal/database/mariadb/user_test.go b/internal/database/mariadb/user_test.go index 9e80c14f..edd04558 100644 --- a/internal/database/mariadb/user_test.go +++ b/internal/database/mariadb/user_test.go @@ -528,7 +528,7 @@ var _ = Describe("User", Label("database", "User"), func() { It("can delete user correctly", func() { user := seedCollection.UserRows[0].AsUser() - err := db.DeleteUser(user.Id) + err := db.DeleteUser(user.Id, systemUserId) By("throwing no error", func() { Expect(err).To(BeNil()) diff --git a/internal/e2e/common/issue.go b/internal/e2e/common/issue.go index 8fc26276..0a05d336 100644 --- a/internal/e2e/common/issue.go +++ b/internal/e2e/common/issue.go @@ -9,6 +9,7 @@ import ( "os" "github.com/cloudoperators/heureka/internal/api/graphql/graph/model" + "github.com/cloudoperators/heureka/internal/entity" util2 "github.com/cloudoperators/heureka/pkg/util" "github.com/machinebox/graphql" @@ -77,6 +78,30 @@ func QueryUpdateIssue(port string, issue Issue, iid string) *model.Issue { return &respData.Issue } +func QueryDeleteIssue(port string, iid string) string { + // create a queryCollection (safe to share across requests) + client := graphql.NewClient(fmt.Sprintf("http://localhost:%s/query", port)) + + //@todo may need to make this more fault proof?! What if the test is executed from the root dir? does it still work? + b, err := os.ReadFile("../api/graphql/graph/queryCollection/issue/delete.graphql") + Expect(err).To(BeNil()) + str := string(b) + req := graphql.NewRequest(str) + + req.Var("id", iid) + + req.Header.Set("Cache-Control", "no-cache") + ctx := context.Background() + + var respData struct { + Id string `json:"deleteIssue"` + } + if err := util2.RequestWithBackoff(func() error { return client.Run(ctx, req, &respData) }); err != nil { + logrus.WithError(err).WithField("request", req).Fatalln("Error while unmarshaling") + } + return respData.Id +} + func QueryGetIssue(port string, issuePrimaryName string) *model.IssueConnection { // create a queryCollection (safe to share across requests) client := graphql.NewClient(fmt.Sprintf("http://localhost:%s/query", port)) @@ -87,7 +112,7 @@ func QueryGetIssue(port string, issuePrimaryName string) *model.IssueConnection str := string(b) req := graphql.NewRequest(str) - req.Var("filter", map[string]string{"primaryName": issuePrimaryName}) + req.Var("filter", map[string]string{"primaryName": issuePrimaryName, "state": fmt.Sprintf("%d", entity.All)}) req.Var("first", 1) req.Var("after", "0") diff --git a/internal/e2e/metadata_test.go b/internal/e2e/metadata_test.go index fed32e26..f4388230 100644 --- a/internal/e2e/metadata_test.go +++ b/internal/e2e/metadata_test.go @@ -37,6 +37,7 @@ func createTestIssue(port string) string { Expect(issue.Type.String()).To(Equal(testCreatedIssueType)) return issue.ID } + func updateTestIssue(port string, iid string) { issue := e2e_common.QueryUpdateIssue(port, e2e_common.Issue{PrimaryName: testIssuePrimaryName, Description: testUpdatedIssueDescription, Type: testUpdatedIssueType}, iid) Expect(*issue.PrimaryName).To(Equal(testIssuePrimaryName)) @@ -44,12 +45,23 @@ func updateTestIssue(port string, iid string) { Expect(issue.Type.String()).To(Equal(testUpdatedIssueType)) } +func deleteTestIssue(port string, iid string) { + issueId := e2e_common.QueryDeleteIssue(port, iid) + Expect(issueId).To(Equal(iid)) +} + func getTestIssue(port string) model.Issue { issues := e2e_common.QueryGetIssue(port, testIssuePrimaryName) Expect(issues.TotalCount).To(Equal(1)) return *issues.Edges[0].Node } +func parseTimeExpectNoError(t string) time.Time { + tt, err := time.Parse(dbDateLayout, t) + Expect(err).Should(BeNil()) + return tt +} + var _ = Describe("Creating and updating entity via API", Label("e2e", "Entities"), func() { var s *server.Server var cfg util.Config @@ -74,22 +86,20 @@ var _ = Describe("Creating and updating entity via API", Label("e2e", "Entities" createTestIssue(cfg.Port) issue = getTestIssue(cfg.Port) }) - It("shall assign CreatedBy, CreatedAt, UpdatedBy and UpdatedAt metadata fields and shall keep nil in DeltedAt metadata fields", func() { + It("shall assign CreatedBy, CreatedAt, UpdatedBy and UpdatedAt metadata fields and shall keep zero value in DeltedAt metadata fields", func() { Expect(*issue.Description).To(Equal(testCreatedIssueDescription)) Expect(issue.Type.String()).To(Equal(testCreatedIssueType)) Expect(issue.Metadata).To(Not(BeNil())) Expect(*issue.Metadata.CreatedBy).To(Equal(fmt.Sprintf("%d", e2e_common.SystemUserId))) - createdAt, err := time.Parse(dbDateLayout, *issue.Metadata.CreatedAt) - Expect(err).Should(BeNil()) - Expect(createdAt).Should(BeTemporally("~", time.Now().UTC(), 3*time.Second)) + createdAt := parseTimeExpectNoError(*issue.Metadata.CreatedAt) + updatedAt := parseTimeExpectNoError(*issue.Metadata.UpdatedAt) + Expect(createdAt).Should(BeTemporally("~", time.Now().UTC(), 3*time.Second)) Expect(*issue.Metadata.UpdatedBy).To(Equal(fmt.Sprintf("%d", e2e_common.SystemUserId))) - - updatedAt, err := time.Parse(dbDateLayout, *issue.Metadata.UpdatedAt) - Expect(err).Should(BeNil()) Expect(updatedAt).To(Equal(createdAt)) + Expect(*issue.Metadata.DeletedAt).To(Equal(time.Unix(0, 0).Local().Format(dbDateLayout))) }) }) When("Issue is updated via API", func() { @@ -100,24 +110,47 @@ var _ = Describe("Creating and updating entity via API", Label("e2e", "Entities" updateTestIssue(cfg.Port, iid) issue = getTestIssue(cfg.Port) }) - It("shall assign UpdatedBy and UpdatedAt metadata fields and shall keep nil in DeletedAt metadata field", func() { + It("shall assign UpdatedBy and UpdatedAt metadata fields and shall keep zero value in DeletedAt metadata field", func() { Expect(*issue.Description).To(Equal(testUpdatedIssueDescription)) Expect(issue.Type.String()).To(Equal(testUpdatedIssueType)) Expect(issue.Metadata).To(Not(BeNil())) Expect(*issue.Metadata.CreatedBy).To(Equal(fmt.Sprintf("%d", e2e_common.SystemUserId))) - createdAt, err := time.Parse(dbDateLayout, *issue.Metadata.CreatedAt) - Expect(err).Should(BeNil()) - Expect(createdAt).Should(BeTemporally("~", time.Now().UTC(), 3*time.Second)) + createdAt := parseTimeExpectNoError(*issue.Metadata.CreatedAt) + updatedAt := parseTimeExpectNoError(*issue.Metadata.UpdatedAt) + Expect(createdAt).Should(BeTemporally("~", time.Now().UTC(), 3*time.Second)) Expect(*issue.Metadata.UpdatedBy).To(Equal(fmt.Sprintf("%d", e2e_common.SystemUserId))) - - updatedAt, err := time.Parse(dbDateLayout, *issue.Metadata.UpdatedAt) - Expect(err).Should(BeNil()) Expect(updatedAt).Should(BeTemporally("~", time.Now().UTC(), 2*time.Second)) Expect(updatedAt).Should(BeTemporally(">", createdAt)) + Expect(*issue.Metadata.DeletedAt).To(Equal(time.Unix(0, 0).Local().Format(dbDateLayout))) }) }) + When("Issue is deleted via API", func() { + var issue model.Issue + BeforeEach(func() { + iid := createTestIssue(cfg.Port) + time.Sleep(1100 * time.Millisecond) + deleteTestIssue(cfg.Port, iid) + issue = getTestIssue(cfg.Port) + }) + It("shall assign UpdatedBy, DeletedAt and UpdatedAt metadata fields on delete", func() { + Expect(*issue.Description).To(Equal(testCreatedIssueDescription)) + Expect(issue.Type.String()).To(Equal(testCreatedIssueType)) + Expect(issue.Metadata).To(Not(BeNil())) + Expect(*issue.Metadata.CreatedBy).To(Equal(fmt.Sprintf("%d", e2e_common.SystemUserId))) + + createdAt := parseTimeExpectNoError(*issue.Metadata.CreatedAt) + deletedAt := parseTimeExpectNoError(*issue.Metadata.DeletedAt) + updatedAt := parseTimeExpectNoError(*issue.Metadata.UpdatedAt) + + Expect(createdAt).Should(BeTemporally("~", time.Now().UTC(), 3*time.Second)) + Expect(*issue.Metadata.UpdatedBy).To(Equal(fmt.Sprintf("%d", e2e_common.SystemUserId))) + Expect(deletedAt).Should(BeTemporally("~", time.Now().UTC(), 2*time.Second)) + Expect(deletedAt).Should(BeTemporally(">", createdAt)) + Expect(deletedAt).To(Equal(updatedAt)) + }) + }) }) diff --git a/internal/entity/activity.go b/internal/entity/activity.go index 2bb0ffa5..fd00b599 100644 --- a/internal/entity/activity.go +++ b/internal/entity/activity.go @@ -57,12 +57,13 @@ type ActivityAggregations struct { type ActivityFilter struct { Paginated - Status []*string `json:"status"` - ServiceCCRN []*string `json:"service_ccrn"` - Id []*int64 `json:"id"` - ServiceId []*int64 `json:"service_id"` - IssueId []*int64 `json:"issue_id"` - EvidenceId []*int64 `json:"evidence_id"` + Status []*string `json:"status"` + ServiceCCRN []*string `json:"service_ccrn"` + Id []*int64 `json:"id"` + ServiceId []*int64 `json:"service_id"` + IssueId []*int64 `json:"issue_id"` + EvidenceId []*int64 `json:"evidence_id"` + State StateFilterType `json:"state"` } type ActivityResult struct { diff --git a/internal/entity/common.go b/internal/entity/common.go index dd1ecafc..ff9a6632 100644 --- a/internal/entity/common.go +++ b/internal/entity/common.go @@ -227,3 +227,18 @@ type Metadata struct { UpdatedBy int64 `json:"updated_by"` DeletedAt time.Time `json:"deleted_at,omitempty"` } + +type StateFilterType int + +const ( + Active StateFilterType = 0 + Deleted StateFilterType = 1 + All StateFilterType = 2 +) + +func GetStateFilterType(sft *int) StateFilterType { + if sft != nil { + return StateFilterType(*sft) + } + return Active +} diff --git a/internal/entity/component.go b/internal/entity/component.go index 82d5d959..8945e947 100644 --- a/internal/entity/component.go +++ b/internal/entity/component.go @@ -18,9 +18,10 @@ type ComponentResult struct { type ComponentFilter struct { Paginated - CCRN []*string `json:"ccrn"` - Id []*int64 `json:"id"` - ComponentVersionId []*int64 `json:"component_version_id"` + CCRN []*string `json:"ccrn"` + Id []*int64 `json:"id"` + ComponentVersionId []*int64 `json:"component_version_id"` + State StateFilterType `json:"state"` } type ComponentAggregations struct { diff --git a/internal/entity/component_instance.go b/internal/entity/component_instance.go index a9249a47..789457eb 100644 --- a/internal/entity/component_instance.go +++ b/internal/entity/component_instance.go @@ -5,13 +5,14 @@ package entity type ComponentInstanceFilter struct { Paginated - IssueMatchId []*int64 `json:"issue_match_id"` - ServiceId []*int64 `json:"service_id"` - ServiceCcrn []*string `json:"service_ccrn"` - ComponentVersionId []*int64 `json:"component_version_id"` - Id []*int64 `json:"id"` - CCRN []*string `json:"ccrn"` - Search []*string `json:"search"` + IssueMatchId []*int64 `json:"issue_match_id"` + ServiceId []*int64 `json:"service_id"` + ServiceCcrn []*string `json:"service_ccrn"` + ComponentVersionId []*int64 `json:"component_version_id"` + Id []*int64 `json:"id"` + CCRN []*string `json:"ccrn"` + Search []*string `json:"search"` + State StateFilterType `json:"state"` } type ComponentInstanceAggregations struct { diff --git a/internal/entity/component_version.go b/internal/entity/component_version.go index 1d76d1f4..1a5399ac 100644 --- a/internal/entity/component_version.go +++ b/internal/entity/component_version.go @@ -5,11 +5,12 @@ package entity type ComponentVersionFilter struct { Paginated - Id []*int64 `json:"id"` - IssueId []*int64 `json:"issue_id"` - ComponentCCRN []*string `json:"component_ccrn"` - ComponentId []*int64 `json:"component_id"` - Version []*string `json:"version"` + Id []*int64 `json:"id"` + IssueId []*int64 `json:"issue_id"` + ComponentCCRN []*string `json:"component_ccrn"` + ComponentId []*int64 `json:"component_id"` + Version []*string `json:"version"` + State StateFilterType `json:"state"` } type ComponentVersionAggregations struct { diff --git a/internal/entity/evidence.go b/internal/entity/evidence.go index ae6becf5..226b5838 100644 --- a/internal/entity/evidence.go +++ b/internal/entity/evidence.go @@ -56,10 +56,11 @@ type Evidence struct { type EvidenceFilter struct { Paginated - Id []*int64 `json:"id"` - ActivityId []*int64 `json:"activity_id"` - IssueMatchId []*int64 `json:"issue_match_id"` - UserId []*int64 `json:"user_id"` + Id []*int64 `json:"id"` + ActivityId []*int64 `json:"activity_id"` + IssueMatchId []*int64 `json:"issue_match_id"` + UserId []*int64 `json:"user_id"` + State StateFilterType `json:"state"` } type EvidenceAggregations struct { } diff --git a/internal/entity/issue.go b/internal/entity/issue.go index 44e52129..dc4f5a10 100644 --- a/internal/entity/issue.go +++ b/internal/entity/issue.go @@ -51,18 +51,19 @@ type IssueResult struct { type IssueFilter struct { Paginated - PrimaryName []*string `json:"primary_name"` - ServiceCCRN []*string `json:"service_ccrn"` - Type []*string `json:"type"` - Id []*int64 `json:"id"` - ActivityId []*int64 `json:"activity_id"` - IssueMatchId []*int64 `json:"issue_match_id"` - ComponentVersionId []*int64 `json:"component_version_id"` - IssueVariantId []*int64 `json:"issue_variant_id"` - Search []*string `json:"search"` - IssueMatchStatus []*string `json:"issue_match_status"` - IssueMatchDiscoveryDate *TimeFilter `json:"issue_match_discovery_date"` - IssueMatchTargetRemediationDate *TimeFilter `json:"issue_match_target_remediation_date"` + PrimaryName []*string `json:"primary_name"` + ServiceCCRN []*string `json:"service_ccrn"` + Type []*string `json:"type"` + Id []*int64 `json:"id"` + ActivityId []*int64 `json:"activity_id"` + IssueMatchId []*int64 `json:"issue_match_id"` + ComponentVersionId []*int64 `json:"component_version_id"` + IssueVariantId []*int64 `json:"issue_variant_id"` + Search []*string `json:"search"` + IssueMatchStatus []*string `json:"issue_match_status"` + IssueMatchDiscoveryDate *TimeFilter `json:"issue_match_discovery_date"` + IssueMatchTargetRemediationDate *TimeFilter `json:"issue_match_target_remediation_date"` + State StateFilterType `json:"state"` } type IssueAggregations struct { diff --git a/internal/entity/issue_match.go b/internal/entity/issue_match.go index 8e020893..cae46abb 100644 --- a/internal/entity/issue_match.go +++ b/internal/entity/issue_match.go @@ -56,18 +56,19 @@ type IssueMatch struct { type IssueMatchFilter struct { Paginated - Id []*int64 `json:"id"` - AffectedServiceCCRN []*string `json:"affected_service_ccrn"` - SeverityValue []*string `json:"severity_value"` - Status []*string `json:"status"` - IssueId []*int64 `json:"issue_id"` - EvidenceId []*int64 `json:"evidence_id"` - ComponentInstanceId []*int64 `json:"component_instance_id"` - SupportGroupCCRN []*string `json:"support_group_ccrn"` - Search []*string `json:"search"` - ComponentCCRN []*string `json:"component_ccrn"` - PrimaryName []*string `json:"primary_name"` - IssueType []*string `json:"issue_type"` + Id []*int64 `json:"id"` + AffectedServiceCCRN []*string `json:"affected_service_ccrn"` + SeverityValue []*string `json:"severity_value"` + Status []*string `json:"status"` + IssueId []*int64 `json:"issue_id"` + EvidenceId []*int64 `json:"evidence_id"` + ComponentInstanceId []*int64 `json:"component_instance_id"` + SupportGroupCCRN []*string `json:"support_group_ccrn"` + Search []*string `json:"search"` + ComponentCCRN []*string `json:"component_ccrn"` + PrimaryName []*string `json:"primary_name"` + IssueType []*string `json:"issue_type"` + State StateFilterType `json:"state"` } type IssueMatchResult struct { diff --git a/internal/entity/issue_match_change.go b/internal/entity/issue_match_change.go index bbcd54a5..e5fa0ff2 100644 --- a/internal/entity/issue_match_change.go +++ b/internal/entity/issue_match_change.go @@ -41,10 +41,11 @@ type IssueMatchChange struct { type IssueMatchChangeFilter struct { Paginated - Id []*int64 `json:"id"` - ActivityId []*int64 `json:"activity_id"` - IssueMatchId []*int64 `json:"issue_match_id"` - Action []*string `json:"action"` + Id []*int64 `json:"id"` + ActivityId []*int64 `json:"activity_id"` + IssueMatchId []*int64 `json:"issue_match_id"` + Action []*string `json:"action"` + State StateFilterType `json:"state"` } type IssueMatchChangeResult struct { diff --git a/internal/entity/issue_repository.go b/internal/entity/issue_repository.go index 4456a549..c3bb606d 100644 --- a/internal/entity/issue_repository.go +++ b/internal/entity/issue_repository.go @@ -14,10 +14,11 @@ type BaseIssueRepository struct { type IssueRepositoryFilter struct { Paginated - Id []*int64 `json:"id"` - ServiceId []*int64 `json:"service_id"` - Name []*string `json:"name"` - ServiceCCRN []*string `json:"service_ccrn"` + Id []*int64 `json:"id"` + ServiceId []*int64 `json:"service_id"` + Name []*string `json:"name"` + ServiceCCRN []*string `json:"service_ccrn"` + State StateFilterType `json:"state"` } func NewIssueRepositoryFilter() *IssueRepositoryFilter { diff --git a/internal/entity/issue_variant.go b/internal/entity/issue_variant.go index 3b891740..18fe7909 100644 --- a/internal/entity/issue_variant.go +++ b/internal/entity/issue_variant.go @@ -17,12 +17,13 @@ type IssueVariant struct { type IssueVariantFilter struct { Paginated - Id []*int64 `json:"id"` - SecondaryName []*string `json:"secondary_name"` - IssueId []*int64 `json:"issue_id"` - IssueRepositoryId []*int64 `json:"issue_repository_id"` - ServiceId []*int64 `json:"service_id"` - IssueMatchId []*int64 `json:"issue_match_id"` + Id []*int64 `json:"id"` + SecondaryName []*string `json:"secondary_name"` + IssueId []*int64 `json:"issue_id"` + IssueRepositoryId []*int64 `json:"issue_repository_id"` + ServiceId []*int64 `json:"service_id"` + IssueMatchId []*int64 `json:"issue_match_id"` + State StateFilterType `json:"state"` } func NewIssueVariantFilter() *IssueVariantFilter { @@ -57,8 +58,9 @@ type ServiceIssueVariant struct { type ServiceIssueVariantFilter struct { Paginated - ComponentInstanceId []*int64 `json:"component_instance_id"` - IssueId []*int64 `json:"issue_id"` + ComponentInstanceId []*int64 `json:"component_instance_id"` + IssueId []*int64 `json:"issue_id"` + State StateFilterType `json:"state"` } func NewServiceIssueVariantFilter() *ServiceIssueVariantFilter { diff --git a/internal/entity/service.go b/internal/entity/service.go index 2c96629e..a2b78359 100644 --- a/internal/entity/service.go +++ b/internal/entity/service.go @@ -26,16 +26,17 @@ type ServiceWithAggregations struct { type ServiceFilter struct { Paginated - SupportGroupCCRN []*string `json:"support_group_ccrn"` - Id []*int64 `json:"id"` - CCRN []*string `json:"ccrn"` - OwnerName []*string `json:"owner_name"` - OwnerId []*int64 `json:"owner_id"` - ActivityId []*int64 `json:"activity_id"` - ComponentInstanceId []*int64 `json:"component_instance_id"` - IssueRepositoryId []*int64 `json:"issue_repository_id"` - SupportGroupId []*int64 `json:"support_group_id"` - Search []*string `json:"search"` + SupportGroupCCRN []*string `json:"support_group_ccrn"` + Id []*int64 `json:"id"` + CCRN []*string `json:"ccrn"` + OwnerName []*string `json:"owner_name"` + OwnerId []*int64 `json:"owner_id"` + ActivityId []*int64 `json:"activity_id"` + ComponentInstanceId []*int64 `json:"component_instance_id"` + IssueRepositoryId []*int64 `json:"issue_repository_id"` + SupportGroupId []*int64 `json:"support_group_id"` + Search []*string `json:"search"` + State StateFilterType `json:"state"` } type Service struct { diff --git a/internal/entity/support_group.go b/internal/entity/support_group.go index f9d48b6b..4f6fcd24 100644 --- a/internal/entity/support_group.go +++ b/internal/entity/support_group.go @@ -11,10 +11,11 @@ type SupportGroup struct { type SupportGroupFilter struct { Paginated - Id []*int64 `json:"id"` - ServiceId []*int64 `json:"service_id"` - UserId []*int64 `json:"user_id"` - CCRN []*string `json:"ccrn"` + Id []*int64 `json:"id"` + ServiceId []*int64 `json:"service_id"` + UserId []*int64 `json:"user_id"` + CCRN []*string `json:"ccrn"` + State StateFilterType `json:"state"` } type SupportGroupAggregations struct { diff --git a/internal/entity/user.go b/internal/entity/user.go index 4f373bcd..90cde32d 100644 --- a/internal/entity/user.go +++ b/internal/entity/user.go @@ -21,12 +21,13 @@ type User struct { type UserFilter struct { Paginated - Name []*string `json:"name"` - UniqueUserID []*string `json:"uniqueUserId"` - Type []UserType `json:"type"` - Id []*int64 `json:"id"` - SupportGroupId []*int64 `json:"support_group_id"` - ServiceId []*int64 `json:"service_id"` + Name []*string `json:"name"` + UniqueUserID []*string `json:"uniqueUserId"` + Type []UserType `json:"type"` + Id []*int64 `json:"id"` + SupportGroupId []*int64 `json:"support_group_id"` + ServiceId []*int64 `json:"service_id"` + State StateFilterType `json:"state"` } type UserAggregations struct {