Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: before_first_request deprecation #161

Merged
merged 10 commits into from
Mar 22, 2024
47 changes: 47 additions & 0 deletions invenio_userprofiles/ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,21 @@
#
# This file is part of Invenio.
# Copyright (C) 2015-2018 CERN.
# Copyright (C) 2024 Graz University of Technology.
#
# 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.

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

from flask_menu import current_menu
from invenio_i18n import LazyString
from invenio_i18n import lazy_gettext as _
from invenio_theme.proxies import current_theme_icons

from . import config
from .api import current_userprofile
from .forms import confirm_register_form_factory, register_form_factory


class InvenioUserProfiles(object):
Expand Down Expand Up @@ -61,6 +68,46 @@ def init_config(self, app):
"invenio_accounts/register_user.html",
),
)

app.config["SECURITY_REGISTER_USER_TEMPLATE"] = (
"invenio_userprofiles/register_user.html"
)


def finalize_app(app):
"""Finalize app.

NOTE: replace former @record_once decorator
"""
init_common(app)
init_menu(app)


def api_finalize_app(app):
"""Finalize app for api.

NOTE: replace former @record_once decorator
"""
init_common(app)


def init_common(app):
"""Post initialization."""
if app.config["USERPROFILES_EXTEND_SECURITY_FORMS"]:
security_ext = app.extensions["security"]
security_ext.confirm_register_form = confirm_register_form_factory(
security_ext.confirm_register_form
)
security_ext.register_form = register_form_factory(security_ext.register_form)


def init_menu(app):
"""Init menu."""
current_menu.submenu("settings.profile").register(
endpoint="invenio_userprofiles.profile",
text=_(
"%(icon)s Profile",
icon=LazyString(lambda: f'<i class="{current_theme_icons.user}"></i>'),
),
order=0,
)
88 changes: 18 additions & 70 deletions invenio_userprofiles/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# This file is part of Invenio.
# Copyright (C) 2015-2018 CERN.
# Copyright (C) 2022 Northwestern University.
# Copyright (C) 2023-2024 Graz University of Technology.
#
# 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.
Expand All @@ -20,89 +21,36 @@
request,
url_for,
)
from flask_breadcrumbs import register_breadcrumb
from flask_login import current_user, login_required
from flask_menu import register_menu
from flask_security.confirmable import send_confirmation_instructions
from invenio_db import db
from invenio_i18n import LazyString
from invenio_i18n import lazy_gettext as _
from invenio_theme.proxies import current_theme_icons

from .forms import (
EmailProfileForm,
PreferencesForm,
ProfileForm,
VerificationForm,
confirm_register_form_factory,
register_form_factory,
)
from .models import UserProfileProxy

blueprint = Blueprint(
"invenio_userprofiles",
__name__,
template_folder="templates",
)

blueprint_api_init = Blueprint(
"invenio_userprofiles_api_init",
__name__,
template_folder="templates",
)

blueprint_ui_init = Blueprint(
"invenio_userprofiles_ui_init",
__name__,
)

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

def init_common(app):
"""Post initialization."""
if app.config["USERPROFILES_EXTEND_SECURITY_FORMS"]:
security_ext = app.extensions["security"]
security_ext.confirm_register_form = confirm_register_form_factory(
security_ext.confirm_register_form
)
security_ext.register_form = register_form_factory(security_ext.register_form)


@blueprint_ui_init.record_once
def init_ui(state):
"""Post initialization for UI application."""
app = state.app
init_common(app)

# Register blueprint for templates
app.register_blueprint(blueprint, url_prefix=app.config["USERPROFILES_PROFILE_URL"])

def create_blueprint(app):
"""Create blueprint."""
blueprint = Blueprint(
"invenio_userprofiles",
__name__,
template_folder="templates",
url_prefix="/account/settings",
)

@blueprint_api_init.record_once
def init_api(state):
"""Post initialization for API application."""
init_common(state.app)
@blueprint.app_template_filter()
def userprofile(value):
"""Retrieve user profile for a given user id."""
warn("userprofile template filter is deprecated.", DeprecationWarning)
return UserProfileProxy.get_by_userid(int(value))

blueprint.add_url_rule("/profile", view_func=profile, methods=["GET", "POST"])

@blueprint.app_template_filter()
def userprofile(value):
"""Retrieve user profile for a given user id."""
warn("userprofile template filter is deprecated.", DeprecationWarning)
return UserProfileProxy.get_by_userid(int(value))
return blueprint


@blueprint.route("/", methods=["GET", "POST"])
@login_required
@register_menu(
blueprint,
"settings.profile",
# NOTE: Menu item text (icon replaced by a user icon).
_(
"%(icon)s Profile",
icon=LazyString(lambda: f'<i class="{current_theme_icons.user}"></i>'),
),
order=0,
)
@register_breadcrumb(blueprint, "breadcrumbs.settings.profile", _("Profile"))
def profile():
"""View for editing a profile."""
# Create forms
Expand Down
13 changes: 8 additions & 5 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,15 @@ packages = find:
python_requires = >=3.7
zip_safe = False
install_requires =
invenio-accounts>=2.0.0
invenio-accounts>=5.0.0
invenio-i18n>=2.0.0,<3.0.0

[options.extras_require]
tests =
pytest-black>=0.3.0
pytest-black-ng>=0.4.0
pytest-invenio>=1.4.7
invenio-db[mysql,postgresql,versioning]>=1.0.14
invenio-app>=1.4.0
sphinx>=4.5
admin =
# empty for backward compatibility
Expand All @@ -49,12 +50,14 @@ sqlite =
[options.entry_points]
invenio_base.api_apps =
invenio_userprofiles = invenio_userprofiles:InvenioUserProfiles
invenio_base.api_blueprints =
invenio_userprofiles = invenio_userprofiles.views:blueprint_api_init
invenio_base.api_finalize_app =
invenio_userprofiles = invenio_userprofiles.ext:api_finalize_app
invenio_base.apps =
invenio_userprofiles = invenio_userprofiles:InvenioUserProfiles
invenio_base.blueprints =
invenio_userprofiles = invenio_userprofiles.views:blueprint_ui_init
invenio_userprofiles = invenio_userprofiles.views:create_blueprint
invenio_base.finalize_app =
invenio_userprofiles = invenio_userprofiles.ext:finalize_app
invenio_db.alembic =
invenio_userprofiles = invenio_userprofiles:alembic
invenio_i18n.translations =
Expand Down
48 changes: 43 additions & 5 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#
# This file is part of Invenio.
# Copyright (C) 2015-2018 CERN.
# Copyright (C) 2022 Graz University of Technology.
# Copyright (C) 2022-2024 Graz University of Technology.
#
# 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.
Expand All @@ -17,14 +17,46 @@
from flask import Flask
from flask_mail import Mail
from flask_menu import Menu
from flask_webpackext.manifest import (
JinjaManifest,
JinjaManifestEntry,
JinjaManifestLoader,
)
from invenio_accounts import InvenioAccounts
from invenio_accounts.views import blueprint as accounts_blueprint
from invenio_accounts.views.settings import (
create_settings_blueprint as create_accounts_blueprint,
)
from invenio_assets import InvenioAssets
from invenio_db import InvenioDB, db
from invenio_i18n import Babel, InvenioI18N
from sqlalchemy_utils.functions import create_database, database_exists, drop_database

from invenio_userprofiles import InvenioUserProfiles
from invenio_userprofiles.views import blueprint_ui_init
from invenio_userprofiles.ext import finalize_app
from invenio_userprofiles.views import create_blueprint


#
# Mock the webpack manifest to avoid having to compile the full assets.
#
class MockJinjaManifest(JinjaManifest):
"""Mock manifest."""

def __getitem__(self, key):
"""Get a manifest entry."""
return JinjaManifestEntry(key, [key])

def __getattr__(self, name):
"""Get a manifest entry."""
return JinjaManifestEntry(name, [name])


class MockManifestLoader(JinjaManifestLoader):
"""Manifest loader creating a mocked manifest."""

def load(self, filepath):
"""Load the manifest."""
return MockJinjaManifest()


@pytest.fixture(scope="module")
Expand All @@ -41,6 +73,9 @@ def app_config(app_config):
TEST_USER_USERNAME="test",
TESTING=True,
WTF_CSRF_ENABLED=False,
ACCOUNTS_BASE_TEMPLATE="invenio_accounts/base.html",
ACCOUNTS_COVER_TEMPLATE="invenio_accounts/base_cover.html",
WEBPACKEXT_MANIFEST_LOADER=MockManifestLoader,
)

return app_config
Expand All @@ -59,7 +94,8 @@ def base_app(app_config):
InvenioDB(base_app)
InvenioAccounts(base_app)
InvenioI18N(base_app)
base_app.register_blueprint(accounts_blueprint)
InvenioAssets(base_app)
base_app.register_blueprint(create_accounts_blueprint(base_app))

with base_app.app_context():
if str(db.engine.url) != "sqlite://" and not database_exists(
Expand Down Expand Up @@ -99,7 +135,9 @@ def delete_user_from_cache(exception):
def _init_userprofiles_app(app_):
"""Init UserProfiles modules."""
InvenioUserProfiles(app_)
app_.register_blueprint(blueprint_ui_init)
app_.register_blueprint(create_blueprint(app_))
with app_.app_context():
finalize_app(app_)
return app_


Expand Down
8 changes: 6 additions & 2 deletions tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# This file is part of Invenio.
# Copyright (C) 2015-2018 CERN.
# Copyright (C) 2022 Northwestern University.
# Copyright (C) 2024 Graz University of Technology.
#
# 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.
Expand All @@ -16,7 +17,8 @@
from test_validators import test_usernames

from invenio_userprofiles import InvenioUserProfiles
from invenio_userprofiles.views import blueprint_ui_init
from invenio_userprofiles.ext import finalize_app
from invenio_userprofiles.views import create_blueprint


def prefix(name, data):
Expand All @@ -30,7 +32,9 @@ def test_profile_in_registration(base_app):
"""Test accounts registration form."""
base_app.config.update(USERPROFILES_EXTEND_SECURITY_FORMS=True)
InvenioUserProfiles(base_app)
base_app.register_blueprint(blueprint_ui_init)
base_app.register_blueprint(create_blueprint(base_app))
with base_app.app_context():
finalize_app(base_app)
app = base_app

with app.test_request_context():
Expand Down
Loading