def connect(request): ''' Handles the view logic around connect user - (if authenticated) connect the user - login - register ''' backend = get_registration_backend() context = RequestContext(request) assert context.get('FACEBOOK_APP_ID'), 'Please specify a facebook app id '\ 'and ensure the context processor is enabled' facebook_login = bool(int(request.REQUEST.get('facebook_login', 0))) if facebook_login: logger.info('trying to connect using facebook') graph = require_persistent_graph(request) if graph: logger.info('found a graph object') facebook = FacebookUserConverter(graph) if facebook.is_authenticated(): logger.info('facebook is authenticated') facebook_data = facebook.facebook_profile_data() #either, login register or connect the user try: action, user = connect_user(request) logger.info('Django facebook performed action: %s', action) except facebook_exceptions.IncompleteProfileError, e: #show them a registration form to add additional data warning_format = u'Incomplete profile data encountered with error %s' warn_message = warning_format % e.message send_warning(warn_message, e=e, facebook_data=facebook_data) context['facebook_mode'] = True context['form'] = e.form return render_to_response( facebook_settings.FACEBOOK_REGISTRATION_TEMPLATE, context_instance=context, ) if action is CONNECT_ACTIONS.CONNECT: #connect means an existing account was attached to facebook messages.info(request, _("You have connected your account " "to %s's facebook profile") % facebook_data['name']) elif action is CONNECT_ACTIONS.REGISTER: #hook for tying in specific post registration functionality response = backend.post_registration_redirect(request, user) #compatability for django registration backends which return tuples instead of a response #alternatively we could wrap django registration backends, but that would be hard to understand response = response if isinstance(response, HttpResponse) else redirect(response) return response else: if 'attempt' in request.GET: return next_redirect(request, next_key=['error_next', 'next'], additional_params=dict(fb_error_or_cancel=1)) else: logger.info('Facebook authentication needed for connect, ' \ 'raising an error') raise OpenFacebookException('please authenticate') #for CONNECT and LOGIN we simple redirect to the next page return next_redirect(request, default=facebook_settings.FACEBOOK_LOGIN_DEFAULT_REDIRECT)
def _register_user(request, facebook, profile_callback=None, remove_old_connections=False): ''' Creates a new user and authenticates The registration form handles the registration and validation Other data on the user profile is updates afterwards if remove_old_connections = True we will disconnect old profiles from their facebook flow ''' if not facebook.is_authenticated(): raise ValueError( 'Facebook needs to be authenticated for connect flows') # get the backend on new registration systems, or none # if we are on an older version backend = get_registration_backend() logger.info('running backend %s for registration', backend) # gets the form class specified in FACEBOOK_REGISTRATION_FORM form_class = get_form_class(backend, request) facebook_data = facebook.facebook_registration_data() data = request.POST.copy() for k, v in facebook_data.items(): if not data.get(k): data[k] = v if remove_old_connections: _remove_old_connections(facebook_data['facebook_id']) if request.REQUEST.get('force_registration_hard'): data['email'] = data['email'].replace( '@', '+test%s@' % randint(0, 1000000000)) form = form_class(data=data, files=request.FILES, initial={'ip': request.META['REMOTE_ADDR']}) if not form.is_valid(): error_message_format = u'Facebook data %s gave error %s' error_message = error_message_format % (facebook_data, form.errors) error = facebook_exceptions.IncompleteProfileError(error_message) error.form = form raise error #for new registration systems use the backends methods of saving new_user = None if backend: new_user = backend.register(request, **form.cleaned_data) #fall back to the form approach if not new_user: # For backward compatibility, if django-registration form is used try: new_user = form.save(profile_callback=profile_callback) except TypeError: new_user = form.save() signals.facebook_user_registered.send(sender=auth.models.User, user=new_user, facebook_data=facebook_data) #update some extra data not yet done by the form new_user = _update_user(new_user, facebook) # IS this the correct way for django 1.3? seems to require the backend # attribute for some reason new_user.backend = 'greenroom.apps.django_facebook_patched.auth_backends.FacebookBackend' auth.login(request, new_user) return new_user