def send(self, graph=None, shared_explicitly=False): result = None # update the last attempt self.last_attempt = datetime.now() self.save() # see if the graph is enabled profile = try_get_profile(self.user) user_or_profile = get_instance_for_attribute( self.user, profile, 'access_token') graph = graph or user_or_profile.get_offline_graph() user_enabled = shared_explicitly or \ (user_or_profile.facebook_open_graph and self.facebook_user_id) # start sharing if graph and user_enabled: graph_location = '%s/%s' % ( self.facebook_user_id, self.action_domain) share_dict = self.get_share_dict() from open_facebook.exceptions import OpenFacebookException try: result = graph.set(graph_location, **share_dict) share_id = result.get('id') if not share_id: error_message = 'No id in Facebook response, found %s for url %s with data %s' % ( result, graph_location, share_dict) logger.error(error_message) raise OpenFacebookException(error_message) self.share_id = share_id self.error_message = None self.completed_at = datetime.now() self.save() except OpenFacebookException as e: logger.warn( 'Open graph share failed, writing message %s' % str(e)) self.error_message = repr(e) self.save() # maybe we need a new access token new_token_required = self.exception_requires_new_token( e, graph) # verify that the token didnt change in the mean time user_or_profile = user_or_profile.__class__.objects.get( id=user_or_profile.id) token_changed = graph.access_token != user_or_profile.access_token logger.info('new token required is %s and token_changed is %s', new_token_required, token_changed) if new_token_required and not token_changed: logger.info( 'a new token is required, setting the flag on the user or profile') # time to ask the user for a new token update_user_attributes(self.user, profile, dict( new_token_required=True), save=True) elif not graph: self.error_message = 'no graph available' self.save() elif not user_enabled: self.error_message = 'user not enabled' self.save() return result
def send(self, graph=None, shared_explicitly=False): result = None # update the last attempt self.last_attempt = datetime.now() self.save() # see if the graph is enabled profile = try_get_profile(self.user) user_or_profile = get_instance_for_attribute( self.user, profile, 'access_token') graph = graph or user_or_profile.get_offline_graph() user_enabled = shared_explicitly or \ (user_or_profile.facebook_open_graph and self.facebook_user_id) # start sharing if graph and user_enabled: graph_location = '%s/%s' % ( self.facebook_user_id, self.action_domain) share_dict = self.get_share_dict() from open_facebook.exceptions import OpenFacebookException try: result = graph.set(graph_location, **share_dict) share_id = result.get('id') if not share_id: error_message = 'No id in Facebook response, found %s for url %s with data %s' % ( result, graph_location, share_dict) logging.error(error_message) raise OpenFacebookException(error_message) self.share_id = share_id self.error_message = None self.completed_at = datetime.now() self.save() except OpenFacebookException as e: logging.warn( 'Open graph share failed, writing message %s' % str(e)) self.error_message = repr(e) self.save() # maybe we need a new access token new_token_required = self.exception_requires_new_token( e, graph) # verify that the token didnt change in the mean time user_or_profile = user_or_profile.__class__.objects.get( id=user_or_profile.id) token_changed = graph.access_token != user_or_profile.access_token logging.info('new token required is %s and token_changed is %s', new_token_required, token_changed) if new_token_required and not token_changed: logging.info( 'a new token is required, setting the flag on the user or profile') # time to ask the user for a new token update_user_attributes(self.user, profile, dict( new_token_required=True), save=True) elif not graph: self.error_message = 'no graph available' self.save() elif not user_enabled: self.error_message = 'user not enabled' self.save() return result
def test_follow_og_share_error(self): user_url = 'http://www.fashiolista.com/style/neni/' kwargs = dict(item=user_url) user = get_user_model().objects.all()[:1][0] profile = try_get_profile(user) user_or_profile = get_instance_for_attribute( user, profile, 'facebook_open_graph') user_or_profile.facebook_open_graph = True user_or_profile.save() some_content_type = ContentType.objects.all()[:1][0] share = OpenGraphShare.objects.create( user_id=user.id, facebook_user_id=13123123, action_domain='fashiolista:follow', content_type=some_content_type, object_id=user.id, ) share.set_share_dict(kwargs) share.save() update_user_attributes(user, profile, dict(new_token_required=False)) from open_facebook.exceptions import FacebookUnreachable, OAuthException with mock.patch('open_facebook.api.OpenFacebook') as mocked: instance = mocked.return_value instance.set = Mock(side_effect=FacebookUnreachable('broken')) share.send(graph=instance) self.assertEqual(share.error_message, 'broken') self.assertFalse(share.completed_at) user = get_user_model().objects.get(id=user.id) if profile: profile = get_profile_model().objects.get(id=profile.id) new_token_required = get_user_attribute( user, profile, 'new_token_required') self.assertEqual(new_token_required, False) # now try with an oauth exception return # Can't figure out how to test this with mock.patch('open_facebook.api.OpenFacebook') as mocked: instance = mocked.return_value instance.set = Mock(side_effect=OAuthException('permissions')) share.send(graph=instance) self.assertEqual(share.error_message, 'permissions') self.assertFalse(share.completed_at) user = get_user_model().objects.get(id=user.id) if profile: profile = get_profile_model().objects.get(id=profile.id) new_token_required = get_user_attribute( user, profile, 'new_token_required') self.assertEqual(new_token_required, True)
def test_send(error, expected_error_message, expected_new_token, has_permissions=False): user, profile, share = self.share_details update_user_attributes( user, profile, dict(new_token_required=False), save=True) with mock.patch('open_facebook.api.OpenFacebook') as mocked: instance = mocked.return_value instance.set = Mock(side_effect=error) instance.has_permissions = Mock(return_value=has_permissions) instance.access_token = get_user_attribute( user, profile, 'access_token') share.send(graph=instance) self.assertEqual(share.error_message, expected_error_message) self.assertFalse(share.completed_at) user = get_user_model().objects.get(id=user.id) if profile: profile = get_profile_model().objects.get(id=profile.id) new_token_required = get_user_attribute( user, profile, 'new_token_required') self.assertEqual(new_token_required, expected_new_token)
def test_update_access_token(self): request = RequestMock().get('/') request.session = {} request.user = AnonymousUser() graph = get_persistent_graph(request, access_token='paul') action, user = connect_user(self.request, facebook_graph=graph) first_user_id = user.id # new token required should start out as False profile = try_get_profile(user) new_token_required = get_user_attribute(user, profile, 'new_token_required') self.assertEqual(new_token_required, False) # we manually set it to true update_user_attributes(user, profile, dict(new_token_required=True), save=True) if profile: profile = get_profile_model().objects.get(id=profile.id) user = get_user_model().objects.get(id=user.id) new_token_required = get_user_attribute(user, profile, 'new_token_required') self.assertEqual(new_token_required, True) # another update should however set it back to False request.facebook = None graph = get_facebook_graph(request, access_token='paul2') logger.info('and the token is %s', graph.access_token) action, user = connect_user(self.request, facebook_graph=graph) user = get_user_model().objects.get(id=user.id) self.assertEqual(user.id, first_user_id) if profile: profile = get_profile_model().objects.get(id=profile.id) user = get_user_model().objects.get(id=user.id) new_token_required = get_user_attribute(user, profile, 'new_token_required') self.assertEqual(new_token_required, False)
def test_update_access_token(self): request = RequestMock().get('/') request.session = {} request.user = AnonymousUser() graph = get_persistent_graph(request, access_token='paul') action, user = connect_user(self.request, facebook_graph=graph) first_user_id = user.id # new token required should start out as False profile = try_get_profile(user) new_token_required = get_user_attribute( user, profile, 'new_token_required') self.assertEqual(new_token_required, False) # we manually set it to true update_user_attributes( user, profile, dict(new_token_required=True), save=True) if profile: profile = get_profile_model().objects.get(id=profile.id) user = get_user_model().objects.get(id=user.id) new_token_required = get_user_attribute( user, profile, 'new_token_required') self.assertEqual(new_token_required, True) # another update should however set it back to False request.facebook = None graph = get_facebook_graph(request, access_token='paul2') logger.info('and the token is %s', graph.access_token) action, user = connect_user(self.request, facebook_graph=graph) user = get_user_model().objects.get(id=user.id) self.assertEqual(user.id, first_user_id) if profile: profile = get_profile_model().objects.get(id=profile.id) user = get_user_model().objects.get(id=user.id) new_token_required = get_user_attribute( user, profile, 'new_token_required') self.assertEqual(new_token_required, False)
def _update_user(user, facebook, overwrite=True): ''' Updates the user and his/her profile with the data from facebook ''' # 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_data = facebook.facebook_registration_data(username=False) facebook_fields = ['facebook_name', 'facebook_profile_url', 'gender', 'date_of_birth', 'about_me', 'website_url', 'first_name', 'last_name'] profile = try_get_profile(user) # which attributes to update attributes_dict = {} # send the signal that we're updating signals.facebook_pre_update.send(sender=get_user_model(), user=user, profile=profile, facebook_data=facebook_data) # set the facebook id and make sure we are the only user with this id current_facebook_id = get_user_attribute(user, profile, 'facebook_id') facebook_id_changed = facebook_data['facebook_id'] != current_facebook_id overwrite_allowed = overwrite or not current_facebook_id # update the facebook id and access token facebook_id_overwritten = False if facebook_id_changed and overwrite_allowed: # when not overwriting we only update if there is no # profile.facebook_id logger.info('profile facebook id changed from %s to %s', repr(facebook_data['facebook_id']), repr(current_facebook_id)) attributes_dict['facebook_id'] = facebook_data['facebook_id'] facebook_id_overwritten = True if facebook_id_overwritten: _remove_old_connections(facebook_data['facebook_id'], user.id) # update all fields on both user and profile for f in facebook_fields: facebook_value = facebook_data.get(f, False) current_value = get_user_attribute(user, profile, f, None) if facebook_value and not current_value: attributes_dict[f] = facebook_value # write the raw data in case we missed something serialized_fb_data = json.dumps(facebook.facebook_profile_data()) current_raw_data = get_user_attribute(user, profile, 'raw_data') if current_raw_data != serialized_fb_data: attributes_dict['raw_data'] = serialized_fb_data image_url = facebook_data['image'] # update the image if we are allowed and have to if facebook_settings.FACEBOOK_STORE_LOCAL_IMAGE: image_field = get_user_attribute(user, profile, 'image', True) if not image_field: image_name, image_file = _update_image( facebook_data['facebook_id'], image_url) image_field.save(image_name, image_file) # save both models if they changed update_user_attributes(user, profile, attributes_dict) if getattr(user, '_fb_is_dirty', False): user.save() if getattr(profile, '_fb_is_dirty', False): profile.save() signals.facebook_post_update.send(sender=get_user_model(), user=user, profile=profile, facebook_data=facebook_data) return user
def _update_user(user, facebook, overwrite=True): ''' Updates the user and his/her profile with the data from facebook ''' # 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_data = facebook.facebook_registration_data(username=False) facebook_fields = [ 'facebook_name', 'facebook_profile_url', 'gender', 'date_of_birth', 'about_me', 'website_url', 'first_name', 'last_name' ] # prepare first_name and last_name name = facebook_data.get('name', ' ').split() if len(name): facebook_data['first_name'] = name[0] if len(name) > 1: facebook_data['last_name'] = ' '.join(name[1:]) facebook_data['facebook_profile_url'] = facebook_data.get('image') profile = try_get_profile(user) # which attributes to update attributes_dict = {} # send the signal that we're updating signals.facebook_pre_update.send(sender=get_user_model(), user=user, profile=profile, facebook_data=facebook_data) # set the facebook id and make sure we are the only user with this id current_facebook_id = get_user_attribute(user, profile, 'facebook_id') facebook_id_changed = facebook_data['facebook_id'] != current_facebook_id overwrite_allowed = overwrite or not current_facebook_id # update the facebook id and access token facebook_id_overwritten = False if facebook_id_changed and overwrite_allowed: # when not overwriting we only update if there is no # profile.facebook_id logger.info('profile facebook id changed from %s to %s', repr(facebook_data['facebook_id']), repr(current_facebook_id)) attributes_dict['facebook_id'] = facebook_data['facebook_id'] facebook_id_overwritten = True if facebook_id_overwritten: _remove_old_connections(facebook_data['facebook_id'], user.id) # update all fields on both user and profile for f in facebook_fields: facebook_value = facebook_data.get(f, False) current_value = get_user_attribute(user, profile, f, None) if facebook_value and not current_value: attributes_dict[f] = facebook_value # write the raw data in case we missed something serialized_fb_data = json.dumps(facebook.facebook_profile_data()) current_raw_data = get_user_attribute(user, profile, 'raw_data') if current_raw_data != serialized_fb_data: attributes_dict['raw_data'] = serialized_fb_data image_url = facebook_data['image'] # update the image if we are allowed and have to if facebook_settings.FACEBOOK_STORE_LOCAL_IMAGE: image_field = get_user_attribute(user, profile, 'image', True) if not image_field: image_name, image_file = _update_image( facebook_data['facebook_id'], image_url) image_field.save(image_name, image_file) # save both models if they changed update_user_attributes(user, profile, attributes_dict) if getattr(user, '_fb_is_dirty', False): user.save() if getattr(profile, '_fb_is_dirty', False): profile.save() signals.facebook_post_update.send(sender=get_user_model(), user=user, profile=profile, facebook_data=facebook_data) return user
def update_user_profile(user): graph = user.get_offline_graph() user_details = graph.get("me") del user_details['id'] update_user_attributes(user, None, user_details, save=True)