Source code for invenio_userprofiles.forms

# -*- coding: utf-8 -*-
#
# This file is part of Invenio.
# Copyright (C) 2015-2018 CERN.
#
# Invenio is free software; you can redistribute it and/or modify it
# under the terms of the MIT License; see LICENSE file for more details.

"""Forms for user profiles."""

from __future__ import absolute_import, print_function

from flask_babelex import lazy_gettext as _
from flask_login import current_user
from flask_security.forms import email_required, email_validator, \
    unique_user_email
from flask_wtf import FlaskForm
from sqlalchemy.orm.exc import NoResultFound
from wtforms import FormField, StringField, SubmitField
from wtforms.validators import DataRequired, EqualTo, StopValidation, \
    ValidationError

from .api import current_userprofile
from .models import UserProfile
from .validators import USERNAME_RULES, validate_username


[docs]def strip_filter(text): """Filter for trimming whitespace. :param text: The text to strip. :returns: The stripped text. """ return text.strip() if text else text
[docs]def current_user_email(form, field): """Field validator to stop validation if email wasn't changed.""" if current_user.email == field.data: raise StopValidation()
[docs]class ProfileForm(FlaskForm): """Form for editing user profile.""" username = StringField( # NOTE: Form field label _('Username'), # NOTE: Form field help text description=_('Required. %(username_rules)s', username_rules=USERNAME_RULES), validators=[DataRequired(message=_('Username not provided.'))], filters=[strip_filter], ) full_name = StringField( # NOTE: Form label _('Full name'), filters=[strip_filter], )
[docs] def validate_username(form, field): """Wrap username validator for WTForms.""" try: validate_username(field.data) except ValueError as e: raise ValidationError(e) try: user_profile = UserProfile.get_by_username(field.data) if current_userprofile.is_anonymous or \ (current_userprofile.user_id != user_profile.user_id and field.data != current_userprofile.username): # NOTE: Form validation error. raise ValidationError(_('Username already exists.')) except NoResultFound: return
[docs]class EmailProfileForm(ProfileForm): """Form to allow editing of email address.""" email = StringField( # NOTE: Form field label _('Email address'), filters=[lambda x: x.lower() if x is not None else x, ], validators=[ email_required, current_user_email, email_validator, unique_user_email, ], ) email_repeat = StringField( # NOTE: Form field label _('Re-enter email address'), # NOTE: Form field help text description=_('Please re-enter your email address.'), filters=[lambda x: x.lower() if x else x, ], validators=[ email_required, # NOTE: Form validation error. EqualTo('email', message=_('Email addresses do not match.')) ] )
[docs]class VerificationForm(FlaskForm): """Form to render a button to request email confirmation.""" # NOTE: Form button label send_verification_email = SubmitField(_('Resend verification email'))
[docs]def register_form_factory(Form): """Factory for creating an extended user registration form.""" class CsrfDisabledProfileForm(ProfileForm): """Subclass of ProfileForm to disable CSRF token in the inner form. This class will always be a inner form field of the parent class `Form`. The parent will add/remove the CSRF token in the form. """ def __init__(self, *args, **kwargs): """Initialize the object by hardcoding CSRF token to false.""" kwargs = _update_with_csrf_disabled(kwargs) super(CsrfDisabledProfileForm, self).__init__(*args, **kwargs) class RegisterForm(Form): """RegisterForm extended with UserProfile details.""" profile = FormField(CsrfDisabledProfileForm, separator='.') return RegisterForm
[docs]def confirm_register_form_factory(Form): """Factory for creating a confirm register form.""" class CsrfDisabledProfileForm(ProfileForm): """Subclass of ProfileForm to disable CSRF token in the inner form. This class will always be a inner form field of the parent class `Form`. The parent will add/remove the CSRF token in the form. """ def __init__(self, *args, **kwargs): """Initialize the object by hardcoding CSRF token to false.""" kwargs = _update_with_csrf_disabled(kwargs) super(CsrfDisabledProfileForm, self).__init__(*args, **kwargs) class ConfirmRegisterForm(Form): """RegisterForm extended with UserProfile details.""" profile = FormField(CsrfDisabledProfileForm, separator='.') return ConfirmRegisterForm
def _update_with_csrf_disabled(d=None): """Update the input dict with CSRF disabled depending on WTF-Form version. From Flask-WTF 0.14.0, `csrf_enabled` param has been deprecated in favor of `meta={csrf: True/False}`. """ if d is None: d = {} import flask_wtf from pkg_resources import parse_version supports_meta = parse_version(flask_wtf.__version__) >= parse_version( "0.14.0") if supports_meta: d.setdefault('meta', {}) d['meta'].update({'csrf': False}) else: d['csrf_enabled'] = False return d