From d008de46ecac29dac4d2eeb2b03bfd0521d73949 Mon Sep 17 00:00:00 2001
From: Maximilian Moser <maximilian.moser@tuwien.ac.at>
Date: Tue, 31 Dec 2024 00:25:17 +0100
Subject: [PATCH] Refactor user-related modules into their own namespace

* to make it more obvious that they are all related to user models
* also, rename the modules to better reflect their content
* also, rename some content (e.g. `CurationForm` to `CurationPreferencesForm`)
---
 invenio_config_tuw/auth/utils.py              |  2 +-
 invenio_config_tuw/config.py                  | 10 +++--
 invenio_config_tuw/users/__init__.py          | 36 ++++++++++++++++
 .../{curation.py => users/preferences.py}     |  4 +-
 .../{forms.py => users/registration.py}       |  2 +-
 invenio_config_tuw/{ => users}/schemas.py     |  2 +-
 invenio_config_tuw/{ => users}/utils.py       | 43 +------------------
 invenio_config_tuw/{ => users}/views.py       | 10 ++---
 pyproject.toml                                |  4 +-
 9 files changed, 57 insertions(+), 56 deletions(-)
 create mode 100644 invenio_config_tuw/users/__init__.py
 rename invenio_config_tuw/{curation.py => users/preferences.py} (96%)
 rename invenio_config_tuw/{forms.py => users/registration.py} (99%)
 rename invenio_config_tuw/{ => users}/schemas.py (96%)
 rename invenio_config_tuw/{ => users}/utils.py (67%)
 rename invenio_config_tuw/{ => users}/views.py (84%)

diff --git a/invenio_config_tuw/auth/utils.py b/invenio_config_tuw/auth/utils.py
index 6373150..d314ac3 100644
--- a/invenio_config_tuw/auth/utils.py
+++ b/invenio_config_tuw/auth/utils.py
@@ -12,7 +12,7 @@ from flask import current_app
 from invenio_accounts.proxies import current_datastore
 from invenio_db import db
 
-from ..utils import get_user_by_username
+from ..users.utils import get_user_by_username
 
 
 def create_username_from_info(user_info):
diff --git a/invenio_config_tuw/config.py b/invenio_config_tuw/config.py
index 3f09b57..794e00e 100644
--- a/invenio_config_tuw/config.py
+++ b/invenio_config_tuw/config.py
@@ -14,15 +14,19 @@ from invenio_oauthclient.views.client import auto_redirect_login
 from invenio_rdm_records.config import RDM_RECORDS_REVIEWS
 
 from .auth import TUWSSOSettingsHelper
-from .forms import tuw_registration_form
 from .permissions import (
     TUWCommunityPermissionPolicy,
     TUWRecordPermissionPolicy,
     TUWRequestsPermissionPolicy,
 )
-from .schemas import TUWUserPreferencesSchema, TUWUserProfileSchema, TUWUserSchema
 from .services import TUWRecordsComponents
-from .utils import check_user_email_for_tuwien, current_user_as_creator
+from .users import (
+    TUWUserPreferencesSchema,
+    TUWUserProfileSchema,
+    TUWUserSchema,
+    tuw_registration_form,
+)
+from .users.utils import check_user_email_for_tuwien, current_user_as_creator
 
 # Invenio-Config-TUW
 # ==================
diff --git a/invenio_config_tuw/users/__init__.py b/invenio_config_tuw/users/__init__.py
new file mode 100644
index 0000000..f61dee6
--- /dev/null
+++ b/invenio_config_tuw/users/__init__.py
@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2024-2025 TU Wien.
+#
+# Invenio-Config-TUW is free software; you can redistribute it and/or modify
+# it under the terms of the MIT License; see LICENSE file for more details.
+
+"""Customizations for the user model at TU Wien.
+
+This includes the curation consent for record metadata as extension for the user's
+preferences, and a custom registration form which requires the terms of use to be
+accepted.
+"""
+
+from .preferences import CurationPreferencesForm, CurationPreferencesProxy
+from .registration import tuw_registration_form
+from .schemas import TUWUserPreferencesSchema, TUWUserProfileSchema, TUWUserSchema
+from .utils import (
+    check_user_email_for_tuwien,
+    current_user_as_creator,
+    get_user_by_username,
+)
+from .views import user_settings_blueprint
+
+__all__ = (
+    "CurationPreferencesForm",
+    "CurationPreferencesProxy",
+    "TUWUserPreferencesSchema",
+    "TUWUserProfileSchema",
+    "TUWUserSchema",
+    "check_user_email_for_tuwien",
+    "current_user_as_creator",
+    "get_user_by_username",
+    "tuw_registration_form",
+    "user_settings_blueprint",
+)
diff --git a/invenio_config_tuw/curation.py b/invenio_config_tuw/users/preferences.py
similarity index 96%
rename from invenio_config_tuw/curation.py
rename to invenio_config_tuw/users/preferences.py
index b544b78..14ac06c 100644
--- a/invenio_config_tuw/curation.py
+++ b/invenio_config_tuw/users/preferences.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2023 TU Wien.
+# Copyright (C) 2023-2025 TU Wien.
 #
 # Invenio-Config-TUW is free software; you can redistribute it and/or modify
 # it under the terms of the MIT License; see LICENSE file for more details.
@@ -37,7 +37,7 @@ class CurationPreferencesProxy:
         return f"curation_{attr}" in self._user.preferences
 
 
-class CurationForm(FlaskForm):
+class CurationPreferencesForm(FlaskForm):
     """Form for editing a user's curation preferences."""
 
     proxy_cls = CurationPreferencesProxy
diff --git a/invenio_config_tuw/forms.py b/invenio_config_tuw/users/registration.py
similarity index 99%
rename from invenio_config_tuw/forms.py
rename to invenio_config_tuw/users/registration.py
index 5e62a5f..ac00174 100644
--- a/invenio_config_tuw/forms.py
+++ b/invenio_config_tuw/users/registration.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2020-2024 TU Wien.
+# Copyright (C) 2020-2025 TU Wien.
 #
 # Invenio-Config-TUW is free software; you can redistribute it and/or modify
 # it under the terms of the MIT License; see LICENSE file for more details.
diff --git a/invenio_config_tuw/schemas.py b/invenio_config_tuw/users/schemas.py
similarity index 96%
rename from invenio_config_tuw/schemas.py
rename to invenio_config_tuw/users/schemas.py
index 60b4b64..1085798 100644
--- a/invenio_config_tuw/schemas.py
+++ b/invenio_config_tuw/users/schemas.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2023 TU Wien.
+# Copyright (C) 2023-2025 TU Wien.
 #
 # Invenio-Config-TUW is free software; you can redistribute it and/or modify
 # it under the terms of the MIT License; see LICENSE file for more details.
diff --git a/invenio_config_tuw/utils.py b/invenio_config_tuw/users/utils.py
similarity index 67%
rename from invenio_config_tuw/utils.py
rename to invenio_config_tuw/users/utils.py
index e7a11bf..823aae3 100644
--- a/invenio_config_tuw/utils.py
+++ b/invenio_config_tuw/users/utils.py
@@ -1,62 +1,23 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2020-2022 TU Wien.
+# Copyright (C) 2020-2025 TU Wien.
 #
 # Invenio-Config-TUW is free software; you can redistribute it and/or modify
 # it under the terms of the MIT License; see LICENSE file for more details.
 
-"""Utility functions."""
+"""User-related utility functions."""
 
 from typing import Dict, Tuple
 
-from flask_principal import Identity
 from flask_security import current_user
-from invenio_access import any_user
-from invenio_access.utils import get_identity
-from invenio_accounts import current_accounts
 from invenio_accounts.models import User
 
-# Utilities for internal use
-# --------------------------
-
 
 def get_user_by_username(username):
     """Get the user identified by the username."""
     return User.query.filter(User.username == username).one_or_none()
 
 
-def get_user(identifier):
-    """Get the user identified by the given ID, email or username."""
-    user = current_accounts.datastore.get_user(identifier)
-    if user is None:
-        get_user_by_username(identifier)
-
-    return user
-
-
-def get_identity_for_user(user):
-    """Get the Identity for the user specified via email, ID or username."""
-    identity = None
-    if user is not None:
-        # note: this seems like the canonical way to go
-        #       'as_user' can be either an integer (id) or email address
-        u = get_user(user)
-        if u is not None:
-            identity = get_identity(u)
-        else:
-            raise LookupError("user not found: %s" % user)
-
-    if identity is None:
-        identity = Identity(1)
-
-    identity.provides.add(any_user)
-    return identity
-
-
-# Utilities for invenio configuration
-# -----------------------------------
-
-
 def check_user_email_for_tuwien(user):
     """Check if the user's email belongs to TU Wien (but not as a student)."""
     domain = user.email.split("@")[-1]
diff --git a/invenio_config_tuw/views.py b/invenio_config_tuw/users/views.py
similarity index 84%
rename from invenio_config_tuw/views.py
rename to invenio_config_tuw/users/views.py
index e17a6da..5b0c350 100644
--- a/invenio_config_tuw/views.py
+++ b/invenio_config_tuw/users/views.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2024 TU Wien.
+# Copyright (C) 2024-2025 TU Wien.
 #
 # Invenio-Config-TUW is free software; you can redistribute it and/or modify
 # it under the terms of the MIT License; see LICENSE file for more details.
@@ -11,9 +11,9 @@ from flask import Blueprint, current_app, flash, render_template, request
 from flask_login import current_user, login_required
 from invenio_db import db
 
-from .curation import CurationForm
+from .preferences import CurationPreferencesForm
 
-blueprint = Blueprint(
+user_settings_blueprint = Blueprint(
     "invenio_config_tuw_settings",
     __name__,
     url_prefix="/account/settings/curation",
@@ -21,11 +21,11 @@ blueprint = Blueprint(
 )
 
 
-@blueprint.route("/", methods=["GET", "POST"])
+@user_settings_blueprint.route("/", methods=["GET", "POST"])
 @login_required
 def curation_settings_view():
     """Page for the curation consent setting in user profiles."""
-    preferences_curation_form = CurationForm(
+    preferences_curation_form = CurationPreferencesForm(
         formdata=None, obj=current_user, prefix="preferences-curation"
     )
 
diff --git a/pyproject.toml b/pyproject.toml
index 5ba6349..ec008a7 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2024 TU Wien.
+# Copyright (C) 2024-2025 TU Wien.
 #
 # Invenio-Config-TUW is free software; you can redistribute it and/or modify
 # it under the terms of the MIT License; see LICENSE file for more details.
@@ -69,7 +69,7 @@ invenio_config_tuw = "invenio_config_tuw:InvenioConfigTUW"
 invenio_config_tuw = "invenio_config_tuw:InvenioConfigTUW"
 
 [project.entry-points."invenio_base.blueprints"]
-invenio_config_tuw_settings = "invenio_config_tuw.views:blueprint"
+invenio_config_tuw_settings = "invenio_config_tuw.users.views:user_settings_blueprint"
 
 [project.entry-points."invenio_base.finalize_app"]
 invenio_config_tuw_mail_handler = "invenio_config_tuw.startup:register_smtp_error_handler"
-- 
GitLab