Fetchers (User Data Retrieval)

django-suap-auth uses the Chain of Responsibility pattern to retrieve and consolidate user profile data from multiple SUAP API endpoints or external systems.

How Fetchers Work

When a user is authenticated via OAuth2, the access_token is acquired and the fetcher chain (USER_INFO_FETCHERS) is executed sequentially. Each fetcher receives the accumulated user_info dictionary and can enrich it with new data.

[Access Token] ──> Fetcher 1 (DefaultEndpointsUserInfoFetcher)
                       │ accumulated user_info
                       ▼
                   Fetcher 2 (Custom Fetcher / LDAP)
                       │ final user_info
                       ▼
                   Mapper Chain

Configuration: USER_INFO_FETCHERS

In settings.py, configure the list of fetchers in SUAP_AUTH:

SUAP_AUTH = {
    "CLIENT_ID": "your-client-id",
    "CLIENT_SECRET": "your-client-secret",
    "REDIRECT_URI": "https://your-app.com/auth/suap/callback/",
    "USER_INFO_FETCHERS": [
        "django_suap_auth.fetchers.DefaultEndpointsUserInfoFetcher",
        "my_app.fetchers.ExternalLdapUserInfoFetcher",
    ],
}

Default Fetcher: DefaultEndpointsUserInfoFetcher

The default fetcher consumes the USER_INFO_ENDPOINTS list defined in SUAP_AUTH and executes HTTP requests for each endpoint.

Supported Endpoint Formats (USER_INFO_ENDPOINTS)

1. Simple Endpoint (String)

"USER_INFO_ENDPOINTS": [
    "/api/rh/eu/",
    "/api/rh/meus-dados/",
]

Data returned at the root of JSON responses are merged directly into the root of the user_info dictionary.

2. Endpoint with Dynamic Formatting (String with {key})

"USER_INFO_ENDPOINTS": [
    "/api/rh/eu/",
    "/api/v2/alunos/{matricula}/",
]

Keys enclosed in braces {...} are substituted with existing values from user_info.

3. Specification Dictionary (dict spec)

Allows isolating responses under a namespace, extracting lists from paginated responses, or iterating over collections:

"USER_INFO_ENDPOINTS": [
    "/api/rh/eu/",
    {
        "endpoint": "/api/rh/meus-vinculos/",
        "namespace": "vinculos",   # Injected under user_info['vinculos']
        "extract_list": "results", # Extracts list from paginated 'results' field
    },
    {
        "endpoint": "/api/rh/meu-vinculo/{id}/",
        "namespace": "detalhes_vinculos",
        "for_each": "vinculos",    # Iterates over each item in user_info['vinculos']
    },
]

Creating a Custom Fetcher

To create a custom fetcher, inherit from BaseUserInfoFetcher and override the fetch method:

# my_app/fetchers.py
from django_suap_auth.fetchers import BaseUserInfoFetcher

class ExternalLdapUserInfoFetcher(BaseUserInfoFetcher):
    """Fetcher that retrieves additional information from corporate LDAP using the user's CPF."""

    def fetch(self, client, access_token, user_info=None):
        user_info = super().fetch(client, access_token, user_info)

        cpf = user_info.get("cpf")
        if cpf:
            # Query external service
            user_info["ldap_data"] = my_ldap_service.search_by_cpf(cpf)

        return user_info

Registering the Custom Fetcher

# settings.py
SUAP_AUTH = {
    # ...
    "USER_INFO_FETCHERS": [
        "django_suap_auth.fetchers.DefaultEndpointsUserInfoFetcher",
        "my_app.fetchers.ExternalLdapUserInfoFetcher",
    ],
}

Fetcher API Utility Functions

  • get_user_info_fetchers(cfg=None): instantiates and returns the list of configured fetcher objects.

  • run_user_info_fetcher_chain(client, access_token, cfg=None): runs the entire fetcher chain and returns the final user_info dictionary.