Skip to content

Commit

Permalink
forms: made ProfileForm configurable
Browse files Browse the repository at this point in the history
  • Loading branch information
0einstein0 committed Dec 19, 2024
1 parent 87cb05b commit c052a9b
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 41 deletions.
5 changes: 5 additions & 0 deletions invenio_userprofiles/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

"""Default configuration."""

from .forms import ProfileForm

USERPROFILES = True
"""Enable or disable module extensions."""

Expand All @@ -31,3 +33,6 @@

USERPROFILES_READ_ONLY = False
"""Make the user profiles read-only."""

USERPROFILES_FORM_CLASS = ProfileForm
"""Default user profiles form class."""
9 changes: 6 additions & 3 deletions invenio_userprofiles/ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# under the terms of the MIT License; see LICENSE file for more details.

"""User profiles module for Invenio."""

from flask import current_app
from flask_menu import current_menu
from invenio_i18n import LazyString
from invenio_i18n import lazy_gettext as _
Expand Down Expand Up @@ -95,10 +95,13 @@ def init_common(app):
"""Post initialization."""
if app.config["USERPROFILES_EXTEND_SECURITY_FORMS"]:
security_ext = app.extensions["security"]
UserProfileForm = app.config.get("USERPROFILES_FORM_CLASS")
security_ext.confirm_register_form = confirm_register_form_factory(
security_ext.confirm_register_form
security_ext.confirm_register_form, UserProfileForm
)
security_ext.register_form = register_form_factory(
security_ext.register_form, UserProfileForm
)
security_ext.register_form = register_form_factory(security_ext.register_form)


def init_menu(app):
Expand Down
71 changes: 38 additions & 33 deletions invenio_userprofiles/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,37 +123,42 @@ def populate_obj(self, user):
super().populate_obj(user)


class EmailProfileForm(ProfileForm):
"""Form to allow editing of email address."""
def create_email_profile_form(UserProfileForm):
"""Factory function to create EmailProfileForm inheriting from UserProfileForm."""

class EmailProfileForm(UserProfileForm):
"""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 = 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.")),
],
)

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.")),
],
)
return EmailProfileForm


class VerificationForm(FlaskForm):
Expand All @@ -163,10 +168,10 @@ class VerificationForm(FlaskForm):
send_verification_email = SubmitField(_("Resend verification email"))


def register_form_factory(Form):
def register_form_factory(Form, UserProfileForm):
"""Factory for creating an extended user registration form."""

class CsrfDisabledProfileForm(ProfileForm):
class CsrfDisabledProfileForm(UserProfileForm):
"""Subclass of ProfileForm to disable CSRF token in the inner form.
This class will always be a inner form field of the parent class
Expand Down Expand Up @@ -252,10 +257,10 @@ def populate_obj(self, user):
super().populate_obj(user)


def confirm_register_form_factory(Form):
def confirm_register_form_factory(Form, UserProfileForm):
"""Factory for creating a confirm register form with UserProfile fields."""

class CsrfDisabledProfileForm(ProfileForm):
class CsrfDisabledProfileForm(UserProfileForm):
"""Subclass of ProfileForm to disable CSRF token in the inner form.
This class will always be an inner form field of the parent class
Expand Down
6 changes: 4 additions & 2 deletions invenio_userprofiles/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from invenio_db import db
from invenio_i18n import lazy_gettext as _

from .forms import EmailProfileForm, PreferencesForm, ProfileForm, VerificationForm
from .forms import PreferencesForm, VerificationForm, create_email_profile_form
from .models import UserProfileProxy


Expand Down Expand Up @@ -92,14 +92,16 @@ def profile():

def profile_form_factory():
"""Create a profile form."""
UserProfileForm = current_app.config.get("USERPROFILES_FORM_CLASS")
EmailProfileForm = create_email_profile_form(UserProfileForm)
if current_app.config["USERPROFILES_EMAIL_ENABLED"]:
return EmailProfileForm(
formdata=None,
obj=current_user,
prefix="profile",
)
else:
return ProfileForm(
return UserProfileForm(
formdata=None,
obj=current_user,
prefix="profile",
Expand Down
7 changes: 4 additions & 3 deletions tests/test_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"""Tests for user profile forms."""

from invenio_userprofiles.forms import (
ProfileForm,
_update_with_csrf_disabled,
confirm_register_form_factory,
confirm_register_form_preferences_factory,
Expand Down Expand Up @@ -56,8 +57,8 @@ def test_confirm_register_form_preferences_factory_no_csrf(app):
"""Test CSRF token is not in confirm form and not in inner forms."""
security = app.extensions["security"]

def factory_profile_preferences(Form):
ProfileForm = confirm_register_form_factory(Form)
def factory_profile_preferences(Form, UserProfileForm):
ProfileForm = confirm_register_form_factory(Form, UserProfileForm)
return confirm_register_form_preferences_factory(ProfileForm)

rf = _get_form(app, security.confirm_register_form, factory_profile_preferences)
Expand Down Expand Up @@ -116,7 +117,7 @@ class AForm(parent_form):
with app.test_request_context():
extra = _update_with_csrf_disabled() if force_disable_csrf else {}

RF = factory_method(AForm)
RF = factory_method(AForm, ProfileForm)
rf = RF(**extra)

rf.profile.username.data = "my username"
Expand Down

0 comments on commit c052a9b

Please sign in to comment.