# Path: sitegate/signals.py

# 
# Path: sitegate/utils.py
# USER = get_user_model()


import logging
import requests
from typing import Optional, List, NamedTuple
from django.contrib.auth import login
from django.db import IntegrityError
from django.db.transaction import atomic
from django.http import HttpResponseRedirect, HttpResponse, HttpRequest
from django.middleware.csrf import get_token
from django.shortcuts import redirect, render
from django.urls import reverse
from django.utils import timezone
from django.utils.functional import cached_property
from etc.toolbox import get_site_url
from ...signals import sig_user_signup_success, sig_user_signup_fail
from ...utils import USER
    from django.contrib.auth.models import User  # noqa
    from ...models import RemoteRecord

    def get_user_data(self, request: HttpRequest, *, data: dict) -> Optional[UserData]:
        """Get user data from a remote.

        :param request:
        :param data: auth data

        """
        try:
            return self._get_user_data(request, data=data)

        except Exception as _:
            LOG.exception(f'{self._auth_fail_prefix} unable get user data from remote.')
            return None

    def construct_user(self, user_data: UserData) -> Optional['User']:
        """Spawns a new user instance. Return None on failure.

        :param user_data:

        """
        # try to get active (presumably with verified emails) users
        # NB: can be slow w/o index on email field if many users
        candidates = USER.objects.filter(email__in=user_data.emails, is_active=True).only('id')

        if len(candidates) == 1:
            # single candidate, let's use it.
            # in case of many candidate we won't guess, but create a new user
            return candidates[0]


# Path: sitegate/signals.py

# 
# Path: sitegate/utils.py
# USER = get_user_model()


# Path: sitegate/signin_flows/remotes/base.py
import logging
import requests
from typing import Optional, List, NamedTuple
from django.contrib.auth import login
from django.db import IntegrityError
from django.db.transaction import atomic
from django.http import HttpResponseRedirect, HttpResponse, HttpRequest
from django.middleware.csrf import get_token
from django.shortcuts import redirect, render
from django.urls import reverse
from django.utils import timezone
from django.utils.functional import cached_property
from etc.toolbox import get_site_url
from ...signals import sig_user_signup_success, sig_user_signup_fail
from ...utils import USER
    from django.contrib.auth.models import User  # noqa
    from ...models import RemoteRecord


    def get_user_data(self, request: HttpRequest, *, data: dict) -> Optional[UserData]:
        """Get user data from a remote.

        :param request:
        :param data: auth data

        """
        try:
            return self._get_user_data(request, data=data)

        except Exception as _:
            LOG.exception(f'{self._auth_fail_prefix} unable get user data from remote.')
            return None

    def construct_user(self, user_data: UserData) -> Optional['User']:
        """Spawns a new user instance. Return None on failure.

        :param user_data:

        """
        # try to get active (presumably with verified emails) users
        # NB: can be slow w/o index on email field if many users
        candidates = USER.objects.filter(email__in=user_data.emails, is_active=True).only('id')

        if len(candidates) == 1:
            # single candidate, let's use it.
            # in case of many candidate we won't guess, but create a new user
            return candidates[0]


        email_field = USER.get_email_field_name()