Skip to content

Commit

Permalink
feat(authN) - Add udpated_by for delete operations
Browse files Browse the repository at this point in the history
  • Loading branch information
michalkrzyz committed Dec 5, 2024
1 parent a5035d9 commit 98e0706
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 28 deletions.
8 changes: 8 additions & 0 deletions internal/api/graphql/graph/baseResolver/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ func IssueBaseResolver(app app.Heureka, ctx context.Context, filter *model.Issue
IssueMatchTargetRemediationDate: nil, //@todo Implement
}

if filter.State != nil {
f.State = entity.StateFilterType(*filter.State)
}

opt := GetIssueListOptions(requestedFields)

issues, err := app.ListIssues(f, opt)
Expand Down Expand Up @@ -179,6 +183,10 @@ func IssueNameBaseResolver(app app.Heureka, ctx context.Context, filter *model.I
IssueMatchTargetRemediationDate: nil, //@todo Implement
}

if filter.State != nil {
f.State = entity.StateFilterType(*filter.State)
}

opt := GetListOptions(requestedFields)

names, err := app.ListIssueNames(f, opt)
Expand Down
1 change: 1 addition & 0 deletions internal/api/graphql/graph/schema/issue.graphqls
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ input IssueFilter {
primaryName: [String],
issueMatchStatus: [IssueMatchStatusValues],
issueType: [IssueTypes],
state: Int

componentVersionId: [String],

Expand Down
7 changes: 6 additions & 1 deletion internal/database/mariadb/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,12 @@ 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")
//TODO: create common function
if filter.State == entity.Active {
fl = append(fl, "I.issue_deleted_at IS NULL")
} else if filter.State == entity.Deleted {
fl = append(fl, "I.issue_deleted_at IS NOT NULL")
}

return combineFilterQueries(fl, OP_AND)
}
Expand Down
27 changes: 26 additions & 1 deletion internal/e2e/common/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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))
Expand All @@ -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")

Expand Down
97 changes: 83 additions & 14 deletions internal/e2e/metadata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,31 @@ 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))
Expect(*issue.Description).To(Equal(testUpdatedIssueDescription))
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
Expand All @@ -74,22 +86,21 @@ 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)
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)))

updatedAt, err := time.Parse(dbDateLayout, *issue.Metadata.UpdatedAt)
Expect(err).Should(BeNil())
Expect(updatedAt).To(Equal(createdAt))
Expect(deletedAt).To(Equal(time.Unix(0, 0).Local()))
})
})
When("Issue is updated via API", func() {
Expand All @@ -100,24 +111,82 @@ 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)
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)))

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(deletedAt).To(Equal(time.Unix(0, 0).Local()))
})
})
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))
})
})
/* When("Issue is deleted via API", func() {
var issue model.Issue
var updatedAt0 time.Time
BeforeEach(func() {
iid := createTestIssue(cfg.Port)
time.Sleep(1100 * time.Millisecond)
updateTestIssue(cfg.Port, iid)
issue = getTestIssue(cfg.Port)
updatedAt0 = parseTimeExpectNoError(*issue.Metadata.UpdatedAt)
time.Sleep(1100 * time.Millisecond)
deleteTestIssue(cfg.Port, iid)
issue = getTestIssue(cfg.Port)
})
It("shall assign UpdatedBy and DeletedAt metadata fields on delete and UpdatedAt should not change after delete", 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 := parseTimeExpectNoError(*issue.Metadata.CreatedAt)
Expect(createdAt).Should(BeTemporally("~", time.Now().UTC(), 3*time.Second))
Expect(*issue.Metadata.UpdatedBy).To(Equal(fmt.Sprintf("%d", e2e_common.SystemUserId)))
updatedAt := parseTimeExpectNoError(*issue.Metadata.UpdatedAt)
Expect(updatedAt0).Should(BeTemporally(">", createdAt))
Expect(updatedAt).Should(BeTemporally(">", updatedAt0))
})
})*/

})
8 changes: 8 additions & 0 deletions internal/entity/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,3 +227,11 @@ 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
)
25 changes: 13 additions & 12 deletions internal/entity/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit 98e0706

Please sign in to comment.