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

feat(recoverable): Add support for username recovery via simple login flows #1041

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

jamesejr
Copy link
Contributor

PR adds support for requesting a forgotten username (closes #980). If the user requesting the username recovery enters an email that is valid, they will receive the associated username via the registered email, otherwise they will not.

Copy link

codecov bot commented Nov 18, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 98.37%. Comparing base (c5aa2b2) to head (dbb8d7b).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1041      +/-   ##
==========================================
+ Coverage   98.36%   98.37%   +0.01%     
==========================================
  Files          37       37              
  Lines        4764     4795      +31     
==========================================
+ Hits         4686     4717      +31     
  Misses         78       78              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Collaborator

@jwag956 jwag956 left a comment

Choose a reason for hiding this comment

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

In general - this is awesome and quite complete... thanks

A few minor things - the only larger issue is to make sure that JSON and GENERIC_RESPONSES are supported for the new endpoint.

docs/configuration.rst Outdated Show resolved Hide resolved
flask_security/core.py Outdated Show resolved Hide resolved
flask_security/forms.py Outdated Show resolved Hide resolved
flask_security/forms.py Outdated Show resolved Hide resolved
flask_security/forms.py Outdated Show resolved Hide resolved
flask_security/views.py Outdated Show resolved Hide resolved
flask_security/views.py Show resolved Hide resolved
flask_security/views.py Outdated Show resolved Hide resolved
@jamesejr
Copy link
Contributor Author

Thanks for the review @jwag956 I'll try to address these changes tomorrow 👍🏽

@jamesejr jamesejr marked this pull request as draft December 13, 2024 05:34
@jamesejr jamesejr marked this pull request as ready for review December 23, 2024 05:29
@jamesejr
Copy link
Contributor Author

In general - this is awesome and quite complete... thanks

A few minor things - the only larger issue is to make sure that JSON and GENERIC_RESPONSES are supported for the new endpoint.

@jwag956 Apologies this took me a bit longer to get back into. But I believe I addressed everything. Please take a look whenever you have a chance and enjoy your holidays!

Copy link
Collaborator

@jwag956 jwag956 left a comment

Choose a reason for hiding this comment

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

Wonderful! just a few more comments - only 1 substantive request...

@@ -127,6 +127,8 @@ def app(request: pytest.FixtureRequest) -> SecurityFixture:
# Make this hex_md5 for token tests
app.config["SECURITY_HASHING_SCHEMES"] = ["hex_md5"]
app.config["SECURITY_DEPRECATED_HASHING_SCHEMES"] = []
# Enable username recovery for tests
app.config["SECURITY_USERNAME_RECOVERY"] = True
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: do this in for loop below with all the other options

@@ -256,6 +256,7 @@ Forms
.. autoclass:: flask_security.WebAuthnVerifyForm
.. autoclass:: flask_security.Form
.. autoclass:: flask_security.FormInfo
.. autoclass:: flask_security.UsernameRecoveryForm
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: alphabetize please!

description: render_template(SECURITY_USERNAME_RECOVERY_TEMPLATE)
example: render_template(SECURITY_USERNAME_RECOVERY_TEMPLATE)
post:
summary: Request username recovery
Copy link
Collaborator

Choose a reason for hiding this comment

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

Not quite complete - both request and response should have both form and JSON

200:
description: Send username recovery email
content:
application/json:
Copy link
Collaborator

Choose a reason for hiding this comment

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

not quite right - this looks like the response for forms - not JSON - and you need to add JSON API

@@ -58,6 +58,7 @@
TwoFactorSetupForm,
TwoFactorVerifyCodeForm,
VerifyForm,
UsernameRecoveryForm,
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: alphabetize

)

if form.validate_on_submit():
user = _datastore.find_user(email=form.email.data)
Copy link
Collaborator

Choose a reason for hiding this comment

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

You don't need to do this - UserEmailFormMixin already looks it up and sets form.user if email exists. So if validation succeeds - form.user will be set.

if _security._want_json(request):
return base_render_json(form, include_user=False)

if form.validate_on_submit():
Copy link
Collaborator

Choose a reason for hiding this comment

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

I am not comfortable calling validate_on_submit twice .... as with many other views I think that on GET or POST errors - the template should be rendered (as you do). Maybe what I am asking is - rather than this if/redirect here - do the redirect up in the validate_on_submit() part:

if validate_on_submit():
  send_username_recovery_email()
  if _security_want_json(request):
    return base_render_json....
  do_flash(xxx)
    return redirect(get_url(".login")

if form.validate_on_submit():
return redirect(url_for_security("login"))

return _security.render_template(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please add a context_processor like all other views!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

username recovery
2 participants