Esempio n. 1
0
def get_username(strategy, details, backend, user=None, *args, **kwargs):
    """Check if the username already exists. Raise an exception if yes."""
    if "username" not in backend.setting("USER_FIELDS", USER_FIELDS):
        return None

    storage = strategy.storage

    if user:
        # The user already exists return its username.
        return {"username": storage.user.get_username(user)}

    email_as_username = strategy.setting("USERNAME_IS_FULL_EMAIL", False)

    if email_as_username and details.get("email"):
        username = details["email"]
    elif details.get("username"):
        username = details["username"]
    else:
        raise AuthFailed(backend, "Failed to retrieve a valid username.")

    if storage.user.user_exists(username=username):
        raise AuthAlreadyAssociated(
            backend, f"user with username {username} already exists."
        )

    return {"username": username}
Esempio n. 2
0
def verify_username(strategy, backend, details, user=None, **kwargs):
    """Verified whether username is still free.

    It can happen that user has registered several times or other user has
    taken the username meanwhile.
    """
    if user or 'username' not in details:
        return
    if User.objects.filter(username__iexact=details['username']).exists():
        raise AuthAlreadyAssociated(backend, 'Username exists')
Esempio n. 3
0
def verify_username(strategy, backend, details, user=None, **kwargs):
    """Verified whether username is still free.

    It can happen that user has registered several times or other user has
    taken the username meanwhile.
    """
    if not user and 'username' in details:
        if User.objects.filter(username__iexact=details['username']).exists():
            raise AuthAlreadyAssociated(
                backend,
                _('This username is already taken. Please choose another.'))
Esempio n. 4
0
def ensure_valid(strategy, backend, user, registering_user, weblate_action,
                 weblate_expires, new_association, details, **kwargs):
    """Ensure the activation link is still."""

    # Didn't the link expire?
    if weblate_expires < time.time():
        raise AuthMissingParameter(backend, 'expires')

    # We allow password reset for unauthenticated users
    if weblate_action == 'reset':
        if strategy.request.user.is_authenticated:
            messages.warning(
                strategy.request,
                _('You can not complete password reset while logged in!'),
            )
            messages.warning(strategy.request,
                             _('The registration link has been invalidated.'))
            raise AuthMissingParameter(backend, 'user')
        return

    # Add e-mail/register should stay on same user
    if user and user.is_authenticated:
        current_user = user.pk
    else:
        current_user = None

    if current_user != registering_user:
        if registering_user is None:
            messages.warning(
                strategy.request,
                _('You can not complete registration while logged in!'),
            )
        else:
            messages.warning(
                strategy.request,
                _('You can confirm your registration only while logged in!'),
            )
        messages.warning(strategy.request,
                         _('The registration link has been invalidated.'))

        raise AuthMissingParameter(backend, 'user')

    # Verify if this mail is not used on other accounts
    if new_association:
        same = VerifiedEmail.objects.filter(email=details['email'])
        if user:
            same = same.exclude(social__user=user)

        if same.exists():
            AuditLog.objects.create(same[0].social.user, strategy.request,
                                    'connect')
            raise AuthAlreadyAssociated(backend, 'E-mail exists')
Esempio n. 5
0
def social_user(backend, uid, user=None, *args, **kwargs):
    provider = backend.name
    social = backend.strategy.storage.user.get_social_auth(provider, uid)
    if social:
        if user and social.user != user:
            msg = 'This account is already in use.'
            raise AuthAlreadyAssociated(backend, msg)
        elif not user:
            user = social.user
    return {'social': social,
            'user': user,
            'is_new': user is None,
            'new_association': social is None}
Esempio n. 6
0
def selective_social_user(backend, uid, user=None, *args, **kwargs):
    provider = backend.name
    social = backend.strategy.storage.user.get_social_auth(provider, uid)
    if social:
        if user and social.user != user:
            if backend.name not in ('twitter', 'facebook'):
                msg = 'This {0} account is already in use.'.format(provider)
                raise AuthAlreadyAssociated(backend, msg)
        elif not user:
            user = social.user
    return {'social': social,
            'user': user,
            'is_new': user is None,
            'new_association': False}
Esempio n. 7
0
    def test_initialize_engine_object_AuthAlreadyAssociated(self):
        input_engine = 'tethys_dataset_services.engines.HydroShareDatasetEngine'
        input_end_point = 'http://localhost/api/3/action'

        mock_user = mock.MagicMock()
        mock_request = mock.MagicMock(user=mock_user, path='path')

        mock_social = mock.MagicMock()

        mock_user.social_auth.get.side_effect = [AuthAlreadyAssociated(mock.MagicMock(), mock.MagicMock()), mock_social]

        self.assertRaises(AuthAlreadyAssociated, initialize_engine_object, engine=input_engine,
                          endpoint=input_end_point, request=mock_request)

        mock_user.social_auth.get.assert_called_once_with(provider='hydroshare')
Esempio n. 8
0
def social_user(backend, uid, user=None, *args, **kwargs):
    provider = backend.name

    social = backend.strategy.storage.user.get_social_auth(provider, uid)

    if social:
        # can happen when user has multiple accounts with same email (apply email uniqueness strictly)
        if user and social.user != user:
            msg = 'This {0} account is already in use.'.format(provider)
            raise AuthAlreadyAssociated(backend, msg)
        elif not user:
            user = social.user
    return {'social': social,
            'user': user,
            'is_new': user is None,
            'new_association': social is None}
Esempio n. 9
0
def social_user(backend, uid, user=None, *args, **kwargs):
    """
    Search for UserSocialAuth.
    """
    provider = backend.name
    social = backend.strategy.storage.user.get_social_auth(provider, uid)
    if social:
        if user and social.user != user and not user.groups.filter(name='Temporary').exists():
            if not_allowed_to_merge(user, social.user):
                msg = 'Merge aborted due to providers intersection.'
                raise AuthAlreadyAssociated(backend, msg)
        elif not user or user.groups.filter(name='Temporary').exists():
            user = social.user
    return {'social': social,
            'user': user,
            'is_new': user is None,
            'new_association': False}
Esempio n. 10
0
def associate_by_email(*args, **kwargs):
    """Check if a user with this email already exists. If they do, don't create an account."""
    backend = kwargs['backend']
    if backend.name in ['google-oauth2', 'github'] or kwargs.get('user'):
        # We provide and exception here for users upgrading.
        return super_associate_by_email(*args, **kwargs)

    email = kwargs['details'].get('email')

    if email:
        User = get_user_model()
        if User.objects.filter(email=email).exists():
            msg = (
                f"This email (associated with {backend.name}) from is already in use. "
                "First login with your other account and under the top right menu "
                "click add account.")

            raise AuthAlreadyAssociated(msg)
Esempio n. 11
0
def test_process_exception(rf, settings):
    """Tests that a process_exception handles auth exceptions correctly"""
    settings.DEBUG = False
    msg = "error message"
    request = rf.get(reverse("social:complete", args=("email", )))
    # social_django depends on request.sesssion, so use the middleware to set that
    SessionMiddleware().process_request(request)
    strategy = load_strategy(request)
    backend = load_backend(strategy, "email", None)
    request.social_strategy = strategy
    request.backend = backend

    middleware = SocialAuthExceptionRedirectMiddleware()
    result = middleware.process_exception(request,
                                          AuthAlreadyAssociated(backend, msg))
    assert result.status_code == status.HTTP_302_FOUND
    assert result.url == "{}?message={}&backend={}".format(
        reverse("login"), urlquote(msg), backend.name)
Esempio n. 12
0
    def test_ensure_oauth2_AuthAlreadyAssociated(self, mock_redirect, mock_reverse):
        from social_core.exceptions import AuthAlreadyAssociated

        mock_user = mock.MagicMock()

        mock_request = mock.MagicMock(user=mock_user, path='path')

        mock_redirect_url = mock.MagicMock()

        mock_reverse.return_value = mock_redirect_url

        mock_user.social_auth.get.side_effect = AuthAlreadyAssociated(mock.MagicMock(), mock.MagicMock())

        self.assertRaises(AuthAlreadyAssociated, enforced_controller, mock_request)

        mock_reverse.assert_called_once_with('social:begin', args=['hydroshare'])

        mock_redirect.assert_called_once()
Esempio n. 13
0
def social_user_uid_swap(backend, uid, user=None, *args, **kwargs):
    """
    This pipeline function migrates UserSocialAuth.uid from an email address to using the 'large int' UID,
    as provided by Google OAuth2. This is specifically intended for use where a production instance was started with
    `settings.SOCIAL_AUTH_GOOGLE_OAUTH2_USE_UNIQUE_USER_ID = False` (the default) and then was switched to `True`.
    It will transparently migrate the existing UserSocialAuth record upon login to use the correct uid, maintaining
    User foreign key associations.

    It is intended to be inserted in settings.SOCIAL_AUTH_PIPELINE after 'social_core.pipeline.social_auth.social_uid'.
    """

    provider = backend.name
    email = kwargs.get('response', {}).get('email', None)
    # logger.debug(f'social_user_lookup_and_uid_swap uid: {uid}')
    # logger.debug(f'social_user_lookup_and_uid_swap email: {email}')
    # logger.debug(f'social_user_lookup_and_uid_swap args: {args}')
    # logger.debug(f'social_user_lookup_and_uid_swap kwargs: {kwargs}')
    # logger.debug(f'social_user_lookup_and_uid_swap backend: {dir(backend)}')

    social = backend.strategy.storage.user.get_social_auth(provider, uid)
    if not social and backend.setting('USE_UNIQUE_USER_ID',
                                      False) and email is not None:
        social = backend.strategy.storage.user.get_social_auth(provider, email)
        if social:
            social.uid = uid
            social.save()

    if social:
        if user and social.user != user:
            msg = 'This account is already in use.'
            raise AuthAlreadyAssociated(backend, msg)
        elif not user:
            user = social.user
    return {
        'social': social,
        'user': user,
        'is_new': user is None,
        'new_association': social is None
    }
Esempio n. 14
0
    def process_exception(self, request, exception):
        """
        Handle exceptions raised during the authentication process.
        """
        referer_url = request.META.get('HTTP_REFERER', '')
        referer_url = urlparse(referer_url).path

        if referer_url != reverse('signin_user') and request.view_name not in [
                'auth', 'complete'
        ]:
            return super().process_exception(request, exception)

        if isinstance(exception, EoxTenantAuthException):
            new_exception = AuthFailed(
                exception.backend,
                str(exception),
            )
            LOG.error("%s", exception)
            return super().process_exception(request, new_exception)

        if isinstance(exception, IntegrityError):
            backend = getattr(request, 'backend', None)
            new_exception = AuthAlreadyAssociated(
                backend,
                "The given email address is associated with another account",
            )
            LOG.error("%s", exception)
            return super().process_exception(request, new_exception)

        if isinstance(exception, HTTPError):
            backend = getattr(request, 'backend', None)
            new_exception = AuthUnreachableProvider(
                backend,
                "Unable to connect with the external provider",
            )
            LOG.error("%s", exception)
            return super().process_exception(request, new_exception)

        return super().process_exception(request, exception)
Esempio n. 15
0
def signup(backend, strategy, is_signup=False, is_new=False, **kwargs):
    if is_signup:  # Signup
        if is_new:
            try:  # Check if already signed up or not
                user = User.objects.get(
                    email=kwargs.get('account_verified_email'))
            except User.DoesNotExist:
                return strategy.redirect(
                    reverse('account:signup-form',
                            args=(kwargs.get('current_partial').token, )))
            else:
                strategy.session_pop('account_verified_email', None)
                return {'user': user}
        else:  # User existed
            msg = _("This {} account is already registered.".format(
                backend.name))
            raise AuthAlreadyAssociated(backend, msg)
    else:  # Login
        if is_new:  # User does not exist
            raise AuthForbidden(backend)
        else:  # All is good, continue
            return None
Esempio n. 16
0
def social_user(backend, uid, user=None, *args, **kwargs):
    provider = backend.name
    unionid = kwargs.get('unionid')
    social = backend.strategy.storage.user.get_social_auth(provider, uid)
    # 如果这个uid未能找到, 需要查看他关联的unionid
    # 是否有其他微信使用
    if not social and unionid:
        social_auth_unionids = SocialAuthUnionID.objects.filter(unionid=unionid)
        for each in social_auth_unionids:
            if each.uid == uid and each.provider == provider:
                continue
            social = backend.strategy.storage.user.get_social_auth(each.provider, each.uid)
            if social:
                break
    if social:
        if user and social.user != user:
            msg = 'This {0} account is already in use.'.format(provider)
            raise AuthAlreadyAssociated(backend, msg)
        elif not user:
            user = social.user
    return {'social': social,
            'user': user,
            'is_new': user is None,
            'new_association': social is None}