diff --git a/flask_security/core.py b/flask_security/core.py index aee6093..a29a573 100644 --- a/flask_security/core.py +++ b/flask_security/core.py @@ -21,6 +21,9 @@ from werkzeug.local import LocalProxy from .utils import config_value as cv, get_config, md5, url_for_security from .views import create_blueprint +from .forms import LoginForm, ConfirmRegisterForm, RegisterForm, \ + ForgotPasswordForm, ResetPasswordForm, SendConfirmationForm, \ + PasswordlessLoginForm # Convenient references _security = LocalProxy(lambda: current_app.extensions['security']) @@ -93,6 +96,17 @@ _default_messages = { } +_default_forms = { + 'login_form': LoginForm, + 'confirm_register_form': ConfirmRegisterForm, + 'register_form': RegisterForm, + 'forgot_password_form': ForgotPasswordForm, + 'reset_password_form': ResetPasswordForm, + 'send_confirmation_form': SendConfirmationForm, + 'passwordless_login_form': PasswordlessLoginForm, +} + + def _user_loader(user_id): return _security.datastore.find_user(id=user_id) @@ -167,10 +181,11 @@ def _get_state(app, datastore, **kwargs): reset_serializer=_get_serializer(app, 'reset'), confirm_serializer=_get_serializer(app, 'confirm'), _context_processors={}, - _form_fns={}, _send_mail_task=None )) + kwargs.update(_default_forms) + return _SecurityState(**kwargs) @@ -237,9 +252,6 @@ class _SecurityState(object): rv.update(fn()) return rv - def _get_form_cls(self, endpoint): - return self._form_fns.get(endpoint, lambda: None)() - def context_processor(self, fn): self._add_ctx_processor(None, fn) @@ -267,27 +279,6 @@ class _SecurityState(object): def send_mail_task(self, fn): self._send_mail_task = fn - def login_form(self, fn): - self._form_fns['login_form'] = fn - - def confirm_register_form(self, fn): - self._form_fns['confirm_register_form'] = fn - - def register_form(self, fn): - self._form_fns['register_form'] = fn - - def forgot_password_form(self, fn): - self._form_fns['forgot_password_form'] = fn - - def reset_password_form(self, fn): - self._form_fns['reset_password_form'] = fn - - def send_confirmation_form(self, fn): - self._form_fns['send_confirmation_form'] = fn - - def passwordless_login_form(self, fn): - self._form_fns['passwordless_login_form'] = fn - class Security(object): """The :class:`Security` class initializes the Flask-Security extension. @@ -302,12 +293,13 @@ class Security(object): if app is not None and datastore is not None: self._state = self.init_app(app, datastore, **kwargs) - def init_app(self, app, datastore=None, register_blueprint=True): + def init_app(self, app, datastore=None, register_blueprint=True, **kwargs): """Initializes the Flask-Security extension for the specified application and datastore implentation. :param app: The application. :param datastore: An instance of a user datastore. + :param register_blueprint: to register the Security blueprint or not. """ datastore = datastore or self.datastore diff --git a/flask_security/views.py b/flask_security/views.py index 72a493a..3efd316 100644 --- a/flask_security/views.py +++ b/flask_security/views.py @@ -17,9 +17,6 @@ from werkzeug.local import LocalProxy from .confirmable import send_confirmation_instructions, \ confirm_user, confirm_email_token_status from .decorators import login_required, anonymous_user_required -from .forms import LoginForm, ConfirmRegisterForm, RegisterForm, \ - ForgotPasswordForm, ResetPasswordForm, SendConfirmationForm, \ - PasswordlessLoginForm from .passwordless import send_login_instructions, \ login_token_status from .recoverable import reset_password_token_status, \ @@ -35,17 +32,6 @@ _security = LocalProxy(lambda: current_app.extensions['security']) _datastore = LocalProxy(lambda: _security.datastore) -_default_forms = { - 'login_form': LoginForm, - 'confirm_register_form': ConfirmRegisterForm, - 'register_form': RegisterForm, - 'forgot_password_form': ForgotPasswordForm, - 'reset_password_form': ResetPasswordForm, - 'send_confirmation_form': SendConfirmationForm, - 'passwordless_login_form': PasswordlessLoginForm, -} - - def _render_json(form, include_auth_token=False): has_errors = len(form.errors) > 0 @@ -71,15 +57,11 @@ def _ctx(endpoint): return _security._run_ctx_processor(endpoint) -def _form_cls(endpoint): - return _security._get_form_cls(endpoint) or _default_forms[endpoint] - - @anonymous_user_required def login(): """View function for login view""" - form_class = _form_cls('login_form') + form_class = _security.login_form if request.json: form = form_class(MultiDict(request.json)) @@ -118,9 +100,9 @@ def register(): """View function which handles a registration request.""" if _security.confirmable or request.json: - form_class = _form_cls('confirm_register_form') + form_class = _security.confirm_register_form else: - form_class = _form_cls('register_form') + form_class = _security.register_form if request.json: form_data = MultiDict(request.json) @@ -153,7 +135,7 @@ def register(): def send_login(): """View function that sends login instructions for passwordless login""" - form_class = _form_cls('passwordless_login_form') + form_class = _security.passwordless_login_form if request.json: form = form_class(MultiDict(request.json)) @@ -198,7 +180,7 @@ def token_login(token): def send_confirmation(): """View function which sends confirmation instructions.""" - form_class = _form_cls('send_confirmation_form') + form_class = _security.send_confirmation_form if request.json: form = form_class(MultiDict(request.json)) @@ -246,7 +228,7 @@ def confirm_email(token): def forgot_password(): """View function that handles a forgotten password request.""" - form_class = _form_cls('forgot_password_form') + form_class = _security.forgot_password_form if request.json: form = form_class(MultiDict(request.json)) @@ -280,7 +262,7 @@ def reset_password(token): if invalid or expired: return redirect(url_for('forgot_password')) - form = _form_cls('reset_password_form')() + form = _security.reset_password_form() if form.validate_on_submit(): after_this_request(_commit) diff --git a/tests/configured_tests.py b/tests/configured_tests.py index 0c6b11d..92a5d3f 100644 --- a/tests/configured_tests.py +++ b/tests/configured_tests.py @@ -6,6 +6,10 @@ import simplejson as json from flask.ext.security.utils import capture_registrations, \ capture_reset_password_requests, capture_passwordless_login_requests +from flask.ext.security.forms import LoginForm, ConfirmRegisterForm, RegisterForm, \ + ForgotPasswordForm, ResetPasswordForm, SendConfirmationForm, \ + PasswordlessLoginForm + from tests import SecurityTest @@ -488,13 +492,21 @@ class NoBlueprintTests(SecurityTest): class ExtendFormsTest(SecurityTest): + class MyLoginForm(LoginForm): + hidden_tag = 'not-so-secret' + APP_KWARGS = { + 'login_form': MyLoginForm, } AUTH_CONFIG = { 'SECURITY_REGISTERABLE': True, } + def test_login_view(self): + r = self._get('/login') + self.assertIn("

Login

", r.data) + def test_register(self): r = self._get('/register') self.assertIn('

Register

', r.data)