### Install Invenio-Users-Resources Source: https://github.com/inveniosoftware/invenio-users-resources/blob/master/INSTALL.rst Use this command to install the package from PyPI. Ensure you have pip installed. ```console $ pip install invenio-users-resources ``` -------------------------------- ### Set Up Virtual Environment and Install Dependencies Source: https://github.com/inveniosoftware/invenio-users-resources/blob/master/CONTRIBUTING.rst Create a virtual environment and install the project with all development dependencies. This prepares your local copy for development. ```console mkvirtualenv invenio-users-resources cd invenio-users-resources/ pip install -e .[all] ``` -------------------------------- ### Install Development Version from Git Source: https://github.com/inveniosoftware/invenio-users-resources/blob/master/requirements-devel.txt Use this format to install a development version of a package directly from a Git repository. This is useful for testing against the latest changes or specific branches. Replace `werkzeug` and `Jinja2` with the desired package names and repository URLs. ```shell -e git+git://github.com/mitsuhiko/werkzeug.git#egg=Werkzeug ``` ```shell -e git+git://github.com/mitsuhiko/jinja2.git#egg=Jinja2 ``` -------------------------------- ### Get a Single User Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Retrieve details for a specific user by their ID. Returns 404 if permission is denied to prevent user enumeration. ```bash # Get a single user (returns 404 when permission is denied to avoid enumeration) curl -H "Authorization: Bearer " \ "https://example.org/api/users/42" ``` -------------------------------- ### Get User Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Retrieves a single user by their ID. Returns 404 if permission is denied to prevent enumeration. ```APIDOC ## GET /users/{user_id} ### Description Retrieves a single user by their ID. Returns 404 if permission is denied to prevent enumeration. ### Method GET ### Endpoint /users/{user_id} ### Parameters #### Path Parameters - **user_id** (string) - Required - The ID of the user to retrieve. ### Response #### Success Response (200) - User object details (similar to search results but for a single user). ### Request Example ```bash curl -H "Authorization: Bearer " \ "https://example.org/api/users/42" ``` ``` -------------------------------- ### Access Services and Registries via Proxies Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Use thread-safe LocalProxy objects to access current services and the actions registry from anywhere within the application context. Example shows searching users and retrieving registered moderation callbacks. ```python from invenio_users_resources.proxies import ( current_user_resources, current_users_service, current_groups_service, current_domains_service, current_actions_registry, ) # Example: search users from a view or task with app.app_context(): result = current_users_service.search(identity, params={"q": "john"}) for hit in result.hits: print(hit["username"], hit["email"]) # Retrieve the actions registered for the "block" moderation action block_callbacks = current_actions_registry.get("block", []) print(f"Registered block callbacks: {len(block_callbacks)}") ``` -------------------------------- ### Get User Avatar Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Retrieve a user's avatar as an SVG image. ```bash # Get a user's SVG avatar curl "https://example.org/api/users/42/avatar.svg" ``` -------------------------------- ### Get a user's avatar using UsersService Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Retrieve a user's avatar. The result object contains bytes, mimetype, and etag. ```python from invenio_users_resources.proxies import current_users_service from flask_principal import Identity, ActionNeed from invenio_access.permissions import superuser_access # Assume `admin_identity` carries the administration-moderation ActionNeed admin_identity = Identity(1) admin_identity.provides.add(ActionNeed("administration-moderation")) # Get a user's avatar (returns AvatarResult with .bytes_io, .mimetype, .etag) avatar = current_users_service.read_avatar(admin_identity, id_="42") ``` -------------------------------- ### Get User Avatar Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Retrieves a user's avatar in SVG format. ```APIDOC ## GET /users/{user_id}/avatar.svg ### Description Retrieves a user's avatar in SVG format. ### Method GET ### Endpoint /users/{user_id}/avatar.svg ### Parameters #### Path Parameters - **user_id** (string) - Required - The ID of the user whose avatar to retrieve. ### Response #### Success Response (200) - SVG content of the user's avatar. ``` -------------------------------- ### Resolve Entity References with UserResolver Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Use UserResolver's internal methods to get an entity proxy and resolve it to a serialised user dictionary or SQLAlchemy model. `pick_resolved_fields` can select public fields based on an identity. ```python # Resolve a reference dict to a serialised user dict (via UserProxy) proxy = user_resolver._get_entity_proxy({"user": "42"}) resolved = proxy._resolve() # Returns User SQLAlchemy model or ghost dict # pick_resolved_fields selects public fields including avatar link from flask_principal import Identity identity = Identity(1) fields = proxy.pick_resolved_fields(identity, { "id": "42", "username": "alice", "profile": {"full_name": "Alice", "affiliations": "CERN"}, "links": {}, "active": True, }) # {"id": "42", "username": "alice", "email": "", # "profile": {"full_name": "Alice", "affiliations": "CERN"}, # "links": {"avatar": "https://..."}, "active": True, ...} ``` -------------------------------- ### Get Group Avatar Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Retrieves the SVG avatar for a group. ```APIDOC ## GET /api/groups/{id}/avatar.svg ### Description Retrieves the SVG avatar for a specific group. ### Method GET ### Endpoint /api/groups/5/avatar.svg ### Request Example ```bash curl "https://example.org/api/groups/5/avatar.svg" ``` ``` -------------------------------- ### Clone the Repository Source: https://github.com/inveniosoftware/invenio-users-resources/blob/master/CONTRIBUTING.rst Clone your forked repository locally to begin development. ```console git clone git@github.com:your_name_here/invenio-users-resources.git ``` -------------------------------- ### Initialize and Use User and Group Resolvers Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Instantiate UserResolver and GroupResolver for cross-module entity referencing. Use `matches_reference_dict` to check compatibility and `_reference_entity` to create reference dictionaries. ```python from invenio_users_resources.entity_resolvers import UserResolver, GroupResolver user_resolver = UserResolver() group_resolver = GroupResolver() # Check if a reference dict is handled by this resolver user_resolver.matches_reference_dict({"user": "42"}) # True group_resolver.matches_reference_dict({"group": "5"}) # True # Create a reference dict from an entity from invenio_accounts.models import User, Role user = User.query.get(42) ref = user_resolver._reference_entity(user) # {"user": "42"} role = Role.query.get(5) ref = group_resolver._reference_entity(role) # {"group": "5"} ``` -------------------------------- ### Run Tests and Checks Source: https://github.com/inveniosoftware/invenio-users-resources/blob/master/CONTRIBUTING.rst Execute the test suite to ensure your changes pass all tests, including code style (PEP8), documentation checks (PEP257), and building documentation. ```console ./run-tests.sh ``` -------------------------------- ### Get Group Avatar Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Retrieve the avatar associated with a specific group using its ID. ```python avatar = current_groups_service.read_avatar(admin_identity, id_="5") ``` -------------------------------- ### Create a Group Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Create a new group with a unique name, title, and description. The name has specific validation rules. ```python new_group = current_groups_service.create( admin_identity, data={"name": "curators", "title": "Curators", "description": "Curates metadata records"}, ) ``` -------------------------------- ### Create a Domain Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Create a new email domain record with specified properties like domain name, status, category, and flagged status. ```python new_domain = current_domains_service.create( admin_identity, data={ "domain": "university.edu", "status_name": "verified", "category_name": "university", "flagged": False, }, ) ``` -------------------------------- ### Commit and Push Changes Source: https://github.com/inveniosoftware/invenio-users-resources/blob/master/CONTRIBUTING.rst Stage, commit, and push your changes to your forked repository. Use a conventional commit message format for clarity. ```console git add . git commit -s -m "component: title without verbs" -m "* NEW Adds your new feature." -m "* FIX Fixes an existing issue." -m "* BETTER Improves and existing feature." -m "* Changes something that should not be visible in release notes." git push origin name-of-your-bugfix-or-feature ``` -------------------------------- ### Get a group's SVG avatar via REST API Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Retrieve the SVG avatar for a specific group. ```bash curl "https://example.org/api/groups/5/avatar.svg" ``` -------------------------------- ### Admin: Create User Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Admin endpoint to create a new user. Automatically sends a password-reset email. Requires user-management permission. ```bash # Admin: create a user (sends password-reset email automatically) curl -X POST -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"email": "alice@example.org", "username": "alice", "profile": {"full_name": "Alice Smith"}}' \ "https://example.org/api/users" ``` -------------------------------- ### Register Moderation Callbacks via Entry Points Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Register custom callbacks for moderation actions (block, restore, approve) using entry points in `setup.cfg`. The callback receives user ID, a unit of work, actor ID, and additional data. ```python # Register a custom callback via entry points in setup.cfg: # [options.entry_points] # invenio_users_resources.moderation.actions = # block = mypackage.moderation:on_user_blocked # mypackage/moderation.py from invenio_records_resources.services.uow import UnitOfWork def on_user_blocked(user_id, uow: UnitOfWork, actor_id=None, **data): """Tombstone all records owned by the blocked user. :param user_id: ID of the blocked user. :param uow: Shared unit of work — register operations here. :param actor_id: ID of the moderator who triggered the block. :param data: Free-form context from the block request body (e.g. removal_reason_id, note). """ removal_reason = data.get("removal_reason_id", "unspecified") # ... tombstone records, communities etc. using uow ... pass ``` -------------------------------- ### Define Permission Policies for Users, Groups, and Domains Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Utilize pre-defined permission policies like UsersPermissionPolicy, GroupsPermissionPolicy, and DomainPermissionPolicy. These policies can be extended or replaced via service configuration to enforce granular access control. ```python from invenio_users_resources.services.permissions import ( UsersPermissionPolicy, GroupsPermissionPolicy, DomainPermissionPolicy, ) # UsersPermissionPolicy — highlights: # can_create → UserManager | SystemProcess # can_read → UserManager | (public profile → AuthenticatedUser | Self) # can_search → AuthenticatedUser | SystemProcess # can_manage → UserManager (PreventSelf) | SystemProcess [moderation actions] # can_search_all → UserManager | SystemProcess # can_impersonate → SuperAdmin (IfSuperAdmin) | UserManager; always PreventSelf # can_read_email → UserManager | (public email → AuthenticatedUser | Self) # can_read_details → UserManager | Self | SystemProcess # GroupsPermissionPolicy — highlights: # can_read → GroupsEnabled + (unmanaged → AuthenticatedUser | GroupManager) # can_create → ProtectedGroupIdentifiers + GroupManager | SystemProcess # can_update → ProtectedGroupIdentifiers + (unmanaged → DenyAll | GroupManager) # can_delete → ProtectedGroupIdentifiers + (unmanaged → DenyAll | GroupManager) # Override in custom config: from invenio_records_resources.services.base.config import ConfiguratorMixin from invenio_records_resources.services import RecordServiceConfig class CustomUsersServiceConfig(UsersServiceConfig): permission_policy_cls = MyCustomPermissionPolicy ``` -------------------------------- ### Create a domain entry via REST API Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Add a new domain entry. The 'domain' field is normalized to lowercase and is create-only. Requires 'user-management' permission. ```bash curl -X POST -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"domain": "spammer.net", "status_name": "blocked", "flagged": true, "flagged_source": "manual", "category_name": "spammer", "org": [{"pid": "ror:123", "name": "Evil Corp", "props": {"country": "XX"}}] }' \ "https://example.org/api/domains" ``` -------------------------------- ### UsersService Operations Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Demonstrates various operations available through the UsersService, such as creating users, performing moderation actions, checking impersonation capabilities, and rebuilding search indexes. ```APIDOC ## Create User ### Description Creates a new user account. This action triggers a password-reset email to the user. ### Method POST (implied) ### Endpoint N/A (Service method call) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **email** (string) - Required - The email address of the new user. - **username** (string) - Required - The username for the new user. - **profile** (object) - Optional - User profile information. - **full_name** (string) - Optional - The full name of the user. ### Request Example ```python current_users_service.create( admin_identity, data={ "email": "bob@example.org", "username": "bob", "profile": {"full_name": "Bob Builder"}, }, ) ``` ## Moderation Actions ### Description Performs moderation actions on user accounts, including blocking, restoring, approving, deactivating, and activating users. These actions may involve acquiring locks and scheduling callbacks. ### Method POST (implied) ### Endpoint N/A (Service method call) ### Parameters #### Path Parameters - **id** (string) - Required - The ID of the user to perform the action on. #### Query Parameters None #### Request Body - **removal_reason_id** (string) - Required for block - The ID of the reason for blocking the user. - **note** (string) - Optional - A note providing additional details for the action. ### Request Example ```python # Block user current_users_service.block( admin_identity, id_="99", data={"removal_reason_id": "spam", "note": "Repeat spammer"}, ) # Restore user current_users_service.restore(admin_identity, id_="99") # Approve user current_users_service.approve(admin_identity, id_="55") # Deactivate user current_users_service.deactivate(admin_identity, id_="77") # Activate user current_users_service.activate(admin_identity, id_="77") ``` ## Check Impersonation Capability ### Description Checks if the current identity has the capability to impersonate a specific user. ### Method GET (implied) ### Endpoint N/A (Service method call) ### Parameters #### Path Parameters - **id** (string) - Required - The ID of the user to check impersonation for. #### Query Parameters None #### Request Body None ### Request Example ```python user_model = current_users_service.can_impersonate(admin_identity, id_="42") ``` ## Rebuild Search Index ### Description Rebuilds the full search index for users. The process yields results in batches of 1000. ### Method POST (implied) ### Endpoint N/A (Service method call) ### Parameters None ### Request Example ```python current_users_service.rebuild_index(admin_identity) ``` ``` -------------------------------- ### Create a group via REST API Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Create a new group with specified name, title, and description. Requires user-management permission. The name must follow a specific pattern. ```bash curl -X POST -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"name": "reviewers", "title": "Reviewers", "description": "Handles record reviews (max 255 chars)"}' \ "https://example.org/api/groups" ``` -------------------------------- ### Push Branch to GitHub Source: https://github.com/inveniosoftware/invenio-users-resources/blob/master/docs/contributing.md Push your local development branch to your forked repository on GitHub. ```bash git push origin name-of-your-bugfix-or-feature ``` -------------------------------- ### Load and Normalize Domain Data with DomainSchema Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Use DomainSchema to load and normalize user-provided domain data, converting domain names to lowercase and status names to integer representations. ```python domain_schema = DomainSchema() data, errors = domain_schema.load({ "domain": "EXAMPLE.COM", # becomes "example.com" "status_name": "verified", # becomes status=2 (DomainStatus.verified) "flagged": False, "org": [{"pid": "ror:456", "name": "Example University"}] }) ``` -------------------------------- ### Create Domain Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Creates a new domain entry. The domain field is create-only and is normalized to lowercase. Requires 'user-management' permission. ```APIDOC ## POST /api/domains ### Description Creates a new domain entry. ### Method POST ### Endpoint /api/domains ### Parameters #### Request Body - **domain** (string) - Required - The domain name (create-only, normalized to lowercase). - **status_name** (string) - Optional - The status of the domain. - **flagged** (boolean) - Optional - Indicates if the domain is flagged. - **flagged_source** (string) - Optional - The source of the flagging. - **category_name** (string) - Optional - The category of the domain. - **org** (array) - Optional - Organization details associated with the domain. - **pid** (string) - Required - Organization PID. - **name** (string) - Required - Organization name. - **props** (object) - Optional - Additional properties. - **country** (string) - Optional - Country code. ### Request Example ```bash curl -X POST -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"domain": "spammer.net", "status_name": "blocked", "flagged": true, "flagged_source": "manual", "category_name": "spammer", "org": [{"pid": "ror:123", "name": "Evil Corp", "props": {"country": "XX"}}] }' \ "https://example.org/api/domains" ``` ### Response #### Success Response (201) - Created domain JSON object. ``` -------------------------------- ### Admin: Create User Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Admin endpoint to create a new user. Automatically sends a password-reset email. ```APIDOC ## POST /users ### Description Admin endpoint to create a new user. Automatically sends a password-reset email. ### Method POST ### Endpoint /users ### Request Body - **email** (string) - Required - The email address of the new user. - **username** (string) - Required - The username for the new user. - **profile** (object) - Optional - User profile information. - **full_name** (string) - Optional - The full name of the user. ### Request Example ```bash curl -X POST -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"email": "alice@example.org", "username": "alice", "profile": {"full_name": "Alice Smith"}}' \ "https://example.org/api/users" ``` ### Response #### Success Response (201) - Created user JSON object. ``` -------------------------------- ### Dump SystemUserSchema for System Users Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Employ SystemUserSchema to serialize data for system-level users, ensuring a consistent format. ```python sys_user = SystemUserSchema().dump({}) # {"id": "system", "username": "System", "email": "noreply@inveniosoftware.org"} ``` -------------------------------- ### Admin: Search All Users Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Admin endpoint to search all users, including inactive and blocked ones. Requires user-management permission. Supports filtering by domain and status, and sorting. ```bash # Admin: search ALL users including inactive/blocked (requires user-management permission) curl -H "Authorization: Bearer " \ "https://example.org/api/users/all?q=domain:example.org&is_blocked=true&sort=newest" ``` -------------------------------- ### GroupsService Operations Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Provides documentation for the GroupsService, detailing how to search, read, create, update, delete, and manage avatars for groups, as well as rebuilding their search index. ```APIDOC ## Search Groups ### Description Searches for groups based on provided parameters. ### Method GET (implied) ### Endpoint N/A (Service method call) ### Parameters #### Path Parameters None #### Query Parameters - **q** (string) - Optional - Query string for searching groups. - **sort** (string) - Optional - Field to sort the results by. - **page** (integer) - Optional - Page number for pagination. - **size** (integer) - Optional - Number of results per page. ### Request Example ```python result = current_groups_service.search( admin_identity, params={"q": "editors", "sort": "name", "page": 1, "size": 20}, ) ``` ## Read Group ### Description Reads a single group by its ID. ### Method GET (implied) ### Endpoint N/A (Service method call) ### Parameters #### Path Parameters - **id** (string) - Required - The ID of the group to read. #### Query Parameters None ### Request Example ```python group_item = current_groups_service.read(admin_identity, id_="5") print(group_item.to_dict()) ``` ## Create Group ### Description Creates a new group. The group name must be unique and follow specific naming conventions. ### Method POST (implied) ### Endpoint N/A (Service method call) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **name** (string) - Required - The unique name of the group (e.g., `[A-Za-z][A-Za-z0-9_-]{0,79}`). - **title** (string) - Required - The display title of the group. - **description** (string) - Optional - A description for the group. ### Request Example ```python new_group = current_groups_service.create( admin_identity, data={"name": "curators", "title": "Curators", "description": "Curates metadata records"}, ) ``` ## Update Group ### Description Updates an existing group. Supports partial updates, meaning only provided fields will be modified. ### Method PUT (implied) ### Endpoint N/A (Service method call) ### Parameters #### Path Parameters - **id** (string) - Required - The ID of the group to update. #### Query Parameters None #### Request Body - **title** (string) - Optional - The updated display title of the group. - **description** (string) - Optional - The updated description for the group. ### Request Example ```python updated_group = current_groups_service.update( admin_identity, id_="5", data={"title": "Senior Editors", "description": "Updated description"}, ) ``` ## Delete Group ### Description Deletes a group by its ID. ### Method DELETE (implied) ### Endpoint N/A (Service method call) ### Parameters #### Path Parameters - **id** (string) - Required - The ID of the group to delete. #### Query Parameters None ### Request Example ```python current_groups_service.delete(admin_identity, id_="5") ``` ## Read Group Avatar ### Description Retrieves the avatar for a specific group. ### Method GET (implied) ### Endpoint N/A (Service method call) ### Parameters #### Path Parameters - **id** (string) - Required - The ID of the group whose avatar to read. #### Query Parameters None ### Request Example ```python avatar = current_groups_service.read_avatar(admin_identity, id_="5") ``` ## Rebuild Group Search Index ### Description Rebuilds the search index for groups. ### Method POST (implied) ### Endpoint N/A (Service method call) ### Parameters None ### Request Example ```python current_groups_service.rebuild_index(admin_identity) ``` ``` -------------------------------- ### Activate or deactivate a user via API Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Endpoints to toggle the active status of a user account. Requires an admin token. ```bash curl -X POST -H "Authorization: Bearer " \ "https://example.org/api/users/42/activate" ``` ```bash curl -X POST -H "Authorization: Bearer " \ "https://example.org/api/users/42/deactivate" ``` -------------------------------- ### Create Group Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Creates a new group. The group name must follow the pattern [A-Za-z][A-Za-z0-9_-]{0,79}. Requires user-management permission. ```APIDOC ## POST /api/groups ### Description Creates a new group. ### Method POST ### Endpoint /api/groups ### Parameters #### Request Body - **name** (string) - Required - The name of the group. Must match [A-Za-z][A-Za-z0-9_-]{0,79}. - **title** (string) - Optional - The title of the group. - **description** (string) - Optional - The description of the group (max 255 chars). ### Request Example ```bash curl -X POST -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"name": "reviewers", "title": "Reviewers", "description": "Handles record reviews (max 255 chars)"}' \ "https://example.org/api/groups" ``` ### Response #### Success Response (201) - Created group JSON object. ``` -------------------------------- ### Search Active Users (Public Endpoint) Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Search for active and confirmed users using a public endpoint. Requires an authenticated user and returns a paginated list of users. ```bash # Search active, confirmed users (public endpoint, requires authenticated user) curl -H "Authorization: Bearer " \ "https://example.org/api/users?q=john&sort=bestmatch&page=1&size=10" ``` -------------------------------- ### Moderation: Approve User Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Approve (verify) a user's account. Requires admin privileges. ```bash # Moderation: approve (verify) a user curl -X POST -H "Authorization: Bearer " \ "https://example.org/api/users/42/approve" ``` -------------------------------- ### Commit Changes with Conventional Commits Source: https://github.com/inveniosoftware/invenio-users-resources/blob/master/docs/contributing.md Commit your changes using a structured format that includes a type (NEW, FIX, BETTER) and a descriptive title and body. This helps in generating release notes. ```bash git add . git commit -s -m "component: title without verbs" -m "* NEW Adds your new feature." -m "* FIX Fixes an existing issue." -m "* BETTER Improves and existing feature." -m "* Changes something that should not be visible in release notes." ``` -------------------------------- ### Search all users (admin only) using UsersService Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Search for all users, including blocked and unconfirmed accounts. Requires an identity with 'administration-moderation' permission. ```python from invenio_users_resources.proxies import current_users_service from flask_principal import Identity, ActionNeed from invenio_access.permissions import superuser_access # Assume `admin_identity` carries the administration-moderation ActionNeed admin_identity = Identity(1) admin_identity.provides.add(ActionNeed("administration-moderation")) # Search ALL users (admin only, includes blocked/unconfirmed) result_all = current_users_service.search_all( admin_identity, params={"q": "domain:example.org", "is_blocked": True}, ) ``` -------------------------------- ### Dump UserGhostSchema for Deleted Users Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Utilize UserGhostSchema to serialize user data into a ghost/system/anonymous format, typically for deleted users. ```python ghost = UserGhostSchema().dump({"id": "deleted-user-id"}) # {"id": "deleted-user-id", "username": "Deleted user", # "profile": {"full_name": "Deleted user"}, "is_ghost": True} ``` -------------------------------- ### UsersService: Search All Users Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Searches for all users, including blocked and unconfirmed accounts. Requires administrator privileges. ```APIDOC ## UsersService.search_all ### Description Searches for all users, including those who are blocked or unconfirmed. This operation is restricted to administrators. ### Method Signature `current_users_service.search_all(identity, params)` ### Parameters - **identity** (Identity) - The identity of the administrator performing the search. - **params** (dict) - Dictionary of search parameters. - **q** (string) - Optional - Query string for searching users (e.g., 'domain:example.org'). - **is_blocked** (boolean) - Optional - Filter to include only blocked users. ### Request Example ```python from invenio_users_resources.proxies import current_users_service from flask_principal import Identity, ActionNeed # Assume admin_identity carries the administration-moderation ActionNeed admin_identity = Identity(1) admin_identity.provides.add(ActionNeed("administration-moderation")) result_all = current_users_service.search_all( admin_identity, params={"q": "domain:example.org", "is_blocked": True}, ) ``` ``` -------------------------------- ### Configure Invenio-Users-Resources Settings Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Update the Flask application's configuration with various settings for Invenio-Users-Resources. These include avatar colors, service schemas, search options, moderation timeouts, protected group names, and group feature enablement. ```python app.config.update({ # Avatar fill colours (rotated by user.id % len) "USERS_RESOURCES_AVATAR_COLORS": ["#e06055", "#ff8a65", ...], # Marshmallow schema for the users service (swappable) "USERS_RESOURCES_SERVICE_SCHEMA": UserSchema, # User search sort options exposed to public search "USERS_RESOURCES_SEARCH": { "sort": ["bestmatch", "username", "email", "domain", "newest", "oldest", "updated"], "facets": ["status", "visibility", "domain_status", "domain", "affiliations"], }, # Domain search sort options "USERS_RESOURCES_DOMAINS_SEARCH": { "sort": ["bestmatch", "domain", "newest", "num-users", "num-active", ...], "facets": ["status", "flagged", "category", "organisation", "tld"], }, # Moderation distributed lock timeouts (seconds) "USERS_RESOURCES_MODERATION_LOCK_DEFAULT_TIMEOUT": 30, "USERS_RESOURCES_MODERATION_LOCK_RENEWAL_TIMEOUT": 120, # Protected group names that cannot be mutated via API "USERS_RESOURCES_PROTECTED_GROUP_NAMES": [ "admin", "administration", "superuser-access", "administration-moderation" ], # Enable/disable group features entirely "USERS_RESOURCES_GROUPS_ENABLED": True, # Domain org props schema (for custom country/property validation) "USERS_RESOURCES_DOMAINS_ORG_SCHEMA": OrgPropsSchema, }) ``` -------------------------------- ### Search groups via REST API Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Search for groups using query parameters and sorting. Requires authentication and USERS_RESOURCES_GROUPS_ENABLED=True. ```bash curl -H "Authorization: Bearer " \ "https://example.org/api/groups?q=editors&sort=name" ``` -------------------------------- ### Create a New Branch Source: https://github.com/inveniosoftware/invenio-users-resources/blob/master/CONTRIBUTING.rst Create a new branch for your bug fixes or new features. This isolates your changes from the main development line. ```console git checkout -b name-of-your-bugfix-or-feature ``` -------------------------------- ### Impersonate a user via API Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Allows a superadmin to impersonate another user. Requires a superadmin token. ```bash curl -X POST -H "Authorization: Bearer " \ "https://example.org/api/users/42/impersonate" ``` -------------------------------- ### Implement Notification Recipient Generators and Filters Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Customize notification recipients using UserRecipient, EmailRecipient, and IfEmailRecipient for generating recipients based on context. Filter recipients using UserPreferencesRecipientFilter to respect user notification preferences. ```python from invenio_users_resources.notifications.generators import ( UserRecipient, EmailRecipient, IfEmailRecipient, IfUserRecipient, ) from invenio_users_resources.notifications.filters import UserPreferencesRecipientFilter # UserRecipient: extract a user dict from notification context by dotted key # and add it to the recipients dict keyed by user id. class MyNotificationBuilder: recipient_generators = [ UserRecipient("request.created_by"), # context["request"]["created_by"] IfEmailRecipient( key="invitation.recipient", then_=[EmailRecipient("invitation.recipient")], # plain email string else_=[UserRecipient("invitation.recipient")], # user dict ), IfUserRecipient( key="ticket.assignee", then_=[UserRecipient("ticket.assignee")], else_=[], ), ] recipient_filters = [ # Removes recipients who have disabled notifications in their preferences UserPreferencesRecipientFilter(), ] # UserPreferencesRecipientFilter inspects recipient.data["preferences"]["notifications"]["enabled"] # and silently drops recipients where it is False. from invenio_notifications.models import Recipient recipients = { "42": Recipient(data={ "id": "42", "preferences": {"notifications": {"enabled": False}}, }), "99": Recipient(data={ "id": "99", "preferences": {"notifications": {"enabled": True}}, }), } filtered = UserPreferencesRecipientFilter()(notification=None, recipients=recipients) # filtered == {"99": Recipient(...)} — user 42 dropped ``` -------------------------------- ### Search Groups with GroupsService Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Search for groups using the GroupsService. Supports query parameters for filtering and sorting. ```python result = current_groups_service.search( admin_identity, params={"q": "editors", "sort": "name", "page": 1, "size": 20}, ) ``` -------------------------------- ### Configure Moderation Lock Timeouts Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Configure the default lock acquisition timeout and the renewal timeout for `ModerationMutex` via Flask application configuration. ```python # Configuration app.config["USERS_RESOURCES_MODERATION_LOCK_DEFAULT_TIMEOUT"] = 30 # seconds app.config["USERS_RESOURCES_MODERATION_LOCK_RENEWAL_TIMEOUT"] = 120 # seconds ``` -------------------------------- ### Read a domain via REST API Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Retrieve details for a specific domain. Requires the 'user-management' permission. ```bash curl -H "Authorization: Bearer " \ "https://example.org/api/domains/spammer.net" ``` -------------------------------- ### Initialize InvenioUsersResources Extension Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Initialize the InvenioUsersResources extension within your Flask application. Access extension attributes like services and registries after initialization. ```python from flask import Flask from invenio_users_resources.ext import InvenioUsersResources app = Flask(__name__) # Standard Invenio-style initialisation (extension is also registered via # entry points automatically when using invenio-base): ext = InvenioUsersResources(app) # Access extension attributes after init: users_service = app.extensions["invenio-users-resources"].users_service groups_service = app.extensions["invenio-users-resources"].groups_service domains_service = app.extensions["invenio-users-resources"].domains_service actions_registry = app.extensions["invenio-users-resources"].actions_registry ``` -------------------------------- ### Search Domains with DomainsService Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Search for email domains using the DomainsService. Supports query parameters for filtering and sorting by user statistics. ```python result = current_domains_service.search( admin_identity, params={"q": "gmail", "sort": "num-users", "page": 1, "size": 30}, ) ``` -------------------------------- ### User Management Operations Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Perform various administrative actions on users, including creation, moderation, and impersonation checks. Index rebuilding is also supported. ```python new_user = current_users_service.create( admin_identity, data={ "email": "bob@example.org", "username": "bob", "profile": {"full_name": "Bob Builder"}, }, ) ``` ```python current_users_service.block( admin_identity, id_="99", data={"removal_reason_id": "spam", "note": "Repeat spammer"}, ) ``` ```python current_users_service.restore(admin_identity, id_="99") ``` ```python current_users_service.approve(admin_identity, id_="55") # marks user as verified ``` ```python current_users_service.deactivate(admin_identity, id_="77") ``` ```python current_users_service.activate(admin_identity, id_="77") ``` ```python user_model = current_users_service.can_impersonate(admin_identity, id_="42") ``` ```python current_users_service.rebuild_index(admin_identity) ``` -------------------------------- ### Search domains via REST API Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Search for domains with advanced filtering, sorting, and faceting. Requires the 'user-management' permission. ```bash curl -H "Authorization: Bearer " \ "https://example.org/api/domains?q=gmail&sort=num-users&f=status:new" ``` -------------------------------- ### Restore a blocked user via API Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Use this endpoint to restore a user account that has been blocked. Requires an admin token. ```bash curl -X POST -H "Authorization: Bearer " \ "https://example.org/api/users/42/restore" ``` -------------------------------- ### Search public users using UsersService Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Search for active and confirmed users. Requires an identity with 'administration-moderation' permission. ```python from invenio_users_resources.proxies import current_users_service from flask_principal import Identity, ActionNeed from invenio_access.permissions import superuser_access # Assume `admin_identity` carries the administration-moderation ActionNeed admin_identity = Identity(1) admin_identity.provides.add(ActionNeed("administration-moderation")) # Search public (active + confirmed) users result = current_users_service.search( admin_identity, params={"q": "alice", "sort": "bestmatch", "page": 1, "size": 5}, ) for item in result.hits: print(item["id"], item["username"]) ``` -------------------------------- ### Admin: Search All Users Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Admin endpoint to search all users, including inactive and blocked ones. Requires 'user-management' permission. ```APIDOC ## GET /users/all ### Description Admin endpoint to search all users, including inactive and blocked ones. Requires 'user-management' permission. ### Method GET ### Endpoint /users/all ### Query Parameters - **q** (string) - Optional - Search query string (e.g., 'domain:example.org'). - **is_blocked** (boolean) - Optional - Filter by blocked status (true/false). - **sort** (string) - Optional - Field to sort results by (e.g., 'newest'). ### Response #### Success Response (200) - Similar to the public user search, but includes all users and potentially more fields. ### Request Example ```bash curl -H "Authorization: Bearer " \ "https://example.org/api/users/all?q=domain:example.org&is_blocked=true&sort=newest" ``` ``` -------------------------------- ### Marshmallow Schemas for Users and Groups Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Utilize Marshmallow schemas for data validation. UserSchema supports field-level permission control for sensitive fields, while GroupSchema enforces naming conventions. ```python from invenio_users_resources.services.schemas import ( UserSchema, GroupSchema, DomainSchema, UserGhostSchema, AnonymousSchema, SystemUserSchema, NotificationPreferences, ) ``` ```python schema = UserSchema() result = schema.dump({ "id": "42", "email": "alice@example.org", # only dumped with "read_email" permission "username": "alice", "profile": {"full_name": "Alice"}, "preferences": {"visibility": "public", "email_visibility": "restricted"}, "active": True, }) ``` ```python group_schema = GroupSchema() data, errors = group_schema.load({"name": "my-group", "title": "My Group", "description": "A group"}) ``` -------------------------------- ### Read a single user using UsersService Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Retrieve details for a specific user by their ID. Requires an identity with 'administration-moderation' permission. ```python from invenio_users_resources.proxies import current_users_service from flask_principal import Identity, ActionNeed from invenio_access.permissions import superuser_access # Assume `admin_identity` carries the administration-moderation ActionNeed admin_identity = Identity(1) admin_identity.provides.add(ActionNeed("administration-moderation")) # Read a single user user_item = current_users_service.read(admin_identity, id_="42") print(user_item.to_dict()) ``` -------------------------------- ### Use ModerationMutex as a Context Manager Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Employ ModerationMutex as a context manager for automatic lock acquisition, renewal, and release. This is used internally by tasks like `execute_moderation_actions`. ```python # Context-manager usage with renewal (used inside execute_moderation_actions task) with ModerationMutex(user_id) as lock: lock.acquire_or_renew(timeout=120) # renew for 120 s # ... perform long-running callbacks ... # Lock is released on exit ``` -------------------------------- ### Execute Celery Tasks for User and Domain Management Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Use these tasks for asynchronous operations like reindexing, unindexing, and executing moderation actions for users, as well as reindexing, deleting, and importing domain blocklists. ```python from invenio_users_resources.services.users.tasks import ( reindex_users, unindex_users, execute_moderation_actions, execute_reset_password_email, ) from invenio_users_resources.services.domains.tasks import ( reindex_domains, delete_domains, import_domain_blocklist, ) # Bulk reindex a list of user IDs reindex_users.delay([1, 2, 3, 42]) # Bulk remove users from search index unindex_users.delay([99]) # Execute moderation callbacks for a given action execute_moderation_actions.delay( user_id=42, action="restore", actor_id=1, data={}, ) # Send password-reset email to a newly admin-created user execute_reset_password_email.delay( user_id=42, token="", reset_link="https://example.org/reset/..." ) # Reindex specific domains reindex_domains.delay(["gmail.com", "yahoo.com"]) # Remove domains from index delete_domains.delay(["old-domain.net"]) # Import a domain blocklist from a URL (marks domains as blocked+flagged) import_domain_blocklist.delay( url="https://raw.githubusercontent.com/.../blocklist.txt", source_name="github-blocklist-2024", ) ``` -------------------------------- ### Read Domain Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Retrieves details of a single domain. Accessible only to users with the 'user-management' permission. ```APIDOC ## GET /api/domains/{domain_id} ### Description Retrieves the details of a specific domain. ### Method GET ### Endpoint /api/domains/spammer.net ### Request Example ```bash curl -H "Authorization: Bearer " \ "https://example.org/api/domains/spammer.net" ``` ``` -------------------------------- ### UsersService: Read User Source: https://context7.com/inveniosoftware/invenio-users-resources/llms.txt Retrieves details of a single user by their ID. ```APIDOC ## UsersService.read ### Description Retrieves the details of a specific user using their unique identifier. ### Method Signature `current_users_service.read(identity, id_)` ### Parameters - **identity** (Identity) - The identity of the user performing the read operation. - **id_** (string) - The unique identifier of the user to retrieve. ### Request Example ```python from invenio_users_resources.proxies import current_users_service from flask_principal import Identity, ActionNeed # Assume admin_identity carries the administration-moderation ActionNeed admin_identity = Identity(1) admin_identity.provides.add(ActionNeed("administration-moderation")) user_item = current_users_service.read(admin_identity, id_="42") print(user_item.to_dict()) ``` ### Response - **User Object** (dict) - A dictionary containing the user's details. - **id** (string) - The user's unique identifier. - **username** (string) - The user's username. - **email** (string) - The user's email address. - **active** (boolean) - Indicates if the user account is active. - **verified** (boolean) - Indicates if the user account is verified. - **blocked** (boolean) - Indicates if the user account is blocked. ### Response Example ```json { "id": "42", "username": "alice", "email": "alice@example.org", "active": True, "verified": True, "blocked": False, ... } ``` ```