- Notifications
You must be signed in to change notification settings - Fork928
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
codecovbot commentedMay 10, 2022 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
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 theEnsureClean
function instead, but that seems difficult because its behavior implicitly depends on the globalmigrations
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!
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
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 thinkcancel
is descriptive enough and addingFunc
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 fromserver_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 isclose
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 thinkpgClose
orcloseConn
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 themigrateSetup
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.
Uh oh!
There was an error while loading.Please reload this page.
}) | ||
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 in9d94f4f
_,err=cliui.Prompt(cmd, cliui.PromptOptions{ | |
Text:"Confirm "+cliui.Styles.Field.Render("password")+":", | |
Secret:true, | |
Validate:func(sstring)error { | |
ifs!=password { | |
returnxerrors.Errorf("Passwords do not match") | |
} | |
returnnil | |
}, | |
}) | |
iferr!=nil { | |
returnxerrors.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 UNIXpasswd
.
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 ofcoder login
slightly in that if the passwords don't match, we just exit instead of repeating the second prompt. This matches the behavior of thepasswd
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.
Uh oh!
There was an error while loading.Please reload this page.
* 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