From a8aecec72b5d09fd26991f2e450c0cde7e480b27 Mon Sep 17 00:00:00 2001 From: gloriacai01 Date: Thu, 19 Dec 2024 12:31:02 -0500 Subject: [PATCH 1/7] add delete to cli --- cli/app.go | 27 ++++++++++++++++++++ cli/client.go | 34 ++++++++++++++++++++++++++ cli/client_test.go | 18 ++++++++++++++ testutils/inject/app_service_client.go | 12 +++++++++ 4 files changed, 91 insertions(+) diff --git a/cli/app.go b/cli/app.go index ba15a22ca00..3f6354de9ca 100644 --- a/cli/app.go +++ b/cli/app.go @@ -129,6 +129,7 @@ const ( authApplicationFlagOriginURIs = "origin-uris" authApplicationFlagRedirectURIs = "redirect-uris" authApplicationFlagLogoutURI = "logout-uri" + authApplicationFlagClientID = "client-id" cpFlagRecursive = "recursive" cpFlagPreserve = "preserve" @@ -424,6 +425,32 @@ var app = &cli.App{ Usage: "work with organizations", HideHelpCommand: true, Subcommands: []*cli.Command{ + { + Name: "auth-service", + Usage: "manage the oauth applications for an organization", + UsageText: createUsageText("organizations auth-service", []string{generalFlagOrgID}, true), + Subcommands: []*cli.Command{ + + { + Name: "delete", + Usage: "delete an oauth application", + UsageText: createUsageText("delete", []string{generalFlagOrgID, authApplicationFlagClientID}, true), + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: generalFlagOrgID, + Required: true, + Usage: "organization ID tied to the oauth application", + }, + &cli.StringFlag{ + Name: authApplicationFlagClientID, + Required: true, + Usage: "ID of the application to delete", + }, + }, + Action: createCommandWithT[deleteOAuthAppArgs](DeleteOAuthAppAction), + }, + }, + }, { Name: "list", Usage: "list organizations for the current user", diff --git a/cli/client.go b/cli/client.go index 6ffc908bddc..05f1e0b9516 100644 --- a/cli/client.go +++ b/cli/client.go @@ -2050,3 +2050,37 @@ func logEntryFieldsToString(fields []*structpb.Struct) (string, error) { } return message + "}", nil } + +type deleteOAuthAppArgs struct { + OrgID string + ClientID string +} + +// DeleteOAuthAppAction is the corresponding action for 'auth-service update'. +func DeleteOAuthAppAction(c *cli.Context, args deleteOAuthAppArgs) error { + client, err := newViamClient(c) + if err != nil { + return err + } + + return client.deleteOAuthAppAction(c, args.OrgID, args.ClientID) +} + +func (c *viamClient) deleteOAuthAppAction(cCtx *cli.Context, orgID, clientID string) error { + if err := c.ensureLoggedIn(); err != nil { + return err + } + + req := &apppb.DeleteOAuthAppRequest{ + OrgId: orgID, + ClientId: clientID, + } + + _, err := c.client.DeleteOAuthApp(c.c.Context, req) + if err != nil { + return err + } + + infof(cCtx.App.Writer, "Successfully deleted oauth application") + return nil +} diff --git a/cli/client_test.go b/cli/client_test.go index bda3d9e26ca..7caa2a24a46 100644 --- a/cli/client_test.go +++ b/cli/client_test.go @@ -358,6 +358,24 @@ func TestGetLogoAction(t *testing.T) { test.That(t, out.messages[0], test.ShouldContainSubstring, "https://logo.com") } +func TestDeleteOAuthAppAction(t *testing.T) { + deleteOAuthAppFunc := func(ctx context.Context, in *apppb.DeleteOAuthAppRequest, opts ...grpc.CallOption) ( + *apppb.DeleteOAuthAppResponse, error, + ) { + return &apppb.DeleteOAuthAppResponse{}, nil + } + + asc := &inject.AppServiceClient{ + DeleteOAuthAppFunc: deleteOAuthAppFunc, + } + + cCtx, ac, _, errOut := setup(asc, nil, nil, nil, nil, "token") + test.That(t, ac.deleteOAuthAppAction(cCtx, "test-org", "client-id"), test.ShouldBeNil) + test.That(t, len(errOut.messages), test.ShouldEqual, 0) + // test.That(t, len(out.messages), test.ShouldEqual, 1) + +} + func TestUpdateBillingServiceAction(t *testing.T) { updateConfigFunc := func(ctx context.Context, in *apppb.UpdateBillingServiceRequest, opts ...grpc.CallOption) ( *apppb.UpdateBillingServiceResponse, error, diff --git a/testutils/inject/app_service_client.go b/testutils/inject/app_service_client.go index 45f35604723..5c7884e9af1 100644 --- a/testutils/inject/app_service_client.go +++ b/testutils/inject/app_service_client.go @@ -56,6 +56,8 @@ type AppServiceClient struct { opts ...grpc.CallOption) (*apppb.OrganizationSetLogoResponse, error) OrganizationGetLogoFunc func(ctx context.Context, in *apppb.OrganizationGetLogoRequest, opts ...grpc.CallOption) (*apppb.OrganizationGetLogoResponse, error) + DeleteOAuthAppFunc func(ctx context.Context, in *apppb.DeleteOAuthAppRequest, + opts ...grpc.CallOption) (*apppb.DeleteOAuthAppResponse, error) CreateLocationFunc func(ctx context.Context, in *apppb.CreateLocationRequest, opts ...grpc.CallOption) (*apppb.CreateLocationResponse, error) GetLocationFunc func(ctx context.Context, in *apppb.GetLocationRequest, @@ -403,6 +405,16 @@ func (asc *AppServiceClient) OrganizationGetLogo( return asc.OrganizationGetLogoFunc(ctx, in, opts...) } +// DeleteOAuthApp calls the injected DeleteOAuthAppFunc or the real version. +func (asc *AppServiceClient) DeleteOAuthApp( + ctx context.Context, in *apppb.DeleteOAuthAppRequest, opts ...grpc.CallOption, +) (*apppb.DeleteOAuthAppResponse, error) { + if asc.DeleteOAuthAppFunc == nil { + return asc.AppServiceClient.DeleteOAuthApp(ctx, in, opts...) + } + return asc.DeleteOAuthAppFunc(ctx, in, opts...) +} + // CreateLocation calls the injected CreateLocationFunc or the real version. func (asc *AppServiceClient) CreateLocation( ctx context.Context, in *apppb.CreateLocationRequest, opts ...grpc.CallOption, From a3542e1ee30c72b2407d48b514a5ea6796f85461 Mon Sep 17 00:00:00 2001 From: gloriacai01 Date: Thu, 19 Dec 2024 12:39:39 -0500 Subject: [PATCH 2/7] test --- cli/client.go | 2 +- cli/client_test.go | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/cli/client.go b/cli/client.go index 05f1e0b9516..d0f043bde29 100644 --- a/cli/client.go +++ b/cli/client.go @@ -2081,6 +2081,6 @@ func (c *viamClient) deleteOAuthAppAction(cCtx *cli.Context, orgID, clientID str return err } - infof(cCtx.App.Writer, "Successfully deleted oauth application") + printf(cCtx.App.Writer, "Successfully deleted oauth application") return nil } diff --git a/cli/client_test.go b/cli/client_test.go index f83640e6bac..fcc83b0c233 100644 --- a/cli/client_test.go +++ b/cli/client_test.go @@ -370,10 +370,11 @@ func TestDeleteOAuthAppAction(t *testing.T) { DeleteOAuthAppFunc: deleteOAuthAppFunc, } - cCtx, ac, _, errOut := setup(asc, nil, nil, nil, nil, "token") + cCtx, ac, out, errOut := setup(asc, nil, nil, nil, nil, "token") test.That(t, ac.deleteOAuthAppAction(cCtx, "test-org", "client-id"), test.ShouldBeNil) test.That(t, len(errOut.messages), test.ShouldEqual, 0) - // test.That(t, len(out.messages), test.ShouldEqual, 1) + test.That(t, len(out.messages), test.ShouldEqual, 1) + test.That(t, out.messages[0], test.ShouldContainSubstring, "Successfully deleted oauth application") } From c756fa7e770bb1c36c882d68cba2303a7cc25379 Mon Sep 17 00:00:00 2001 From: gloriacai01 Date: Thu, 19 Dec 2024 13:03:07 -0500 Subject: [PATCH 3/7] add oauth-app flag --- cli/app.go | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/cli/app.go b/cli/app.go index fdf78d6f005..9992ea474dd 100644 --- a/cli/app.go +++ b/cli/app.go @@ -427,28 +427,32 @@ var app = &cli.App{ HideHelpCommand: true, Subcommands: []*cli.Command{ { - Name: "auth-service", - Usage: "manage the oauth applications for an organization", - UsageText: createUsageText("organizations auth-service", []string{generalFlagOrgID}, true), + Name: "auth-service", + Usage: "manage auth-service", Subcommands: []*cli.Command{ - { - Name: "delete", - Usage: "delete an oauth application", - UsageText: createUsageText("delete", []string{generalFlagOrgID, authApplicationFlagClientID}, true), - Flags: []cli.Flag{ - &cli.StringFlag{ - Name: generalFlagOrgID, - Required: true, - Usage: "organization ID tied to the oauth application", - }, - &cli.StringFlag{ - Name: authApplicationFlagClientID, - Required: true, - Usage: "ID of the application to delete", + Name: "oauth-app", + Usage: "manage the oauth applications for an organization", + Subcommands: []*cli.Command{ + { + Name: "delete", + Usage: "delete an oauth application", + UsageText: createUsageText("delete", []string{generalFlagOrgID, authApplicationFlagClientID}, true), + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: generalFlagOrgID, + Required: true, + Usage: "organization ID tied to the oauth application", + }, + &cli.StringFlag{ + Name: authApplicationFlagClientID, + Required: true, + Usage: "ID of the application to delete", + }, + }, + Action: createCommandWithT[deleteOAuthAppArgs](DeleteOAuthAppAction), }, }, - Action: createCommandWithT[deleteOAuthAppArgs](DeleteOAuthAppAction), }, }, }, From 834ef12abb3d120adc43eb8281ae886fe170e923 Mon Sep 17 00:00:00 2001 From: gloriacai01 Date: Thu, 19 Dec 2024 17:23:50 -0500 Subject: [PATCH 4/7] add deletion confirmation --- cli/app.go | 9 +++++---- cli/client.go | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/cli/app.go b/cli/app.go index 9992ea474dd..defe4a537b7 100644 --- a/cli/app.go +++ b/cli/app.go @@ -432,24 +432,25 @@ var app = &cli.App{ Subcommands: []*cli.Command{ { Name: "oauth-app", - Usage: "manage the oauth applications for an organization", + Usage: "manage the OAuth applications for an organization", Subcommands: []*cli.Command{ { Name: "delete", - Usage: "delete an oauth application", + Usage: "delete an OAuth application", UsageText: createUsageText("delete", []string{generalFlagOrgID, authApplicationFlagClientID}, true), Flags: []cli.Flag{ &cli.StringFlag{ Name: generalFlagOrgID, Required: true, - Usage: "organization ID tied to the oauth application", + Usage: "organization ID tied to the OAuth application", }, &cli.StringFlag{ Name: authApplicationFlagClientID, Required: true, - Usage: "ID of the application to delete", + Usage: "client ID of the OAuth application to delete", }, }, + Before: createCommandWithT[deleteOAuthAppArgs](DeleteOAuthAppConfirmation), Action: createCommandWithT[deleteOAuthAppArgs](DeleteOAuthAppAction), }, }, diff --git a/cli/client.go b/cli/client.go index d0f043bde29..24b8ec3a3c8 100644 --- a/cli/client.go +++ b/cli/client.go @@ -2,6 +2,7 @@ package cli import ( + "bufio" "context" "encoding/json" "fmt" @@ -2056,7 +2057,38 @@ type deleteOAuthAppArgs struct { ClientID string } -// DeleteOAuthAppAction is the corresponding action for 'auth-service update'. +func DeleteOAuthAppConfirmation(c *cli.Context, args deleteOAuthAppArgs) error { + if args.OrgID == "" { + return errors.New("cannot delete oauth app without an organization ID") + } + + if args.ClientID == "" { + return errors.New("cannot delete oauth app without a client ID") + } + + yellow := "\033[1;33m%s\033[0m" + printf(c.App.Writer, yellow, "WARNING!!\n") + printf(c.App.Writer, yellow, fmt.Sprintf("You are trying to delete OAuth application with client ID %s."+ + "Once deleted, any web or mobile apps with this client ID will no longer be able to authenticate users.\n", args.ClientID)) + printf(c.App.Writer, yellow, "Do you want to continue?") + printf(c.App.Writer, "Continue: y/n") + if err := c.Err(); err != nil { + return err + } + + rawInput, err := bufio.NewReader(c.App.Reader).ReadString('\n') + if err != nil { + return err + } + + input := strings.ToUpper(strings.TrimSpace(rawInput)) + if input != "Y" { + return errors.New("aborted") + } + return nil +} + +// DeleteOAuthAppAction is the corresponding action for 'oauth-app delete'. func DeleteOAuthAppAction(c *cli.Context, args deleteOAuthAppArgs) error { client, err := newViamClient(c) if err != nil { @@ -2081,6 +2113,6 @@ func (c *viamClient) deleteOAuthAppAction(cCtx *cli.Context, orgID, clientID str return err } - printf(cCtx.App.Writer, "Successfully deleted oauth application") + printf(cCtx.App.Writer, "Successfully deleted OAuth application") return nil } From 54f37131fb6466fbee8d4c3c1da6628f26e75cd3 Mon Sep 17 00:00:00 2001 From: gloriacai01 Date: Thu, 19 Dec 2024 17:31:01 -0500 Subject: [PATCH 5/7] lint --- cli/client.go | 4 +++- cli/client_test.go | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cli/client.go b/cli/client.go index 24b8ec3a3c8..e186dd45915 100644 --- a/cli/client.go +++ b/cli/client.go @@ -2057,6 +2057,8 @@ type deleteOAuthAppArgs struct { ClientID string } +// DeleteOAuthAppConfirmation is the Before action for 'organizations auth-service oauth-app delete'. +// It asks for the user to confirm that they want to delete the oauth app. func DeleteOAuthAppConfirmation(c *cli.Context, args deleteOAuthAppArgs) error { if args.OrgID == "" { return errors.New("cannot delete oauth app without an organization ID") @@ -2068,7 +2070,7 @@ func DeleteOAuthAppConfirmation(c *cli.Context, args deleteOAuthAppArgs) error { yellow := "\033[1;33m%s\033[0m" printf(c.App.Writer, yellow, "WARNING!!\n") - printf(c.App.Writer, yellow, fmt.Sprintf("You are trying to delete OAuth application with client ID %s."+ + printf(c.App.Writer, yellow, fmt.Sprintf("You are trying to delete OAuth application with client ID %s. "+ "Once deleted, any web or mobile apps with this client ID will no longer be able to authenticate users.\n", args.ClientID)) printf(c.App.Writer, yellow, "Do you want to continue?") printf(c.App.Writer, "Continue: y/n") diff --git a/cli/client_test.go b/cli/client_test.go index fcc83b0c233..55fb1c5b20d 100644 --- a/cli/client_test.go +++ b/cli/client_test.go @@ -375,7 +375,6 @@ func TestDeleteOAuthAppAction(t *testing.T) { test.That(t, len(errOut.messages), test.ShouldEqual, 0) test.That(t, len(out.messages), test.ShouldEqual, 1) test.That(t, out.messages[0], test.ShouldContainSubstring, "Successfully deleted oauth application") - } func TestUpdateBillingServiceAction(t *testing.T) { From 56ff979580813c616a7a501c23056e09cbe46dd8 Mon Sep 17 00:00:00 2001 From: gloriacai01 Date: Thu, 19 Dec 2024 17:38:01 -0500 Subject: [PATCH 6/7] update message --- cli/client.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cli/client.go b/cli/client.go index e186dd45915..54ee2ad63a7 100644 --- a/cli/client.go +++ b/cli/client.go @@ -2070,8 +2070,8 @@ func DeleteOAuthAppConfirmation(c *cli.Context, args deleteOAuthAppArgs) error { yellow := "\033[1;33m%s\033[0m" printf(c.App.Writer, yellow, "WARNING!!\n") - printf(c.App.Writer, yellow, fmt.Sprintf("You are trying to delete OAuth application with client ID %s. "+ - "Once deleted, any web or mobile apps with this client ID will no longer be able to authenticate users.\n", args.ClientID)) + printf(c.App.Writer, yellow, fmt.Sprintf("You are trying to delete an OAuth application with client ID %s. "+ + "Once deleted, any existing apps that rely on this OAuth application will no longer be able to authenticate users.\n", args.ClientID)) printf(c.App.Writer, yellow, "Do you want to continue?") printf(c.App.Writer, "Continue: y/n") if err := c.Err(); err != nil { From e445d50a2a94a4ebc69f64a74689d47384ba6185 Mon Sep 17 00:00:00 2001 From: gloriacai01 Date: Fri, 20 Dec 2024 09:35:03 -0500 Subject: [PATCH 7/7] capitalize oauth --- cli/client_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/client_test.go b/cli/client_test.go index 55fb1c5b20d..ff2e6a58fd5 100644 --- a/cli/client_test.go +++ b/cli/client_test.go @@ -374,7 +374,7 @@ func TestDeleteOAuthAppAction(t *testing.T) { test.That(t, ac.deleteOAuthAppAction(cCtx, "test-org", "client-id"), test.ShouldBeNil) test.That(t, len(errOut.messages), test.ShouldEqual, 0) test.That(t, len(out.messages), test.ShouldEqual, 1) - test.That(t, out.messages[0], test.ShouldContainSubstring, "Successfully deleted oauth application") + test.That(t, out.messages[0], test.ShouldContainSubstring, "Successfully deleted OAuth application") } func TestUpdateBillingServiceAction(t *testing.T) {