From 02c49ee423d15c058c6815e0065cf1b91f25f082 Mon Sep 17 00:00:00 2001 From: Chris Haines Date: Tue, 29 Jan 2013 22:24:11 -0500 Subject: [PATCH] Paths for templates are now configurable --- docs/configuration.rst | 29 ++++++++ docs/customizing.rst | 4 +- flask_security/core.py | 6 ++ flask_security/views.py | 15 ++-- tests/configured_tests.py | 73 +++++++++++++++++++ .../custom_security/forgot_password.html | 1 + .../templates/custom_security/login_user.html | 1 + .../custom_security/register_user.html | 1 + .../custom_security/reset_password.html | 1 + .../custom_security/send_confirmation.html | 1 + .../templates/custom_security/send_login.html | 1 + 11 files changed, 125 insertions(+), 8 deletions(-) create mode 100644 tests/test_app/templates/custom_security/forgot_password.html create mode 100644 tests/test_app/templates/custom_security/login_user.html create mode 100644 tests/test_app/templates/custom_security/register_user.html create mode 100644 tests/test_app/templates/custom_security/reset_password.html create mode 100644 tests/test_app/templates/custom_security/send_confirmation.html create mode 100644 tests/test_app/templates/custom_security/send_login.html diff --git a/docs/configuration.rst b/docs/configuration.rst index e187a16..1b8f56b 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -96,6 +96,35 @@ URLs and Views =============================== ================================================ +Template Paths +-------------- + +.. tabularcolumns:: |p{6.5cm}|p{8.5cm}| + +======================================== ======================================= +``SECURITY_FORGOT_PASSWORD_TEMPLATE`` Specifies the path to the template for + the forgot password page. Defaults to + ``security/forgot_password.html``. +``SECURITY_LOGIN_USER_TEMPLATE`` Specifies the path to the template for + the user login page. Defaults to + ``security/login_user.html``. +``SECURITY_REGISTER_USER_TEMPLATE`` Specifies the path to the template for + the user registration page. Defaults to + ``security/register_user.html``. +``SECURITY_RESET_PASSWORD_TEMPLATE`` Specifies the path to the template for + the reset password page. Defaults to + ``security/reset_password.html``. +``SECURITY_SEND_CONFIRMATION_TEMPLATE`` Specifies the path to the template for + the resend confirmation instructions + page. Defaults to + ``security/send_confirmation.html``. +``SECURITY_SEND_LOGIN_TEMPLATE`` Specifies the path to the template for + the send login instructions page for + passwordless logins. Defaults to + ``security/send_login.html``. +======================================== ======================================= + + Feature Flags ------------- diff --git a/docs/customizing.rst b/docs/customizing.rst index 8bc5601..1eabf27 100644 --- a/docs/customizing.rst +++ b/docs/customizing.rst @@ -26,9 +26,11 @@ Overriding these templates is simple: 1. Create a folder named ``security`` within your application's templates folder 2. Create a template with the same name for the template you wish to override +You can also specify custom template file paths in the :doc:`configuration `. + Each template is passed a template context object that includes the following, including the objects/values that are passed to the template by the main -Flask application context processory: +Flask application context processor: * ``_form``: A form object for the view * ``security``: The Flask-Security extension object diff --git a/flask_security/core.py b/flask_security/core.py index b30af10..a06c5d0 100644 --- a/flask_security/core.py +++ b/flask_security/core.py @@ -48,6 +48,12 @@ _default_config = { 'POST_CONFIRM_VIEW': None, 'POST_RESET_VIEW': None, 'UNAUTHORIZED_VIEW': None, + 'FORGOT_PASSWORD_TEMPLATE': 'security/forgot_password.html', + 'LOGIN_USER_TEMPLATE': 'security/login_user.html', + 'REGISTER_USER_TEMPLATE': 'security/register_user.html', + 'RESET_PASSWORD_TEMPLATE': 'security/reset_password.html', + 'SEND_CONFIRMATION_TEMPLATE': 'security/send_confirmation.html', + 'SEND_LOGIN_TEMPLATE': 'security/send_login.html', 'CONFIRMABLE': False, 'REGISTERABLE': False, 'RECOVERABLE': False, diff --git a/flask_security/views.py b/flask_security/views.py index 3efd316..f09d8b5 100644 --- a/flask_security/views.py +++ b/flask_security/views.py @@ -23,7 +23,8 @@ from .recoverable import reset_password_token_status, \ send_reset_password_instructions, update_password from .registerable import register_user from .utils import get_url, get_post_login_redirect, do_flash, \ - get_message, login_user, logout_user, url_for_security as url_for + get_message, login_user, logout_user, url_for_security as url_for, \ + config_value # Convenient references @@ -81,7 +82,7 @@ def login(): if request.json: return _render_json(form, True) - return render_template('security/login_user.html', + return render_template(config_value('LOGIN_USER_TEMPLATE'), login_user_form=form, **_ctx('login')) @@ -127,7 +128,7 @@ def register(): if request.json: return _render_json(form) - return render_template('security/register_user.html', + return render_template(config_value('REGISTER_USER_TEMPLATE'), register_user_form=form, **_ctx('register')) @@ -150,7 +151,7 @@ def send_login(): if request.json: return _render_json(form) - return render_template('security/send_login.html', + return render_template(config_value('SEND_LOGIN_TEMPLATE'), send_login_form=form, **_ctx('send_login')) @@ -195,7 +196,7 @@ def send_confirmation(): if request.json: return _render_json(form) - return render_template('security/send_confirmation.html', + return render_template(config_value('SEND_CONFIRMATION_TEMPLATE'), send_confirmation_form=form, **_ctx('send_confirmation')) @@ -243,7 +244,7 @@ def forgot_password(): if request.json: return _render_json(form) - return render_template('security/forgot_password.html', + return render_template(config_value('FORGOT_PASSWORD_TEMPLATE'), forgot_password_form=form, **_ctx('forgot_password')) @@ -272,7 +273,7 @@ def reset_password(token): return redirect(get_url(_security.post_reset_view) or get_url(_security.post_login_view)) - return render_template('security/reset_password.html', + return render_template(config_value('RESET_PASSWORD_TEMPLATE'), reset_password_form=form, reset_password_token=token, **_ctx('reset_password')) diff --git a/tests/configured_tests.py b/tests/configured_tests.py index f1e0d7d..d56854d 100644 --- a/tests/configured_tests.py +++ b/tests/configured_tests.py @@ -107,6 +107,79 @@ class BadConfiguredSecurityTests(SecurityTest): self.assertRaises(RuntimeError, self.authenticate) +class DefaultTemplatePathTests(SecurityTest): + AUTH_CONFIG = { + 'SECURITY_LOGIN_USER_TEMPLATE': 'custom_security/login_user.html', + } + + + def test_login_user_template(self): + r = self._get('/login') + + self.assertIn('CUSTOM LOGIN USER', r.data) + + +class RegisterableTemplatePathTests(SecurityTest): + AUTH_CONFIG = { + 'SECURITY_REGISTERABLE': True, + 'SECURITY_REGISTER_USER_TEMPLATE': 'custom_security/register_user.html' + } + + def test_register_user_template(self): + r = self._get('/register') + + self.assertIn('CUSTOM REGISTER USER', r.data) + + +class RecoverableTemplatePathTests(SecurityTest): + AUTH_CONFIG = { + 'SECURITY_RECOVERABLE': True, + 'SECURITY_FORGOT_PASSWORD_TEMPLATE': 'custom_security/forgot_password.html', + 'SECURITY_RESET_PASSWORD_TEMPLATE': 'custom_security/reset_password.html', + } + + def test_forgot_password_template(self): + r = self._get('/reset') + + self.assertIn('CUSTOM FORGOT PASSWORD', r.data) + + def test_reset_password_template(self): + with capture_reset_password_requests() as requests: + r = self.client.post('/reset', + data=dict(email='joe@lp.com'), + follow_redirects=True) + t = requests[0]['token'] + + r = self._get('/reset/' + t) + + self.assertIn('CUSTOM RESET PASSWORD', r.data) + + +class ConfirmableTemplatePathTests(SecurityTest): + AUTH_CONFIG = { + 'SECURITY_CONFIRMABLE': True, + 'SECURITY_SEND_CONFIRMATION_TEMPLATE': 'custom_security/send_confirmation.html' + } + + def test_send_confirmation_template(self): + r = self._get('/confirm') + + self.assertIn('CUSTOM SEND CONFIRMATION', r.data) + + +class PasswordlessTemplatePathTests(SecurityTest): + AUTH_CONFIG = { + 'SECURITY_PASSWORDLESS': True, + 'SECURITY_SEND_LOGIN_TEMPLATE': 'custom_security/send_login.html' + } + + def test_send_login_template(self): + r = self._get('/login') + + self.assertIn('CUSTOM SEND LOGIN', r.data) + + + class RegisterableTests(SecurityTest): AUTH_CONFIG = { 'SECURITY_REGISTERABLE': True, diff --git a/tests/test_app/templates/custom_security/forgot_password.html b/tests/test_app/templates/custom_security/forgot_password.html new file mode 100644 index 0000000..e268b44 --- /dev/null +++ b/tests/test_app/templates/custom_security/forgot_password.html @@ -0,0 +1 @@ +CUSTOM FORGOT PASSWORD diff --git a/tests/test_app/templates/custom_security/login_user.html b/tests/test_app/templates/custom_security/login_user.html new file mode 100644 index 0000000..abbe2c1 --- /dev/null +++ b/tests/test_app/templates/custom_security/login_user.html @@ -0,0 +1 @@ +CUSTOM LOGIN USER diff --git a/tests/test_app/templates/custom_security/register_user.html b/tests/test_app/templates/custom_security/register_user.html new file mode 100644 index 0000000..927c1f0 --- /dev/null +++ b/tests/test_app/templates/custom_security/register_user.html @@ -0,0 +1 @@ +CUSTOM REGISTER USER diff --git a/tests/test_app/templates/custom_security/reset_password.html b/tests/test_app/templates/custom_security/reset_password.html new file mode 100644 index 0000000..dc8e874 --- /dev/null +++ b/tests/test_app/templates/custom_security/reset_password.html @@ -0,0 +1 @@ +CUSTOM RESET PASSWORD diff --git a/tests/test_app/templates/custom_security/send_confirmation.html b/tests/test_app/templates/custom_security/send_confirmation.html new file mode 100644 index 0000000..a01892d --- /dev/null +++ b/tests/test_app/templates/custom_security/send_confirmation.html @@ -0,0 +1 @@ +CUSTOM SEND CONFIRMATION diff --git a/tests/test_app/templates/custom_security/send_login.html b/tests/test_app/templates/custom_security/send_login.html new file mode 100644 index 0000000..7ef81de --- /dev/null +++ b/tests/test_app/templates/custom_security/send_login.html @@ -0,0 +1 @@ +CUSTOM SEND LOGIN