github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/cmd/juju/user/change_password_test.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package user_test 5 6 import ( 7 "strings" 8 9 "github.com/juju/cmd" 10 "github.com/juju/cmd/cmdtesting" 11 "github.com/juju/errors" 12 "github.com/juju/testing" 13 jc "github.com/juju/testing/checkers" 14 gc "gopkg.in/check.v1" 15 16 "github.com/juju/juju/api" 17 "github.com/juju/juju/cmd/juju/user" 18 "github.com/juju/juju/juju" 19 "github.com/juju/juju/jujuclient" 20 ) 21 22 type ChangePasswordCommandSuite struct { 23 BaseSuite 24 mockAPI *mockChangePasswordAPI 25 store jujuclient.ClientStore 26 } 27 28 var _ = gc.Suite(&ChangePasswordCommandSuite{}) 29 30 func (s *ChangePasswordCommandSuite) SetUpTest(c *gc.C) { 31 s.BaseSuite.SetUpTest(c) 32 s.mockAPI = &mockChangePasswordAPI{version: 2} 33 s.store = s.BaseSuite.store 34 } 35 36 func (s *ChangePasswordCommandSuite) run(c *gc.C, args ...string) (*cmd.Context, *juju.NewAPIConnectionParams, error) { 37 var argsOut juju.NewAPIConnectionParams 38 newAPIConnection := func(args juju.NewAPIConnectionParams) (api.Connection, error) { 39 argsOut = args 40 return mockAPIConnection{}, nil 41 } 42 changePasswordCommand, _ := user.NewChangePasswordCommandForTest( 43 newAPIConnection, s.mockAPI, s.store, 44 ) 45 ctx := cmdtesting.Context(c) 46 ctx.Stdin = strings.NewReader("sekrit\nsekrit\n") 47 err := cmdtesting.InitCommand(changePasswordCommand, args) 48 if err != nil { 49 return ctx, nil, err 50 } 51 return ctx, &argsOut, changePasswordCommand.Run(ctx) 52 } 53 54 func (s *ChangePasswordCommandSuite) TestInit(c *gc.C) { 55 for i, test := range []struct { 56 args []string 57 user string 58 reset bool 59 errorString string 60 }{ 61 { 62 // no args is fine 63 }, { 64 args: []string{"foobar"}, 65 user: "foobar", 66 }, { 67 args: []string{"--foobar"}, 68 errorString: "option provided but not defined: --foobar", 69 }, { 70 args: []string{"--reset"}, 71 reset: true, 72 }, { 73 args: []string{"foobar", "extra"}, 74 errorString: `unrecognized args: \["extra"\]`, 75 }, 76 } { 77 c.Logf("test %d", i) 78 wrappedCommand, command := user.NewChangePasswordCommandForTest(nil, nil, s.store) 79 err := cmdtesting.InitCommand(wrappedCommand, test.args) 80 if test.errorString == "" { 81 c.Check(command.User, gc.Equals, test.user) 82 c.Check(command.Reset, gc.Equals, test.reset) 83 } else { 84 c.Check(err, gc.ErrorMatches, test.errorString) 85 } 86 } 87 } 88 89 func (s *ChangePasswordCommandSuite) assertAPICalls(c *gc.C, user, pass string) { 90 s.mockAPI.CheckCall(c, 0, "SetPassword", user, pass) 91 } 92 93 func (s *ChangePasswordCommandSuite) TestChangePassword(c *gc.C) { 94 context, args, err := s.run(c) 95 c.Assert(err, jc.ErrorIsNil) 96 s.assertAPICalls(c, "current-user", "sekrit") 97 c.Assert(cmdtesting.Stdout(context), gc.Equals, "") 98 c.Assert(cmdtesting.Stderr(context), gc.Equals, ` 99 new password: 100 type new password again: 101 Your password has been changed. 102 `[1:]) 103 // The command should have logged in without a password to get a macaroon. 104 c.Assert(args.AccountDetails, jc.DeepEquals, &jujuclient.AccountDetails{ 105 User: "current-user", 106 }) 107 } 108 109 func (s *ChangePasswordCommandSuite) TestChangePasswordFail(c *gc.C) { 110 s.mockAPI.SetErrors(errors.New("failed to do something")) 111 _, _, err := s.run(c) 112 c.Assert(err, gc.ErrorMatches, "failed to do something") 113 s.assertAPICalls(c, "current-user", "sekrit") 114 } 115 116 func (s *ChangePasswordCommandSuite) TestChangeOthersPassword(c *gc.C) { 117 // The checks for user existence and admin rights are tested 118 // at the apiserver level. 119 _, _, err := s.run(c, "other") 120 c.Assert(err, jc.ErrorIsNil) 121 s.assertAPICalls(c, "other", "sekrit") 122 } 123 124 func (s *ChangePasswordCommandSuite) TestResetSelfPasswordFail(c *gc.C) { 125 context, _, err := s.run(c, "--reset") 126 s.assertResetSelfPasswordFail(c, context, err) 127 } 128 129 func (s *ChangePasswordCommandSuite) TestResetSelfPasswordSpecifyYourselfFail(c *gc.C) { 130 context, _, err := s.run(c, "--reset", "current-user") 131 s.assertResetSelfPasswordFail(c, context, err) 132 } 133 134 func (s *ChangePasswordCommandSuite) TestResetPasswordFail(c *gc.C) { 135 s.mockAPI.SetErrors(errors.New("failed to do something")) 136 context, _, err := s.run(c, "--reset", "other") 137 c.Assert(err, gc.ErrorMatches, "failed to do something") 138 s.mockAPI.CheckCalls(c, []testing.StubCall{ 139 {"BestAPIVersion", nil}, 140 {"ResetPassword", []interface{}{"other"}}, 141 }) 142 // TODO (anastasiamac 2017-08-17) 143 // should probably warn user that something did not go well enough 144 c.Assert(cmdtesting.Stdout(context), gc.Equals, "") 145 c.Assert(cmdtesting.Stderr(context), gc.Equals, "") 146 } 147 148 func (s *ChangePasswordCommandSuite) TestResetOthersPassword(c *gc.C) { 149 // The checks for user existence and admin rights are tested 150 // at the apiserver level. 151 s.mockAPI.key = []byte("no cats or dragons") 152 context, _, err := s.run(c, "other", "--reset") 153 c.Assert(err, jc.ErrorIsNil) 154 s.mockAPI.CheckCalls(c, []testing.StubCall{ 155 {"BestAPIVersion", nil}, 156 {"ResetPassword", []interface{}{"other"}}, 157 }) 158 c.Assert(cmdtesting.Stdout(context), gc.Equals, "") 159 c.Assert(cmdtesting.Stderr(context), gc.Matches, ` 160 Password for "other" has been reset. 161 Ask the user to run: 162 juju register (.+) 163 `[1:]) 164 } 165 166 func (s *ChangePasswordCommandSuite) TestResetPasswordOldAPI(c *gc.C) { 167 s.mockAPI.version = 1 168 context, _, err := s.run(c, "--reset", "other") 169 c.Assert(err, gc.ErrorMatches, "on this juju controller, reset password not supported") 170 s.mockAPI.CheckCalls(c, []testing.StubCall{ 171 {"BestAPIVersion", nil}, 172 }) 173 c.Assert(cmdtesting.Stdout(context), gc.Equals, "") 174 c.Assert(cmdtesting.Stderr(context), gc.Equals, "") 175 } 176 177 func (s *ChangePasswordCommandSuite) assertResetSelfPasswordFail(c *gc.C, context *cmd.Context, err error) { 178 c.Assert(err, jc.ErrorIsNil) 179 s.mockAPI.CheckCalls(c, nil) 180 c.Assert(cmdtesting.Stdout(context), gc.Equals, "") 181 c.Assert(cmdtesting.Stderr(context), gc.Matches, ` 182 You cannot reset your own password. 183 If you want to change it, please call `[1:]+"`juju change-user-password`"+` without --reset option. 184 `) 185 } 186 187 type mockChangePasswordAPI struct { 188 testing.Stub 189 key []byte 190 version int 191 } 192 193 func (m *mockChangePasswordAPI) SetPassword(username, password string) error { 194 m.MethodCall(m, "SetPassword", username, password) 195 return m.NextErr() 196 } 197 198 func (m *mockChangePasswordAPI) ResetPassword(username string) ([]byte, error) { 199 m.MethodCall(m, "ResetPassword", username) 200 return m.key, m.NextErr() 201 } 202 203 func (m *mockChangePasswordAPI) Close() error { 204 m.MethodCall(m, "Close") 205 return nil 206 } 207 208 func (m *mockChangePasswordAPI) BestAPIVersion() int { 209 m.MethodCall(m, "BestAPIVersion") 210 return m.version 211 } 212 213 type mockAPIConnection struct { 214 api.Connection 215 } 216 217 func (mockAPIConnection) Close() error { 218 return nil 219 }