Skip to content

Commit

Permalink
Minor changes to username_recovery
Browse files Browse the repository at this point in the history
- username recovery is an independent feature - so it can exist w/o the recovery feature. Separate that out when initialiing blueprint

- update docs around username, username_recovery
  • Loading branch information
jwag956 committed Jan 7, 2025
1 parent d24e376 commit 812d599
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 49 deletions.
40 changes: 21 additions & 19 deletions docs/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1557,7 +1557,9 @@ Username-Recovery

.. py:data:: SECURITY_USERNAME_RECOVERY
Specifies whether username recovery is enabled.
Specifies whether username recovery is enabled. If set to ``True`` the UserModel
must contain a column ``"username"``. Note that this feature is independent
of the :py:data:`SECURITY_USERNAME_ENABLE` feature.

Default: ``False``.

Expand Down Expand Up @@ -1888,7 +1890,7 @@ Social Oauth

Feature Flags
-------------
All feature flags. By default all are 'False'/not enabled.
All feature flags. By default all are ``False``/not enabled.

* :py:data:`SECURITY_CHANGE_EMAIL`
* :py:data:`SECURITY_CONFIRMABLE`
Expand All @@ -1908,23 +1910,23 @@ URLs and Views
--------------
A list of all URLs and Views:

* :py:data:`SECURITY_LOGIN_URL`
* :py:data:`SECURITY_LOGOUT_URL`
* :py:data:`SECURITY_VERIFY_URL`
* :py:data:`SECURITY_REGISTER_URL`
* :py:data:`SECURITY_CHANGE_EMAIL_URL`
* :py:data:`SECURITY_CHANGE_EMAIL_CONFIRM_URL`
* :py:data:`SECURITY_RESET_URL`
* :py:data:`SECURITY_CHANGE_URL`
* :py:data:`SECURITY_CONFIRM_URL`
* :py:data:`SECURITY_MULTI_FACTOR_RECOVERY_CODES_URL`
* :py:data:`SECURITY_MULTI_FACTOR_RECOVERY_URL`
* :py:data:`SECURITY_OAUTH_START_URL`
* :py:data:`SECURITY_OAUTH_RESPONSE_URL`
* :py:data:`SECURITY_TWO_FACTOR_SELECT_URL`
* :py:data:`SECURITY_TWO_FACTOR_SETUP_URL`
* :py:data:`SECURITY_TWO_FACTOR_TOKEN_VALIDATION_URL`
* :py:data:`SECURITY_TWO_FACTOR_RESCUE_URL`
* :py:data:`SECURITY_LOGIN_URL` ``"/login"``
* :py:data:`SECURITY_LOGOUT_URL` ``"/logout"``
* :py:data:`SECURITY_VERIFY_URL` ``"/verify"``
* :py:data:`SECURITY_REGISTER_URL` ``"/register"``
* :py:data:`SECURITY_CHANGE_EMAIL_URL` ``"change-email"``
* :py:data:`SECURITY_CHANGE_EMAIL_CONFIRM_URL` ``"/change-email-confirm"``
* :py:data:`SECURITY_RESET_URL` ``"/reset"``
* :py:data:`SECURITY_CHANGE_URL` ``"/change"``
* :py:data:`SECURITY_CONFIRM_URL` ``"/confirm"``
* :py:data:`SECURITY_MULTI_FACTOR_RECOVERY_CODES_URL` ``"/mf-recovery-codes"``
* :py:data:`SECURITY_MULTI_FACTOR_RECOVERY_URL` ``"/mf-recovery"``
* :py:data:`SECURITY_OAUTH_START_URL` ``"/login/oauthstart"``
* :py:data:`SECURITY_OAUTH_RESPONSE_URL` ``"/login/oauthresponse"``
* :py:data:`SECURITY_TWO_FACTOR_SELECT_URL` ``"/tf-select"``
* :py:data:`SECURITY_TWO_FACTOR_SETUP_URL` ``"/tf-setup"``
* :py:data:`SECURITY_TWO_FACTOR_TOKEN_VALIDATION_URL` ``"/tf-validate"``
* :py:data:`SECURITY_TWO_FACTOR_RESCUE_URL` ``"/tf-rescue"``
* :py:data:`SECURITY_TWO_FACTOR_ERROR_VIEW`
* :py:data:`SECURITY_TWO_FACTOR_POST_SETUP_VIEW`
* :py:data:`SECURITY_POST_LOGIN_VIEW`
Expand Down
1 change: 1 addition & 0 deletions docs/customizing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,7 @@ welcome_existing SECURITY_SEND_REGISTER_EMAIL SECURITY_EM
welcome_existing_username SECURITY_SEND_REGISTER_EMAIL SECURITY_EMAIL_SUBJECT_REGISTER - email user_not_registered
SECURITY_RETURN_GENERIC_RESPONSES - username
username_recovery SECURITY_USERNAME_RECOVERY SECURITY_EMAIL_SUBJECT_USERNAME_RECOVERY - user username_recovery_email_sent
- username
============================= ================================== ============================================= ====================== ===============================

When sending an email, Flask-Security goes through the following steps:
Expand Down
39 changes: 16 additions & 23 deletions docs/features.rst
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,20 @@ This view can be overridden if your registration process requires more fields.
User email is validated and normalized using the
`email_validator <https://pypi.org/project/email-validator/>`_ package.

The :py:data:`SECURITY_USERNAME_ENABLE` configuration option, when set to ``True``, will add
support for the user to register a username in addition to an email. By default, the user will be
Username Support
-----------------
Flask-Security supports configuring and using a ``username`` is addition to or instead of an email for
authentication.

If the :py:data:`SECURITY_USERNAME_ENABLE` configuration option is set to ``True``, ``username``
will be added to the register and login forms.
By default, the user will be
able to authenticate with EITHER email or username - however that can be changed via the
:py:data:`SECURITY_USER_IDENTITY_ATTRIBUTES`.

The :py:data:`SECURITY_USERNAME_RECOVERY` option adds an endpoint that allows users
to recover a forgotten username (via email).

Email Confirmation
------------------
If :ref:`configured<configuration:Confirmable>`, your application
Expand Down Expand Up @@ -185,8 +194,6 @@ generated and downloaded one-time code (see :py:data:`SECURITY_MULTI_FACTOR_RECO

Unified Sign In
---------------
**This feature is in Beta - mostly due to it being brand new and little to no production soak time**

If :ref:`configured<configuration:Unified Signin>`,
a generalized login endpoint is provided that takes an `identity`
and a `passcode`; where (based on configuration):
Expand Down Expand Up @@ -260,24 +267,10 @@ JSON/Ajax Support
-----------------
Flask-Security supports JSON/Ajax requests where appropriate. Please
look at :ref:`csrf_topic` for details on how to work with JSON and
Single Page Applications. More specifically
JSON is supported for the following operations:

* Login requests
* Unified sign in requests
* Registration requests
* Change password requests
* Change email requests
* Confirmation requests
* Forgot password requests
* Passwordless login requests
* Two-factor login requests
* Change two-factor method requests
* WebAuthn registration and signin requests
* Two-Factor recovery code requests

In addition, Single-Page-Applications (like those built with Vue, Angular, and
React) are supported via customizable redirect links.
Single Page Applications.

In addition, :ref:`spa:Working With Single Page Applications`
(like those built with Vue, Angular, and React) are supported via customizable redirect links.

Note: All registration requests done through JSON/Ajax utilize the ``confirm_register_form``.

Expand Down Expand Up @@ -315,7 +308,7 @@ in the `examples` directory.

.. _Click: https://palletsprojects.com/p/click/
.. _Flask-Login: https://flask-login.readthedocs.org/en/latest/
.. _Flask-WTF: https://flask-wtf.readthedocs.io/en/1.0.x/csrf/
.. _Flask-WTF: https://flask-wtf.readthedocs.io/en/1.2.x/csrf/
.. _alternative token: https://flask-login.readthedocs.io/en/latest/#alternative-tokens
.. _Flask-Principal: https://pypi.org/project/Flask-Principal/
.. _documentation on this topic: http://packages.python.org/Flask-Principal/#granular-resource-protection
Expand Down
1 change: 1 addition & 0 deletions flask_security/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1405,6 +1405,7 @@ def __init__(
self.two_factor: bool = False
self.unified_signin: bool = False
self.passwordless: bool = False
self.username_recovery: bool = False
self.webauthn: bool = False

self.support_mfa: bool = False
Expand Down
15 changes: 8 additions & 7 deletions flask_security/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1289,7 +1289,6 @@ def create_blueprint(app, state, import_name):

if state.recoverable:
reset_url = cv("RESET_URL", app=app)
username_recovery_url = cv("USERNAME_RECOVERY_URL", app=app)
bp.route(reset_url, methods=["GET", "POST"], endpoint="forgot_password")(
forgot_password
)
Expand All @@ -1298,12 +1297,14 @@ def create_blueprint(app, state, import_name):
methods=["GET", "POST"],
endpoint="reset_password",
)(reset_password)
if cv("USERNAME_RECOVERY", app=app):
bp.route(
username_recovery_url,
methods=["GET", "POST"],
endpoint="recover_username",
)(recover_username)

if state.username_recovery:
username_recovery_url = cv("USERNAME_RECOVERY_URL", app=app)
bp.route(
username_recovery_url,
methods=["GET", "POST"],
endpoint="recover_username",
)(recover_username)

if state.changeable:
bp.route(
Expand Down

0 comments on commit 812d599

Please sign in to comment.