From 779f549530ccb37de5a11b9c855ab009f10e868a Mon Sep 17 00:00:00 2001 From: Bryan Frimin Date: Sun, 15 Mar 2026 12:24:39 +0100 Subject: [PATCH] Fix missing __typename checks and standalone var declarations Add __typename to GraphQL queries and type guards in risk view, risk list, user view, and user list commands to prevent silent garbage output when a wrong node type ID is passed. Wrap standalone var declarations in var () blocks per style guide. Signed-off-by: Bryan Frimin --- cmd/proboctl/main.go | 4 +++- pkg/cli/config/config.go | 16 +++++++++------- pkg/cmd/api/api.go | 10 ++++++---- pkg/cmd/risk/list/list.go | 12 ++++++++++-- pkg/cmd/risk/view/view.go | 6 ++++++ pkg/cmd/user/list/list.go | 10 +++++++++- pkg/cmd/user/view/view.go | 6 ++++++ 7 files changed, 49 insertions(+), 15 deletions(-) diff --git a/cmd/proboctl/main.go b/cmd/proboctl/main.go index b52a3644c..2e627a02c 100644 --- a/cmd/proboctl/main.go +++ b/cmd/proboctl/main.go @@ -24,7 +24,9 @@ import ( "go.probo.inc/probo/pkg/cmd/root" ) -var version string = "unknown" +var ( + version string = "unknown" +) func main() { ios := iostreams.System() diff --git a/pkg/cli/config/config.go b/pkg/cli/config/config.go index 7502ee287..b16fbc872 100644 --- a/pkg/cli/config/config.go +++ b/pkg/cli/config/config.go @@ -44,13 +44,15 @@ type ( } ) -var ValidKeys = []string{ - "editor", - "browser", - "pager", - "prompt", - "http_timeout", -} +var ( + ValidKeys = []string{ + "editor", + "browser", + "pager", + "prompt", + "http_timeout", + } +) func (c *Config) Get(key string) (string, error) { switch key { diff --git a/pkg/cmd/api/api.go b/pkg/cmd/api/api.go index f37c09309..e82369432 100644 --- a/pkg/cmd/api/api.go +++ b/pkg/cmd/api/api.go @@ -26,10 +26,12 @@ import ( "go.probo.inc/probo/pkg/cmd/cmdutil" ) -var schemaEndpoints = map[string]string{ - "console": "/api/console/v1/graphql", - "connect": "/api/connect/v1/graphql", -} +var ( + schemaEndpoints = map[string]string{ + "console": "/api/console/v1/graphql", + "connect": "/api/connect/v1/graphql", + } +) func NewCmdAPI(f *cmdutil.Factory) *cobra.Command { var ( diff --git a/pkg/cmd/risk/list/list.go b/pkg/cmd/risk/list/list.go index c692ce97c..4fabcf221 100644 --- a/pkg/cmd/risk/list/list.go +++ b/pkg/cmd/risk/list/list.go @@ -26,6 +26,7 @@ import ( const listQuery = ` query($id: ID!, $first: Int, $after: CursorKey, $orderBy: RiskOrder, $filter: RiskFilter) { node(id: $id) { + __typename ... on Organization { risks(first: $first, after: $after, orderBy: $orderBy, filter: $filter) { totalCount @@ -138,13 +139,20 @@ func NewCmdList(f *cmdutil.Factory) *cobra.Command { flagLimit, func(data json.RawMessage) (*api.Connection[risk], error) { var resp struct { - Node struct { - Risks api.Connection[risk] `json:"risks"` + Node *struct { + Typename string `json:"__typename"` + Risks api.Connection[risk] `json:"risks"` } `json:"node"` } if err := json.Unmarshal(data, &resp); err != nil { return nil, err } + if resp.Node == nil { + return nil, fmt.Errorf("organization %s not found", flagOrg) + } + if resp.Node.Typename != "Organization" { + return nil, fmt.Errorf("expected Organization node, got %s", resp.Node.Typename) + } return &resp.Node.Risks, nil }, ) diff --git a/pkg/cmd/risk/view/view.go b/pkg/cmd/risk/view/view.go index a94d25244..3f2b2ea20 100644 --- a/pkg/cmd/risk/view/view.go +++ b/pkg/cmd/risk/view/view.go @@ -27,6 +27,7 @@ import ( const viewQuery = ` query($id: ID!) { node(id: $id) { + __typename ... on Risk { id name @@ -49,6 +50,7 @@ query($id: ID!) { type viewResponse struct { Node *struct { + Typename string `json:"__typename"` ID string `json:"id"` Name string `json:"name"` Description *string `json:"description"` @@ -112,6 +114,10 @@ func NewCmdView(f *cmdutil.Factory) *cobra.Command { return fmt.Errorf("risk %s not found", args[0]) } + if resp.Node.Typename != "Risk" { + return fmt.Errorf("expected Risk node, got %s", resp.Node.Typename) + } + if *flagOutput == cmdutil.OutputJSON { return cmdutil.PrintJSON(f.IOStreams.Out, resp.Node) } diff --git a/pkg/cmd/user/list/list.go b/pkg/cmd/user/list/list.go index 11ab05977..135f11e96 100644 --- a/pkg/cmd/user/list/list.go +++ b/pkg/cmd/user/list/list.go @@ -26,6 +26,7 @@ import ( const listQuery = ` query($id: ID!, $first: Int, $after: CursorKey, $orderBy: ProfileOrder, $filter: ProfileFilter) { node(id: $id) { + __typename ... on Organization { profiles(first: $first, after: $after, orderBy: $orderBy, filter: $filter) { totalCount @@ -135,13 +136,20 @@ func NewCmdList(f *cmdutil.Factory) *cobra.Command { flagLimit, func(data json.RawMessage) (*api.Connection[profile], error) { var resp struct { - Node struct { + Node *struct { + Typename string `json:"__typename"` Profiles api.Connection[profile] `json:"profiles"` } `json:"node"` } if err := json.Unmarshal(data, &resp); err != nil { return nil, err } + if resp.Node == nil { + return nil, fmt.Errorf("organization %s not found", flagOrg) + } + if resp.Node.Typename != "Organization" { + return nil, fmt.Errorf("expected Organization node, got %s", resp.Node.Typename) + } return &resp.Node.Profiles, nil }, ) diff --git a/pkg/cmd/user/view/view.go b/pkg/cmd/user/view/view.go index 26e2a94bb..5057bcaee 100644 --- a/pkg/cmd/user/view/view.go +++ b/pkg/cmd/user/view/view.go @@ -27,6 +27,7 @@ import ( const viewQuery = ` query($id: ID!) { node(id: $id) { + __typename ... on Profile { id fullName @@ -46,6 +47,7 @@ query($id: ID!) { type viewResponse struct { Node *struct { + Typename string `json:"__typename"` ID string `json:"id"` FullName string `json:"fullName"` EmailAddress string `json:"emailAddress"` @@ -106,6 +108,10 @@ func NewCmdView(f *cmdutil.Factory) *cobra.Command { return fmt.Errorf("user %s not found", args[0]) } + if resp.Node.Typename != "Profile" { + return fmt.Errorf("expected Profile node, got %s", resp.Node.Typename) + } + if *flagOutput == cmdutil.OutputJSON { return cmdutil.PrintJSON(f.IOStreams.Out, resp.Node) }