diff --git a/CHANGES.rst b/CHANGES.rst index b8a2bf0b..f7f49e6f 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,5 +1,5 @@ -Change Log -========== +Change history +============== * v1.0 -- Initial version. diff --git a/README.rst b/README.rst index 3ce51753..08c9b3c3 100644 --- a/README.rst +++ b/README.rst @@ -30,7 +30,7 @@ Secure and Reliable Fully customizable, yet Ready to use ------------------------------------ * **Largely configurable** -- Through configuration settings -* **Fully customizable** -- Through customizable functions and email templates +* **Almost fully customizable** -- Through customizable functions and email templates * **Ready to use** -- Through sensible defaults * Supports **SQL Databases** and **MongoDB Databases** * **Event hooking** -- Through signals diff --git a/docs/source/_static/custom.css b/docs/source/_static/custom.css new file mode 100644 index 00000000..33d5127a --- /dev/null +++ b/docs/source/_static/custom.css @@ -0,0 +1,6 @@ +/* Switch off word hyphenation */ +div.body p, +div.body dd, +div.body li { + hyphens: None; +} \ No newline at end of file diff --git a/docs/source/api.rst b/docs/source/api.rst index 68aea1ba..2903c4b2 100644 --- a/docs/source/api.rst +++ b/docs/source/api.rst @@ -73,7 +73,7 @@ Typical use: # Customize the DB Adapter for SQLAlchemy with this User model self.db_adapter = SQLAlchemyAdapter(db, User) # Customize Flask-User settings - self.enable_email = True + self.USER_ENABLE_EMAIL = True # Setup Flask-User user_manager = CustomUserManager(app) @@ -90,7 +90,7 @@ As an a alternative, user_manager.init_app(app) can be used:: # Customize the DB Adapter for SQLAlchemy with this User model self.db_adapter = SQLAlchemyAdapter(db, User) # Customize Flask-User settings - self.enable_email = True + self.USER_ENABLE_EMAIL = True db = SQLAlchemy(app) # Setup SQLAlchemy user_manager = CustomUserManager(UserManager) # Setup Flask-User diff --git a/docs/source/authorization.rst b/docs/source/authorization.rst index 095b7fd3..acbc706a 100644 --- a/docs/source/authorization.rst +++ b/docs/source/authorization.rst @@ -41,7 +41,7 @@ In the example below the current user is required to have the 'admin' role:: Note: Comparison of role names is case sensitive, so 'Member' will NOT match 'member'. Multiple string arguments -- the AND operation -~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The @roles_required decorator accepts multiple strings if the current_user is required to have **ALL** of these roles. @@ -54,7 +54,7 @@ In the example below the current user is required to have the **ALL** of these r Multiple string arguments represent the 'AND' operation. Array arguments -- the OR operation -~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The @roles_required decorator accepts an array (or a tuple) of roles. @@ -65,7 +65,7 @@ In the example below the current user is required to have **One or more** of the # Array arguments require at least ONE of these roles. AND/OR operations -~~~~~~~~ +~~~~~~~~~~~~~~~~~ The potentially confusing syntax described above allows us to construct complex AND/OR operations. @@ -83,7 +83,7 @@ Note: The nesting level only goes as deep as this example shows. Required Tables --------------- +--------------- For @login_required only the User model is required diff --git a/docs/source/conf.py b/docs/source/conf.py index 5c799ba9..95c1cb8d 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -187,6 +187,10 @@ autodoc_member_order = 'bysource' autoclass_content = 'both' # Show class doc, but not __init__ doc +def setup(app): + # Disable word hyphenation by HTML/CSS + app.add_stylesheet('custom.css') + # -- Global substitutions rst_epilog = """ .. |supported_python_versions_and| replace:: {supported_python_versions_and} diff --git a/docs/source/configure.rst b/docs/source/configure.rst new file mode 100644 index 00000000..f912616b --- /dev/null +++ b/docs/source/configure.rst @@ -0,0 +1,32 @@ +Configure +========= + +Flask-User is designed to be **largely configurable** and **almost fully customizable**. + +Flask-User default features and settings can overridden in one of two ways: + +1) By changing the settings in the application config file:: + + # Customize Flask-User settings + USER_ENABLE_EMAIL = True + USER_ENABLE_USERNAME = False + +2) By changing the setting in the ``UserManager.customize()``:: + + # Customize Flask-User + class CustomUserManager(UserManager): + + def customize(self): + # Customize Flask-User settings + self.USER_ENABLE_EMAIL = True + self.USER_ENABLE_USERNAME = False + +The :ref:`UserManager` documents all Flask-User settings (over 70 of them). + +If a setting is defined in both the application config file and in ``UserManager.customize()``, +the ``UserManager.customize()`` setting will override the config file setting. + +To keep the code base simple and robust, we offer no easy way to change +the '/user' base URL or the '/flask_user' base directory in bulk. +Please copy them from the :ref:`UserManager` docs use your editor to find-and-replace these bases. + diff --git a/docs/source/customization.rst b/docs/source/customize.rst similarity index 99% rename from docs/source/customization.rst rename to docs/source/customize.rst index d97eeb6c..049ee88e 100644 --- a/docs/source/customization.rst +++ b/docs/source/customize.rst @@ -155,7 +155,7 @@ and define the confirmation specific messages in ``templates/flask_user/emails/c The email template files, along with available template variables listed below: * Template variables available in any email template - * ``user_manager`` - For example: ``{% if user_manager.enable_confirm_email %}`` + * ``user_manager`` - For example: ``{% if user_manager.USER_ENABLE_CONFIRM_EMAIL %}`` * ``user`` - For example: ``{{ user.email }}`` * templates/flask_user/confirm_email_[subject.txt|message.html|message.txt] * ``confirm_email_link`` - For example: ``{{ confirm_email_link }}`` diff --git a/docs/source/index.rst b/docs/source/index.rst index d39350cc..3ffbc473 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -18,15 +18,16 @@ Table of Contents limitations data_models porting - changes + configure + customize flask_user_api authorization roles_required_app base_templates - customization signals recipes internationalization faq + changes diff --git a/docs/source/misc_api.rst b/docs/source/misc_api.rst index 15969ec4..3ce2dd15 100644 --- a/docs/source/misc_api.rst +++ b/docs/source/misc_api.rst @@ -4,7 +4,8 @@ Miscellaneous API - DbAdapterForSQLAlchemy_ - DbAdapterForMongoAlchemy_ - EmailMailerForFlaskMail_ -- SendmailEmailMailer_ +- EmailMailerForFlaskSendmail_ +- EmailMailerForSendgrid_ -------- diff --git a/docs/source/porting.rst b/docs/source/porting.rst index f328f521..2a751f8f 100644 --- a/docs/source/porting.rst +++ b/docs/source/porting.rst @@ -42,15 +42,17 @@ appropriate DbAdapter will be configured internally. Configuration settings changes ------------------------------ -we renamed the `PASSWORD_HASH` setting to `PASSWORD_HASH_SCHEME` to better reflect what this setting means. +We split ``USER_SHOW_USERNAME_EMAIL_DOES_NOT_EXIST`` into ``USER_SHOW_USERNAME_DOES_NOT_EXIST`` +and ``USER_SHOW_EMAIL_DOES_NOT_EXIST`` and set the default to False for increased security. Flask-User v0.6:: - USER_PASSWORD_HASH = 'brcypt' + USER_SHOW_USERNAME_EMAIL_DOES_NOT_EXIST = True Flask-User v1.0:: - USER_PASSWORD_HASH_SCHEME = 'brcypt' + USER_SHOW_EMAIL_DOES_NOT_EXIST = False + USER_SHOW_USERNAME_DOES_NOT_EXIST = False Data-model changes @@ -105,7 +107,7 @@ We changed the `verify_user_password()` parameter order to be consistent with th We renamed `update_password()` to `update_user_hashed_password()` to better reflect what this method does. -we renamed the `PASSWORD_HASH` setting to `PASSWORD_HASH_SCHEME` to better reflect what this setting means. +we renamed the `PASSWORD_HASH` setting to `PASSWORD_HASH` to better reflect what this setting means. Flask-User v0.6:: diff --git a/flask_user/email_manager.py b/flask_user/email_manager.py index ec58a9fd..d66a41bb 100644 --- a/flask_user/email_manager.py +++ b/flask_user/email_manager.py @@ -27,8 +27,8 @@ def send_email_confirmation_email(self, user, user_email): """Send the 'email confirmation' email.""" # Verify email settings - if not self.user_manager.enable_email: return - if not self.user_manager.send_registered_email and not self.user_manager.enable_confirm_email: return + if not self.user_manager.USER_ENABLE_EMAIL: return + if not self.user_manager.USER_SEND_REGISTERED_EMAIL and not self.user_manager.USER_ENABLE_CONFIRM_EMAIL: return # Generate confirm email link object_id = user_email.id if user_email else user.id @@ -41,9 +41,9 @@ def send_email_confirmation_email(self, user, user_email): # Render subject, html message and text message subject, html_message, text_message = self._render_email( - self.user_manager.confirm_email_email_template, + self.user_manager.USER_CONFIRM_EMAIL_EMAIL_TEMPLATE, user=user, - app_name=self.user_manager.app_name, + app_name=self.user_manager.USER_APP_NAME, confirm_email_link=confirm_email_link) # Send email message using Flask-Mail @@ -53,8 +53,8 @@ def send_password_has_changed_email(self, user): """Send the 'password has changed' notification email.""" # Verify email settings - if not self.user_manager.enable_email: return - if not self.user_manager.send_password_changed_email: return + if not self.user_manager.USER_ENABLE_EMAIL: return + if not self.user_manager.USER_SEND_PASSWORD_CHANGED_EMAIL: return # Retrieve email address from User or UserEmail object user_email = self.get_primary_user_email(user) @@ -64,9 +64,9 @@ def send_password_has_changed_email(self, user): # Render subject, html message and text message subject, html_message, text_message = self._render_email( - self.user_manager.password_changed_email_template, + self.user_manager.USER_PASSWORD_CHANGED_EMAIL_TEMPLATE, user=user, - app_name=self.user_manager.app_name) + app_name=self.user_manager.USER_APP_NAME) # Send email message using Flask-Mail self._send_email_message(email, subject, html_message, text_message) @@ -75,8 +75,8 @@ def send_reset_password_email(self, user, user_email): """Send the 'reset password' email.""" # Verify email settings - if not self.user_manager.enable_email: return - assert self.user_manager.enable_forgot_password + if not self.user_manager.USER_ENABLE_EMAIL: return + assert self.user_manager.USER_ENABLE_FORGOT_PASSWORD # Generate reset password link token = self.user_manager.token_manager.generate_token(user.id) @@ -88,9 +88,9 @@ def send_reset_password_email(self, user, user_email): # Render subject, html message and text message subject, html_message, text_message = self._render_email( - self.user_manager.forgot_password_email_template, + self.user_manager.USER_FORGOT_PASSWORD_EMAIL_TEMPLATE, user=user, - app_name=self.user_manager.app_name, + app_name=self.user_manager.USER_APP_NAME, reset_password_link=reset_password_link) # Send email message using Flask-Mail @@ -107,9 +107,9 @@ def send_user_invitation_email(self, user): # Render subject, html message and text message subject, html_message, text_message = self._render_email( - self.user_manager.invite_email_template, + self.user_manager.USER_INVITE_EMAIL_TEMPLATE, user=user, - app_name=self.user_manager.app_name, + app_name=self.user_manager.USER_APP_NAME, accept_invite_link=accept_invite_link) # Send email message using Flask-Mail @@ -119,8 +119,8 @@ def send_user_has_registered_email(self, user, user_email, confirm_email_link): """Send the 'user has registered' notification email.""" # Verify email settings - if not self.user_manager.enable_email: return - if not self.user_manager.send_registered_email: return + if not self.user_manager.USER_ENABLE_EMAIL: return + if not self.user_manager.USER_SEND_REGISTERED_EMAIL: return # Retrieve email address from User or UserEmail object email = user_email.email if user_email else user.email @@ -128,9 +128,9 @@ def send_user_has_registered_email(self, user, user_email, confirm_email_link): # Render subject, html message and text message subject, html_message, text_message = self._render_email( - self.user_manager.registered_email_template, + self.user_manager.USER_REGISTERED_EMAIL_TEMPLATE, user=user, - app_name=self.user_manager.app_name, + app_name=self.user_manager.USER_APP_NAME, confirm_email_link=confirm_email_link) # Send email message using Flask-Mail @@ -140,8 +140,8 @@ def send_username_has_changed_email(self, user): # pragma: no cover """Send the 'username has changed' notification email.""" # Verify email settings - if not self.user_manager.enable_email: return - if not self.user_manager.send_username_changed_email: return + if not self.user_manager.USER_ENABLE_EMAIL: return + if not self.user_manager.USER_SEND_USERNAME_CHANGED_EMAIL: return # Retrieve email address from User or UserEmail object user_email = self.get_primary_user_email(user) @@ -151,9 +151,9 @@ def send_username_has_changed_email(self, user): # pragma: no cover # Render subject, html message and text message subject, html_message, text_message = self._render_email( - self.user_manager.username_changed_email_template, + self.user_manager.USER_USERNAME_CHANGED_EMAIL_TEMPLATE, user=user, - app_name=self.user_manager.app_name) + app_name=self.user_manager.USER_APP_NAME) # Send email message using Flask-Mail self._send_email_message(email, subject, html_message, text_message) diff --git a/flask_user/forms.py b/flask_user/forms.py index d4de1205..d8f5f246 100644 --- a/flask_user/forms.py +++ b/flask_user/forms.py @@ -97,7 +97,7 @@ class ChangePasswordForm(FlaskForm): def validate(self): # Use feature config to remove unused form fields user_manager = current_app.user_manager - if not user_manager.enable_retype_password: + if not user_manager.USER_ENABLE_RETYPE_PASSWORD: delattr(self, 'retype_password') # Add custom password validator if needed @@ -165,7 +165,7 @@ class ForgotPasswordForm(FlaskForm): def validate_email(form, field): user_manager = current_app.user_manager - if user_manager.show_username_email_does_not_exist: + if user_manager.USER_SHOW_EMAIL_DOES_NOT_EXIST: user, user_email = user_manager.find_user_by_email(field.data) if not user: raise ValidationError(_('%(username_or_email)s does not exist', username_or_email=_('Email'))) @@ -192,14 +192,14 @@ class LoginForm(FlaskForm): def __init__(self, *args, **kwargs): super(LoginForm, self).__init__(*args, **kwargs) user_manager = current_app.user_manager - if user_manager.enable_username and user_manager.enable_email: + if user_manager.USER_ENABLE_USERNAME and user_manager.USER_ENABLE_EMAIL: # Renamed 'Username' label to 'Username or Email' self.username.label.text = _('Username or Email') def validate(self): # Remove fields depending on configuration user_manager = current_app.user_manager - if user_manager.enable_username: + if user_manager.USER_ENABLE_USERNAME: delattr(self, 'email') else: delattr(self, 'username') @@ -211,12 +211,12 @@ def validate(self): # Find user by username and/or email user = None user_email = None - if user_manager.enable_username: + if user_manager.USER_ENABLE_USERNAME: # Find user by username user = user_manager.find_user_by_username(self.username.data) # Find user by email address (username field) - if not user and user_manager.enable_email: + if not user and user_manager.USER_ENABLE_EMAIL: user, user_email = user_manager.find_user_by_email(self.username.data) else: @@ -229,25 +229,28 @@ def validate(self): # Handle unsuccessful authentication # Email, Username or Email/Username depending on settings - if user_manager.enable_username and user_manager.enable_email: + if user_manager.USER_ENABLE_USERNAME and user_manager.USER_ENABLE_EMAIL: username_or_email_field = self.username username_or_email_text = (_('Username/Email')) - elif user_manager.enable_username: + show_does_not_exist = user_manager.USER_SHOW_EMAIL_DOES_NOT_EXIST or user_manager.USER_SHOW_USERNAME_DOES_NOT_EXIST + elif user_manager.USER_ENABLE_USERNAME: username_or_email_field = self.username username_or_email_text = (_('Username')) + show_does_not_exist = user_manager.USER_SHOW_USERNAME_DOES_NOT_EXIST else: username_or_email_field = self.email username_or_email_text = (_('Email')) + show_does_not_exist = user_manager.USER_SHOW_EMAIL_DOES_NOT_EXIST - # Show 'username/email does not exist error message - if user_manager.show_username_email_does_not_exist: + # Show 'username/email does not exist' or 'incorrect password' error message + if show_does_not_exist: if not user: message = _('%(username_or_email)s does not exist', username_or_email=username_or_email_text) username_or_email_field.errors.append(message) else: self.password.errors.append(_('Incorrect Password')) - # Hide 'username/email does not exist error message for additional security + # Always show 'incorrect username/email or password' error message for additional security else: message = _('Incorrect %(username_or_email)s and/or Password', username_or_email=username_or_email_text) username_or_email_field.errors.append(message) @@ -280,14 +283,14 @@ class RegisterForm(FlaskForm): def validate(self): # remove certain form fields depending on user manager config user_manager = current_app.user_manager - if not user_manager.enable_username: + if not user_manager.USER_ENABLE_USERNAME: delattr(self, 'username') - if not user_manager.enable_email: + if not user_manager.USER_ENABLE_EMAIL: delattr(self, 'email') - if not user_manager.enable_retype_password: + if not user_manager.USER_ENABLE_RETYPE_PASSWORD: delattr(self, 'retype_password') # Add custom username validator if needed - if user_manager.enable_username: + if user_manager.USER_ENABLE_USERNAME: has_been_added = False for v in self.username.validators: if v==user_manager.username_validator: @@ -327,7 +330,7 @@ class ResetPasswordForm(FlaskForm): def validate(self): # Use feature config to remove unused form fields user_manager = current_app.user_manager - if not user_manager.enable_retype_password: + if not user_manager.USER_ENABLE_RETYPE_PASSWORD: delattr(self, 'retype_password') # Add custom password validator if needed has_been_added = False diff --git a/flask_user/password_manager.py b/flask_user/password_manager.py index 4751038b..d2df2c60 100644 --- a/flask_user/password_manager.py +++ b/flask_user/password_manager.py @@ -7,17 +7,17 @@ from __future__ import print_function -from passlib.context import CryptContext -import hashlib -import hmac -import base64 from flask import current_app +from passlib.context import CryptContext -def generate_sha512_hmac(self, password_salt, password): - """ Generate SHA512 HMAC -- for compatibility with Flask-Security """ - return base64.b64encode(hmac.new(password_salt, password.encode('utf-8'), hashlib.sha512).digest()) +# def generate_sha512_hmac(self, password_salt, password): +# """ Generate SHA512 HMAC -- for compatibility with Flask-Security """ +# import hashlib +# import hmac +# import base64 +# return base64.b64encode(hmac.new(password_salt, password.encode('utf-8'), hashlib.sha512).digest()) # The UserManager is implemented across several source code files. @@ -40,9 +40,9 @@ def __init__(self, password_crypt_context, password_hash_scheme, password_hash_m def hash_password(self, password): """ Generate hashed password using SHA512 HMAC and the USER_PASSWORD_HASH hash function.""" - # Pre-generate SHA512 HMAC -- For compatibility with Flask-Security - if self.password_hash_mode == 'Flask-Security': - password = generate_sha512_hmac(self.password_salt, password) + # # Pre-generate SHA512 HMAC -- For compatibility with Flask-Security + # if self.password_hash_mode == 'Flask-Security': + # password = generate_sha512_hmac(self.password_salt, password) # Use passlib's CryptContext to hash password hashed_password = self.password_crypt_context.encrypt(password) @@ -55,7 +55,7 @@ def verify_user_password(self, user, password): Returns True on matching password. Returns False otherwise.""" - # Perform some Python magic to allow for: + # Perform some Python magic to flip param order for v0.6-style calls: # - v0.6 verify_user_password(password, user), and # - v0.9+ verify_user_password(user, password) parameter order if isinstance(user, (b''.__class__, u''.__class__)): @@ -66,9 +66,9 @@ def verify_user_password(self, user, password): hashed_password = user.password - # Pre-generate SHA512 HMAC -- For compatibility with Flask-Security - if self.password_hash_mode == 'Flask-Security': - password = generate_sha512_hmac(self.password_salt, password) + # # Pre-generate SHA512 HMAC -- For compatibility with Flask-Security + # if self.password_hash_mode == 'Flask-Security': + # password = generate_sha512_hmac(self.password_salt, password) # Use passlib's CryptContext to verify return self.password_crypt_context.verify(password, hashed_password) diff --git a/flask_user/templates/base.html b/flask_user/templates/base.html index b6909de2..85f859e7 100644 --- a/flask_user/templates/base.html +++ b/flask_user/templates/base.html @@ -4,7 +4,7 @@ - {{ user_manager.app_name }} + {{ user_manager.USER_APP_NAME }} @@ -29,7 +29,7 @@ {% block body %}
-

{{ user_manager.app_name }}

+

{{ user_manager.USER_APP_NAME }}

{% if call_or_get(current_user.is_authenticated) %} {{ current_user.username or current_user.email }} @@ -71,7 +71,7 @@

{% endblock %} diff --git a/flask_user/templates/flask_user/change_password.html b/flask_user/templates/flask_user/change_password.html index 2f490c60..2732df56 100644 --- a/flask_user/templates/flask_user/change_password.html +++ b/flask_user/templates/flask_user/change_password.html @@ -8,7 +8,7 @@

{%trans%}Change password{%endtrans%}

{{ form.hidden_tag() }} {{ render_field(form.old_password, tabindex=10) }} {{ render_field(form.new_password, tabindex=20) }} - {% if user_manager.enable_retype_password %} + {% if user_manager.USER_ENABLE_RETYPE_PASSWORD %} {{ render_field(form.retype_password, tabindex=30) }} {% endif %} {{ render_submit_field(form.submit, tabindex=90) }} diff --git a/flask_user/templates/flask_user/emails/password_changed_message.html b/flask_user/templates/flask_user/emails/password_changed_message.html index def42b90..8f62038c 100644 --- a/flask_user/templates/flask_user/emails/password_changed_message.html +++ b/flask_user/templates/flask_user/emails/password_changed_message.html @@ -2,7 +2,7 @@ {% block message %}

Your password has been changed.

-{% if user_manager.enable_forgot_password %} +{% if user_manager.USER_ENABLE_FORGOT_PASSWORD %}

If you did not initiate this password change, click here to reset it.

{% endif %} {% endblock %} diff --git a/flask_user/templates/flask_user/emails/registered_message.html b/flask_user/templates/flask_user/emails/registered_message.html index cc3305c2..dcbe0622 100644 --- a/flask_user/templates/flask_user/emails/registered_message.html +++ b/flask_user/templates/flask_user/emails/registered_message.html @@ -4,7 +4,7 @@

Thank you for registering with {{ app_name }}.

-{% if user_manager.enable_confirm_email and not user.email_confirmed_at %} +{% if user_manager.USER_ENABLE_CONFIRM_EMAIL and not user.email_confirmed_at %}

You will need to confirm your email next.

If you initiated this registration, please click on the link below:
diff --git a/flask_user/templates/flask_user/login.html b/flask_user/templates/flask_user/login.html index 3d8f9634..4a62d502 100644 --- a/flask_user/templates/flask_user/login.html +++ b/flask_user/templates/flask_user/login.html @@ -8,7 +8,7 @@

{%trans%}Sign in{%endtrans%}

{{ form.hidden_tag() }} {# Username or Email field #} - {% set field = form.username if user_manager.enable_username else form.email %} + {% set field = form.username if user_manager.USER_ENABLE_USERNAME else form.email %}
{# Label on left, "New here? Register." on right #}
@@ -16,7 +16,7 @@

{%trans%}Sign in{%endtrans%}

- {% if user_manager.enable_register and not user_manager.require_invitation %} + {% if user_manager.USER_ENABLE_REGISTER and not user_manager.USER_REQUIRE_INVITATION %} {%trans%}New here? Register.{%endtrans%} {% endif %} @@ -39,7 +39,7 @@

{%trans%}Sign in{%endtrans%}

- {% if user_manager.enable_forgot_password %} + {% if user_manager.USER_ENABLE_FORGOT_PASSWORD %} {%trans%}Forgot your Password?{%endtrans%} {% endif %} @@ -54,7 +54,7 @@

{%trans%}Sign in{%endtrans%}

{# Remember me #} - {% if user_manager.enable_remember_me %} + {% if user_manager.USER_ENABLE_REMEMBER_ME %} {{ render_checkbox_field(login_form.remember_me, tabindex=130) }} {% endif %} diff --git a/flask_user/templates/flask_user/login_or_register.html b/flask_user/templates/flask_user/login_or_register.html index c741c2ff..907c54f8 100644 --- a/flask_user/templates/flask_user/login_or_register.html +++ b/flask_user/templates/flask_user/login_or_register.html @@ -13,21 +13,21 @@

{%trans%}Sign in{%endtrans%}

{{ login_form.hidden_tag() }} {# Username or Email #} - {% set field = login_form.username if user_manager.enable_username else login_form.email %} + {% set field = login_form.username if user_manager.USER_ENABLE_USERNAME else login_form.email %} {{ render_field(field, tabindex=110) }} {# Password #} {{ render_field(login_form.password, tabindex=120) }} {# Remember me #} - {% if user_manager.enable_remember_me %} + {% if user_manager.USER_ENABLE_REMEMBER_ME %} {{ render_checkbox_field(login_form.remember_me, tabindex=130) }} {% endif %} {# Submit button #} {{ render_submit_field(login_form.submit, tabindex=180) }} - {% if user_manager.enable_forgot_password %} + {% if user_manager.USER_ENABLE_FORGOT_PASSWORD %}


@@ -45,16 +45,16 @@

{%trans%}Register{%endtrans%}

{{ register_form.hidden_tag() }} {# Username or Email #} - {% set field = register_form.username if user_manager.enable_username else register_form.email %} + {% set field = register_form.username if user_manager.USER_ENABLE_USERNAME else register_form.email %} {{ render_field(field, tabindex=210) }} - {% if user_manager.enable_email and user_manager.enable_username %} + {% if user_manager.USER_ENABLE_EMAIL and user_manager.USER_ENABLE_USERNAME %} {{ render_field(register_form.email, tabindex=220) }} {% endif %} {{ render_field(register_form.password, tabindex=230) }} - {% if user_manager.enable_retype_password %} + {% if user_manager.USER_ENABLE_RETYPE_PASSWORD %} {{ render_field(register_form.retype_password, tabindex=240) }} {% endif %} diff --git a/flask_user/templates/flask_user/register.html b/flask_user/templates/flask_user/register.html index 0c2c924c..a6ecad42 100644 --- a/flask_user/templates/flask_user/register.html +++ b/flask_user/templates/flask_user/register.html @@ -8,7 +8,7 @@

{%trans%}Register{%endtrans%}

{{ form.hidden_tag() }} {# Username or Email #} - {% set field = form.username if user_manager.enable_username else form.email %} + {% set field = form.username if user_manager.USER_ENABLE_USERNAME else form.email %}
{# Label on left, "Already registered? Sign in." on right #}
@@ -16,7 +16,7 @@

{%trans%}Register{%endtrans%}

- {% if user_manager.enable_email and user_manager.enable_username %} + {% if user_manager.USER_ENABLE_EMAIL and user_manager.USER_ENABLE_USERNAME %} {{ render_field(form.email, tabindex=220) }} {% endif %} {{ render_field(form.password, tabindex=230) }} - {% if user_manager.enable_retype_password %} + {% if user_manager.USER_ENABLE_RETYPE_PASSWORD %} {{ render_field(form.retype_password, tabindex=240) }} {% endif %} diff --git a/flask_user/templates/flask_user/reset_password.html b/flask_user/templates/flask_user/reset_password.html index b0f3c935..f150cf33 100644 --- a/flask_user/templates/flask_user/reset_password.html +++ b/flask_user/templates/flask_user/reset_password.html @@ -7,7 +7,7 @@

{%trans%}Reset Password{%endtrans%}

{{ form.hidden_tag() }} {{ render_field(form.new_password, tabindex=10) }} - {% if user_manager.enable_retype_password %} + {% if user_manager.USER_ENABLE_RETYPE_PASSWORD %} {{ render_field(form.retype_password, tabindex=20) }} {% endif %} {{ render_submit_field(form.submit, tabindex=90) }} diff --git a/flask_user/templates/flask_user/user_profile.html b/flask_user/templates/flask_user/user_profile.html index 0d5c02a6..20ce6569 100644 --- a/flask_user/templates/flask_user/user_profile.html +++ b/flask_user/templates/flask_user/user_profile.html @@ -4,10 +4,10 @@ {% from "flask_user/_macros.html" import render_field, render_checkbox_field, render_submit_field %}

{%trans%}User profile{%endtrans%}

-{% if user_manager.enable_change_username %} +{% if user_manager.USER_ENABLE_CHANGE_USERNAME %}

{%trans%}Change username{%endtrans%}

{% endif %} -{% if user_manager.enable_change_password %} +{% if user_manager.USER_ENABLE_CHANGE_PASSWORD %}

{%trans%}Change password{%endtrans%}

{% endif %} diff --git a/flask_user/tests/test_authorization.py b/flask_user/tests/test_authorization.py index 847106bb..429718b7 100644 --- a/flask_user/tests/test_authorization.py +++ b/flask_user/tests/test_authorization.py @@ -33,11 +33,11 @@ def test_authorization(client): Test various authorization scenarios """ um = current_app.user_manager - um.enable_register = True - um.enable_username = True - um.enable_email = False - um.enable_confirm_email = False - um.enable_retype_password = False + um.USER_ENABLE_REGISTER = True + um.USER_ENABLE_USERNAME = True + um.USER_ENABLE_EMAIL = False + um.USER_ENABLE_CONFIRM_EMAIL = False + um.USER_ENABLE_RETYPE_PASSWORD = False # Test as anonymous user client.get_valid_page(url_for('home_page')) diff --git a/flask_user/tests/test_invalid_forms.py b/flask_user/tests/test_invalid_forms.py index 8a970ee9..8f9de45e 100644 --- a/flask_user/tests/test_invalid_forms.py +++ b/flask_user/tests/test_invalid_forms.py @@ -61,13 +61,13 @@ def test_init(db): # Enable all features um = current_app.user_manager - um.enable_register = True - um.enable_change_username = True - um.enable_change_password = True - um.enable_confirm_email = True + um.USER_ENABLE_REGISTER = True + um.USER_ENABLE_CHANGE_USERNAME = True + um.USER_ENABLE_CHANGE_PASSWORD = True + um.USER_ENABLE_CONFIRM_EMAIL = True um.enable_reset_password = True - um.enable_email = True - um.enable_retype_password = True + um.USER_ENABLE_EMAIL = True + um.USER_ENABLE_RETYPE_PASSWORD = True # Tests have not been written with auto_login in mind um.auto_login = False @@ -100,7 +100,7 @@ def test_invalid_register_with_username_form(client): # Choose config um = current_app.user_manager - um.enable_username = True + um.USER_ENABLE_USERNAME = True User = um.UserClass # Set default values @@ -144,7 +144,7 @@ def test_invalid_register_with_email_form(client): # Choose config um = current_app.user_manager - um.enable_username = False + um.USER_ENABLE_USERNAME = False User = um.UserClass # Set default values @@ -191,10 +191,10 @@ def test_invalid_confirm_email_page(client): url = url_for('user.confirm_email', token=token) # Test Expired token - orig_expiration = um.confirm_email_expiration # Save old expiration - um.confirm_email_expiration = -1 # Make it expire immediately + orig_expiration = um.USER_CONFIRM_EMAIL_EXPIRATION # Save old expiration + um.USER_CONFIRM_EMAIL_EXPIRATION = -1 # Make it expire immediately client.get_invalid_page(url, 'Invalid confirmation token') - um.confirm_email_expiration = orig_expiration # Restors old expiration + um.USER_CONFIRM_EMAIL_EXPIRATION = orig_expiration # Restors old expiration def test_invalid_login_with_username_form(client): @@ -202,8 +202,8 @@ def test_invalid_login_with_username_form(client): # Choose config um = current_app.user_manager - um.enable_email = True - um.enable_username = True + um.USER_ENABLE_EMAIL = True + um.USER_ENABLE_USERNAME = True # Set default values url = url_for('user.login') @@ -215,34 +215,40 @@ def test_invalid_login_with_username_form(client): username='', password=password) # Test incorrect username - um.show_username_email_does_not_exist = False + um.USER_SHOW_EMAIL_DOES_NOT_EXIST = False + um.USER_SHOW_USERNAME_DOES_NOT_EXIST = False client.post_invalid_form(url, 'Incorrect Username/Email and/or Password', username='Xuser1', password=password) - um.show_username_email_does_not_exist = True + um.USER_SHOW_EMAIL_DOES_NOT_EXIST = True + um.USER_SHOW_USERNAME_DOES_NOT_EXIST = True client.post_invalid_form(url, 'Username/Email does not exist', username='Xuser1', password=password) - um.show_username_email_does_not_exist = False + um.USER_SHOW_EMAIL_DOES_NOT_EXIST = False + um.USER_SHOW_USERNAME_DOES_NOT_EXIST = False # Test empty password client.post_invalid_form(url, 'Password is required', username=username, password='') # Test incorrect password - um.show_username_email_does_not_exist = False + um.USER_SHOW_EMAIL_DOES_NOT_EXIST = False + um.USER_SHOW_USERNAME_DOES_NOT_EXIST = False client.post_invalid_form(url, 'Incorrect Username/Email and/or Password', username=username, password='XPassword1') - um.show_username_email_does_not_exist = True + um.USER_SHOW_EMAIL_DOES_NOT_EXIST = True + um.USER_SHOW_USERNAME_DOES_NOT_EXIST = True client.post_invalid_form(url, 'Incorrect Password', username=username, password='XPassword1') - um.show_username_email_does_not_exist = False + um.USER_SHOW_EMAIL_DOES_NOT_EXIST = False + um.USER_SHOW_USERNAME_DOES_NOT_EXIST = False def test_invalid_login_with_email_form(client): print("test_invalid_login_with_email_form") # Choose config um = current_app.user_manager - um.enable_email = True - um.enable_username = False + um.USER_ENABLE_EMAIL = True + um.USER_ENABLE_USERNAME = False # Set default values url = url_for('user.login') @@ -254,34 +260,41 @@ def test_invalid_login_with_email_form(client): email='', password=password) # Test incorrect email - um.show_username_email_does_not_exist = False + um.USER_SHOW_EMAIL_DOES_NOT_EXIST = False + um.USER_SHOW_USERNAME_DOES_NOT_EXIST = False client.post_invalid_form(url, 'Incorrect Email and/or Password', email='Xuser2@example.com', password=password) - um.show_username_email_does_not_exist = True + um.USER_SHOW_EMAIL_DOES_NOT_EXIST = True + um.USER_SHOW_USERNAME_DOES_NOT_EXIST = True client.post_invalid_form(url, 'Email does not exist', email='Xuser2@example.com', password=password) - um.show_username_email_does_not_exist = False + um.USER_SHOW_EMAIL_DOES_NOT_EXIST = False + um.USER_SHOW_USERNAME_DOES_NOT_EXIST = False # Test empty password client.post_invalid_form(url, 'Password is required', email=email, password='') # Test incorrect password - um.show_username_email_does_not_exist = False + um.USER_SHOW_EMAIL_DOES_NOT_EXIST = False + um.USER_SHOW_USERNAME_DOES_NOT_EXIST = False client.post_invalid_form(url, 'Incorrect Email and/or Password', email=email, password='XPassword1') - um.show_username_email_does_not_exist = True + um.USER_SHOW_EMAIL_DOES_NOT_EXIST = True + um.USER_SHOW_USERNAME_DOES_NOT_EXIST = True client.post_invalid_form(url, 'Incorrect Password', email=email, password='XPassword1') - um.show_username_email_does_not_exist = False + um.USER_SHOW_EMAIL_DOES_NOT_EXIST = False + um.USER_SHOW_USERNAME_DOES_NOT_EXIST = False def test_invalid_change_username_form(client): print("test_invalid_change_username_form") # Set user manager config um = current_app.user_manager - um.enable_username = True - um.enable_email = False + um.USER_ENABLE_EMAIL = False + um.USER_ENABLE_USERNAME = True + um.USER_ENABLE_CHANGE_USERNAME = True # Set default values username = 'user1' @@ -319,7 +332,7 @@ def test_invalid_change_password_form(client): # Set user manager config um = current_app.user_manager - um.enable_username = False + um.USER_ENABLE_USERNAME = False # Set default values email = 'user2@example.com' @@ -382,11 +395,11 @@ def test_invalid_reset_password(client): # Expired Token url = url_for('user.reset_password', token=token) - orig_expiration = um.reset_password_expiration # Save old expiration - um.reset_password_expiration = -1 # Make it expire immediately + orig_expiration = um.USER_PASSWORD_EXPIRATION # Save old expiration + um.USER_PASSWORD_EXPIRATION = -1 # Make it expire immediately client.post_invalid_form(url, 'Your reset password token is invalid', new_password=new_password, retype_password=new_password) - um.reset_password_expiration = orig_expiration # Restore old expiration + um.USER_PASSWORD_EXPIRATION = orig_expiration # Restore old expiration # Invalid retype password client.post_invalid_form(url, 'New Password and Retype Password did not match', @@ -401,7 +414,7 @@ def test_valid_roles(client): if not user007: return print("test_valid_roles") - um.enable_username = True + um.USER_ENABLE_USERNAME = True client.login(username='user007', password='Password1') url = url_for('special_page') @@ -418,7 +431,7 @@ def test_invalid_roles(client): if not user007: return print("test_invalid_roles") - um.enable_username = True + um.USER_ENABLE_USERNAME = True client.login(username='user1', password='Password1') url = url_for('special_page') @@ -429,10 +442,10 @@ def test_login_without_confirm_email(client): print("test_login_without_confirm_email") um = current_app.user_manager - um.enable_username = False - um.enable_email = True - um.enable_confirm_email = True - um.enable_retype_password = False + um.USER_ENABLE_USERNAME = False + um.USER_ENABLE_EMAIL = True + um.USER_ENABLE_CONFIRM_EMAIL = True + um.USER_ENABLE_RETYPE_PASSWORD = False email = 'notconfirmed@example.com' password = 'Password1' diff --git a/flask_user/tests/test_multiple_emails.py b/flask_user/tests/test_multiple_emails.py index bf050f2f..b4075d4e 100644 --- a/flask_user/tests/test_multiple_emails.py +++ b/flask_user/tests/test_multiple_emails.py @@ -33,22 +33,22 @@ def test_multiple_emails(app, db, client): # Set Flask-User settings um = current_app.user_manager - um.enable_register = True - um.enable_username = False - um.enable_email = True - um.enable_confirm_email = True - um.enable_change_username = False - um.enable_change_password = False - um.enable_forgot_password = False - um.enable_multiple_emails = True - um.enable_retype_password = False + um.USER_ENABLE_REGISTER = True + um.USER_ENABLE_USERNAME = False + um.USER_ENABLE_EMAIL = True + um.USER_ENABLE_CONFIRM_EMAIL = True + um.USER_ENABLE_CHANGE_USERNAME = False + um.USER_ENABLE_CHANGE_PASSWORD = False + um.USER_ENABLE_FORGOT_PASSWORD = False + um.USER_ENABLE_MULTIPLE_EMAILS = True + um.USER_ENABLE_RETYPE_PASSWORD = False # Adjust DbAdapter settings um.UserEmailClass = app.UserEmailClass # Adjust URL routes - app.add_url_rule(um.email_action_url, 'user.email_action', um.email_action_view_function) - app.add_url_rule(um.manage_emails_url, 'user.manage_emails', um.manage_emails_view_function, methods=['GET', 'POST']) + app.add_url_rule(um.USER_EMAIL_ACTION_URL, 'user.email_action', um.email_action_view_function) + app.add_url_rule(um.USER_MANAGE_EMAILS_URL, 'user.manage_emails', um.manage_emails_view_function, methods=['GET', 'POST']) # constants EMAIL1 = 'email1@multi-email.com' @@ -107,8 +107,8 @@ def test_multiple_emails(app, db, client): client.logout() # Restore settings - um.enable_multiple_emails = False - um.enable_confirm_email = True - um.enable_retype_password = True + um.USER_ENABLE_MULTIPLE_EMAILS = False + um.USER_ENABLE_CONFIRM_EMAIL = True + um.USER_ENABLE_RETYPE_PASSWORD = True um.UserEmailClass = None diff --git a/flask_user/tests/test_valid_forms.py b/flask_user/tests/test_valid_forms.py index 58c336dc..e995c79b 100644 --- a/flask_user/tests/test_valid_forms.py +++ b/flask_user/tests/test_valid_forms.py @@ -34,40 +34,40 @@ def test_with_email(client): """ - Test all forms with all enabled features and enable_username=False + Test all forms with all enabled features and USER_ENABLE_USERNAME=False """ print('test_with_email()') um = current_app.user_manager - um.enable_register = True - um.enable_username = False - um.enable_email = True # Login with email - um.enable_confirm_email = True - um.enable_change_username = False - um.enable_change_password = True - um.enable_forgot_password = True - um.enable_multiple_emails = False - um.enable_retype_password = True + um.USER_ENABLE_REGISTER = True + um.USER_ENABLE_USERNAME = False + um.USER_ENABLE_EMAIL = True # Login with email + um.USER_ENABLE_CONFIRM_EMAIL = True + um.USER_ENABLE_CHANGE_USERNAME = False + um.USER_ENABLE_CHANGE_PASSWORD = True + um.USER_ENABLE_FORGOT_PASSWORD = True + um.USER_ENABLE_MULTIPLE_EMAILS = False + um.USER_ENABLE_RETYPE_PASSWORD = True check_all_valid_forms(um, client) def test_with_username(client): """ - Test all forms with all enabled features and enable_username=True + Test all forms with all enabled features and USER_ENABLE_USERNAME=True """ print('test_with_username()') # Enable all features um = current_app.user_manager - um.enable_register = True - um.enable_username = True # Login with username - um.enable_email = False - um.enable_confirm_email = False - um.enable_change_username = True - um.enable_change_password = True - um.enable_forgot_password = False - um.enable_multiple_emails = False - um.enable_retype_password = True + um.USER_ENABLE_REGISTER = True + um.USER_ENABLE_USERNAME = True # Login with username + um.USER_ENABLE_EMAIL = False + um.USER_ENABLE_CONFIRM_EMAIL = False + um.USER_ENABLE_CHANGE_USERNAME = True + um.USER_ENABLE_CHANGE_PASSWORD = True + um.USER_ENABLE_FORGOT_PASSWORD = False + um.USER_ENABLE_MULTIPLE_EMAILS = False + um.USER_ENABLE_RETYPE_PASSWORD = True check_all_valid_forms(um, client) @@ -84,15 +84,15 @@ def do_test_all_possible_config_combinations(client, db): print("Testing all forms for all possible config combinations") um = current_app.user_manager - for um.enable_register in (True, False): - for um.enable_email in (True, False): - for um.enable_retype_password in (True, False): - for um.enable_confirm_email in (True, False): - for um.enable_username in (True, False): - for um.enable_change_password in (True, False): - for um.enable_change_username in (True, False): - for um.enable_forgot_password in (True, False): - for um.enable_invitation in (True, False): + for um.USER_ENABLE_REGISTER in (True, False): + for um.USER_ENABLE_EMAIL in (True, False): + for um.USER_ENABLE_RETYPE_PASSWORD in (True, False): + for um.USER_ENABLE_CONFIRM_EMAIL in (True, False): + for um.USER_ENABLE_USERNAME in (True, False): + for um.USER_ENABLE_CHANGE_PASSWORD in (True, False): + for um.USER_ENABLE_CHANGE_USERNAME in (True, False): + for um.USER_ENABLE_FORGOT_PASSWORD in (True, False): + for um.USER_ENABLE_INVITATION in (True, False): check_all_valid_forms(um, client, db) # ************************** @@ -103,13 +103,13 @@ def do_test_all_possible_config_combinations(client, db): def check_all_valid_forms(um, client): # ** Skip tests for invalid config combinations # USER_ENABLE_REGISTER=True must have USER_ENABLE_USERNAME=True or USER_ENABLE_EMAIL=True or both. - if um.enable_register and not um.enable_email and not um.enable_username: return + if um.USER_ENABLE_REGISTER and not um.USER_ENABLE_EMAIL and not um.USER_ENABLE_USERNAME: return # USER_ENABLE_CONFIRM_EMAIL=True must have USER_ENABLE_EMAIL=True - if um.enable_confirm_email and not um.enable_email: return + if um.USER_ENABLE_CONFIRM_EMAIL and not um.USER_ENABLE_EMAIL: return # USER_ENABLE_MULTIPLE_EMAILS=True must have USER_ENABLE_EMAIL=True - if um.enable_multiple_emails and not um.enable_email: return + if um.USER_ENABLE_MULTIPLE_EMAILS and not um.USER_ENABLE_EMAIL: return # ENABLE_CHANGE_USERNAME=True must have ENABLE_USERNAME=True. - if um.enable_change_username and not um.enable_username: return + if um.USER_ENABLE_CHANGE_USERNAME and not um.USER_ENABLE_USERNAME: return check_valid_register_form(um, client, client.db) check_valid_resend_confirm_email_form(um, client) @@ -133,23 +133,23 @@ def check_valid_register_form(um, client, db): # Build variable argument list depending on config settings kwargs = {} - if um.enable_username: + if um.USER_ENABLE_USERNAME: kwargs['username'] = VALID_USERNAME - if um.enable_email: + if um.USER_ENABLE_EMAIL: kwargs['email'] = VALID_EMAIL kwargs['password'] = VALID_PASSWORD - if um.enable_register: + if um.USER_ENABLE_REGISTER: print("test_valid_register_form") # Create User by submitting a form - if um.enable_retype_password: + if um.USER_ENABLE_RETYPE_PASSWORD: kwargs['retype_password'] = VALID_PASSWORD # Submit form and verify that response has no errors client.post_valid_form(url_for('user.register'), **kwargs) - if um.enable_username: + if um.USER_ENABLE_USERNAME: valid_user = User.query.filter(User.username==VALID_USERNAME).first() else: valid_user = User.query.filter(User.email==VALID_EMAIL).first() @@ -169,9 +169,9 @@ def check_valid_register_form(um, client, db): def check_valid_resend_confirm_email_form(um, client): # Skip test for certain config combinations - if not um.enable_register: return - if not um.enable_email: return - if not um.enable_confirm_email: return + if not um.USER_ENABLE_REGISTER: return + if not um.USER_ENABLE_EMAIL: return + if not um.USER_ENABLE_CONFIRM_EMAIL: return print("test_valid_resend_confirm_email_form") @@ -180,9 +180,9 @@ def check_valid_resend_confirm_email_form(um, client): def check_valid_confirm_email_page(um, client): # Skip test for certain config combinations - if not um.enable_register: return - if not um.enable_email: return - if not um.enable_confirm_email: return + if not um.USER_ENABLE_REGISTER: return + if not um.USER_ENABLE_EMAIL: return + if not um.USER_ENABLE_CONFIRM_EMAIL: return print("test_valid_confirm_email_page") global valid_user @@ -202,9 +202,9 @@ def check_valid_login_form(um, client): # Build variable argument list depending on config settings kwargs = {} - if um.enable_username: + if um.USER_ENABLE_USERNAME: kwargs['username'] = VALID_USERNAME - if um.enable_email: + if um.USER_ENABLE_EMAIL: kwargs['email'] = VALID_EMAIL kwargs['password'] = VALID_PASSWORD @@ -216,7 +216,7 @@ def check_valid_login_form(um, client): def check_valid_change_password_form(um, client): # Skip test for certain config combinations - if not um.enable_change_password: return + if not um.USER_ENABLE_CHANGE_PASSWORD: return print("test_valid_change_password_form") global valid_user @@ -229,7 +229,7 @@ def check_valid_change_password_form(um, client): kwargs = {} kwargs['old_password'] = VALID_PASSWORD kwargs['new_password'] = new_password - if um.enable_retype_password: + if um.USER_ENABLE_RETYPE_PASSWORD: kwargs['retype_password'] = new_password # Submit form and verify that response has no errors @@ -244,7 +244,7 @@ def check_valid_change_password_form(um, client): def check_valid_change_username_form(um, client): # Skip test for certain config combinations - if not um.enable_change_username: return + if not um.USER_ENABLE_CHANGE_USERNAME: return print("test_valid_change_username_form") global valid_user @@ -268,8 +268,8 @@ def check_valid_logout_link(um, client): def check_valid_forgot_password_form(um, client): # Skip test for certain config combinations - if not um.enable_email: return - if not um.enable_forgot_password: return + if not um.USER_ENABLE_EMAIL: return + if not um.USER_ENABLE_FORGOT_PASSWORD: return print("test_valid_forgot_password_form") @@ -278,8 +278,8 @@ def check_valid_forgot_password_form(um, client): def check_valid_reset_password_page(um, client): # Skip test for certain config combinations - if not um.enable_email: return - if not um.enable_forgot_password: return + if not um.USER_ENABLE_EMAIL: return + if not um.USER_ENABLE_FORGOT_PASSWORD: return print("test_valid_reset_password_page") global valid_user @@ -296,7 +296,7 @@ def check_valid_reset_password_page(um, client): # Build variable argument list depending on config settings kwargs = {} kwargs['new_password'] = new_password - if um.enable_retype_password: + if um.USER_ENABLE_RETYPE_PASSWORD: kwargs['retype_password'] = new_password # Submit form and verify that response has no errors @@ -312,7 +312,7 @@ def check_valid_reset_password_page(um, client): def check_valid_invite_email(um, client): """ If a valid email is submitted using the invite form, then it should generate the proper email and response """ - if not um.enable_invitation: return + if not um.USER_ENABLE_INVITATION: return # Submit form and verify that response has no errors global valid_user_invite UserInvite = um.UserInvitationClass diff --git a/flask_user/user_manager.py b/flask_user/user_manager.py index 553595ea..92f54475 100644 --- a/flask_user/user_manager.py +++ b/flask_user/user_manager.py @@ -37,12 +37,177 @@ class ConfigurationError(Exception): pass -# The UserManager is implemented across several source code files. + + + # The UserManager is implemented across several source code files. # Mixins are used to aggregate all member functions into the one UserManager class. class UserManager(): """ Customizable User Authentication and Management. """ + # ***** default config settings ***** + + Section_one = "Default feature settings." #: + + #: | Allow users to login and register with an email address + USER_ENABLE_EMAIL = True + + #: | Require users to confirm their email. + #: | Depends on USER_ENABLE_EMAIL=True. + USER_ENABLE_CONFIRM_EMAIL = True + + #: | Allow users to associate multiple email addresses with one user account. + #: | Depends on USER_ENABLE_EMAIL=True + USER_ENABLE_MULTIPLE_EMAILS = False + + #: | Allow users to login without a confirmed email address. + #: | Depends on USER_ENABLE_EMAIL=True. + #: | Make sure to protect vulnerable views using @confirm_email_required. + USER_ENABLE_LOGIN_WITHOUT_CONFIRM_EMAIL = False + + + #: | Allow users to login and register with a username + USER_ENABLE_USERNAME = True + + #: | Allow users to change their username or not. + #: | Depends on USER_ENABLE_USERNAME=True. + USER_ENABLE_CHANGE_USERNAME = True + + + #: | Allow users to change their password. + USER_ENABLE_CHANGE_PASSWORD = True + + #: | Allow users to reset their passwords. + #: | Depends on USER_ENABLE_EMAIL=True. + USER_ENABLE_FORGOT_PASSWORD = True + + #: | Require users to retype their password. + #: | Affects registration, change password and reset password forms. + USER_ENABLE_RETYPE_PASSWORD = True + + + #: | Allow unknown users to register. + USER_ENABLE_REGISTER = True + + #: | Remember user sessions across browser restarts. + USER_ENABLE_REMEMBER_ME = True, + + Section_two = "Default settings." #: + + #: The application name displayed in email templates and page template footers. + USER_APP_NAME = 'USER_APP_NAME' + + + #: Automatic sign-in if the user session has not expired. + USER_AUTO_LOGIN = True + + #: Automatic sign-in after a user confirms their email address. + USER_AUTO_LOGIN_AFTER_CONFIRM = True + + #: Automatic sign-in after a user registers. + USER_AUTO_LOGIN_AFTER_REGISTER = True + + #: Automatic sign-in after a user resets their password. + USER_AUTO_LOGIN_AFTER_RESET_PASSWORD = True + + #: Automatic sign-in at the login form (if the user session has not expired). + USER_AUTO_LOGIN_AT_LOGIN = True + + #: | Send notification email after a password change. + #: | Requires USER_ENABLE_EMAIL=True. + USER_SEND_PASSWORD_CHANGED_EMAIL = True + + #: | Send notification email after a registration. + #: | Requires USER_ENABLE_EMAIL=True. + USER_SEND_REGISTERED_EMAIL = True + + #: | Send notification email after a username change. + #: | Requires USER_ENABLE_EMAIL=True. + USER_SEND_USERNAME_CHANGED_EMAIL = True + + #: Password hash scheme. + #: Accepts valid pass hash schemes such as 'bcrypt', 'pbkdf2_sha512', 'sha512_crypt' or 'argon2'. + USER_PASSWORD_HASH = 'bcrypt' + + #: | Only invited users may register. + #: | Depends on USER_ENABLE_EMAIL=True. + USER_REQUIRE_INVITATION = False + + #: | Show 'Email does not exist' message instead of 'Incorrect Email or password'. + #: | Depends on USER_ENABLE_EMAIL=True. + USER_SHOW_EMAIL_DOES_NOT_EXIST = False + + #: | Show 'Username does not exist' message instead of 'Incorrect Username or password'. + #: | Depends on USER_ENABLE_USERNAME=True. + USER_SHOW_USERNAME_DOES_NOT_EXIST = False + + #: | Email confirmation token expiration in seconds. + #: | Default is 2 days (2*24*3600 seconds). + USER_CONFIRM_EMAIL_EXPIRATION = 2*24*3600 + + #: | Invitation token expiration in seconds. + #: | Default is 90 days (90*24*3600 seconds). + USER_INVITE_EXPIRATION = 90*24*3600 + + #: | Reset password token expiration in seconds. + #: | Default is 2 days (2*24*3600 seconds). + USER_RESET_PASSWORD_EXPIRATION = 2*24*3600 + + Section_three = "Default URLs." #: + + USER_CHANGE_PASSWORD_URL = '/user/change-password' #: + USER_CHANGE_USERNAME_URL = '/user/change-username' #: + USER_CONFIRM_EMAIL_URL = '/user/confirm-email/' #: + USER_EMAIL_ACTION_URL = '/user/email//' #: + USER_FORGOT_PASSWORD_URL = '/user/forgot-password' #: + USER_INVITE_URL = '/user/invite' #: + USER_LOGIN_URL = '/user/sign-in' #: + USER_LOGOUT_URL = '/user/sign-out' #: + USER_MANAGE_EMAILS_URL = '/user/manage-emails' #: + USER_REGISTER_URL = '/user/register' #: + USER_RESEND_CONFIRM_EMAIL_URL = '/user/resend-confirm-email' #: + USER_RESET_PASSWORD_URL = '/user/reset-password/' #: + USER_USER_PROFILE_URL = '/user/profile' #: + + Section_four = "Default template files." #: + + USER_CHANGE_PASSWORD_TEMPLATE = 'flask_user/change_password.html' #: + USER_CHANGE_USERNAME_TEMPLATE = 'flask_user/change_username.html' #: + USER_FORGOT_PASSWORD_TEMPLATE = 'flask_user/forgot_password.html' #: + USER_INVITE_TEMPLATE = 'flask_user/invite.html' #: + USER_INVITE_ACCEPT_TEMPLATE = 'flask_user/register.html' #: + USER_LOGIN_TEMPLATE = 'flask_user/login.html' #: + USER_MANAGE_EMAILS_TEMPLATE = 'flask_user/manage_emails.html' #: + USER_REGISTER_TEMPLATE = 'flask_user/register.html' #: + USER_RESEND_CONFIRM_EMAIL_TEMPLATE = 'flask_user/resend_confirm_email.html' #: + USER_RESET_PASSWORD_TEMPLATE = 'flask_user/reset_password.html' #: + USER_USER_PROFILE_TEMPLATE = 'flask_user/user_profile.html' #: + + Section_five = "Default email template files." #: + + USER_CONFIRM_EMAIL_EMAIL_TEMPLATE = 'flask_user/emails/confirm_email' #: + USER_FORGOT_PASSWORD_EMAIL_TEMPLATE = 'flask_user/emails/forgot_password' #: + USER_INVITE_EMAIL_TEMPLATE = 'flask_user/emails/invite' #: + USER_PASSWORD_CHANGED_EMAIL_TEMPLATE = 'flask_user/emails/password_changed' #: + USER_REGISTERED_EMAIL_TEMPLATE = 'flask_user/emails/registered' #: + USER_USERNAME_CHANGED_EMAIL_TEMPLATE = 'flask_user/emails/username_changed' #: + + Section_six = "Default endpoints." #: + + USER_AFTER_CHANGE_PASSWORD_ENDPOINT = '' #: + USER_AFTER_CHANGE_USERNAME_ENDPOINT = '' #: + USER_AFTER_CONFIRM_ENDPOINT = '' #: + USER_AFTER_FORGOT_PASSWORD_ENDPOINT = '' #: + USER_AFTER_LOGIN_ENDPOINT = '' #: + USER_AFTER_REGISTER_ENDPOINT = '' #: + USER_AFTER_RESEND_CONFIRM_EMAIL_ENDPOINT = '' #: + USER_AFTER_RESET_PASSWORD_ENDPOINT = '' #: + USER_AFTER_INVITE_ENDPOINT = '' #: + USER_UNCONFIRMED_EMAIL_ENDPOINT = '' #: + USER_UNAUTHORIZED_ENDPOINT = '' #: + USER_AFTER_LOGOUT_ENDPOINT = 'user.login' #: + USER_UNAUTHENTICATED_ENDPOINT = 'user.login' #: + # ***** Initialization methods ***** def __init__(self, app=None, db=None, UserClass=None, **kwargs): @@ -112,6 +277,109 @@ def init_app(self, app, db, UserClass, "instead of a subclass of class 'flask.Flask'." % app.__class__.__name__) + # Bind Flask-User to app + app.user_manager = self + + # Save DB and Class params + self.db = db + self.UserClass = UserClass + self.UserEmailClass = UserEmailClass + self.UserInvitationClass = UserInvitationClass + + # Define default settings + default_enable_mail = True + default_user_enable_username = True + default_auto_login = True + default_home_endpoint = '' + default_login_endpoint = 'user.login' + default_settings = dict( + #: What happens to this docstring? + USER_ENABLE_CHANGE_PASSWORD = True, + USER_ENABLE_EMAIL = default_enable_mail, + USER_ENABLE_CONFIRM_EMAIL = default_enable_mail, + USER_ENABLE_FORGOT_PASSWORD = default_enable_mail, + USER_ENABLE_INVITATION = False, + USER_ENABLE_LOGIN_WITHOUT_CONFIRM_EMAIL = False, + USER_ENABLE_MULTIPLE_EMAILS = False, + USER_ENABLE_REGISTER = True, + USER_ENABLE_REMEMBER_ME=True, + USER_ENABLE_RETYPE_PASSWORD = True, + USER_ENABLE_USERNAME = default_user_enable_username, + USER_ENABLE_CHANGE_USERNAME = default_user_enable_username, + + USER_APP_NAME = 'USER_APP_NAME', + USER_AUTO_LOGIN = default_auto_login, + USER_AUTO_LOGIN_AFTER_CONFIRM = default_auto_login, + USER_AUTO_LOGIN_AFTER_REGISTER = default_auto_login, + USER_AUTO_LOGIN_AFTER_RESET_PASSWORD = default_auto_login, + USER_AUTO_LOGIN_AT_LOGIN = default_auto_login, + USER_CONFIRM_EMAIL_EXPIRATION = 2 * 24 * 3600, # 2 days + USER_INVITE_EXPIRATION = 90 * 24 * 3600, # 90 days + USER_PASSWORD_HASH = 'bcrypt', + USER_RESET_PASSWORD_EXPIRATION = 2 * 24 * 3600, # 2 days + USER_REQUIRE_INVITATION = False, + USER_SHOW_EMAIL_DOES_NOT_EXIST = True, + USER_SHOW_USERNAME_DOES_NOT_EXIST = True, + USER_SEND_PASSWORD_CHANGED_EMAIL = True, + USER_SEND_REGISTERED_EMAIL = True, + USER_SEND_USERNAME_CHANGED_EMAIL = True, + + USER_CHANGE_PASSWORD_URL = '/user/change-password', + USER_CHANGE_USERNAME_URL = '/user/change-username', + USER_CONFIRM_EMAIL_URL = '/user/confirm-email/', + USER_EMAIL_ACTION_URL = '/user/email//', + USER_FORGOT_PASSWORD_URL = '/user/forgot-password', + USER_INVITE_URL = '/user/invite', + USER_LOGIN_URL = '/user/sign-in', + USER_LOGOUT_URL = '/user/sign-out', + USER_MANAGE_EMAILS_URL = '/user/manage-emails', + USER_REGISTER_URL = '/user/register', + USER_RESEND_CONFIRM_EMAIL_URL = '/user/resend-confirm-email', + USER_RESET_PASSWORD_URL = '/user/reset-password/', + USER_USER_PROFILE_URL = '/user/profile', + + USER_AFTER_CHANGE_PASSWORD_ENDPOINT = default_home_endpoint, + USER_AFTER_CHANGE_USERNAME_ENDPOINT = default_home_endpoint, + USER_AFTER_CONFIRM_ENDPOINT = default_home_endpoint, + USER_AFTER_FORGOT_PASSWORD_ENDPOINT = default_home_endpoint, + USER_AFTER_LOGIN_ENDPOINT = default_home_endpoint, + USER_AFTER_LOGOUT_ENDPOINT = default_login_endpoint, + USER_AFTER_REGISTER_ENDPOINT = default_home_endpoint, + USER_AFTER_RESEND_CONFIRM_EMAIL_ENDPOINT = default_home_endpoint, + USER_AFTER_RESET_PASSWORD_ENDPOINT = default_home_endpoint, + USER_AFTER_INVITE_ENDPOINT = default_home_endpoint, + USER_UNCONFIRMED_EMAIL_ENDPOINT = default_home_endpoint, + USER_UNAUTHENTICATED_ENDPOINT = default_login_endpoint, + USER_UNAUTHORIZED_ENDPOINT = default_home_endpoint, + + USER_CHANGE_PASSWORD_TEMPLATE = 'flask_user/change_password.html', + USER_CHANGE_USERNAME_TEMPLATE = 'flask_user/change_username.html', + USER_FORGOT_PASSWORD_TEMPLATE = 'flask_user/forgot_password.html', + USER_INVITE_TEMPLATE = 'flask_user/invite.html', + USER_INVITE_ACCEPT_TEMPLATE = 'flask_user/register.html', + USER_LOGIN_TEMPLATE = 'flask_user/login.html', + USER_MANAGE_EMAILS_TEMPLATE = 'flask_user/manage_emails.html', + USER_REGISTER_TEMPLATE = 'flask_user/register.html', + USER_RESEND_CONFIRM_EMAIL_TEMPLATE = 'flask_user/resend_confirm_email.html', + USER_RESET_PASSWORD_TEMPLATE = 'flask_user/reset_password.html', + USER_USER_PROFILE_TEMPLATE = 'flask_user/user_profile.html', + + USER_CONFIRM_EMAIL_EMAIL_TEMPLATE = 'flask_user/emails/confirm_email', + USER_FORGOT_PASSWORD_EMAIL_TEMPLATE = 'flask_user/emails/forgot_password', + USER_INVITE_EMAIL_TEMPLATE = 'flask_user/emails/invite', + USER_PASSWORD_CHANGED_EMAIL_TEMPLATE = 'flask_user/emails/password_changed', + USER_REGISTERED_EMAIL_TEMPLATE = 'flask_user/emails/registered', + USER_USERNAME_CHANGED_EMAIL_TEMPLATE = 'flask_user/emails/username_changed', + + # Deprecated: + # USER_PASSWORD_HASH_MODE='passlib', + # USER_PASSWORD_SALT=app.config.get('SECRET_KEY', None), + ) + + # Set UserManager settings from app.config and default_settings + for name, default_value in default_settings.items(): + setattr(self, name, app.config.get(name, default_value)) + # Configure a DbAdapter based on the class of the 'db' parameter self.db_adapter = None # Check if db is a SQLAlchemy instance @@ -137,19 +405,6 @@ def init_app(self, app, db, UserClass, from .email_mailers.email_mailer_for_flask_mail import EmailMailerForFlaskMail self.email_mailer = EmailMailerForFlaskMail(app) - # Start moving the Model attributes from db_adapter to user_manager - self.db = db - self.UserClass = UserClass - self.UserEmailClass = UserEmailClass - self.UserInvitationClass = UserInvitationClass - - # Bind Flask-USER to app - app.user_manager = self - # Flask seems to also support the current_app.extensions[] list - if not hasattr(app, 'extensions'): - app.extensions = {} - app.extensions['user'] = self - # Initialize Translations -- Only if Flask-Babel has been installed if hasattr(app.jinja_env, 'install_gettext_callables'): app.jinja_env.install_gettext_callables( @@ -160,7 +415,7 @@ def init_app(self, app, db, UserClass, app.jinja_env.add_extension('jinja2.ext.i18n') app.jinja_env.install_null_translations() - # Allow CustomUserManager to customize certain settings + # Allow CustomUserManager to customize settings and methods self.customize(app) # Initialize default settings, when they haven't been set @@ -206,7 +461,7 @@ def init_app(self, app, db, UserClass, self._create_default_attr('make_safe_url_function', make_safe_url_function) # Setup PasswordManager - self.password_manager = PasswordManager(self.password_crypt_context, self.password_hash_scheme, self.password_hash_mode, self.password_salt) + self.password_manager = PasswordManager(self.password_crypt_context, self.USER_PASSWORD_HASH, self.USER_PASSWORD_HASH_MODE, self.USER_PASSWORD_SALT) # Setup EmailManager self.email_manager = EmailManager(self) @@ -248,9 +503,15 @@ def customize(self, app): :: # Customize Flask-User - class MyCustomFlaskUser(FlaskUser): + class CustomUserManager(UserManager): + def customize(): - # Add customization here + # Add custom settings here + # Note: This can also be changed in the applicationc config file. + self.USER_ENABLE_EMAIL = True + self.USER_ENABLE_USERNAME = False + + # Add custom behavior here self.token_manager = MyJwtTokenManager() self.email_manager = MySendGridEmailManager() @@ -266,92 +527,93 @@ def _create_default_settings(self, app): # sets self.attribute = self.ATTRIBUTE or app.config.USER_ATTRIBUTE or default_value # Create default features - self._create_default_setting('enable_change_password', app, True) - self._create_default_setting('enable_email', app, True) - self._create_default_setting('enable_confirm_email', app, self.enable_email) - self._create_default_setting('enable_forgot_password', app, self.enable_email) - self._create_default_setting('enable_login_without_confirm_email', app, False) - self._create_default_setting('enable_multiple_emails', app, False) - self._create_default_setting('enable_register', app, True) - self._create_default_setting('enable_remember_me', app, True) - self._create_default_setting('enable_retype_password', app, True) - self._create_default_setting('enable_username', app, True) - self._create_default_setting('enable_change_username', app, self.enable_username) + self._create_default_setting('USER_ENABLE_CHANGE_PASSWORD', app, True) + self._create_default_setting('USER_ENABLE_EMAIL', app, True) + self._create_default_setting('USER_ENABLE_CONFIRM_EMAIL', app, self.USER_ENABLE_EMAIL) + self._create_default_setting('USER_ENABLE_FORGOT_PASSWORD', app, self.USER_ENABLE_EMAIL) + self._create_default_setting('USER_ENABLE_LOGIN_WITHOUT_CONFIRM_EMAIL', app, False) + self._create_default_setting('USER_ENABLE_MULTIPLE_EMAILS', app, False) + self._create_default_setting('USER_ENABLE_REGISTER', app, True) + self._create_default_setting('USER_ENABLE_REMEMBER_ME', app, True) + self._create_default_setting('USER_ENABLE_RETYPE_PASSWORD', app, True) + self._create_default_setting('USER_ENABLE_USERNAME', app, True) + self._create_default_setting('USER_ENABLE_CHANGE_USERNAME', app, self.USER_ENABLE_USERNAME) # Create default settings - self._create_default_setting('app_name', app, 'MyApp') + self._create_default_setting('APP_NAME', app, 'MyApp') self._create_default_setting('auto_login', app, True) - self._create_default_setting('auto_login_after_confirm', app, self.auto_login) - self._create_default_setting('auto_login_after_register', app, self.auto_login) - self._create_default_setting('auto_login_after_reset_password', app, self.auto_login) - self._create_default_setting('auto_login_at_login', app, self.auto_login) - self._create_default_setting('confirm_email_expiration', app, 2 * 24 * 3600) # 2 days - self._create_default_setting('invite_expiration', app, 90 * 24 * 3600) # 90 days - self._create_default_setting('password_hash_mode', app, 'passlib') - self._create_default_setting('password_hash_scheme', app, 'bcrypt') - self._create_default_setting('password_salt', app, app.config['SECRET_KEY']) - self._create_default_setting('reset_password_expiration', app, 2 * 24 * 3600) # 2 days - self._create_default_setting('enable_invitation', app, False) - self._create_default_setting('require_invitation', app, False) - self._create_default_setting('send_password_changed_email',app, self.enable_email) - self._create_default_setting('send_registered_email', app, self.enable_email) - self._create_default_setting('send_username_changed_email',app, self.enable_email) - self._create_default_setting('show_username_email_does_not_exist', app, self.enable_register) + self._create_default_setting('USER_AUTO_LOGIN_AFTER_CONFIRM', app, self.auto_login) + self._create_default_setting('USER_AUTO_LOGIN_AFTER_REGISTER', app, self.auto_login) + self._create_default_setting('USER_AUTO_LOGIN_AFTER_RESET_PASSWORD', app, self.auto_login) + self._create_default_setting('USER_AUTO_LOGIN_AT_LOGIN', app, self.auto_login) + self._create_default_setting('USER_CONFIRM_EMAIL_EXPIRATION', app, 2 * 24 * 3600) # 2 days + self._create_default_setting('USER_INVITE_EXPIRATION', app, 90 * 24 * 3600) # 90 days + self._create_default_setting('USER_PASSWORD_HASH_MODE', app, 'passlib') + self._create_default_setting('USER_PASSWORD_HASH', app, 'bcrypt') + self._create_default_setting('USER_PASSWORD_SALT', app, app.config['SECRET_KEY']) + self._create_default_setting('USER_PASSWORD_EXPIRATION', app, 2 * 24 * 3600) # 2 days + self._create_default_setting('USER_ENABLE_INVITATION', app, False) + self._create_default_setting('USER_REQUIRE_INVITATION', app, False) + self._create_default_setting('USER_SEND_PASSWORD_CHANGED_EMAIL',app, self.USER_ENABLE_EMAIL) + self._create_default_setting('USER_SEND_REGISTERED_EMAIL', app, self.USER_ENABLE_EMAIL) + self._create_default_setting('USER_SEND_USERNAME_CHANGED_EMAIL',app, self.USER_ENABLE_EMAIL) + self._create_default_setting('USER_SHOW_EMAIL_DOES_NOT_EXIST', app, self.USER_ENABLE_REGISTER) + self._create_default_setting('USER_SHOW_USERNAME_DOES_NOT_EXIST', app, self.USER_ENABLE_REGISTER) # Create default URLs self._create_default_setting('base_url', app, '/user') - self._create_default_setting('change_password_url', app, self.base_url+'/change-password') - self._create_default_setting('change_username_url', app, self.base_url+'/change-username') - self._create_default_setting('confirm_email_url', app, self.base_url+'/confirm-email/') - self._create_default_setting('email_action_url', app, self.base_url+'/email//') - self._create_default_setting('forgot_password_url', app, self.base_url+'/forgot-password') - self._create_default_setting('login_url', app, self.base_url+'/sign-in') - self._create_default_setting('logout_url', app, self.base_url+'/sign-out') - self._create_default_setting('manage_emails_url', app, self.base_url+'/manage-emails') - self._create_default_setting('register_url', app, self.base_url+'/register') - self._create_default_setting('resend_confirm_email_url', app, self.base_url+'/resend-confirm-email') - self._create_default_setting('reset_password_url', app, self.base_url+'/reset-password/') - self._create_default_setting('user_profile_url', app, self.base_url+'/profile') - self._create_default_setting('invite_url', app, self.base_url+'/invite') + self._create_default_setting('USER_CHANGE_PASSWORD_URL', app, self.base_url+'/change-password') + self._create_default_setting('USER_CHANGE_USERNAME_URL', app, self.base_url+'/change-username') + self._create_default_setting('USER_CHANGE_CONFIRM_EMAIL_URL', app, self.base_url+'/confirm-email/') + self._create_default_setting('USER_EMAIL_ACTION_URL', app, self.base_url+'/email//') + self._create_default_setting('USER_FORGOT_PASSWORD_URL', app, self.base_url+'/forgot-password') + self._create_default_setting('USER_LOGIN_URL', app, self.base_url+'/sign-in') + self._create_default_setting('USER_LOGOUT_URL', app, self.base_url+'/sign-out') + self._create_default_setting('USER_MANAGE_EMAILS_URL', app, self.base_url+'/manage-emails') + self._create_default_setting('USER_REGISTER_URL', app, self.base_url+'/register') + self._create_default_setting('USER_RESEND_USER_CHANGE_CONFIRM_EMAIL_URL', app, self.base_url+'/resend-confirm-email') + self._create_default_setting('USER_RESET_PASSWORD_URL', app, self.base_url+'/reset-password/') + self._create_default_setting('USER_USER_PROFILE_URL', app, self.base_url+'/profile') + self._create_default_setting('USER_INVITE_URL', app, self.base_url+'/invite') # Create default ENDPOINTs self._create_default_setting('home_endpoint', app, '') self._create_default_setting('login_endpoint', app, 'user.login') - self._create_default_setting('after_change_password_endpoint', app, self.home_endpoint) - self._create_default_setting('after_change_username_endpoint', app, self.home_endpoint) - self._create_default_setting('after_confirm_endpoint', app, self.home_endpoint) - self._create_default_setting('after_forgot_password_endpoint', app, self.home_endpoint) - self._create_default_setting('after_login_endpoint', app, self.home_endpoint) - self._create_default_setting('after_logout_endpoint', app, self.login_endpoint) - self._create_default_setting('after_register_endpoint', app, self.home_endpoint) - self._create_default_setting('after_resend_confirm_email_endpoint', app, self.home_endpoint) - self._create_default_setting('after_reset_password_endpoint', app, self.home_endpoint) - self._create_default_setting('after_invite_endpoint', app, self.home_endpoint) - self._create_default_setting('unconfirmed_email_endpoint', app, self.home_endpoint) - self._create_default_setting('unauthenticated_endpoint', app, self.login_endpoint) - self._create_default_setting('unauthorized_endpoint', app, self.home_endpoint) + self._create_default_setting('USER_AFTER_CHANGE_PASSWORD_ENDPOINT', app, self.home_endpoint) + self._create_default_setting('USER_AFTER_CHANGE_USERNAME_ENDPOINT', app, self.home_endpoint) + self._create_default_setting('USER_AFTER_CONFIRM_ENDPOINT', app, self.home_endpoint) + self._create_default_setting('USER_AFTER_FORGOT_PASSWORD_ENDPOINT', app, self.home_endpoint) + self._create_default_setting('USER_AFTER_LOGIN_ENDPOINT', app, self.home_endpoint) + self._create_default_setting('USER_AFTER_LOGOUT_ENDPOINT', app, self.login_endpoint) + self._create_default_setting('USER_AFTER_REGISTER_ENDPOINT', app, self.home_endpoint) + self._create_default_setting('USER_AFTER_RESEND_CONFIRM_EMAIL_ENDPOINT', app, self.home_endpoint) + self._create_default_setting('USER_AFTER_RESET_PASSWORD_ENDPOINT', app, self.home_endpoint) + self._create_default_setting('USER_AFTER_INVITE_ENDPOINT', app, self.home_endpoint) + self._create_default_setting('USER_AFTER_UNCONFIRMED_EMAIL_ENDPOINT', app, self.home_endpoint) + self._create_default_setting('USER_UNAUTHENTICATED_ENDPOINT', app, self.login_endpoint) + self._create_default_setting('USER_UNAUTHORIZED_ENDPOINT', app, self.home_endpoint) # Create default template files template_base = 'flask_user' - self._create_default_setting('change_password_template', app, template_base+'/change_password.html') - self._create_default_setting('change_username_template', app, template_base+'/change_username.html') - self._create_default_setting('forgot_password_template', app, template_base+'/forgot_password.html') - self._create_default_setting('login_template', app, template_base+'/login.html') - self._create_default_setting('manage_emails_template', app, template_base+'/manage_emails.html') - self._create_default_setting('register_template', app, template_base+'/register.html') - self._create_default_setting('resend_confirm_email_template', app, template_base+'/resend_confirm_email.html') - self._create_default_setting('reset_password_template', app, template_base+'/reset_password.html') - self._create_default_setting('user_profile_template', app, template_base+'/user_profile.html') - self._create_default_setting('invite_template', app, template_base+'/invite.html') - self._create_default_setting('invite_accept_template', app, template_base+'/register.html') + self._create_default_setting('USER_CHANGE_PASSWORD_TEMPLATE', app, template_base+'/change_password.html') + self._create_default_setting('USER_CHANGE_USERNAME_TEMPLATE', app, template_base+'/change_username.html') + self._create_default_setting('USER_FORGOT_PASSWORD_TEMPLATE', app, template_base+'/forgot_password.html') + self._create_default_setting('USER_LOGIN_TEMPLATE', app, template_base+'/login.html') + self._create_default_setting('USER_MANAGE_EMAILS_TEMPLATE', app, template_base+'/manage_emails.html') + self._create_default_setting('USER_REGISTER_TEMPLATE', app, template_base+'/register.html') + self._create_default_setting('USER_RESENT_CONFIRM_EMAIL_TEMPLATE', app, template_base+'/resend_confirm_email.html') + self._create_default_setting('USER_RESET_PASSWORD_TEMPLATE', app, template_base+'/reset_password.html') + self._create_default_setting('USER_PROFILE_TEMPLATE', app, template_base+'/user_profile.html') + self._create_default_setting('USER_INVITE_TEMPLATE', app, template_base+'/invite.html') + self._create_default_setting('USER_INVITE_ACCEPT_TEMPLATE', app, template_base+'/register.html') # Create default email template files - self._create_default_setting('confirm_email_email_template', app, template_base+'/emails/confirm_email') - self._create_default_setting('forgot_password_email_template', app, template_base+'/emails/forgot_password') - self._create_default_setting('password_changed_email_template',app, template_base+'/emails/password_changed') - self._create_default_setting('registered_email_template', app, template_base+'/emails/registered') - self._create_default_setting('username_changed_email_template',app, template_base+'/emails/username_changed') - self._create_default_setting('invite_email_template', app, template_base+'/emails/invite') + self._create_default_setting('USER_CONFIRM_EMAIL_EMAIL_TEMPLATE', app, template_base+'/emails/confirm_email') + self._create_default_setting('USER_FORGOT_PASSWORD_EMAIL_TEMPLATE', app, template_base+'/emails/forgot_password') + self._create_default_setting('USER_PASSWORD_CHANGED_EMAIL_TEMPLATE',app, template_base+'/emails/password_changed') + self._create_default_setting('USER_REGISTERED_EMAIL_TEMPLATE', app, template_base+'/emails/registered') + self._create_default_setting('USER_USERNAME_CHANGED_EMAIL_TEMPLATE',app, template_base+'/emails/username_changed') + self._create_default_setting('USER_INVITE_EMAIL_TEMPLATE', app, template_base+'/emails/invite') # ***** Internal methods ***** @@ -384,50 +646,50 @@ def _check_settings(self): if self.db_adapter is None: raise ConfigurationError('You must specify a DbAdapter interface or install Flask-SQLAlchemy or FlaskMongAlchemy.') - # USER_ENABLE_REGISTER=True must have USER_ENABLE_USERNAME=True or USER_ENABLE_EMAIL=True or both. - if self.enable_register and not (self.enable_username or self.enable_email): - raise ConfigurationError('USER_ENABLE_REGISTER=True must have USER_ENABLE_USERNAME=True or USER_ENABLE_EMAIL=True or both.') + # USER_ENABLE_REGISTER=True must have USER_ENABLE_USERNAME=True or USER_ENABLE_EMAIL=True. + if self.USER_ENABLE_REGISTER and not (self.USER_ENABLE_USERNAME or self.USER_ENABLE_EMAIL): + raise ConfigurationError('USER_ENABLE_REGISTER=True must have USER_ENABLE_USERNAME=True or USER_ENABLE_EMAIL=True.') # USER_ENABLE_CONFIRM_EMAIL=True must have USER_ENABLE_EMAIL=True - if self.enable_confirm_email and not self.enable_email: + if self.USER_ENABLE_CONFIRM_EMAIL and not self.USER_ENABLE_EMAIL: raise ConfigurationError('USER_ENABLE_CONFIRM_EMAIL=True must have USER_ENABLE_EMAIL=True.') # USER_ENABLE_MULTIPLE_EMAILS=True must have USER_ENABLE_EMAIL=True - if self.enable_multiple_emails and not self.enable_email: + if self.USER_ENABLE_MULTIPLE_EMAILS and not self.USER_ENABLE_EMAIL: raise ConfigurationError('USER_ENABLE_MULTIPLE_EMAILS=True must have USER_ENABLE_EMAIL=True.') # USER_SEND_REGISTERED_EMAIL=True must have USER_ENABLE_EMAIL=True - if self.send_registered_email and not self.enable_email: + if self.USER_SEND_REGISTERED_EMAIL and not self.USER_ENABLE_EMAIL: raise ConfigurationError('USER_SEND_REGISTERED_EMAIL=True must have USER_ENABLE_EMAIL=True.') # USER_ENABLE_CHANGE_USERNAME=True must have USER_ENABLE_USERNAME=True. - if self.enable_change_username and not self.enable_username: + if self.USER_ENABLE_CHANGE_USERNAME and not self.USER_ENABLE_USERNAME: raise ConfigurationError('USER_ENABLE_CHANGE_USERNAME=True must have USER_ENABLE_USERNAME=True.') - if self.require_invitation and not self.enable_invitation: + if self.USER_REQUIRE_INVITATION and not self.USER_ENABLE_INVITATION: raise ConfigurationError('USER_REQUIRE_INVITATION=True must have USER_ENABLE_INVITATION=True.') - if self.enable_invitation and not self.UserInvitationClass: + if self.USER_ENABLE_INVITATION and not self.UserInvitationClass: raise ConfigurationError( 'USER_ENABLE_INVITATION=True must pass UserInvitationClass to SQLAlchemyAdapter().') def _add_url_routes(self, app): """ Add URL Routes""" - app.add_url_rule(self.login_url, 'user.login', self.login_view_function, methods=['GET', 'POST']) - app.add_url_rule(self.logout_url, 'user.logout', self.logout_view_function, methods=['GET', 'POST']) - if self.enable_confirm_email: - app.add_url_rule(self.confirm_email_url, 'user.confirm_email', self.confirm_email_view_function) - app.add_url_rule(self.resend_confirm_email_url, 'user.resend_confirm_email', self.resend_confirm_email_view_function, methods=['GET', 'POST']) - if self.enable_change_password: - app.add_url_rule(self.change_password_url, 'user.change_password', self.change_password_view_function, methods=['GET', 'POST']) - if self.enable_change_username: - app.add_url_rule(self.change_username_url, 'user.change_username', self.change_username_view_function, methods=['GET', 'POST']) - if self.enable_forgot_password: - app.add_url_rule(self.forgot_password_url, 'user.forgot_password', self.forgot_password_view_function, methods=['GET', 'POST']) - app.add_url_rule(self.reset_password_url, 'user.reset_password', self.reset_password_view_function, methods=['GET', 'POST']) - if self.enable_register: - app.add_url_rule(self.register_url, 'user.register', self.register_view_function, methods=['GET', 'POST']) + app.add_url_rule(self.USER_LOGIN_URL, 'user.login', self.login_view_function, methods=['GET', 'POST']) + app.add_url_rule(self.USER_LOGOUT_URL, 'user.logout', self.logout_view_function, methods=['GET', 'POST']) + if self.USER_ENABLE_CONFIRM_EMAIL: + app.add_url_rule(self.USER_CHANGE_CONFIRM_EMAIL_URL, 'user.confirm_email', self.confirm_email_view_function) + app.add_url_rule(self.USER_RESEND_USER_CHANGE_CONFIRM_EMAIL_URL, 'user.resend_confirm_email', self.resend_confirm_email_view_function, methods=['GET', 'POST']) + if self.USER_ENABLE_CHANGE_PASSWORD: + app.add_url_rule(self.USER_CHANGE_PASSWORD_URL, 'user.change_password', self.change_password_view_function, methods=['GET', 'POST']) + if self.USER_ENABLE_CHANGE_USERNAME: + app.add_url_rule(self.USER_CHANGE_USERNAME_URL, 'user.change_username', self.change_username_view_function, methods=['GET', 'POST']) + if self.USER_ENABLE_FORGOT_PASSWORD: + app.add_url_rule(self.USER_FORGOT_PASSWORD_URL, 'user.forgot_password', self.forgot_password_view_function, methods=['GET', 'POST']) + app.add_url_rule(self.USER_RESET_PASSWORD_URL, 'user.reset_password', self.reset_password_view_function, methods=['GET', 'POST']) + if self.USER_ENABLE_REGISTER: + app.add_url_rule(self.USER_REGISTER_URL, 'user.register', self.register_view_function, methods=['GET', 'POST']) if self.UserEmailClass: - app.add_url_rule(self.email_action_url, 'user.email_action', self.email_action_view_function) - app.add_url_rule(self.manage_emails_url, 'user.manage_emails', self.manage_emails_view_function, methods=['GET', 'POST']) - app.add_url_rule(self.user_profile_url, 'user.profile', self.user_profile_view_function, methods=['GET', 'POST']) - if self.enable_invitation: - app.add_url_rule(self.invite_url, 'user.invite', self.invite_view_function, methods=['GET', 'POST']) + app.add_url_rule(self.USER_EMAIL_ACTION_URL, 'user.email_action', self.email_action_view_function) + app.add_url_rule(self.USER_MANAGE_EMAILS_URL, 'user.manage_emails', self.manage_emails_view_function, methods=['GET', 'POST']) + app.add_url_rule(self.USER_USER_PROFILE_URL, 'user.profile', self.user_profile_view_function, methods=['GET', 'POST']) + if self.USER_ENABLE_INVITATION: + app.add_url_rule(self.USER_INVITE_URL, 'user.invite', self.invite_view_function, methods=['GET', 'POST']) def get_user_by_id(self, user_id): """Retrieve a User by ID.""" diff --git a/flask_user/utils.py b/flask_user/utils.py index e57b4e28..61f7c9b1 100644 --- a/flask_user/utils.py +++ b/flask_user/utils.py @@ -25,8 +25,8 @@ def user_is_authenticated(user): # Return False otherwise def user_has_confirmed_email(user): user_manager = current_app.user_manager - if not user_manager.enable_email: return True - if not user_manager.enable_confirm_email: return True + if not user_manager.USER_ENABLE_EMAIL: return True + if not user_manager.USER_ENABLE_CONFIRM_EMAIL: return True user_manager = current_app.user_manager db_adapter = user_manager.db_adapter diff --git a/flask_user/views.py b/flask_user/views.py index 229b85bb..460c66de 100644 --- a/flask_user/views.py +++ b/flask_user/views.py @@ -42,7 +42,7 @@ def confirm_email(token): db_adapter = user_manager.db_adapter data_items = user_manager.token_manager.verify_token( token, - user_manager.confirm_email_expiration) + user_manager.USER_CONFIRM_EMAIL_EXPIRATION) if not data_items: flash(_('Invalid confirmation token.'), 'error') @@ -79,8 +79,8 @@ def confirm_email(token): flash(_('Your email has been confirmed.'), 'success') # Auto-login after confirm or redirect to login page - safe_next = _get_safe_next_param('next', user_manager.after_confirm_endpoint) - if user_manager.auto_login_after_confirm: + safe_next = _get_safe_next_param('next', user_manager.USER_AFTER_CONFIRM_ENDPOINT) + if user_manager.USER_AUTO_LOGIN_AFTER_CONFIRM: return _do_login_user(user, safe_next) # auto-login else: return redirect(url_for('user.login')+'?next='+quote(safe_next)) # redirect to login page @@ -95,7 +95,7 @@ def change_password(): # Initialize form form = user_manager.change_password_form(request.form) - safe_next = _get_safe_next_param('next', user_manager.after_change_password_endpoint) + safe_next = _get_safe_next_param('next', user_manager.USER_AFTER_CHANGE_PASSWORD_ENDPOINT) form.next.data = safe_next # Process valid POST @@ -107,7 +107,7 @@ def change_password(): user_manager.password_manager.update_user_hashed_password(current_user, hashed_password) # Send 'password_changed' email - if user_manager.enable_email and user_manager.send_password_changed_email: + if user_manager.USER_ENABLE_EMAIL and user_manager.USER_SEND_PASSWORD_CHANGED_EMAIL: user_manager.send_password_has_changed_email(current_user) # Send password_changed signal @@ -121,7 +121,7 @@ def change_password(): return redirect(safe_next) # Process GET or invalid POST - return render(user_manager.change_password_template, form=form) + return render(user_manager.USER_CHANGE_PASSWORD_TEMPLATE, form=form) @login_required @confirm_email_required @@ -132,7 +132,7 @@ def change_username(): # Initialize form form = user_manager.change_username_form(request.form) - safe_next = _get_safe_next_param('next', user_manager.after_change_username_endpoint) + safe_next = _get_safe_next_param('next', user_manager.USER_AFTER_CHANGE_USERNAME_ENDPOINT) form.next.data = safe_next # Process valid POST @@ -144,7 +144,7 @@ def change_username(): db_adapter.commit() # Send 'username_changed' email - if user_manager.enable_email and user_manager.send_username_changed_email: + if user_manager.USER_ENABLE_EMAIL and user_manager.USER_SEND_USERNAME_CHANGED_EMAIL: user_manager.send_username_has_changed_email(current_user) # Send username_changed signal @@ -158,7 +158,7 @@ def change_username(): return redirect(safe_next) # Process GET or invalid POST - return render(user_manager.change_username_template, form=form) + return render(user_manager.USER_CHANGE_USERNAME_TEMPLATE, form=form) @login_required @confirm_email_required @@ -226,10 +226,10 @@ def forgot_password(): flash(_("A reset password email has been sent to '%(email)s'. Open that email and follow the instructions to reset your password.", email=email), 'success') # Redirect to the login page - return redirect(_endpoint_url(user_manager.after_forgot_password_endpoint)) + return redirect(_endpoint_url(user_manager.USER_AFTER_FORGOT_PASSWORD_ENDPOINT)) # Process GET or invalid POST - return render(user_manager.forgot_password_template, form=form) + return render(user_manager.USER_FORGOT_PASSWORD_TEMPLATE, form=form) def login(): @@ -237,11 +237,11 @@ def login(): user_manager = current_app.user_manager db_adapter = user_manager.db_adapter - safe_next = _get_safe_next_param('next', user_manager.after_login_endpoint) - safe_reg_next = _get_safe_next_param('reg_next', user_manager.after_register_endpoint) + safe_next = _get_safe_next_param('next', user_manager.USER_AFTER_LOGIN_ENDPOINT) + safe_reg_next = _get_safe_next_param('reg_next', user_manager.USER_AFTER_REGISTER_ENDPOINT) # Immediately redirect already logged in users - if _call_or_get(current_user.is_authenticated) and user_manager.auto_login_at_login: + if _call_or_get(current_user.is_authenticated) and user_manager.USER_AUTO_LOGIN_AT_LOGIN: return redirect(safe_next) # Initialize form @@ -256,7 +256,7 @@ def login(): # Retrieve User user = None user_email = None - if user_manager.enable_username: + if user_manager.USER_ENABLE_USERNAME: # Find user record by username user = user_manager.find_user_by_username(login_form.username.data) user_email = None @@ -267,7 +267,7 @@ def login(): is_primary=True, ) # Find user record by email (with form.username) - if not user and user_manager.enable_email: + if not user and user_manager.USER_ENABLE_EMAIL: user, user_email = user_manager.find_user_by_email(login_form.username.data) else: # Find user by email (with form.email) @@ -279,7 +279,7 @@ def login(): return _do_login_user(user, safe_next, login_form.remember_me.data) # Process GET or invalid POST - return render(user_manager.login_template, + return render(user_manager.USER_LOGIN_TEMPLATE, form=login_form, login_form=login_form, register_form=register_form) @@ -298,7 +298,7 @@ def logout(): flash(_('You have signed out successfully.'), 'success') # Redirect to logout_next endpoint or '/' - safe_next = _get_safe_next_param('next', user_manager.after_logout_endpoint) + safe_next = _get_safe_next_param('next', user_manager.USER_AFTER_LOGOUT_ENDPOINT) return redirect(safe_next) @@ -320,7 +320,7 @@ def manage_emails(): return redirect(url_for('user.manage_emails')) # Process GET or invalid POST request - return render(user_manager.manage_emails_template, + return render(user_manager.USER_MANAGE_EMAILS_TEMPLATE, user_emails=user_emails, form=form, ) @@ -331,8 +331,8 @@ def register(): user_manager = current_app.user_manager db_adapter = user_manager.db_adapter - safe_next = _get_safe_next_param('next', user_manager.after_login_endpoint) - safe_reg_next = _get_safe_next_param('reg_next', user_manager.after_register_endpoint) + safe_next = _get_safe_next_param('next', user_manager.USER_AFTER_LOGIN_ENDPOINT) + safe_reg_next = _get_safe_next_param('reg_next', user_manager.USER_AFTER_REGISTER_ENDPOINT) # Initialize form login_form = user_manager.login_form() # for login_or_register.html @@ -342,7 +342,7 @@ def register(): invite_token = request.values.get("token") # require invite without a token should disallow the user from registering - if user_manager.require_invitation and not invite_token: + if user_manager.USER_REQUIRE_INVITATION and not invite_token: flash("Registration is invite only", "error") return redirect(url_for('user.login')) @@ -413,10 +413,10 @@ def register(): db_adapter.commit() # Send 'registered' email and delete new User object if send fails - if user_manager.send_registered_email: + if user_manager.USER_SEND_REGISTERED_EMAIL: try: # Send 'registered' email - _send_registered_email(user, user_email, require_email_confirmation) + _USER_SEND_REGISTERED_EMAIL(user, user_email, require_email_confirmation) except Exception as e: # delete new User object if send fails db_adapter.delete_object(user) @@ -429,7 +429,7 @@ def register(): user_invite=user_invite) # Redirect if USER_ENABLE_CONFIRM_EMAIL is set - if user_manager.enable_confirm_email and require_email_confirmation: + if user_manager.USER_ENABLE_CONFIRM_EMAIL and require_email_confirmation: safe_reg_next = user_manager.make_safe_url_function(register_form.reg_next.data) return redirect(safe_reg_next) @@ -437,14 +437,14 @@ def register(): if 'reg_next' in request.args: safe_reg_next = user_manager.make_safe_url_function(register_form.reg_next.data) else: - safe_reg_next = _endpoint_url(user_manager.after_confirm_endpoint) - if user_manager.auto_login_after_register: + safe_reg_next = _endpoint_url(user_manager.USER_AFTER_CONFIRM_ENDPOINT) + if user_manager.USER_AUTO_LOGIN_AFTER_REGISTER: return _do_login_user(user, safe_reg_next) # auto-login else: return redirect(url_for('user.login')+'?next='+quote(safe_reg_next)) # redirect to login page # Process GET or invalid POST - return render(user_manager.register_template, + return render(user_manager.USER_REGISTER_TEMPLATE, form=register_form, login_form=login_form, register_form=register_form) @@ -493,10 +493,10 @@ def invite(): form=invite_form) flash(_('Invitation has been sent.'), 'success') - safe_next = _get_safe_next_param('next', user_manager.after_invite_endpoint) + safe_next = _get_safe_next_param('next', user_manager.USER_AFTER_INVITE_ENDPOINT) return redirect(safe_next) - return render(user_manager.invite_template, form=invite_form) + return render(user_manager.USER_INVITE_TEMPLATE, form=invite_form) def resend_confirm_email(): """Prompt for email and re-send email conformation email.""" @@ -516,10 +516,10 @@ def resend_confirm_email(): _send_confirm_email(user, user_email) # Redirect to the login page - return redirect(_endpoint_url(user_manager.after_resend_confirm_email_endpoint)) + return redirect(_endpoint_url(user_manager.USER_AFTER_RESEND_CONFIRM_EMAIL_ENDPOINT)) # Process GET or invalid POST - return render(user_manager.resend_confirm_email_template, form=form) + return render(user_manager.USER_RESENT_CONFIRM_EMAIL_TEMPLATE, form=form) def reset_password(token): @@ -533,7 +533,7 @@ def reset_password(token): data_items = user_manager.token_manager.verify_token( token, - user_manager.reset_password_expiration) + user_manager.USER_PASSWORD_EXPIRATION) if not data_items: flash(_('Your reset password token is invalid.'), 'error') @@ -558,21 +558,21 @@ def reset_password(token): db_adapter.commit() # Send 'password_changed' email - if user_manager.enable_email and user_manager.send_password_changed_email: + if user_manager.USER_ENABLE_EMAIL and user_manager.USER_SEND_PASSWORD_CHANGED_EMAIL: user_manager.send_password_has_changed_email(user) # Prepare one-time system message flash(_("Your password has been reset successfully."), 'success') # Auto-login after reset password or redirect to login page - safe_next = _get_safe_next_param('next', user_manager.after_reset_password_endpoint) - if user_manager.auto_login_after_reset_password: + safe_next = _get_safe_next_param('next', user_manager.USER_AFTER_RESET_PASSWORD_ENDPOINT) + if user_manager.USER_AUTO_LOGIN_AFTER_RESET_PASSWORD: return _do_login_user(user, safe_next) # auto-login else: return redirect(url_for('user.login')+'?next='+quote(safe_next)) # redirect to login page # Process GET or invalid POST - return render(user_manager.reset_password_template, form=form) + return render(user_manager.USER_RESET_PASSWORD_TEMPLATE, form=form) def unconfirmed(): @@ -583,7 +583,7 @@ def unconfirmed(): # Redirect to USER_UNCONFIRMED_EMAIL_ENDPOINT user_manager = current_app.user_manager - return redirect(_endpoint_url(user_manager.unconfirmed_email_endpoint)) + return redirect(_endpoint_url(user_manager.USER_AFTER_UNCONFIRMED_EMAIL_ENDPOINT)) def unauthenticated(): @@ -595,7 +595,7 @@ def unauthenticated(): # Redirect to USER_UNAUTHENTICATED_ENDPOINT safe_next = user_manager.make_safe_url_function(url) - return redirect(_endpoint_url(user_manager.unauthenticated_endpoint)+'?next='+quote(safe_next)) + return redirect(_endpoint_url(user_manager.USER_UNAUTHENTICATED_ENDPOINT)+'?next='+quote(safe_next)) def unauthorized(): @@ -606,22 +606,22 @@ def unauthorized(): # Redirect to USER_UNAUTHORIZED_ENDPOINT user_manager = current_app.user_manager - return redirect(_endpoint_url(user_manager.unauthorized_endpoint)) + return redirect(_endpoint_url(user_manager.USER_UNAUTHORIZED_ENDPOINT)) @login_required @confirm_email_required def user_profile(): user_manager = current_app.user_manager - return render(user_manager.user_profile_template) + return render(user_manager.USER_PROFILE_TEMPLATE) -def _send_registered_email(user, user_email, require_email_confirmation=True): +def _USER_SEND_REGISTERED_EMAIL(user, user_email, require_email_confirmation=True): user_manager = current_app.user_manager db_adapter = user_manager.db_adapter # Send 'confirm_email' or 'registered' email - if user_manager.enable_email and user_manager.enable_confirm_email: + if user_manager.USER_ENABLE_EMAIL and user_manager.USER_ENABLE_CONFIRM_EMAIL: # Generate confirm email link object_id = user_email.id if user_email else user.id token = user_manager.token_manager.generate_token(object_id) @@ -631,7 +631,7 @@ def _send_registered_email(user, user_email, require_email_confirmation=True): user_manager.email_manager.send_user_has_registered_email(user, user_email, confirm_email_link) # Prepare one-time system message - if user_manager.enable_confirm_email and require_email_confirmation: + if user_manager.USER_ENABLE_CONFIRM_EMAIL and require_email_confirmation: email = user_email.email if user_email else user.email flash(_('A confirmation email has been sent to %(email)s with instructions to complete your registration.', email=email), 'success') else: @@ -643,7 +643,7 @@ def _send_confirm_email(user, user_email): db_adapter = user_manager.db_adapter # Send 'confirm_email' or 'registered' email - if user_manager.enable_email and user_manager.enable_confirm_email: + if user_manager.USER_ENABLE_EMAIL and user_manager.USER_ENABLE_CONFIRM_EMAIL: # Send email user_manager.email_manager.send_email_confirmation_email(user, user_email) @@ -663,8 +663,8 @@ def _do_login_user(user, safe_next, remember_me=False): # Check if user has a confirmed email address user_manager = current_app.user_manager - if user_manager.enable_email and user_manager.enable_confirm_email \ - and not current_app.user_manager.enable_login_without_confirm_email \ + if user_manager.USER_ENABLE_EMAIL and user_manager.USER_ENABLE_CONFIRM_EMAIL \ + and not current_app.user_manager.USER_ENABLE_LOGIN_WITHOUT_CONFIRM_EMAIL \ and not user_has_confirmed_email(user): url = url_for('user.resend_confirm_email') flash(_('Your email address has not yet been confirmed. Check your email Inbox and Spam folders for the confirmation email or Re-send confirmation email.', url=url), 'error')