From aacdf44666ce34e1340b0576ec4c5abb74003924 Mon Sep 17 00:00:00 2001 From: Mike Rostermund Date: Wed, 14 Aug 2024 12:39:29 +0200 Subject: [PATCH] Ensure view actions validate type --- api/error.go | 8 +++ api/internal/humiographql/searchdomains.go | 7 +++ api/repositories.go | 15 +++++ api/searchdomains.go | 70 ++++++++++++++++++++++ api/views.go | 33 +++++++++- 5 files changed, 130 insertions(+), 3 deletions(-) create mode 100644 api/internal/humiographql/searchdomains.go create mode 100644 api/searchdomains.go diff --git a/api/error.go b/api/error.go index 1c249d1..9a78cb3 100644 --- a/api/error.go +++ b/api/error.go @@ -7,6 +7,7 @@ import ( type EntityType string const ( + EntityTypeSearchDomain EntityType = "search-domain" EntityTypeRepository EntityType = "repository" EntityTypeView EntityType = "view" EntityTypeIngestToken EntityType = "ingest-token" @@ -39,6 +40,13 @@ func (e EntityNotFound) Error() string { return fmt.Sprintf("%s %q not found", e.entityType.String(), e.key) } +func SearchDomainNotFound(name string) error { + return EntityNotFound{ + entityType: EntityTypeSearchDomain, + key: name, + } +} + func RepositoryNotFound(name string) error { return EntityNotFound{ entityType: EntityTypeRepository, diff --git a/api/internal/humiographql/searchdomains.go b/api/internal/humiographql/searchdomains.go new file mode 100644 index 0000000..a0dc9b9 --- /dev/null +++ b/api/internal/humiographql/searchdomains.go @@ -0,0 +1,7 @@ +package humiographql + +import graphql "github.com/cli/shurcooL-graphql" + +const ( + SearchDomainTypeView graphql.String = "View" +) diff --git a/api/repositories.go b/api/repositories.go index 351bda3..753107b 100644 --- a/api/repositories.go +++ b/api/repositories.go @@ -80,6 +80,11 @@ func (r *Repositories) Create(name string) error { } func (r *Repositories) Delete(name, reason string, allowDataDeletion bool) error { + _, err := r.Get(name) + if err != nil { + return err + } + if !allowDataDeletion { return fmt.Errorf("repository may contain data and data deletion not enabled") } @@ -231,6 +236,11 @@ func (r *Repositories) UpdateIngestBasedRetention(name string, ingestInGB float6 } func (r *Repositories) UpdateDescription(name, description string) error { + _, err := r.Get(name) + if err != nil { + return err + } + var mutation struct { UpdateDescription struct { // We have to make a selection, so just take __typename @@ -331,6 +341,11 @@ func (r *Repositories) UpdateS3ArchivingConfiguration(name string, bucket string } func (r *Repositories) UpdateAutomaticSearch(name string, automaticSearch bool) error { + _, err := r.Get(name) + if err != nil { + return err + } + var mutation struct { SetAutomaticSearching struct { // We have to make a selection, so just take __typename diff --git a/api/searchdomains.go b/api/searchdomains.go new file mode 100644 index 0000000..2dcb8e1 --- /dev/null +++ b/api/searchdomains.go @@ -0,0 +1,70 @@ +package api + +import ( + "sort" + "strings" + + graphql "github.com/cli/shurcooL-graphql" +) + +type SearchDomains struct { + client *Client +} + +type SearchDomainsQueryData struct { + Name string + Description string + AutomaticSearch bool + Typename graphql.String `graphql:"__typename"` +} + +type SearchDomain struct { + Name string + Description string + AutomaticSearch bool +} + +func (s *Client) SearchDomains() *SearchDomains { return &SearchDomains{client: s} } + +func (s *SearchDomains) Get(name string) (*SearchDomain, error) { + var query struct { + Result SearchDomainsQueryData `graphql:"searchDomain(name: $name)"` + } + + variables := map[string]interface{}{ + "name": graphql.String(name), + } + + err := s.client.Query(&query, variables) + if err != nil { + return nil, SearchDomainNotFound(name) + } + + searchDomain := SearchDomain{ + Name: query.Result.Name, + Description: query.Result.Description, + AutomaticSearch: query.Result.AutomaticSearch, + } + + return &searchDomain, nil +} + +type SearchDomainListItem struct { + Name string + Typename string `graphql:"__typename"` + AutomaticSearch bool +} + +func (s *SearchDomains) List() ([]SearchDomainListItem, error) { + var query struct { + SearchDomain []SearchDomainListItem `graphql:"searchDomains"` + } + + err := s.client.Query(&query, nil) + + sort.Slice(query.SearchDomain, func(i, j int) bool { + return strings.ToLower(query.SearchDomain[i].Name) < strings.ToLower(query.SearchDomain[j].Name) + }) + + return query.SearchDomain, err +} diff --git a/api/views.go b/api/views.go index 7f0dc73..6a9c5ed 100644 --- a/api/views.go +++ b/api/views.go @@ -1,6 +1,7 @@ package api import ( + "github.com/humio/cli/api/internal/humiographql" "sort" "strings" @@ -26,6 +27,7 @@ type ViewQueryData struct { Filter string } } `graphql:"... on View"` + Typename graphql.String `graphql:"__typename"` } type View struct { @@ -50,6 +52,9 @@ func (c *Views) Get(name string) (*View, error) { if err != nil { return nil, ViewNotFound(name) } + if query.Result.Typename != "View" { + return nil, ViewNotFound("name") + } connections := make([]ViewConnection, len(query.Result.ViewInfo.Connections)) for i, data := range query.Result.ViewInfo.Connections { @@ -82,11 +87,18 @@ func (c *Views) List() ([]ViewListItem, error) { err := c.client.Query(&query, nil) - sort.Slice(query.View, func(i, j int) bool { - return strings.ToLower(query.View[i].Name) < strings.ToLower(query.View[j].Name) + viewsList := []ViewListItem{} + for k, v := range query.View { + if v.Typename == string(humiographql.SearchDomainTypeView) { + viewsList = append(viewsList, query.View[k]) + } + } + + sort.Slice(viewsList, func(i, j int) bool { + return strings.ToLower(viewsList[i].Name) < strings.ToLower(viewsList[j].Name) }) - return query.View, err + return viewsList, err } type ViewConnectionInput struct { @@ -112,6 +124,11 @@ func (c *Views) Create(name, description string, connections []ViewConnectionInp } func (c *Views) Delete(name, reason string) error { + _, err := c.Get(name) + if err != nil { + return err + } + var mutation struct { DeleteSearchDomain struct { // We have to make a selection, so just take __typename @@ -142,6 +159,11 @@ func (c *Views) UpdateConnections(name string, connections []ViewConnectionInput } func (c *Views) UpdateDescription(name string, description string) error { + _, err := c.Get(name) + if err != nil { + return err + } + var mutation struct { UpdateDescriptionMutation struct { // We have to make a selection, so just take __typename @@ -158,6 +180,11 @@ func (c *Views) UpdateDescription(name string, description string) error { } func (c *Views) UpdateAutomaticSearch(name string, automaticSearch bool) error { + _, err := c.Get(name) + if err != nil { + return err + } + var mutation struct { SetAutomaticSearching struct { // We have to make a selection, so just take __typename