Skip to content

Commit 9a2ec62

Browse files
authored
CLOUDP-106123: [mongocli ] Implement mongocli auth logout (#963)
1 parent 8af582a commit 9a2ec62

File tree

8 files changed

+269
-7
lines changed

8 files changed

+269
-7
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ require (
2121
github.com/spf13/viper v1.10.1
2222
github.com/stretchr/testify v1.7.0
2323
github.com/tangzero/inflector v1.0.0
24-
go.mongodb.org/atlas v0.14.1-0.20220126105350-5816bca2f88c
24+
go.mongodb.org/atlas v0.14.1-0.20220202080947-4a7d97e77246
2525
go.mongodb.org/ops-manager v0.34.0
2626
gopkg.in/yaml.v2 v2.4.0
2727
)

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -401,8 +401,8 @@ go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQc
401401
go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
402402
go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs=
403403
go.mongodb.org/atlas v0.14.0/go.mod h1:lQhRHIxc6jQHEK3/q9WLu/SdBkPj2fQYhjLGUF6Z3U8=
404-
go.mongodb.org/atlas v0.14.1-0.20220126105350-5816bca2f88c h1:K3Q2ggsg1XtJuurBbJspNRzmkPtIZl5lD1oICR6lW28=
405-
go.mongodb.org/atlas v0.14.1-0.20220126105350-5816bca2f88c/go.mod h1:lQhRHIxc6jQHEK3/q9WLu/SdBkPj2fQYhjLGUF6Z3U8=
404+
go.mongodb.org/atlas v0.14.1-0.20220202080947-4a7d97e77246 h1:BkSHgSH3o6KawlMdsnR+XpZ/pCDbWK5secDmcUmytL0=
405+
go.mongodb.org/atlas v0.14.1-0.20220202080947-4a7d97e77246/go.mod h1:lQhRHIxc6jQHEK3/q9WLu/SdBkPj2fQYhjLGUF6Z3U8=
406406
go.mongodb.org/ops-manager v0.34.0 h1:d8TgpJpPFeVLr+6HrAbbbYnKkdk+2JW6E20OBdgqXg8=
407407
go.mongodb.org/ops-manager v0.34.0/go.mod h1:85LPPdME1TFJ/Eau/IgOmy37YWGw1p/S8PBSME8ukXs=
408408
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=

internal/cli/auth/login.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ func Builder() *cobra.Command {
228228
}
229229
cmd.AddCommand(
230230
LoginBuilder(),
231+
LogoutBuilder(),
231232
)
232233

233234
return cmd

internal/cli/auth/login_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func TestBuilder(t *testing.T) {
3535
test.CmdValidator(
3636
t,
3737
Builder(),
38-
1,
38+
2,
3939
[]string{},
4040
)
4141
}

internal/cli/auth/logout.go

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// Copyright 2022 MongoDB Inc
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package auth
16+
17+
import (
18+
"context"
19+
"errors"
20+
"io"
21+
22+
"github.com/mongodb/mongocli/internal/cli"
23+
"github.com/mongodb/mongocli/internal/cli/require"
24+
"github.com/mongodb/mongocli/internal/config"
25+
"github.com/mongodb/mongocli/internal/flag"
26+
"github.com/mongodb/mongocli/internal/oauth"
27+
"github.com/mongodb/mongocli/internal/usage"
28+
"github.com/spf13/cobra"
29+
atlas "go.mongodb.org/atlas/mongodbatlas"
30+
)
31+
32+
type logoutOpts struct {
33+
*cli.DeleteOpts
34+
OutWriter io.Writer
35+
config ConfigDeleter
36+
flow Revoker
37+
}
38+
39+
//go:generate mockgen -destination=../../mocks/mock_logout.go -package=mocks github.com/mongodb/mongocli/internal/cli/auth Revoker,ConfigDeleter
40+
41+
type ConfigDeleter interface {
42+
Delete() error
43+
}
44+
45+
type Revoker interface {
46+
Revoke(context.Context, string, string) (*atlas.Response, error)
47+
}
48+
49+
func (opts *logoutOpts) initFlow() error {
50+
var err error
51+
opts.flow, err = oauth.FlowWithConfig(config.Default())
52+
return err
53+
}
54+
55+
func (opts *logoutOpts) Run(ctx context.Context) error {
56+
// revoking a refresh token revokes the access token
57+
if _, err := opts.flow.Revoke(ctx, config.RefreshToken(), "refresh_token"); err != nil {
58+
return err
59+
}
60+
61+
return opts.Delete(opts.config.Delete)
62+
}
63+
64+
func LogoutBuilder() *cobra.Command {
65+
opts := &logoutOpts{
66+
DeleteOpts: cli.NewDeleteOpts("Successfully logged out\n", " "),
67+
}
68+
69+
cmd := &cobra.Command{
70+
Use: "logout",
71+
Short: "Log out the CLI.",
72+
Example: ` To log out from the CLI:
73+
$ mongocli auth logout
74+
`,
75+
PreRunE: func(cmd *cobra.Command, args []string) error {
76+
opts.OutWriter = cmd.OutOrStdout()
77+
opts.config = config.Default()
78+
return opts.initFlow()
79+
},
80+
RunE: func(cmd *cobra.Command, args []string) error {
81+
if config.RefreshToken() == "" {
82+
return errors.New("not logged in")
83+
}
84+
if err := opts.PromptWithMessage("Are you sure you want to log out?"); err != nil {
85+
return err
86+
}
87+
return opts.Run(cmd.Context())
88+
},
89+
Args: require.NoArgs,
90+
}
91+
92+
cmd.Flags().BoolVar(&opts.Confirm, flag.Force, false, usage.Force)
93+
94+
return cmd
95+
}

internal/cli/auth/logout_test.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Copyright 2022 MongoDB Inc
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
//go:build unit
16+
// +build unit
17+
18+
package auth
19+
20+
import (
21+
"bytes"
22+
"context"
23+
"testing"
24+
25+
"github.com/golang/mock/gomock"
26+
"github.com/mongodb/mongocli/internal/cli"
27+
"github.com/mongodb/mongocli/internal/flag"
28+
"github.com/mongodb/mongocli/internal/mocks"
29+
"github.com/mongodb/mongocli/internal/test"
30+
"github.com/stretchr/testify/require"
31+
)
32+
33+
func TestLogoutBuilder(t *testing.T) {
34+
test.CmdValidator(
35+
t,
36+
LogoutBuilder(),
37+
0,
38+
[]string{flag.Force},
39+
)
40+
}
41+
42+
func Test_logoutOpts_Run(t *testing.T) {
43+
ctrl := gomock.NewController(t)
44+
mockFlow := mocks.NewMockRevoker(ctrl)
45+
mockConfig := mocks.NewMockConfigDeleter(ctrl)
46+
defer ctrl.Finish()
47+
buf := new(bytes.Buffer)
48+
49+
opts := logoutOpts{
50+
OutWriter: buf,
51+
config: mockConfig,
52+
flow: mockFlow,
53+
DeleteOpts: &cli.DeleteOpts{
54+
Confirm: true,
55+
},
56+
}
57+
ctx := context.TODO()
58+
mockFlow.
59+
EXPECT().
60+
Revoke(ctx, gomock.Any(), gomock.Any()).
61+
Return(nil, nil).
62+
Times(1)
63+
mockConfig.
64+
EXPECT().
65+
Delete().
66+
Return(nil).
67+
Times(1)
68+
require.NoError(t, opts.Run(ctx))
69+
}

internal/cli/delete_opts.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ func (opts *DeleteOpts) Delete(d interface{}, a ...string) error {
5454

5555
var err error
5656
switch f := d.(type) {
57+
case func() error:
58+
err = f()
5759
case func(string) error:
5860
err = f(opts.Entry)
5961
case func(string, string) error:
@@ -69,8 +71,11 @@ func (opts *DeleteOpts) Delete(d interface{}, a ...string) error {
6971
if err != nil {
7072
return err
7173
}
72-
73-
fmt.Printf(opts.SuccessMessage(), opts.Entry)
74+
if opts.Entry == "" {
75+
fmt.Print(opts.SuccessMessage())
76+
} else {
77+
fmt.Printf(opts.SuccessMessage(), opts.Entry)
78+
}
7479

7580
return nil
7681
}
@@ -91,7 +96,11 @@ func (opts *DeleteOpts) PromptWithMessage(message string) error {
9196
return nil
9297
}
9398

94-
p := prompt.NewConfirm(fmt.Sprintf(message, opts.Entry))
99+
m := message
100+
if opts.Entry != "" {
101+
m = fmt.Sprintf(message, opts.Entry)
102+
}
103+
p := prompt.NewConfirm(m)
95104
return survey.AskOne(p, &opts.Confirm)
96105
}
97106

internal/mocks/mock_logout.go

Lines changed: 88 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)