def social_register(request, backend, disallowed_url="registration_disallowed"):
    backend = BACKENDS[backend]
    backend = backend()

    if request.method == "POST":
        # The user has posted a registration request
        # The access token will provide us with the information from the users' social network account
        access_token = request.POST.get("access_token", None)
        # The form data will provide us with additional information
        form = SocialRegistrationForm(request.POST)
        if form.is_valid():
            # User agreed to tos, and if he provided password, they match
            if access_token:
                # We also need to check if the additional information provided by the user is valid
                try:
                    user_info = backend.get_user_info(access_token)
                except PermissionDenied:
                    messages.add_message(
                        request,
                        messages.INFO,
                        _(
                            "You cannot use this type of "
                            + backend.name()
                            + " account to register on Seasoning. Please try another..."
                        ),
                    )
                    return redirect("/register/")
                if user_info:
                    try:
                        # Check if a user with this social id already exists
                        User.objects.get(**{backend.ID_FIELD: user_info["id"]})
                        messages.add_message(
                            request,
                            messages.INFO,
                            _(
                                "A user has already registered with your "
                                + backend.name()
                                + " account. If this is you, please log in, otherwise, contact an administrator"
                            ),
                        )
                        return redirect("/login/")
                    except User.DoesNotExist:
                        pass
                    try:
                        # Check if a user with this Facebook email is already registered
                        User.objects.get(email=user_info["email"])
                        messages.add_message(
                            request,
                            messages.INFO,
                            _(
                                "A user has already registered on Seasoning with the email in your "
                                + backend.name()
                                + ". If this is your account, would you like to connect it to your "
                                + backend.name()
                                + "account?"
                            ),
                        )
                        return redirect(backend.connect_url)
                    except User.DoesNotExist:
                        # A user with this Google email does not exist, so we will register a new one
                        pass

                    # Check if registration is allowed
                    if not backend.registration_allowed(request):
                        return redirect(disallowed_url)
                    # Register the user
                    password = form.cleaned_data["password"] or None
                    user = backend.register(
                        request,
                        social_id=user_info["id"],
                        givenname=user_info["givenname"],
                        surname=user_info["surname"],
                        email=user_info["email"],
                        date_of_birth=user_info["date_of_birth"],
                        password=password,
                    )
                    # And log him in, because we don't need to validate his information
                    user = authenticate(**{backend.ID_FIELD: user_info["id"]})
                    auth_login(request, user)
                    messages.add_message(
                        request,
                        messages.INFO,
                        _(
                            "You have successfully registered your "
                            + backend.name()
                            + " account on Seasoning. Have fun!"
                        ),
                    )
                    return redirect(home)
                # If we're here, we had a faulty access token. Set the access token to None so as not to get caught in the if condition below and display the error
                # message as expected
                access_token = None
    else:
        # User wants to register using his social account
        code = request.GET.get("code", None)

        redirect_uri = "http://" + str(get_current_site(request)) + backend.registration_url
        if code is None:
            # User has just click the 'Register with ...' button to start a social registration.
            # Redirect him to the social network, so we may get an authorization code.
            return redirect(backend.get_auth_code_url(redirect_uri=redirect_uri))
        else:
            # User has been redirected to the social network, and has come back with a code
            # We now need to exchange this code for an access token in our backend
            form = SocialRegistrationForm()

            access_token = backend.get_access_token(code, redirect_uri=redirect_uri)
    if access_token:
        # We now have an access token either by getting one with an authorization code, or by extracting it from the
        # POST parameters
        try:
            user_info = backend.get_user_info(access_token)
        except PermissionDenied:
            messages.add_message(
                request,
                messages.INFO,
                _(
                    "You cannot use this type of "
                    + backend.name()
                    + " account to register on Seasoning. Please try another..."
                ),
            )
            return redirect("/register/")

        try:
            # Check if a user with this social id already exists
            User.objects.get(**{backend.ID_FIELD: user_info["id"]})
            messages.add_message(
                request,
                messages.INFO,
                _(
                    "A user has already registered with your "
                    + backend.name()
                    + " account. If this is you, please log in, otherwise, contact an administrator"
                ),
            )
            return redirect("/login/")
        except User.DoesNotExist:
            pass
        try:
            # Check if a user with this Facebook email is already registered
            User.objects.get(email=user_info["email"])
            messages.add_message(
                request,
                messages.INFO,
                _(
                    "A user has already registered on Seasoning with the email in your "
                    + backend.name()
                    + ". If this is your account, please log in to connect it to your "
                    + backend.name()
                    + " account?"
                ),
            )
            return redirect(backend.connect_url)
        except User.DoesNotExist:
            # A user with this Google email does not exist, so we will register a new one
            pass

        context = {"backend": backend, "form": form, "access_token": access_token}
        context.update(user_info)
        if user_info:
            return render(request, "authentication/social_register.html", context)

    # If we're here, something above must have gone wrong...
    messages.add_message(
        request,
        messages.INFO,
        _("An error occurred while checking your identity with " + backend.name() + ". Please try again."),
    )
    return redirect(backend.registration_url)
Beispiel #2
0
def social_registration(request):
    name = setting('SOCIAL_AUTH_PARTIAL_PIPELINE_KEY', 'partial_pipeline')
    data = request.session.get(name)

    if not data:
        return redirect('login')

    details = data['kwargs']['details']
    response = data['kwargs']['response']

    email = details['email']
    location = None

    # Check whether email is verified
    if data['backend'] == 'google-oauth2':
        email_verified = data['kwargs']['response']['verified_email']
        link = response['link']
        picture = response['picture']
        gender = response['gender']
    elif data['backend'] == 'facebook':
        email_verified = True
        link = response['link']
        picture = response['picture']
        gender = response['gender']
        # TODO: use location to autofill form field (hometown/location);
    elif data['backend'] == 'vkontakte-oauth2':
        email_verified = False
        link = 'http://vk.com/id' + str(response['user_id'])
        picture = response['photo']
        gender = ''
        # TODO: get more data http://vk.com/developers.php?oid=-1&p=%D0%9E%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE%D0%BB%D0%B5%D0%B9_%D0%BF%D0%B0%D1%80%D0%B0%D0%BC%D0%B5%D1%82%D1%80%D0%B0_fields

    # TODO: use link, picture, gender

    # Check if account with this email already exists
    try:
        user = User.objects.get(email=email)
    except (User.DoesNotExist, User.MultipleObjectsReturned):
        pass
    else:
        if email_verified:
            return finish_social_registration(request, data, user)
        else:
            pass # TODO: what to do?

    form_params = {'email_verified': email_verified}
    if email_verified:
        form_params['email'] = email

    if request.method == 'POST':
        form = SocialRegistrationForm(request.POST, **form_params)

        if form.is_valid():
            profile = form.save()

            if email_verified:
                return finish_social_registration(request, data, profile.user)
            else:
                # TODO: redirect to registration_completed before logging in
                return finish_social_registration(request, data, profile.user)

            # TODO: if email needs to be confirmed, redirect to registration_completed or /complete/<backend>/,
            #       else - profile
            return redirect('registration_completed')
    else:
        form = SocialRegistrationForm(**form_params)

    form.initial['first_name'] = details['first_name']
    form.initial['last_name'] = details['last_name']

    if not email_verified:
        form.initial['email'] = email

    return TemplateResponse(request, 'auth/register.html', {'form': form})