From 2abcd157417b0a54a8e5ecda1ef643b1669caaa4 Mon Sep 17 00:00:00 2001 From: Jens Feodor Nielsen Date: Tue, 11 Jun 2024 10:08:51 +0200 Subject: [PATCH] fix(cli): simpler output for some access denied errors --- cli/cmd/deploy/deploy.go | 2 +- cli/internal/app/app_create.go | 4 ++- cli/internal/app/app_create_test.go | 30 +++++++++++++++++++++ cli/internal/app/app_deploy.go | 3 ++- cli/internal/app/app_deploy_test.go | 29 +++++++++++++++++++- cli/internal/app/app_read.go | 12 +++++---- cli/internal/app/app_read_test.go | 42 +++++++++++++++++++++++++---- cli/internal/gql/access_denied.go | 16 +++++++++++ 8 files changed, 124 insertions(+), 14 deletions(-) create mode 100644 cli/internal/gql/access_denied.go diff --git a/cli/cmd/deploy/deploy.go b/cli/cmd/deploy/deploy.go index 85149ab..4330bc4 100644 --- a/cli/cmd/deploy/deploy.go +++ b/cli/cmd/deploy/deploy.go @@ -188,8 +188,8 @@ func readOrCreateApp(ctx context.Context, apps AppService, slug string, appName return appCreateOutput.AppID, nil default: - output.PrintErrorDetails("Error reading remote app", err) task.Error() + output.PrintErrorDetails("Error reading remote app", err) return "", err } diff --git a/cli/internal/app/app_create.go b/cli/internal/app/app_create.go index b6ac11e..479dd6d 100644 --- a/cli/internal/app/app_create.go +++ b/cli/internal/app/app_create.go @@ -2,6 +2,8 @@ package app import ( "context" + + "numerous/cli/internal/gql" ) type CreateAppInput struct { @@ -40,7 +42,7 @@ func (s *Service) Create(ctx context.Context, input CreateAppInput) (CreateAppOu } err := s.client.Exec(ctx, appCreateText, &resp, variables) if err != nil { - return CreateAppOutput{}, err + return CreateAppOutput{}, gql.CheckAccessDenied(err) } return CreateAppOutput{ diff --git a/cli/internal/app/app_create_test.go b/cli/internal/app/app_create_test.go index 9927f6a..2380144 100644 --- a/cli/internal/app/app_create_test.go +++ b/cli/internal/app/app_create_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "numerous/cli/internal/gql" "numerous/cli/test" "github.com/stretchr/testify/assert" @@ -43,6 +44,35 @@ func TestCreate(t *testing.T) { assert.Equal(t, expected, output) }) + t.Run("returns access denied error", func(t *testing.T) { + doer := test.MockDoer{} + c := test.CreateTestGQLClient(t, &doer) + s := New(c, nil, nil) + + respBody := ` + { + "errors": [{ + "message": "access denied", + "location": [{"line": 1, "column": 1}], + "path": ["appCreate"] + }] + } + ` + resp := test.JSONResponse(respBody) + doer.On("Do", mock.Anything).Return(resp, nil) + input := CreateAppInput{ + OrganizationSlug: "organization-slug", + Name: "app-name", + DisplayName: "App Name", + Description: "App description", + } + output, err := s.Create(context.TODO(), input) + + expected := CreateAppOutput{} + assert.ErrorIs(t, err, gql.ErrAccesDenied) + assert.Equal(t, expected, output) + }) + t.Run("returns expected error", func(t *testing.T) { doer := test.MockDoer{} c := test.CreateTestGQLClient(t, &doer) diff --git a/cli/internal/app/app_deploy.go b/cli/internal/app/app_deploy.go index 20e269e..0e2eb70 100644 --- a/cli/internal/app/app_deploy.go +++ b/cli/internal/app/app_deploy.go @@ -3,6 +3,7 @@ package app import ( "context" + "numerous/cli/internal/gql" "numerous/cli/internal/gql/secret" ) @@ -36,7 +37,7 @@ func (s *Service) DeployApp(ctx context.Context, input DeployAppInput) (DeployAp err := s.client.Exec(ctx, appDeployText, &resp, variables) if err != nil { - return DeployAppOutput{}, err + return DeployAppOutput{}, gql.CheckAccessDenied(err) } return DeployAppOutput{DeploymentVersionID: resp.AppDeploy.ID}, nil diff --git a/cli/internal/app/app_deploy_test.go b/cli/internal/app/app_deploy_test.go index 4f69518..b5c74f7 100644 --- a/cli/internal/app/app_deploy_test.go +++ b/cli/internal/app/app_deploy_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "numerous/cli/internal/gql" "numerous/cli/test" "github.com/stretchr/testify/assert" @@ -41,6 +42,32 @@ func TestDeployApp(t *testing.T) { assert.Equal(t, expected, output) }) + t.Run("returns access denied error", func(t *testing.T) { + doer := test.MockDoer{} + c := test.CreateTestGQLClient(t, &doer) + s := New(c, nil, nil) + + respBody := ` + { + "errors": [{ + "message": "access denied", + "location": [{"line": 1, "column": 1}], + "path": ["appDeploy"] + }] + } + ` + resp := test.JSONResponse(respBody) + doer.On("Do", mock.Anything).Return(resp, nil) + input := DeployAppInput{ + AppVersionID: "some-app-version-id", + } + output, err := s.DeployApp(context.TODO(), input) + + expected := DeployAppOutput{} + assert.ErrorIs(t, err, gql.ErrAccesDenied) + assert.Equal(t, expected, output) + }) + t.Run("returns expected error", func(t *testing.T) { doer := test.MockDoer{} c := test.CreateTestGQLClient(t, &doer) @@ -51,7 +78,7 @@ func TestDeployApp(t *testing.T) { "errors": [{ "message": "expected error message", "location": [{"line": 1, "column": 1}], - "path": ["appCreate"] + "path": ["appDeploy"] }] } ` diff --git a/cli/internal/app/app_read.go b/cli/internal/app/app_read.go index 477a9e2..0d17fe8 100644 --- a/cli/internal/app/app_read.go +++ b/cli/internal/app/app_read.go @@ -4,6 +4,8 @@ import ( "context" "errors" "strings" + + "numerous/cli/internal/gql" ) type ReadAppInput struct { @@ -36,14 +38,14 @@ func (s *Service) ReadApp(ctx context.Context, input ReadAppInput) (ReadAppOutpu variables := map[string]any{"slug": input.OrganizationSlug, "name": input.Name} err := s.client.Exec(ctx, queryAppText, &resp, variables) - if err != nil && !strings.Contains(err.Error(), "app not found") { - return ReadAppOutput{}, err + if err == nil { + return ReadAppOutput{AppID: resp.App.ID}, nil } - empty := appResponse{} - if resp == empty { + errMsg := err.Error() + if strings.Contains(errMsg, "app not found") { return ReadAppOutput{}, ErrAppNotFound } - return ReadAppOutput{AppID: resp.App.ID}, nil + return ReadAppOutput{}, gql.CheckAccessDenied(err) } diff --git a/cli/internal/app/app_read_test.go b/cli/internal/app/app_read_test.go index 0adf918..f916018 100644 --- a/cli/internal/app/app_read_test.go +++ b/cli/internal/app/app_read_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "numerous/cli/internal/gql" "numerous/cli/test" "github.com/stretchr/testify/assert" @@ -41,7 +42,7 @@ func TestAppRead(t *testing.T) { assert.Equal(t, expected, output) }) - t.Run("given empty response then it returns not found error", func(t *testing.T) { + t.Run("given app not found error then it returns not found error", func(t *testing.T) { doer := test.MockDoer{} c := test.CreateTestGQLClient(t, &doer) s := New(c, nil, nil) @@ -50,7 +51,12 @@ func TestAppRead(t *testing.T) { { "data": { "app": null - } + }, + "errors": [{ + "message": "app not found", + "location": [{"line": 1, "column": 1}], + "path": ["app"] + }] } ` resp := test.JSONResponse(respBody) @@ -62,9 +68,35 @@ func TestAppRead(t *testing.T) { } output, err := s.ReadApp(context.TODO(), input) - expected := ReadAppOutput{} assert.ErrorIs(t, err, ErrAppNotFound) - assert.Equal(t, expected, output) + assert.Equal(t, ReadAppOutput{}, output) + }) + + t.Run("given access denied error then it returns access denied error", func(t *testing.T) { + doer := test.MockDoer{} + c := test.CreateTestGQLClient(t, &doer) + s := New(c, nil, nil) + + respBody := ` + { + "errors": [{ + "message": "access denied", + "location": [{"line": 1, "column": 1}], + "path": ["app"] + }] + } + ` + resp := test.JSONResponse(respBody) + doer.On("Do", mock.Anything).Return(resp, nil) + + input := ReadAppInput{ + OrganizationSlug: "organization-slug", + Name: "app-name", + } + output, err := s.ReadApp(context.TODO(), input) + + assert.ErrorIs(t, err, gql.ErrAccesDenied) + assert.Equal(t, ReadAppOutput{}, output) }) t.Run("given graphql error then it returns expected error", func(t *testing.T) { @@ -77,7 +109,7 @@ func TestAppRead(t *testing.T) { "errors": [{ "message": "expected error message", "location": [{"line": 1, "column": 1}], - "path": ["appCreate"] + "path": ["app"] }] } ` diff --git a/cli/internal/gql/access_denied.go b/cli/internal/gql/access_denied.go new file mode 100644 index 0000000..1f02f21 --- /dev/null +++ b/cli/internal/gql/access_denied.go @@ -0,0 +1,16 @@ +package gql + +import ( + "errors" + "strings" +) + +var ErrAccesDenied = errors.New("access denied") + +func CheckAccessDenied(err error) error { + if strings.Contains(err.Error(), "access denied") { + return ErrAccesDenied + } + + return err +}