def test_check_connect_facebook(self): graph = get_facebook_graph(access_token='new_user') facebook = FacebookUserConverter(graph) data = facebook.facebook_registration_data() self.assertEqual(data['gender'], 'm') response = self.client.get(reverse('login:index'))
def connect_user(self): """Main functionality """ #TODO, instead of using access_token this should probably accept a facebook_graph as well user = None facebook = self.facebook_graph or get_facebook_graph(self.request, self.access_token) assert facebook.is_authenticated(), 'Facebook not authenticated' facebook_user_converter = FacebookUserConverter(facebook) facebook_data = facebook_user_converter.facebook_profile_data() force_registration = self.request.REQUEST.get('force_registration') or self.request.REQUEST.get('force_registration_hard') logger.debug('force registration is set to %s', force_registration) if self.request.user.is_authenticated() and not force_registration: action = CONNECT_ACTIONS.CONNECT user = self._connect_user(facebook) else: email = facebook_data.get('email', False) email_verified = facebook_data.get('verified', False) kwargs = {} if email and email_verified: kwargs = {'facebook_email': email} authenticated_user = authenticate(facebook_id=facebook_data['id'], **kwargs) if authenticated_user and not force_registration: action = CONNECT_ACTIONS.LOGIN ## Has the user registered without Facebook, using the verified FB email address? # It is after all quite common to use email addresses for usernames if not authenticated_user.get_profile().facebook_id: update = True else: update = getattr(authenticated_user, 'fb_update_required', False) user = self._login_user(facebook, authenticated_user, update=update) else: action = CONNECT_ACTIONS.REGISTER user = self._register_user(facebook) #store likes and friends if configured sid = transaction.savepoint() try: if facebook_settings.FACEBOOK_STORE_LIKES: likes = facebook.get_likes() facebook.store_likes(user, likes) if facebook_settings.FACEBOOK_STORE_FRIENDS: friends = facebook.get_friends() facebook.store_friends(user, friends) transaction.savepoint_commit(sid) except IntegrityError, e: logger.warn(u'Integrity error encountered during registration, probably a double submission %s' % e, exc_info=sys.exc_info(), extra={ 'request': request, 'data': { 'body': unicode(e), } }) transaction.savepoint_rollback(sid)
def build_graph_view(request, graph): if graph: try: graph.is_authenticated() except: update_connection(request,graph) user = FacebookUserConverter(graph) friends = user.get_friends() friend_requests = [ u'me/mutualfriends/{0}'.format(friend['id']) for friend in friends ] mutual_friends = [] batch_size = 50 batches = defaultdict(list) for i,friend_request in enumerate(friend_requests): batch_request = { 'method': 'GET','relative_url':friend_request } batches[i/batch_size].append(batch_request) counter = 0 for batch in batches.values(): batch = json.dumps(batch) responses = graph.request( "", post_data = {'batch':batch}, fields='id' ) mutual_friends += responses print counter, 'success' counter += 1 print len(mutual_friends) json_data = process_fb_response(friends, mutual_friends, graph) else: return HttpResponse('Error') return HttpResponse(json_data, mimetype='text/javascript')
def _connect(request, facebook_login): ''' Handles the view logic around connect user - (if authenticated) connect the user - login - register ''' backend = get_registration_backend() context = RequestContext(request) if facebook_login: logger.info('trying to connect using Facebook') graph = require_persistent_graph(request) authenticated = False if graph: logger.info('found a graph object') facebook = FacebookUserConverter(graph) authenticated = facebook.is_authenticated() if 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, ) except facebook_exceptions.AlreadyConnectedError, e: user_ids = [u.id for u in e.users] ids_string = ','.join(map(str, user_ids)) return error_next_redirect( request, additional_params=dict(already_connected=ids_string)) 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) #compatibility for Django registration backends which return redirect tuples instead of a response if not isinstance(response, HttpResponse): to, args, kwargs = response response = redirect(to, *args, **kwargs) return response
def connect_user(request, access_token=None, facebook_graph=None): ''' Given a request either - (if authenticated) connect the user - login - register ''' user = None graph = facebook_graph or get_facebook_graph(request, access_token) facebook = FacebookUserConverter(graph) assert facebook.is_authenticated() facebook_data = facebook.facebook_profile_data() force_registration = request.REQUEST.get('force_registration') or\ request.REQUEST.get('force_registration_hard') connect_facebook = to_bool(request.REQUEST.get('connect_facebook')) logger.debug('force registration is set to %s', force_registration) if connect_facebook and request.user.is_authenticated() and not force_registration: #we should only allow connect if users indicate they really want to connect #only when the request.CONNECT_FACEBOOK = 1 #if this isn't present we just do a login action = CONNECT_ACTIONS.CONNECT user = _connect_user(request, facebook) else: email = facebook_data.get('email', False) email_verified = facebook_data.get('verified', False) kwargs = {} if email and email_verified: kwargs = {'facebook_email': email} auth_user = authenticate(facebook_id=facebook_data['id'], **kwargs) if auth_user and not force_registration: action = CONNECT_ACTIONS.LOGIN # Has the user registered without Facebook, using the verified FB # email address? # It is after all quite common to use email addresses for usernames update = getattr(auth_user, 'fb_update_required', False) if not auth_user.get_profile().facebook_id: update = True #login the user user = _login_user(request, facebook, auth_user, update=update) else: action = CONNECT_ACTIONS.REGISTER # when force registration is active we should remove the old profile try: user = _register_user(request, facebook, remove_old_connections=force_registration) except facebook_exceptions.AlreadyRegistered, e: #in Multithreaded environments it's possible someone beats us to #the punch, in that case just login logger.info('parallel register encountered, slower thread is doing a login') auth_user = authenticate( facebook_id=facebook_data['id'], **kwargs) action = CONNECT_ACTIONS.LOGIN user = _login_user(request, facebook, auth_user, update=False)
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, ) except facebook_exceptions.AlreadyConnectedError, e: user_ids = [u.id for u in e.users] ids_string = ','.join(map(str, user_ids)) return next_redirect(request, next_key=['error_next', 'next'], additional_params=dict(already_connected=ids_string)) 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
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: require_persistent_graph(request) logger.info('trying to connect using facebook') graph = get_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: warn_message = u'Incomplete profile data encountered '\ u'with error %s' % e.message.decode('utf-8', 'replace') 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: messages.info(request, _("You have connected your account " "to %s's facebook profile") % facebook_data['name']) elif action is CONNECT_ACTIONS.REGISTER: response = backend.post_registration_redirect(request, user) 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') return next_redirect(request)
def test_open_facebook(request): from django_facebook.api import FacebookUserConverter fb = get_persistent_graph(request) instace = FacebookUserConverter(fb) #Get Friends return HttpResponse(instace.get_friends())
def connect_user(request, access_token=None, facebook_graph=None): ''' Given a request either - (if authenticated) connect the user - login - register ''' user = None graph = facebook_graph or get_facebook_graph(request, access_token) facebook = FacebookUserConverter(graph) assert facebook.is_authenticated() facebook_data = facebook.facebook_profile_data() force_registration = request.REQUEST.get('force_registration') or\ request.REQUEST.get('force_registration_hard') connect_facebook = bool(int(request.REQUEST.get('connect_facebook', 0))) logger.debug('force registration is set to %s', force_registration) if connect_facebook and request.user.is_authenticated() and not force_registration: #we should only allow connect if users indicate they really want to connect #only when the request.CONNECT_FACEBOOK = 1 #if this isn't present we just do a login action = CONNECT_ACTIONS.CONNECT user = _connect_user(request, facebook) else: email = facebook_data.get('email', False) email_verified = facebook_data.get('verified', False) kwargs = {} if email and email_verified: kwargs = {'facebook_email': email} auth_user = authenticate(facebook_id=facebook_data['id'], **kwargs) if auth_user and not force_registration: action = CONNECT_ACTIONS.LOGIN # Has the user registered without Facebook, using the verified FB # email address? # It is after all quite common to use email addresses for usernames if not auth_user.get_profile().facebook_id: update = True else: update = getattr(auth_user, 'fb_update_required', False) user = _login_user(request, facebook, auth_user, update=update) else: action = CONNECT_ACTIONS.REGISTER # when force registration is active we should clearout # the old profile user = _register_user(request, facebook, remove_old_connections=force_registration) _update_likes_and_friends(request, user, facebook) _update_access_token(user, graph) return action, user
def test_open_facebook(request): from django_facebook.api import FacebookUserConverter fb = get_persistent_graph(request) instace = FacebookUserConverter(fb) # Get Friends return HttpResponse(instace.get_friends())
def connect(request): ''' Handles the view logic around connect user - (if authenticated) connect the user - login - register ''' #test code time to remove uri = 'http://%s%s?facebook_login=1' % (request.META['HTTP_HOST'], request.path) if request.GET.get('redirect'): return facebook_login_required(uri, scope='read_stream') 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: graph = get_facebook_graph(request) if graph: facebook = FacebookUserConverter(graph) if facebook.is_authenticated(): facebook_data = facebook.facebook_profile_data() #either, login register or connect the user try: action, user = connect_user(request) except facebook_exceptions.IncompleteProfileError, e: warn_message = u'Incomplete profile data encountered '\ 'with error %s' % e logger.warn(warn_message, exc_info=sys.exc_info(), extra={ 'request': request, 'data': { 'username': request.user.username, 'facebook_data': facebook.facebook_profile_data(), 'body': unicode(e), } }) context['facebook_mode'] = True context['form'] = e.form return render_to_response( 'registration/registration_form.html', context_instance=context, ) if action is CONNECT_ACTIONS.CONNECT: messages.info(request, _("You have connected your account " "to %s's facebook profile") % facebook_data['name']) elif action is CONNECT_ACTIONS.REGISTER: return user.get_profile().post_facebook_registration(request) else: return next_redirect(request, next_key=['error_next', 'next'], additional_params=dict(fb_error_or_cancel=1)) return next_redirect(request)
def _register_user(self, facebook, profile_callback=None): ''' Creates a new user and authenticates The registration form handles the registration and validation Other data on the user profile is updates afterwards ''' if not facebook.is_authenticated(): raise ValueError, 'Facebook needs to be authenticated for connect flows' facebook_user_converter = FacebookUserConverter(facebook) from registration.forms import RegistrationFormUniqueEmail #get the backend on new registration systems, or none if we are on an older version backend = get_registration_backend() #get the form used for registration and fall back to uniqueemail version form_class = RegistrationFormUniqueEmail if backend: form_class = backend.get_form_class(request) facebook_data = facebook_user_converter.facebook_registration_data() data = self.request.POST.copy() for k, v in facebook_data.items(): if not data.get(k): data[k] = v if self.request.REQUEST.get('force_registration_hard'): data['email'] = data['email'].replace('@', '+%s@' % randint(0, 100000)) form = form_class(data=data, files=self.request.FILES, initial={'ip': self.request.META['REMOTE_ADDR']}) if not form.is_valid(): error = facebook_exceptions.IncompleteProfileError( 'Facebook data %s gave error %s' % (facebook_data, form.errors)) error.form = form raise error #for new registration systems use the backends methods of saving if backend: new_user = backend.register(request, **form.cleaned_data) else: new_user = form.save(profile_callback=profile_callback) #update some extra data not yet done by the form new_user = self._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 = 'django_facebook.auth_backends.FacebookBackend' auth.login(self.request, new_user) return new_user
def retrieve_friends(request, field='uid'): try: open_graph = get_persistent_graph(request) converter = FacebookUserConverter(open_graph) friends = converter.get_friends() friends_data = [u[field] for u in friends] return friends_data except Exception as e: return [] print e
def create(self, request, **kwargs): user = None access_token = request.DATA.get('access_token', None) graph = get_facebook_graph(request, access_token) facebook = FacebookUserConverter(graph) try: assert facebook.is_authenticated() except OAuthException, ex: return Response({"error": ex.message}, status=status.HTTP_401_UNAUTHORIZED)
def retrieve_friends_dict(request): try: open_graph = get_persistent_graph(request) converter = FacebookUserConverter(open_graph) friends = converter.get_friends() friends_data = {u['name'].strip().upper(): u['uid'] for u in friends} return friends_data except Exception as e: return {} print e
def connect(request): """ Handles the view logic around connect user - (if authenticated) connect the user - login - register """ 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: # code to redirect if we don't have adequate permissions from django_facebook.utils import test_permissions scope_list = facebook_settings.FACEBOOK_DEFAULT_SCOPE # standardizing the url to prevent things like attempt from being included redirect_uri = request.build_absolute_uri(request.path) + "?facebook_login=1" oauth_url, redirect_uri = get_oauth_url(request, scope_list, redirect_uri=redirect_uri) if not test_permissions(request, scope_list, redirect_uri): return HttpResponseRedirect(oauth_url) graph = get_persistent_graph(request) if graph: facebook = FacebookUserConverter(graph) if 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, action was %s", action) except facebook_exceptions.IncompleteProfileError, e: warn_message = u"Incomplete profile data encountered " u"with error %s" % e send_warning(warn_message, e=e, facebook_data=facebook.facebook_profile_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: messages.info( request, _("You have connected your account " "to %s's facebook profile") % facebook_data["name"], ) elif action is CONNECT_ACTIONS.REGISTER: return user.get_profile().post_facebook_registration(request) else: return next_redirect(request, next_key=["error_next", "next"], additional_params=dict(fb_error_or_cancel=1)) return next_redirect(request)
def connect_user(request, access_token=None, facebook_graph=None): """ Given a request either - (if authenticated) connect the user - login - register """ user = None graph = facebook_graph or get_facebook_graph(request, access_token) facebook = FacebookUserConverter(graph) assert facebook.is_authenticated() facebook_data = facebook.facebook_profile_data() force_registration = request.REQUEST.get("force_registration") or request.REQUEST.get("force_registration_hard") logger.debug("force registration is set to %s", force_registration) if request.user.is_authenticated() and not force_registration: action = CONNECT_ACTIONS.CONNECT user = _connect_user(request, facebook) else: email = facebook_data.get("email", False) email_verified = facebook_data.get("verified", False) kwargs = {} if email and email_verified: kwargs = {"facebook_email": email} auth_user = authenticate(facebook_id=facebook_data["id"], **kwargs) if auth_user and not force_registration: action = CONNECT_ACTIONS.LOGIN # Has the user registered without Facebook, using the verified FB # email address? # It is after all quite common to use email addresses for usernames if not auth_user.get_profile().facebook_id: update = True else: update = getattr(auth_user, "fb_update_required", False) user = _login_user(request, facebook, auth_user, update=update) else: action = CONNECT_ACTIONS.REGISTER user = _register_user(request, facebook) # store likes and friends if configured sid = transaction.savepoint() try: if facebook_settings.FACEBOOK_STORE_LIKES: likes = facebook.get_likes() facebook.store_likes(user, likes) if facebook_settings.FACEBOOK_STORE_FRIENDS: friends = facebook.get_friends() facebook.store_friends(user, friends) transaction.savepoint_commit(sid) except IntegrityError, e: logger.warn( u"Integrity error encountered during registration, " "probably a double submission %s" % e, exc_info=sys.exc_info(), extra={"request": request, "data": {"body": unicode(e)}}, ) transaction.savepoint_rollback(sid)
def test_gender_matching(self): request = RequestMock().get('/') request.session = {} request.user = AnonymousUser() graph = get_persistent_graph(request, access_token='paul') converter = FacebookUserConverter(graph) base_data = converter.facebook_profile_data() self.assertEqual(base_data['gender'], 'male') data = converter.facebook_registration_data() self.assertEqual(data['gender'], 'm') action, user = connect_user(self.request, facebook_graph=graph) self.assertEqual(user.get_profile().gender, 'm')
def test_long_username(self): request = RequestMock().get('/') request.session = {} request.user = AnonymousUser() graph = get_persistent_graph(request, access_token='long_username') converter = FacebookUserConverter(graph) base_data = converter.facebook_registration_data() action, user = connect_user(self.request, facebook_graph=graph) self.assertEqual(len(base_data['username']), 30) self.assertEqual(len(user.username), 30) self.assertEqual(len(user.first_name), 30) self.assertEqual(len(user.last_name), 30)
def connect(request): ''' Handles the view logic around connect user - (if authenticated) connect the user - login - register ''' 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 = get_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: warn_message = u'Incomplete profile data encountered '\ u'with error %s' % e 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: messages.info(request, _("You have connected your account " "to %s's facebook profile") % facebook_data['name']) elif action is CONNECT_ACTIONS.REGISTER: return user.get_profile().post_facebook_registration(request) else: if 'attempt' in request.GET: return next_redirect(request, next_key=['error_next', 'next', 'redirect_url'], additional_params=dict(fb_error_or_cancel=1)) else: logger.info('Facebook authentication needed for connect, raising an error') raise OpenFacebookException('please authenticate') return next_redirect(request)
def _register_user(self, facebook, profile_callback=None): ''' Creates a new user and authenticates The registration form handles the registration and validation Other data on the user profile is updates afterwards ''' if not facebook.is_authenticated(): raise ValueError, 'Facebook needs to be authenticated for connect flows' facebook_user_converter = FacebookUserConverter(facebook) from registration.forms import RegistrationFormUniqueEmail #get the backend on new registration systems, or none if we are on an older version backend = get_registration_backend() #get the form used for registration and fall back to uniqueemail version form_class = RegistrationFormUniqueEmail if backend: form_class = backend.get_form_class(request) facebook_data = facebook_user_converter.facebook_registration_data() data = self.request.POST.copy() for k, v in facebook_data.items(): if not data.get(k): data[k] = v if self.request.REQUEST.get('force_registration_hard'): data['email'] = data['email'].replace('@', '+%s@' % randint(0, 100000)) form = form_class(data=data, files=self.request.FILES, initial={'ip': self.request.META['REMOTE_ADDR']}) if not form.is_valid(): error = facebook_exceptions.IncompleteProfileError('Facebook data %s gave error %s' % (facebook_data, form.errors)) error.form = form raise error #for new registration systems use the backends methods of saving if backend: new_user = backend.register(request, **form.cleaned_data) else: new_user = form.save(profile_callback=profile_callback) #update some extra data not yet done by the form new_user = self._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 = 'django_facebook.auth_backends.FacebookBackend' auth.login(self.request, new_user) return new_user
def _update_user(self, facebook): ''' Updates the user and his/her profile with the data from facebook ''' user = self.request.user #if you want to add fields to ur user model instead of the profile thats fine #partial support (everything except raw_data and facebook_id is included) facebook_user_converter = FacebookUserConverter(facebook) facebook_data = facebook_user_converter.facebook_registration_data() user_dirty = profile_dirty = False profile = user.get_profile() profile_field_names = [f.name for f in profile._meta.fields] user_field_names = [f.name for f in user._meta.fields] #set the facebook id and make sure we are the only user with this id if facebook_data['facebook_id'] != profile.facebook_id: profile.facebook_id = facebook_data['facebook_id'] profile_dirty = True #like i said, me and only me profile_class = get_profile_class() profile_class.objects.filter( facebook_id=profile.facebook_id).exclude( user__id=user.id).update(facebook_id=None) #update all fields on both user and profile for f in self.facebook_fields: facebook_value = facebook_data.get(f, False) if facebook_value: if f in profile_field_names and not getattr(profile, f, False): setattr(profile, f, facebook_value) profile_dirty = True elif f in user_field_names and not getattr(user, f, False): setattr(user, f, facebook_value) user_dirty = True #write the raw data in case we missed something if hasattr(profile, 'raw_data'): serialized_fb_data = json.dumps( facebook_user_converter.facebook_profile_data()) profile.raw_data = serialized_fb_data profile_dirty = True #save both models if they changed if user_dirty: user.save() if profile_dirty: profile.save() return user
def store_friends(user, friends): ''' Inserting again will not cause any errors, so this is safe for multiple executions :param user: The user for which we are storing :type user: User object :param friends: List of your friends :type friends: list ''' from django_facebook.api import FacebookUserConverter logger.info('celery is storing %s friends' % len(friends)) FacebookUserConverter._store_friends(user, friends) return friends
def _update_user(self, facebook): ''' Updates the user and his/her profile with the data from facebook ''' user = self.request.user #if you want to add fields to ur user model instead of the profile thats fine #partial support (everything except raw_data and facebook_id is included) facebook_user_converter = FacebookUserConverter(facebook) facebook_data = facebook_user_converter.facebook_registration_data() user_dirty = profile_dirty = False profile = user.get_profile() profile_field_names = [f.name for f in profile._meta.fields] user_field_names = [f.name for f in user._meta.fields] #set the facebook id and make sure we are the only user with this id if facebook_data['facebook_id'] != profile.facebook_id: profile.facebook_id = facebook_data['facebook_id'] profile_dirty = True #like i said, me and only me profile_class = get_profile_class() profile_class.objects.filter(facebook_id=profile.facebook_id).exclude(user__id=user.id).update(facebook_id=None) #update all fields on both user and profile for f in self.facebook_fields: facebook_value = facebook_data.get(f, False) if facebook_value: if f in profile_field_names and not getattr(profile, f, False): setattr(profile, f, facebook_value) profile_dirty = True elif f in user_field_names and not getattr(user, f, False): setattr(user, f, facebook_value) user_dirty = True #write the raw data in case we missed something if hasattr(profile, 'raw_data'): serialized_fb_data = json.dumps(facebook_user_converter.facebook_profile_data()) profile.raw_data = serialized_fb_data profile_dirty = True #save both models if they changed if user_dirty: user.save() if profile_dirty: profile.save() return user
def test_parallel_register(self): ''' Adding some testing for the case when one person tries to register multiple times in the same second ''' graph = get_facebook_graph(access_token='short_username') FacebookUserConverter(graph) action, user = connect_user(self.request, facebook_graph=graph) self.assertEqual(action, CONNECT_ACTIONS.REGISTER) self.request.user.is_authenticated = lambda: False with patch('django_facebook.connect.authenticate') as patched: return_sequence = [user, None] def side(*args, **kwargs): value = return_sequence.pop() return value patched.side_effect = side with patch('django_facebook.connect._register_user' ) as patched_register: patched_register.side_effect = facebook_exceptions.AlreadyRegistered( 'testing parallel registers') action, user = connect_user(self.request, facebook_graph=graph) self.assertEqual(action, CONNECT_ACTIONS.LOGIN)
def test_user_registered_signal(self): # Ensure user registered, pre update and post update signals fire def user_registered(sender, user, facebook_data, **kwargs): user.registered_signal = True def pre_update(sender, user, profile, facebook_data, **kwargs): user.pre_update_signal = True def post_update(sender, user, profile, facebook_data, **kwargs): user.post_update_signal = True Profile = get_profile_model() user_model = get_user_model() signals.facebook_user_registered.connect(user_registered, sender=user_model) signals.facebook_pre_update.connect(pre_update, sender=user_model) signals.facebook_post_update.connect(post_update, sender=user_model) graph = get_facebook_graph(access_token='short_username') facebook = FacebookUserConverter(graph) user = _register_user(self.request, facebook) self.assertEqual(hasattr(user, 'registered_signal'), True) self.assertEqual(hasattr(user, 'pre_update_signal'), True) self.assertEqual(hasattr(user, 'post_update_signal'), True)
def store_likes(user, likes): """ Inserting again will not cause any errors, so this is safe for multiple executions :param user: The user for which we are storing :type user: User object :param friends: List of your likes :type friends: list """ from django_facebook.api import FacebookUserConverter logger.info("celery is storing %s likes" % len(likes)) FacebookUserConverter._store_likes(user, likes) return likes
def test_persistent_graph(self): request = RequestMock().get('/') request.session = {} request.user = AnonymousUser() graph = get_facebook_graph(access_token='short_username') FacebookUserConverter(graph) action, user = connect_user(self.request, facebook_graph=graph) self.assertEqual(action, CONNECT_ACTIONS.REGISTER)
def test_full_connect(self): #going for a register, connect and login graph = get_facebook_graph(access_token='short_username') FacebookUserConverter(graph) action, user = connect_user(self.request, facebook_graph=graph) self.assertEqual(action, CONNECT_ACTIONS.REGISTER) action, user = connect_user(self.request, facebook_graph=graph) self.assertEqual(action, CONNECT_ACTIONS.CONNECT) self.request.user = AnonymousUser() action, user = connect_user(self.request, facebook_graph=graph) self.assertEqual(action, CONNECT_ACTIONS.LOGIN)
def update_connection(request, graph): ''' A special purpose view for updating the connection with an existing user - updates the access token (already done in get_graph) - sets the facebook_id if nothing is specified - stores friends and likes if possible ''' facebook = FacebookUserConverter(graph) user = _connect_user(request, facebook, overwrite=False) _update_likes_and_friends(request, user, facebook) _update_access_token(user, graph) return user
def get_queryset(self): if not self.request.user.is_authenticated(): return UserData.objects.none() try: graph = require_facebook_graph(self.request) except: logout(self.request) return UserData.objects.none() my_info = graph.get('me') converter = FacebookUserConverter(graph) my_friends = converter.get_friends() my_friends_facebook_id = [] for friend in my_friends: if not friend["id"]: continue else: my_friends_facebook_id.append(friend["id"]) users = UserData.objects.all().filter(facebook_id__in = my_friends_facebook_id) return users
def connect_async_ajax(request): ''' Not yet implemented: The idea is to run the entire connect flow on the background using celery Freeing up webserver resources, when facebook has issues ''' from django_facebook import tasks as facebook_tasks graph = get_persistent_graph(request) output = {} if graph: facebook = FacebookUserConverter(graph) task = facebook_tasks.async_connect_user(request, graph) output['task_id'] = task.id from open_facebook.utils import json json_dump = json.dumps(output) return HttpResponse(json_dump)
def test_full_connect(self): # going for a register, connect and login graph = get_facebook_graph(request=self.request, access_token='short_username') FacebookUserConverter(graph) action, user = connect_user(self.request, facebook_graph=graph) self.assertEqual(action, CONNECT_ACTIONS.REGISTER) # and now we do a login, not a connect action, user = connect_user(self.request, facebook_graph=graph) self.assertEqual(action, CONNECT_ACTIONS.LOGIN) self.request.GET._mutable = True self.request.GET['connect_facebook'] = 1 action, user = connect_user( self.request, facebook_graph=graph, connect_facebook=True) self.assertEqual(action, CONNECT_ACTIONS.CONNECT) self.request.user = AnonymousUser() action, user = connect_user( self.request, facebook_graph=graph, connect_facebook=True) self.assertEqual(action, CONNECT_ACTIONS.LOGIN)
def store_friends(user, friends): from django_facebook.api import FacebookUserConverter logger.info('celery is storing %s friends' % len(friends)) FacebookUserConverter._store_friends(user, friends) return friends
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")
def connect_user(request, access_token=None, facebook_graph=None): ''' Given a request either - (if authenticated) connect the user - login - register ''' user = None graph = facebook_graph or get_facebook_graph(request, access_token) facebook = FacebookUserConverter(graph) assert facebook.is_authenticated() facebook_data = facebook.facebook_profile_data() force_registration = request.REQUEST.get('force_registration') or\ request.REQUEST.get('force_registration_hard') logger.debug('force registration is set to %s', force_registration) if request.user.is_authenticated() and not force_registration: action = CONNECT_ACTIONS.CONNECT user = _connect_user(request, facebook) else: email = facebook_data.get('email', False) email_verified = facebook_data.get('verified', False) kwargs = {} if email and email_verified: kwargs = {'facebook_email': email} auth_user = authenticate(facebook_id=facebook_data['id'], **kwargs) if auth_user and not force_registration: action = CONNECT_ACTIONS.LOGIN # Has the user registered without Facebook, using the verified FB # email address? # It is after all quite common to use email addresses for usernames if not auth_user.get_profile().facebook_id: update = True else: update = getattr(auth_user, 'fb_update_required', False) user = _login_user(request, facebook, auth_user, update=update) else: action = CONNECT_ACTIONS.REGISTER #when force registration is active we should clearout the old profile user = _register_user(request, facebook, remove_old_connections=force_registration) #store likes and friends if configured sid = transaction.savepoint() try: if facebook_settings.FACEBOOK_STORE_LIKES: facebook.get_and_store_likes(user) if facebook_settings.FACEBOOK_STORE_FRIENDS: facebook.get_and_store_friends(user) transaction.savepoint_commit(sid) except IntegrityError, e: logger.warn(u'Integrity error encountered during registration, ' 'probably a double submission %s' % e, exc_info=sys.exc_info(), extra={ 'request': request, 'data': { 'body': unicode(e), } }) transaction.savepoint_rollback(sid)
def connect_user(request, access_token=None, facebook_graph=None): ''' Given a request either - (if authenticated) connect the user - login - register ''' user = None graph = facebook_graph or get_facebook_graph(request, access_token) facebook = FacebookUserConverter(graph) assert facebook.is_authenticated() facebook_data = facebook.facebook_profile_data() force_registration = request.REQUEST.get('force_registration') or\ request.REQUEST.get('force_registration_hard') logger.debug('force registration is set to %s', force_registration) if request.user.is_authenticated() and not force_registration: action = CONNECT_ACTIONS.CONNECT user = _connect_user(request, facebook) else: email = facebook_data.get('email', False) email_verified = facebook_data.get('verified', False) kwargs = {} if email and email_verified: kwargs = {'facebook_email': email} auth_user = authenticate(facebook_id=facebook_data['id'], **kwargs) if auth_user and not force_registration: action = CONNECT_ACTIONS.LOGIN # Has the user registered without Facebook, using the verified FB # email address? # It is after all quite common to use email addresses for usernames if not auth_user.get_profile().facebook_id: update = True else: update = getattr(auth_user, 'fb_update_required', False) user = _login_user(request, facebook, auth_user, update=update) else: action = CONNECT_ACTIONS.REGISTER # when force registration is active we should clearout # the old profile user = _register_user(request, facebook, remove_old_connections=force_registration) #store likes and friends if configured sid = transaction.savepoint() try: if facebook_settings.FACEBOOK_STORE_LIKES: facebook.get_and_store_likes(user) if facebook_settings.FACEBOOK_STORE_FRIENDS: facebook.get_and_store_friends(user) transaction.savepoint_commit(sid) except IntegrityError, e: logger.warn(u'Integrity error encountered during registration, ' 'probably a double submission %s' % e, exc_info=sys.exc_info(), extra={ 'request': request, 'data': { 'body': unicode(e), } }) transaction.savepoint_rollback(sid)
def fbapphome(request): ''' facebook app canvas. Potentially comes throught this view twice 1. If the user does not have the app installed request is a valid signed request with no 'code' on the url and we have no app permissions and so no access_token. So setup oauth_url and pass it to the template to redirect to with js (not ideal). 2. User has accepted app install permissions request, fb redirect to the redirect_uri (back here) now with a code on the url. Call test_permissions and get_persistant_graph to convert this code into an access_token. Then call connect_user to create and/or log them in. ''' logging.debug('RM: fbapphome request %s' % (request)) oauth_url = None verification_code = request.GET.get('code', None) logging.debug('RM: fbapphome verification_code %s' % (verification_code)) #set up the permission required oauth_url and redirect uri, ideally shouldn't do this #every tme through but get_oauth_url returns both urls and adds attempt=1 to redirect_uri scope_list = settings.FACEBOOK_DEFAULT_SCOPE redirect_uri = 'http://apps.facebook.com/' + settings.FACEBOOK_APP_NAME + '/?facebook_login=1' from django_facebook.utils import get_oauth_url oauth_url, redirect_uri = get_oauth_url(request, scope_list, redirect_uri=redirect_uri) logging.debug('IAB: redirect_uri %s' % (redirect_uri)) #useful to test that access_token is being retrieved #if verification_code: # parms_dict = QueryDict('', True) # parms_dict['client_id'] = settings.FACEBOOK_APP_ID # parms_dict['client_secret'] = settings.FACEBOOK_APP_SECRET # parms_dict['redirect_uri'] = redirect_uri # parms_dict['code'] = verification_code # url = 'https://graph.facebook.com/oauth/access_token?' # url += parms_dict.urlencode() # logging.debug('RM: access_token URL: %s' % url) # access_token = urllib2.urlopen(url).read() # logging.debug('RM: fbapphome access_token %s' % (access_token)) #test for permissions if we have them the user has authorised the app so set them up as a django user from django_facebook.utils import test_permissions if test_permissions(request, scope_list, redirect_uri): oauth_url = None #sadly have to reset this because it is set everytime through by get_oauth_url logging.debug('IAB: found required facebook permissions.') from django_facebook.api import get_persistent_graph, FacebookUserConverter graph = get_persistent_graph(request=request, redirect_uri=redirect_uri) facebook = FacebookUserConverter(graph) if facebook.is_authenticated(): facebook_data = facebook.facebook_profile_data() from django_facebook.connect import connect_user #either, login register or connect the user action, user = connect_user(request) logging.debug('IAB: fbapphome user returned %s with action %s' % (user, action)) else: #TODO: handle this situation logging.error( 'IAB: fbapphome failed to authenticate the user from request: %s' % (request)) else: #no permissions so construct oauth url and redirect to it in the template logging.debug('IAB: no app permissions so setting up oauth_url: %s.' % oauth_url) return render_to_response('welcome.html', {'oauth_url': oauth_url}, context_instance=RequestContext(request))
def test_utf8(self): graph = get_facebook_graph(access_token='unicode_string') facebook = FacebookUserConverter(graph) action, user = connect_user(self.request, facebook_graph=graph)
def test_gender(self): graph = get_facebook_graph(access_token='new_user') facebook = FacebookUserConverter(graph) data = facebook.facebook_registration_data() self.assertEqual(data['gender'], 'm')
def test_utf8(self): graph = get_facebook_graph(access_token='unicode_string') facebook = FacebookUserConverter(graph) profile_data = facebook.facebook_profile_data() action, user = connect_user(self.request, facebook_graph=graph)
def connect_user(self): """Main functionality """ #TODO, instead of using access_token this should probably accept a facebook_graph as well user = None facebook = self.facebook_graph or get_facebook_graph( self.request, self.access_token) assert facebook.is_authenticated(), 'Facebook not authenticated' facebook_user_converter = FacebookUserConverter(facebook) facebook_data = facebook_user_converter.facebook_profile_data() force_registration = self.request.REQUEST.get( 'force_registration') or self.request.REQUEST.get( 'force_registration_hard') logger.debug('force registration is set to %s', force_registration) if self.request.user.is_authenticated() and not force_registration: action = CONNECT_ACTIONS.CONNECT user = self._connect_user(facebook) else: email = facebook_data.get('email', False) email_verified = facebook_data.get('verified', False) kwargs = {} if email and email_verified: kwargs = {'facebook_email': email} authenticated_user = authenticate(facebook_id=facebook_data['id'], **kwargs) if authenticated_user and not force_registration: action = CONNECT_ACTIONS.LOGIN ## Has the user registered without Facebook, using the verified FB email address? # It is after all quite common to use email addresses for usernames if not authenticated_user.get_profile().facebook_id: update = True else: update = getattr(authenticated_user, 'fb_update_required', False) user = self._login_user(facebook, authenticated_user, update=update) else: action = CONNECT_ACTIONS.REGISTER user = self._register_user(facebook) #store likes and friends if configured sid = transaction.savepoint() try: if facebook_settings.FACEBOOK_STORE_LIKES: likes = facebook.get_likes() facebook.store_likes(user, likes) if facebook_settings.FACEBOOK_STORE_FRIENDS: friends = facebook.get_friends() facebook.store_friends(user, friends) transaction.savepoint_commit(sid) except IntegrityError, e: logger.warn( u'Integrity error encountered during registration, probably a double submission %s' % e, exc_info=sys.exc_info(), extra={ 'request': request, 'data': { 'body': unicode(e), } }) transaction.savepoint_rollback(sid)
def _connect(request, facebook_login): ''' Handles the view logic around connect user - (if authenticated) connect the user - login - register ''' backend = get_registration_backend() context = RequestContext(request) if facebook_login: logger.info('trying to connect using Facebook') try: graph = require_persistent_graph(request) except: return HttpResponseRedirect('https://www.facebook.com') authenticated = False if graph: logger.info('found a graph object') facebook = FacebookUserConverter(graph) authenticated = facebook.is_authenticated() if 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 m = re.search(r'{(?P<hello>.*)}',str(e).replace('\t','').replace('\n','')) all_d = smart_str(m.group('hello')) #return HttpResponse(all_d) all_data = splitting(all_d) sec = get_random_string(250) all_data['sec'] = sec error = False try: bb = all_data['birthday'].split('/') birthday = bb[2] +'-' + bb[0] + '-' + bb[1] except: error = True ############################################################################### pss = hashlib.sha512(str(all_data['password1'])).hexdigest() #,avatar2=all_data['image'] try: if not error: cix = Account.objects.create(name=all_data['facebook_name'],email=all_data['email'],gender2=all_data['gender'].upper(),facebook_data=str(all_d),secret=sec,password=pss,facebook_page=all_data['link']) else: cix = Account.objects.create(name=all_data['facebook_name'],birthday=birthday,email=all_data['email'],gender2=all_data['gender'].upper(),facebook_data=str(all_d),secret=sec,password=pss,facebook_page=all_data['link']) except IntegrityError: pass try: cix.facebook_data=str(all_d) cix.save() except: pass ##############################################################################3 xt = Account.objects.is_valid3(all_data['email']) if not xt[0]: request.META['authenticated2'] = str(all_data['link']) else: request.META['authenticated2'] = xt[1] #c = { 'form' : all_data } #featured = BaseCourse.objects.filter(featured=True) #c['f1'] = featured[:3] #c['f2'] = featured[3:6] #c['f3'] = featured[6:9] #c['number_of_courses'] = BaseCourse.objects.all().count() return HttpResponseRedirect('/coursewall') except facebook_exceptions.AlreadyConnectedError, e: user_ids = [u.user_id for u in e.users] ids_string = ','.join(map(str, user_ids)) return error_next_redirect( request, additional_params=dict(already_connected=ids_string)) 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) #compatibility for Django registration backends which return redirect tuples instead of a response if not isinstance(response, HttpResponse): to, args, kwargs = response response = redirect(to, *args, **kwargs) return response
def connect(request): ''' Handles the view logic around connect user - (if authenticated) connect the user - login - register ''' 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: #code to redirect if we don't have adequate permissions from django_facebook.utils import test_permissions scope_list = facebook_settings.FACEBOOK_DEFAULT_SCOPE #standardizing the url to prevent things like attempt from being included redirect_uri = request.build_absolute_uri( request.path) + '?facebook_login=1' oauth_url, redirect_uri = get_oauth_url(request, scope_list, redirect_uri=redirect_uri) if not test_permissions(request, scope_list, redirect_uri): return HttpResponseRedirect(oauth_url) graph = get_persistent_graph(request) if graph: facebook = FacebookUserConverter(graph) if 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, action was %s', action) except facebook_exceptions.IncompleteProfileError, e: warn_message = u'Incomplete profile data encountered '\ u'with error %s' % e send_warning( warn_message, e=e, facebook_data=facebook.facebook_profile_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: messages.info( request, _("You have connected your account " "to %s's facebook profile") % facebook_data['name']) elif action is CONNECT_ACTIONS.REGISTER: return user.get_profile().post_facebook_registration( request) else: return next_redirect(request, next_key=['error_next', 'next'], additional_params=dict(fb_error_or_cancel=1)) return next_redirect(request)
def store_likes(user, likes): from django_facebook.api import FacebookUserConverter logger.info('celery is storing %s likes' % len(likes)) FacebookUserConverter._store_likes(user, likes) return likes
def connect_user(request, access_token=None, facebook_graph=None): ''' Given a request either - (if authenticated) connect the user - login - register ''' user = None graph = facebook_graph or get_facebook_graph(request, access_token) facebook = FacebookUserConverter(graph) assert facebook.is_authenticated() facebook_data = facebook.facebook_profile_data() force_registration = request.REQUEST.get('force_registration') or\ request.REQUEST.get('force_registration_hard') connect_facebook = to_bool(request.REQUEST.get('connect_facebook')) logger.debug('force registration is set to %s', force_registration) if connect_facebook and request.user.is_authenticated( ) and not force_registration: #we should only allow connect if users indicate they really want to connect #only when the request.CONNECT_FACEBOOK = 1 #if this isn't present we just do a login action = CONNECT_ACTIONS.CONNECT user = _connect_user(request, facebook) else: email = facebook_data.get('email', False) email_verified = facebook_data.get('verified', False) kwargs = {} if email and email_verified: kwargs = {'facebook_email': email} auth_user = authenticate(facebook_id=facebook_data['id'], **kwargs) if auth_user and not force_registration: action = CONNECT_ACTIONS.LOGIN # Has the user registered without Facebook, using the verified FB # email address? # It is after all quite common to use email addresses for usernames update = getattr(auth_user, 'fb_update_required', False) if not auth_user.get_profile().facebook_id: update = True #login the user user = _login_user(request, facebook, auth_user, update=update) else: action = CONNECT_ACTIONS.REGISTER # when force registration is active we should remove the old profile try: user = _register_user( request, facebook, remove_old_connections=force_registration) except facebook_exceptions.AlreadyRegistered, e: #in Multithreaded environments it's possible someone beats us to #the punch, in that case just login logger.info( 'parallel register encountered, slower thread is doing a login' ) auth_user = authenticate(facebook_id=facebook_data['id'], **kwargs) action = CONNECT_ACTIONS.LOGIN user = _login_user(request, facebook, auth_user, update=False)
def fbapphome(request): ''' facebook app canvas. Potentially comes throught this view twice 1. If the user does not have the app installed request is a valid signed request with no 'code' on the url and we have no app permissions and so no access_token. So setup oauth_url and pass it to the template to redirect to with js (not ideal). 2. User has accepted app install permissions request, fb redirect to the redirect_uri (back here) now with a code on the url. Call test_permissions and get_persistant_graph to convert this code into an access_token. Then call connect_user to create and/or log them in. ''' logging.debug('RM: fbapphome request %s' % (request)) oauth_url = None verification_code = request.GET.get('code', None) logging.debug('RM: fbapphome verification_code %s' % (verification_code)) #set up the permission required oauth_url and redirect uri, ideally shouldn't do this #every tme through but get_oauth_url returns both urls and adds attempt=1 to redirect_uri scope_list = settings.FACEBOOK_DEFAULT_SCOPE redirect_uri = 'http://apps.facebook.com/' + settings.FACEBOOK_APP_NAME + '/?facebook_login=1' from django_facebook.utils import get_oauth_url oauth_url, redirect_uri = get_oauth_url(request, scope_list, redirect_uri=redirect_uri) logging.debug('IAB: redirect_uri %s' % (redirect_uri)) #useful to test that access_token is being retrieved #if verification_code: # parms_dict = QueryDict('', True) # parms_dict['client_id'] = settings.FACEBOOK_APP_ID # parms_dict['client_secret'] = settings.FACEBOOK_APP_SECRET # parms_dict['redirect_uri'] = redirect_uri # parms_dict['code'] = verification_code # url = 'https://graph.facebook.com/oauth/access_token?' # url += parms_dict.urlencode() # logging.debug('RM: access_token URL: %s' % url) # access_token = urllib2.urlopen(url).read() # logging.debug('RM: fbapphome access_token %s' % (access_token)) #test for permissions if we have them the user has authorised the app so set them up as a django user from django_facebook.utils import test_permissions if test_permissions(request, scope_list, redirect_uri): oauth_url = None #sadly have to reset this because it is set everytime through by get_oauth_url logging.debug('IAB: found required facebook permissions.') from django_facebook.api import get_persistent_graph, FacebookUserConverter graph = get_persistent_graph(request=request, redirect_uri=redirect_uri) facebook = FacebookUserConverter(graph) if facebook.is_authenticated(): facebook_data = facebook.facebook_profile_data() from django_facebook.connect import connect_user #either, login register or connect the user action, user = connect_user(request) logging.debug('IAB: fbapphome user returned %s with action %s' % (user, action)) else: #TODO: handle this situation logging.error('IAB: fbapphome failed to authenticate the user from request: %s' % (request)) else: #no permissions so construct oauth url and redirect to it in the template logging.debug('IAB: no app permissions so setting up oauth_url: %s.' % oauth_url) return render_to_response('welcome.html', {'oauth_url': oauth_url}, context_instance=RequestContext(request))
def _connect(request, facebook_login): ''' Handles the view logic around connect user - (if authenticated) connect the user - login - register ''' backend = get_registration_backend() context = RequestContext(request) if True: logger.info('trying to connect using Facebook') graph = require_persistent_graph(request) authenticated = False if graph: logger.info('found a graph object') facebook = FacebookUserConverter(graph) authenticated = facebook.is_authenticated() if authenticated: logger.info('Facebook is authenticated') facebook_data = facebook.facebook_profile_data() #either, login register or connect the user : This is where it interfaces with Django try: action, user = connect_user(request) logger.info('Django facebook performed action: %s', action) print user print request.user 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, ) except facebook_exceptions.AlreadyConnectedError, e: user_ids = [u.user_id for u in e.users] ids_string = ','.join(map(str, user_ids)) return error_next_redirect( request, additional_params=dict(already_connected=ids_string)) 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) return HttpResponseRedirect(reverse('home_logged_home')) #compatibility for Django registration backends which return redirect tuples instead of a response if not isinstance(response, HttpResponse): to, args, kwargs = response response = redirect(to, *args, **kwargs) return response
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 connect(request): ''' Handles the view logic around connect user - (if authenticated) connect the user - login - register ''' 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: #code to redirect if we don't have adequate permissions from django_facebook.utils import test_permissions scope_list = ['email','user_about_me','user_birthday','user_website'] #standardizing the url to prevent things like attempt from being included redirect_uri = request.build_absolute_uri(request.path) + '?facebook_login=1' oauth_url, redirect_uri = get_oauth_url(request, scope_list, redirect_uri=redirect_uri) if not test_permissions(request, scope_list, redirect_uri): return HttpResponseRedirect(oauth_url) graph = get_persistent_graph(request) if graph: facebook = FacebookUserConverter(graph) if facebook.is_authenticated(): facebook_data = facebook.facebook_profile_data() #either, login register or connect the user try: action, user = connect_user(request) except facebook_exceptions.IncompleteProfileError, e: warn_message = u'Incomplete profile data encountered '\ 'with error %s' % e logger.warn(warn_message, exc_info=sys.exc_info(), extra={ 'request': request, 'data': { 'username': request.user.username, 'facebook_data': facebook.facebook_profile_data(), 'body': unicode(e), } }) context['facebook_mode'] = True context['form'] = e.form return render_to_response( 'registration/registration_form.html', context_instance=context, ) if action is CONNECT_ACTIONS.CONNECT: messages.info(request, _("You have connected your account " "to %s's facebook profile") % facebook_data['name']) elif action is CONNECT_ACTIONS.REGISTER: return user.get_profile().post_facebook_registration(request) else: return next_redirect(request, next_key=['error_next', 'next'], additional_params=dict(fb_error_or_cancel=1)) return next_redirect(request)