Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reset user password, cli. #7754

Merged
merged 9 commits into from
Aug 24, 2017
Merged

Reset user password, cli. #7754

merged 9 commits into from
Aug 24, 2017

Conversation

anastasiamac
Copy link
Contributor

Description of change

This PR introduces --reset option on change-user-password command that enables controller admins to re-issue a controller access registration key for users.
This functionality can also be used when user forgot their password.

QA steps

  1. bootstrap
  2. add user (note registration string)
  3. change password for new user using --reset option (note different registration string issued)
  4. login as new user using newer registration string.

Documentation changes

Final, cli layer, for https://bugs.launchpad.net/juju/+bug/1657187

Bug reference

Does this change fix a bug? Please add a link to it.

A controller administrator can change the password for another user (on
that controller).
A controller administrator can change the password for another user
on the specified controller. If no controller is specified, current controller
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"the" current controller is used.

on the specified controller. If no controller is specified, current controller
will be used.

A controller administrator can also reset the password for another user.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for any user is probably how I would phrase it. It feels weird to have 2 paragraphs starting with the same sentence.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sentence is not the same :D
First one says "..can change...", Second one says ".. can also reset.."

A controller administrator can also reset the password for another user.
This will invalidate previously set user password (if any) or
previously issued registration tokens.
Succefull password reset will result in a new registration token.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will invalidate any password or registration string that was previously issued, and issue a new registration string to be used with juju register.

(or Successful if we want to keep that word)

controllerName, err := c.ControllerName()
if err != nil {
return errors.Trace(err)
}
store := c.ClientStore()
accountDetails, err := store.AccountDetails(controllerName)
c.controllerName = controllerName
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels odd to have a "c.ControllerName()" that doesn't set c.controllerName, and then a side effect of prepareRun that does.
Maybe we need
func (changePasswordCommand) EnsureControllerName() error {
}

after which we are sure that c.controllerName is valid?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure as previously this was all part of Run, I guess it did not matter. I'll refactor into a separate method for maintainability.

return nil
}

func (c *changePasswordCommand) changeOrResetString(past ...bool) string {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the ...bool aids clarity. (what could it mean to pass 2 booleans).
Just passing an always-required true/false is sufficient.

I'd also call the variable "pastTense"

if err != nil {
return errors.Annotate(err, "generating controller user access token")
}
fmt.Fprintf(ctx.Stdout, "New controller access token for this user is %v\n", base64RegistrationData)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe for "add-user" we just generate the full CLI to give to them, so more:
Ask the user to run:
juju register BASE64STRING+OETUH

I'd like us to be consistent between the two, and giving the full CLI means they don't need to figure out what command that string is used for.

ctx.Infof("Password for %q has been updated.", c.User)
func (c *changePasswordCommand) updateClientStore(ctx *cmd.Context, password string) error {
if c.accountDetails == nil {
ctx.Infof("Password for %q has been %v.", c.User, c.changeOrResetString(true))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its often a bit cleaner to do:
if c.accountDetails != nil {
//report
return nil
}
// Then the rest of the function doesn't have to be indented.

if err := store.UpdateAccount(controllerName, *accountDetails); err != nil {
return errors.Annotate(err, "failed to update client credentials")
if c.accountDetails.Password != "" {
if password != "" {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly here, you can invert these checks and just return 'nil' rather than getting deeper-and-deeper nesting.

context, _, err := s.run(c, "--reset")
c.Assert(err, jc.ErrorIsNil)
s.mockAPI.CheckCall(c, 0, "ResetPassword", "current-user")
c.Assert(cmdtesting.Stdout(context), gc.Matches, `
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels odd to have some of the content on stdout and some on stderr.
I understand the rationale (Your password has been reset being more of an informative messaage).

It would be nice to know that "You password has been reset" gets printed before the other.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well, i think the ourder of stderr/stdout depends on how stderr and stdout is configured on the client side?
The best I can do code-wise is either put both as ctx.Infof (which currently goes to stderr) or both on stdout explicitly.

@anastasiamac
Copy link
Contributor Author

!!build!!

failed to build?

Copy link
Member

@jameinel jameinel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems good overall. Thanks for the updates.

if c.accountDetails.Password != "" {
macaroonErr = c.ClearControllerMacaroons(c.ClientStore(), c.controllerName)
if macaroonErr != nil {
macaroonErr = errors.Annotatef(err, "could not clear macaroon")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do wonder if we want to expose the user to the concept of macaroon. Or if we should just say:
"could not clear local credential cache".
Not a big deal either way, just something to consider.

@anastasiamac
Copy link
Contributor Author

$$merge$$

@jujubot
Copy link
Collaborator

jujubot commented Aug 24, 2017

Status: merge request accepted. Url: http://ci.jujucharms.com/job/github-merge-juju

@jujubot jujubot merged commit 5190853 into juju:develop Aug 24, 2017
@anastasiamac anastasiamac deleted the reset-pwd-cli branch August 24, 2017 21:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants