-
Notifications
You must be signed in to change notification settings - Fork 875
feat: Add reset-password command #1380
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
Conversation
Codecov Report
@@ Coverage Diff @@
## main #1380 +/- ##
==========================================
+ Coverage 66.93% 67.13% +0.19%
==========================================
Files 288 289 +1
Lines 18856 19220 +364
Branches 241 241
==========================================
+ Hits 12622 12903 +281
- Misses 4944 4983 +39
- Partials 1290 1334 +44
Continue to review full report at Codecov.
|
// Returns nil if currentVersion corresponds to the latest available migration, | ||
// otherwise an error explaining why not. | ||
func CheckLatestVersion(sourceDriver source.Driver, currentVersion uint) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the only thing I'm significantly unhappy about with this commit. I feel like this ought to be a private function, but that doesn't play nicely with the way we put tests in a separate package.
The alternative would be to test the EnsureClean
function instead, but that seems difficult because its behavior implicitly depends on the global migrations
data, for consistency with the rest of the package.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a few minor suggestions, looks good otherwise!
connectionURL, closeFunc, err := postgres.Open() | ||
require.NoError(t, err) | ||
defer closeFunc() | ||
ctx, cancelFunc := context.WithCancel(context.Background()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor nit: Variables should be named after what they do or contain, not their types. As such, I think cancel
is descriptive enough and adding Func
is redundant (similarly with pg open above).
Dave Cheney has a pretty good writeup on this: https://dave.cheney.net/2019/01/29/you-shouldnt-name-your-variables-after-their-types-for-the-same-reason-you-wouldnt-name-your-pets-dog-or-cat
PS. I'm reviewing this with new-hire goggles, fully aware this may be based on existing code, but thought I'd call this out anyway 😄.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, fair point! This particular chunk of code is copy-and-pasted from server_test.go
. I should probably go back and see if I can break it out into a cleaner "test helper" abstraction.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One problem is close
overrides a builtin function, one of the linters gets mad :(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a very good point @coadler, missed that. In that situation I think pgClose
or closeConn
could be a good fit (i.e. adds a bit more meaning whilst avoiding the naming conflict).
// EnsureClean checks whether all migrations for the current version have been | ||
// applied, without making any changes to the database. If not, returns a | ||
// non-nil error. | ||
func EnsureClean(db *sql.DB) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if it helps, but if you want to test 99% of this function, you could write this as e.g. func EnsureClean(db *sql.DB) error { return ensureClean(db, migrateSetup); }
.
This would let you swap out the migrateSetup
function in your test, if that helps with the global state (considering your comment here #1380 (comment)). It would still require an internal test package but I think that's fine for this use-case.
}) | ||
if err != nil { | ||
return xerrors.Errorf("password prompt: %w", err) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we add a confirm step, similar to create first user?
Lines 121 to 133 in 9d94f4f
_, err = cliui.Prompt(cmd, cliui.PromptOptions{ | |
Text: "Confirm " + cliui.Styles.Field.Render("password") + ":", | |
Secret: true, | |
Validate: func(s string) error { | |
if s != password { | |
return xerrors.Errorf("Passwords do not match") | |
} | |
return nil | |
}, | |
}) | |
if err != nil { | |
return xerrors.Errorf("confirm password prompt: %w", err) | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question.
Personally, I think the value of a password confirmation step is in making it harder to accidentally lock yourself out by changing your own password to something with a typo in it. I understand why it's helpful in the "create first user" flow, since you can only do that once, but if you make a typo when resetting a password it's easy to just re-run the command and fix it, since you're assumed to have direct access to the DB.
On the other hand, I can see the argument for just doing the confirmation anyway, for consistency with "create first user" and with UNIX passwd
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I agree that it's a bit redundant since you can just change it again.
My thought was both for uniformity and that the repetition increases the chance of typing the correct password, which could help when the user hops onto e.g. the webui and tries to login. If they're very confident they typed in the right password on the cli, but can't login on the web, that could lead to a frustrating experience.
I think either approach is fine though so I'll leave it up to you. 👍🏻
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that makes sense. I added a confirmation prompt, but I deviated from the behavior of coder login
slightly in that if the passwords don't match, we just exit instead of repeating the second prompt. This matches the behavior of the passwd
command, and I think it makes more sense because if you make a typo, you probably don't know whether it's the first or second input that's correct.
* allow non-destructively checking if database needs to be migrated * feat: Add reset-password command * fix linter errors * clean up reset-password usage prompt * Add confirmation to reset-password command * Ping database before checking migration, to improve error message
This PR introduces a
coder reset-password
command that allows resetting a user's password on a production instance by directly updating the DB. This allows an administrator to recover access even if they can't authenticate normally through the API.Fixes #1024