From 2fcfb80e8e6feda1923ac743fa3f51f31a822ac1 Mon Sep 17 00:00:00 2001 From: Matt Wright Date: Thu, 16 Aug 2012 13:41:13 -0400 Subject: [PATCH] Refactor templates and added `url_for_security` utility. Can also configure the blueprint name. --- example/templates/_nav.html | 2 +- example/templates/login.html | 2 +- example/templates/passwordless_login.html | 2 +- example/templates/register.html | 2 +- flask_security/__init__.py | 2 +- flask_security/confirmable.py | 4 ++-- flask_security/core.py | 16 +++++++++++----- flask_security/passwordless.py | 7 ++++--- flask_security/recoverable.py | 8 ++++---- .../security/{macros.html => _macros.html} | 0 .../security/{messages.html => _messages.html} | 0 .../templates/security/confirmations/new.html | 8 -------- .../{registrations/edit.html => edit_user.html} | 6 +++--- .../templates/security/forgot_password.html | 8 ++++++++ .../security/{logins/new.html => login.html} | 6 +++--- .../templates/security/logins/passwordless.html | 9 --------- .../templates/security/passwords/new.html | 8 -------- .../new.html => register_user.html} | 6 +++--- .../{passwords/edit.html => reset_password.html} | 6 +++--- .../templates/security/send_confirmation.html | 8 ++++++++ .../templates/security/send_login.html | 9 +++++++++ flask_security/utils.py | 15 +++++++++++++++ flask_security/views.py | 10 +++++----- 23 files changed, 83 insertions(+), 61 deletions(-) rename flask_security/templates/security/{macros.html => _macros.html} (100%) rename flask_security/templates/security/{messages.html => _messages.html} (100%) delete mode 100644 flask_security/templates/security/confirmations/new.html rename flask_security/templates/security/{registrations/edit.html => edit_user.html} (62%) create mode 100644 flask_security/templates/security/forgot_password.html rename flask_security/templates/security/{logins/new.html => login.html} (57%) delete mode 100644 flask_security/templates/security/logins/passwordless.html delete mode 100644 flask_security/templates/security/passwords/new.html rename flask_security/templates/security/{registrations/new.html => register_user.html} (58%) rename flask_security/templates/security/{passwords/edit.html => reset_password.html} (50%) create mode 100644 flask_security/templates/security/send_confirmation.html create mode 100644 flask_security/templates/security/send_login.html diff --git a/example/templates/_nav.html b/example/templates/_nav.html index 3796955..7dd1347 100644 --- a/example/templates/_nav.html +++ b/example/templates/_nav.html @@ -12,7 +12,7 @@ {% endif -%}
  • {%- if current_user.is_authenticated() -%} - Log out + Log out {%- else -%} Log in {%- endif -%} diff --git a/example/templates/login.html b/example/templates/login.html index 137fc6c..231bb56 100644 --- a/example/templates/login.html +++ b/example/templates/login.html @@ -1,6 +1,6 @@ {% include "_messages.html" %} {% include "_nav.html" %} -
    + {{ form.hidden_tag() }} {{ form.email.label }} {{ form.email }}
    {{ form.password.label }} {{ form.password }}
    diff --git a/example/templates/passwordless_login.html b/example/templates/passwordless_login.html index 715179b..1827982 100644 --- a/example/templates/passwordless_login.html +++ b/example/templates/passwordless_login.html @@ -1,6 +1,6 @@ {% include "_messages.html" %} {% include "_nav.html" %} - + {{ form.hidden_tag() }} {{ form.email.label }} {{ form.email }}
    {{ form.next }} diff --git a/example/templates/register.html b/example/templates/register.html index 440fdd2..7f4e27a 100644 --- a/example/templates/register.html +++ b/example/templates/register.html @@ -1,7 +1,7 @@ {% include "_messages.html" %} {% include "_nav.html" %}

    Register

    - + {{ register_user_form.hidden_tag() }} {{ register_user_form.email.label }} {{ register_user_form.email }}
    {{ register_user_form.password.label }} {{ register_user_form.password }}
    diff --git a/flask_security/__init__.py b/flask_security/__init__.py index 2abe3a2..1f72c84 100644 --- a/flask_security/__init__.py +++ b/flask_security/__init__.py @@ -22,4 +22,4 @@ from .forms import ForgotPasswordForm, LoginForm, RegisterForm, \ from .signals import confirm_instructions_sent, password_reset, \ password_reset_requested, reset_instructions_sent, user_confirmed, \ user_registered -from .utils import login_user, logout_user +from .utils import login_user, logout_user, url_for_security diff --git a/flask_security/confirmable.py b/flask_security/confirmable.py index 9dd5f14..c2c1d29 100644 --- a/flask_security/confirmable.py +++ b/flask_security/confirmable.py @@ -16,7 +16,7 @@ from flask import current_app as app, request, url_for from werkzeug.local import LocalProxy from .exceptions import ConfirmationError -from .utils import send_mail, get_max_age, md5, get_message +from .utils import send_mail, get_max_age, md5, get_message, url_for_security from .signals import user_confirmed, confirm_instructions_sent @@ -32,7 +32,7 @@ def send_confirmation_instructions(user, token): :param user: The user to send the instructions to :param token: The confirmation token """ - url = url_for('flask_security.confirm_email', token=token) + url = url_for_security('confirm_email', token=token) confirmation_link = request.url_root[:-1] + url diff --git a/flask_security/core.py b/flask_security/core.py index 6a0d428..b810ac1 100644 --- a/flask_security/core.py +++ b/flask_security/core.py @@ -9,7 +9,7 @@ :license: MIT, see LICENSE for more details. """ -from itsdangerous import URLSafeTimedSerializer, BadSignature +from itsdangerous import URLSafeTimedSerializer from flask import current_app from flask.ext.login import AnonymousUser as AnonymousUserBase, \ UserMixin as BaseUserMixin, LoginManager, current_user @@ -21,7 +21,8 @@ from werkzeug.local import LocalProxy from . import views, exceptions from .confirmable import requires_confirmation -from .utils import config_value as cv, get_config, verify_password, md5 +from .utils import config_value as cv, get_config, verify_password, md5, \ + url_for_security # Convenient references _security = LocalProxy(lambda: current_app.extensions['security']) @@ -29,6 +30,7 @@ _security = LocalProxy(lambda: current_app.extensions['security']) #: Default Flask-Security configuration _default_config = { + 'BLUEPRINT_NAME': 'security', 'URL_PREFIX': None, 'FLASH_MESSAGES': True, 'PASSWORD_HASH': 'plaintext', @@ -246,11 +248,15 @@ class Security(object): identity_loaded.connect_via(app)(_on_identity_loaded) if register_blueprint: - bp = views.create_blueprint(app, 'flask_security', __name__, - template_folder='templates', - url_prefix=cv('URL_PREFIX', app=app)) + name = cv('BLUEPRINT_NAME', app=app) + url_prefix = cv('URL_PREFIX', app=app) + bp = views.create_blueprint(app, name, __name__, + url_prefix=url_prefix, + template_folder='templates') app.register_blueprint(bp) + app.context_processor(lambda: dict(url_for_security=url_for_security)) + state = self._get_state(app, datastore or self.datastore) app.extensions['security'] = state diff --git a/flask_security/passwordless.py b/flask_security/passwordless.py index 6820e4c..cc3332c 100644 --- a/flask_security/passwordless.py +++ b/flask_security/passwordless.py @@ -9,13 +9,14 @@ :license: MIT, see LICENSE for more details. """ -from flask import url_for, request, current_app as app +from flask import request, current_app as app from itsdangerous import SignatureExpired, BadSignature from werkzeug.local import LocalProxy from .exceptions import PasswordlessLoginError from .signals import login_instructions_sent -from .utils import send_mail, md5, get_max_age, login_user, get_message +from .utils import send_mail, md5, get_max_age, login_user, get_message, \ + url_for_security # Convenient references @@ -32,7 +33,7 @@ def send_login_instructions(user, next): """ token = generate_login_token(user, next) - url = url_for('flask_security.token_login', token=token) + url = url_for_security('token_login', token=token) login_link = request.url_root[:-1] + url diff --git a/flask_security/recoverable.py b/flask_security/recoverable.py index ea20aa9..c6125a3 100644 --- a/flask_security/recoverable.py +++ b/flask_security/recoverable.py @@ -10,13 +10,14 @@ """ from itsdangerous import BadSignature, SignatureExpired -from flask import current_app as app, request, url_for +from flask import current_app as app, request from werkzeug.local import LocalProxy from .exceptions import ResetPasswordError, UserNotFoundError from .signals import password_reset, password_reset_requested, \ reset_instructions_sent -from .utils import send_mail, get_max_age, md5, get_message, encrypt_password +from .utils import send_mail, get_max_age, md5, get_message, encrypt_password, \ + url_for_security # Convenient references @@ -30,8 +31,7 @@ def send_reset_password_instructions(user, reset_token): :param user: The user to send the instructions to """ - url = url_for('flask_security.reset_password', - token=reset_token) + url = url_for_security('reset_password', token=reset_token) reset_link = request.url_root[:-1] + url diff --git a/flask_security/templates/security/macros.html b/flask_security/templates/security/_macros.html similarity index 100% rename from flask_security/templates/security/macros.html rename to flask_security/templates/security/_macros.html diff --git a/flask_security/templates/security/messages.html b/flask_security/templates/security/_messages.html similarity index 100% rename from flask_security/templates/security/messages.html rename to flask_security/templates/security/_messages.html diff --git a/flask_security/templates/security/confirmations/new.html b/flask_security/templates/security/confirmations/new.html deleted file mode 100644 index e3e523c..0000000 --- a/flask_security/templates/security/confirmations/new.html +++ /dev/null @@ -1,8 +0,0 @@ -{% from "security/macros.html" import render_field_with_errors, render_field %} -{% include "security/messages.html" %} -

    Resend confirmation instructions

    - - {{ reset_confirmation_form.hidden_tag() }} - {{ render_field_with_errors(reset_confirmation_form.email) }} - {{ render_field(reset_confirmation_form.submit) }} -
    \ No newline at end of file diff --git a/flask_security/templates/security/registrations/edit.html b/flask_security/templates/security/edit_user.html similarity index 62% rename from flask_security/templates/security/registrations/edit.html rename to flask_security/templates/security/edit_user.html index 0d5c637..7169a2c 100644 --- a/flask_security/templates/security/registrations/edit.html +++ b/flask_security/templates/security/edit_user.html @@ -1,7 +1,7 @@ -{% from "security/macros.html" import render_field_with_errors, render_field %} -{% include "security/messages.html" %} +{% from "security/_macros.html" import render_field_with_errors, render_field %} +{% include "security/_messages.html" %}

    Edit Account

    -
    + {{ edit_user_form.hidden_tag() }} {{ render_field_with_errors(edit_user_form.email) }} {{ render_field_with_errors(edit_user_form.password) }} diff --git a/flask_security/templates/security/forgot_password.html b/flask_security/templates/security/forgot_password.html new file mode 100644 index 0000000..27a0d54 --- /dev/null +++ b/flask_security/templates/security/forgot_password.html @@ -0,0 +1,8 @@ +{% from "security/_macros.html" import render_field_with_errors, render_field %} +{% include "security/_messages.html" %} +

    Send reset password instructions

    + + {{ forgot_password_form.hidden_tag() }} + {{ render_field_with_errors(forgot_password_form.email) }} + {{ render_field(forgot_password_form.submit) }} +
    \ No newline at end of file diff --git a/flask_security/templates/security/logins/new.html b/flask_security/templates/security/login.html similarity index 57% rename from flask_security/templates/security/logins/new.html rename to flask_security/templates/security/login.html index a81d1fe..9d9c26f 100644 --- a/flask_security/templates/security/logins/new.html +++ b/flask_security/templates/security/login.html @@ -1,7 +1,7 @@ -{% from "security/macros.html" import render_field_with_errors, render_field %} -{% include "security/messages.html" %} +{% from "security/_macros.html" import render_field_with_errors, render_field %} +{% include "security/_messages.html" %}

    Login

    -
    + {{ login_form.hidden_tag() }} {{ render_field_with_errors(login_form.email) }} {{ render_field_with_errors(login_form.password) }} diff --git a/flask_security/templates/security/logins/passwordless.html b/flask_security/templates/security/logins/passwordless.html deleted file mode 100644 index d0f353e..0000000 --- a/flask_security/templates/security/logins/passwordless.html +++ /dev/null @@ -1,9 +0,0 @@ -{% from "security/macros.html" import render_field_with_errors, render_field %} -{% include "security/messages.html" %} -

    Login

    - - {{ login_form.hidden_tag() }} - {{ render_field_with_errors(login_form.email) }} - {{ render_field(login_form.next) }} - {{ render_field(login_form.submit) }} -
    \ No newline at end of file diff --git a/flask_security/templates/security/passwords/new.html b/flask_security/templates/security/passwords/new.html deleted file mode 100644 index 31c4f1f..0000000 --- a/flask_security/templates/security/passwords/new.html +++ /dev/null @@ -1,8 +0,0 @@ -{% from "security/macros.html" import render_field_with_errors, render_field %} -{% include "security/messages.html" %} -

    Send reset password instructions

    -
    - {{ forgot_password_form.hidden_tag() }} - {{ render_field_with_errors(forgot_password_form.email) }} - {{ render_field(forgot_password_form.submit) }} -
    \ No newline at end of file diff --git a/flask_security/templates/security/registrations/new.html b/flask_security/templates/security/register_user.html similarity index 58% rename from flask_security/templates/security/registrations/new.html rename to flask_security/templates/security/register_user.html index b9f9773..3219472 100644 --- a/flask_security/templates/security/registrations/new.html +++ b/flask_security/templates/security/register_user.html @@ -1,7 +1,7 @@ -{% from "security/macros.html" import render_field_with_errors, render_field %} -{% include "security/messages.html" %} +{% from "security/_macros.html" import render_field_with_errors, render_field %} +{% include "security/_messages.html" %}

    Register

    -
    + {{ register_user_form.hidden_tag() }} {{ render_field_with_errors(register_user_form.email) }} {{ render_field_with_errors(register_user_form.password) }} diff --git a/flask_security/templates/security/passwords/edit.html b/flask_security/templates/security/reset_password.html similarity index 50% rename from flask_security/templates/security/passwords/edit.html rename to flask_security/templates/security/reset_password.html index 4a505be..ca573c8 100644 --- a/flask_security/templates/security/passwords/edit.html +++ b/flask_security/templates/security/reset_password.html @@ -1,7 +1,7 @@ -{% from "security/macros.html" import render_field_with_errors, render_field %} -{% include "security/messages.html" %} +{% from "security/_macros.html" import render_field_with_errors, render_field %} +{% include "security/_messages.html" %}

    Change password

    - + {{ reset_password_form.hidden_tag() }} {{ render_field_with_errors(reset_password_form.password) }} {{ render_field_with_errors(reset_password_form.password_confirm) }} diff --git a/flask_security/templates/security/send_confirmation.html b/flask_security/templates/security/send_confirmation.html new file mode 100644 index 0000000..3c90523 --- /dev/null +++ b/flask_security/templates/security/send_confirmation.html @@ -0,0 +1,8 @@ +{% from "security/_macros.html" import render_field_with_errors, render_field %} +{% include "security/_messages.html" %} +

    Resend confirmation instructions

    + + {{ reset_confirmation_form.hidden_tag() }} + {{ render_field_with_errors(reset_confirmation_form.email) }} + {{ render_field(reset_confirmation_form.submit) }} +
    \ No newline at end of file diff --git a/flask_security/templates/security/send_login.html b/flask_security/templates/security/send_login.html new file mode 100644 index 0000000..7a3ea31 --- /dev/null +++ b/flask_security/templates/security/send_login.html @@ -0,0 +1,9 @@ +{% from "security/_macros.html" import render_field_with_errors, render_field %} +{% include "security/_messages.html" %} +

    Login

    +
    + {{ login_form.hidden_tag() }} + {{ render_field_with_errors(login_form.email) }} + {{ render_field(login_form.next) }} + {{ render_field(login_form.submit) }} +
    \ No newline at end of file diff --git a/flask_security/utils.py b/flask_security/utils.py index 2680ec5..42a28c7 100644 --- a/flask_security/utils.py +++ b/flask_security/utils.py @@ -115,6 +115,21 @@ def get_url(endpoint_or_url): return endpoint_or_url +def url_for_security(endpoint, **values): + """Return a URL for the security blueprint + + :param endpoint: the endpoint of the URL (name of the function) + :param values: the variable arguments of the URL rule + :param _external: if set to `True`, an absolute URL is generated. Server + address can be changed via `SERVER_NAME` configuration variable which + defaults to `localhost`. + :param _anchor: if provided this is added as anchor to the URL. + :param _method: if provided this explicitly specifies an HTTP method. + """ + endpoint = '%s.%s' % (_security.blueprint_name, endpoint) + return url_for(endpoint, **values) + + def get_post_login_redirect(): """Returns the URL to redirect to after a user logs in successfully.""" return (get_url(request.args.get('next')) or diff --git a/flask_security/views.py b/flask_security/views.py index ee3b66d..d7f6e86 100644 --- a/flask_security/views.py +++ b/flask_security/views.py @@ -128,7 +128,7 @@ def register_user(): return redirect(_security.post_register_view or _security.post_login_view) - return render_template('security/registrations/new.html', + return render_template('security/register_user.html', register_user_form=form) @@ -143,7 +143,7 @@ def send_login(): else: do_flash(*get_message('DISABLED_ACCOUNT')) - return render_template('security/logins/passwordless.html', login_form=form) + return render_template('security/send_login.html', login_form=form) def token_login(token): @@ -182,7 +182,7 @@ def send_confirmation(): do_flash(msg, cat) - return render_template('security/confirmations/new.html', + return render_template('security/send_confirmation.html', reset_confirmation_form=form) @@ -231,7 +231,7 @@ def forgot_password(): for key, value in form.errors.items(): do_flash(value[0], 'error') - return render_template('security/passwords/new.html', + return render_template('security/forgot_password.html', forgot_password_form=form) @@ -267,7 +267,7 @@ def reset_password(token): do_flash(msg, cat) - return render_template('security/passwords/edit.html', + return render_template('security/reset_password.html', reset_password_form=form, password_reset_token=token)