diff --git a/invenio_config_tuw/auth/utils.py b/invenio_config_tuw/auth/utils.py
index 6373150b7c0af015041aa55e5c0b5225104ba033..d314ac32c2288a67051c9ac31a665681bef077e4 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 3f09b57d9341e9c517bac582289bafb8e7bbb888..794e00ed879f472bff45351caa68967c6be8816a 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 0000000000000000000000000000000000000000..f61dee6863a412e3adaa6ead17b631dfc8fbd270
--- /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 b544b78929863b1d39f339c3881b0d71873dc19a..14ac06c18b8f9c6fa4ec104ffd20a9515d311825 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 5e62a5f87c53462541e9592ec33c7812ab94a125..ac00174cb019301c01be0d07a28e953ec4978ad1 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 60b4b64f5971fedbae5ca13643c25e5534583768..10857988edc470c257725ded490454b80026bb09 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 e7a11bf597fdd728591da2cd22595dd6f9a6d93e..823aae3c8ea6ba40fe1fdd3adaca679a94caeb1c 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 e17a6da4fd2d41d3c78c06baff538a2aee771cb9..5b0c35043760a79e8f6137212c697d3a02d4f050 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 5ba634963eab4986081855e9830ee74e2e01c292..ec008a7b82eca4d82f75e3533883d750973e169f 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"