about summary refs log tree commit diff
path: root/wqflask/flask_security/forms.py
diff options
context:
space:
mode:
authorZachary Sloan2013-06-20 22:20:23 +0000
committerZachary Sloan2013-06-20 22:20:23 +0000
commit4ffee373494170e708678039dca132f1bd729ab1 (patch)
treea9d6054380f5a9d612a4d1d88889f68ea4923a75 /wqflask/flask_security/forms.py
parent939058c4a3b668037974f2876b072c4be008da26 (diff)
parent52ac4b6e1c014801080cbbcad53df868058d2657 (diff)
downloadgenenetwork2-4ffee373494170e708678039dca132f1bd729ab1.tar.gz
Merge branch 'flask'
Diffstat (limited to 'wqflask/flask_security/forms.py')
-rw-r--r--wqflask/flask_security/forms.py277
1 files changed, 277 insertions, 0 deletions
diff --git a/wqflask/flask_security/forms.py b/wqflask/flask_security/forms.py
new file mode 100644
index 00000000..e64e1502
--- /dev/null
+++ b/wqflask/flask_security/forms.py
@@ -0,0 +1,277 @@
+# -*- coding: utf-8 -*-
+"""
+    flask.ext.security.forms
+    ~~~~~~~~~~~~~~~~~~~~~~~~
+
+    Flask-Security forms module
+
+    :copyright: (c) 2012 by Matt Wright.
+    :license: MIT, see LICENSE for more details.
+"""
+
+import inspect
+import urlparse
+
+import flask_wtf as wtf
+
+from flask import request, current_app
+from flask_wtf import Form as BaseForm, TextField, PasswordField, \
+     SubmitField, HiddenField, BooleanField, ValidationError, Field
+from flask_login import current_user
+from werkzeug.local import LocalProxy
+
+from .confirmable import requires_confirmation
+from .utils import verify_and_update_password, get_message
+
+# Convenient reference
+_datastore = LocalProxy(lambda: current_app.extensions['security'].datastore)
+
+_default_field_labels = {
+    'email': 'Email Address',
+    'password': 'Password',
+    'remember_me': 'Remember Me',
+    'login': 'Login',
+    'retype_password': 'Retype Password',
+    'register': 'Register',
+    'send_confirmation': 'Resend Confirmation Instructions',
+    'recover_password': 'Recover Password',
+    'reset_password': 'Reset Password',
+    'retype_password': 'Retype Password',
+    'new_password': 'New Password',
+    'change_password': 'Change Password',
+    'send_login_link': 'Send Login Link'
+}
+
+
+class ValidatorMixin(object):
+    def __call__(self, form, field):
+        if self.message and self.message.isupper():
+            self.message = get_message(self.message)[0]
+        return super(ValidatorMixin, self).__call__(form, field)
+
+
+class EqualTo(ValidatorMixin, wtf.EqualTo):
+    pass
+
+
+class Required(ValidatorMixin, wtf.Required):
+    pass
+
+
+class Email(ValidatorMixin, wtf.Email):
+    pass
+
+
+class Length(ValidatorMixin, wtf.Length):
+    pass
+
+
+email_required = Required(message='EMAIL_NOT_PROVIDED')
+email_validator = Email(message='INVALID_EMAIL_ADDRESS')
+password_required = Required(message='PASSWORD_NOT_PROVIDED')
+
+
+def get_form_field_label(key):
+    return _default_field_labels.get(key, '')
+
+
+def unique_user_email(form, field):
+    if _datastore.find_user(email=field.data) is not None:
+        msg = get_message('EMAIL_ALREADY_ASSOCIATED', email=field.data)[0]
+        raise ValidationError(msg)
+
+
+def valid_user_email(form, field):
+    form.user = _datastore.find_user(email=field.data)
+    if form.user is None:
+        raise ValidationError(get_message('USER_DOES_NOT_EXIST')[0])
+
+
+class Form(BaseForm):
+    def __init__(self, *args, **kwargs):
+        if current_app.testing:
+            self.TIME_LIMIT = None
+        super(Form, self).__init__(*args, **kwargs)
+
+
+class EmailFormMixin():
+    email = TextField(get_form_field_label('email'),
+        validators=[email_required,
+                    email_validator])
+
+
+class UserEmailFormMixin():
+    user = None
+    email = TextField(get_form_field_label('email'),
+        validators=[email_required,
+                    email_validator,
+                    valid_user_email])
+
+
+class UniqueEmailFormMixin():
+    email = TextField(get_form_field_label('email'),
+        validators=[email_required,
+                    email_validator,
+                    unique_user_email])
+
+
+class PasswordFormMixin():
+    password = PasswordField(get_form_field_label('password'),
+        validators=[password_required])
+
+
+class NewPasswordFormMixin():
+    password = PasswordField(get_form_field_label('password'),
+        validators=[password_required,
+                    Length(min=6, max=128)])
+
+
+class PasswordConfirmFormMixin():
+    password_confirm = PasswordField(
+        get_form_field_label('retype_password'),
+        validators=[EqualTo('password', message='RETYPE_PASSWORD_MISMATCH')])
+
+
+class NextFormMixin():
+    next = HiddenField()
+
+    def validate_next(self, field):
+        url_next = urlparse.urlsplit(field.data)
+        url_base = urlparse.urlsplit(request.host_url)
+        if url_next.netloc and url_next.netloc != url_base.netloc:
+            field.data = ''
+            raise ValidationError(get_message('INVALID_REDIRECT')[0])
+
+
+class RegisterFormMixin():
+    submit = SubmitField(get_form_field_label('register'))
+
+    def to_dict(form):
+        def is_field_and_user_attr(member):
+            return isinstance(member, Field) and \
+                hasattr(_datastore.user_model, member.name)
+
+        fields = inspect.getmembers(form, is_field_and_user_attr)
+        return dict((key, value.data) for key, value in fields)
+
+
+class SendConfirmationForm(Form, UserEmailFormMixin):
+    """The default forgot password form"""
+
+    submit = SubmitField(get_form_field_label('send_confirmation'))
+
+    def __init__(self, *args, **kwargs):
+        super(SendConfirmationForm, self).__init__(*args, **kwargs)
+        if request.method == 'GET':
+            self.email.data = request.args.get('email', None)
+
+    def validate(self):
+        if not super(SendConfirmationForm, self).validate():
+            return False
+        if self.user.confirmed_at is not None:
+            self.email.errors.append(get_message('ALREADY_CONFIRMED')[0])
+            return False
+        return True
+
+
+class ForgotPasswordForm(Form, UserEmailFormMixin):
+    """The default forgot password form"""
+
+    submit = SubmitField(get_form_field_label('recover_password'))
+
+
+class PasswordlessLoginForm(Form, UserEmailFormMixin):
+    """The passwordless login form"""
+
+    submit = SubmitField(get_form_field_label('send_login_link'))
+
+    def __init__(self, *args, **kwargs):
+        super(PasswordlessLoginForm, self).__init__(*args, **kwargs)
+
+    def validate(self):
+        if not super(PasswordlessLoginForm, self).validate():
+            return False
+        if not self.user.is_active():
+            self.email.errors.append(get_message('DISABLED_ACCOUNT')[0])
+            return False
+        return True
+
+
+class LoginForm(Form, NextFormMixin):
+    """The default login form"""
+
+    email = TextField(get_form_field_label('email'))
+    password = PasswordField(get_form_field_label('password'))
+    remember = BooleanField(get_form_field_label('remember_me'))
+    submit = SubmitField(get_form_field_label('login'))
+
+    def __init__(self, *args, **kwargs):
+        super(LoginForm, self).__init__(*args, **kwargs)
+
+    def validate(self):
+        if not super(LoginForm, self).validate():
+            return False
+
+        if self.email.data.strip() == '':
+            self.email.errors.append(get_message('EMAIL_NOT_PROVIDED')[0])
+            return False
+
+        if self.password.data.strip() == '':
+            self.password.errors.append(get_message('PASSWORD_NOT_PROVIDED')[0])
+            return False
+
+        self.user = _datastore.find_user(email=self.email.data)
+
+        if self.user is None:
+            self.email.errors.append(get_message('USER_DOES_NOT_EXIST')[0])
+            return False
+        if not verify_and_update_password(self.password.data, self.user):
+            self.password.errors.append(get_message('INVALID_PASSWORD')[0])
+            return False
+        if requires_confirmation(self.user):
+            self.email.errors.append(get_message('CONFIRMATION_REQUIRED')[0])
+            return False
+        if not self.user.is_active():
+            self.email.errors.append(get_message('DISABLED_ACCOUNT')[0])
+            return False
+        return True
+
+
+class ConfirmRegisterForm(Form, RegisterFormMixin,
+                          UniqueEmailFormMixin, NewPasswordFormMixin):
+    pass
+
+
+class RegisterForm(ConfirmRegisterForm, PasswordConfirmFormMixin):
+    pass
+
+
+class ResetPasswordForm(Form, NewPasswordFormMixin, PasswordConfirmFormMixin):
+    """The default reset password form"""
+
+    submit = SubmitField(get_form_field_label('reset_password'))
+
+
+class ChangePasswordForm(Form, PasswordFormMixin):
+    """The default change password form"""
+
+    new_password = PasswordField(get_form_field_label('new_password'),
+        validators=[password_required,
+                    Length(min=6, max=128)])
+
+    new_password_confirm = PasswordField(get_form_field_label('retype_password'),
+        validators=[EqualTo('new_password', message='RETYPE_PASSWORD_MISMATCH')])
+
+    submit = SubmitField(get_form_field_label('change_password'))
+
+    def validate(self):
+        if not super(ChangePasswordForm, self).validate():
+            return False
+
+        if self.password.data.strip() == '':
+            self.password.errors.append(get_message('PASSWORD_NOT_PROVIDED')[0])
+            return False
+        if not verify_and_update_password(self.password.data, current_user):
+            self.password.errors.append(get_message('INVALID_PASSWORD')[0])
+            return False
+        return True