def _ValidateUploadOneContact(contact):
        contact = deepcopy(contact)

        # Transform into proper form for Contact.CalculateContactId()
        identities_properties = [
            (identity_properties['identity'],
             identity_properties.get('description', None))
            for identity_properties in contact['identities']
        ]
        contact.pop('identities')
        contact_dict = Contact.CreateContactDict(user_id,
                                                 identities_properties,
                                                 op_dict['op_timestamp'],
                                                 **contact)
        predicate = lambda c: c.contact_id == contact_dict['contact_id']
        existing_contacts = validator.QueryModelObjects(Contact,
                                                        predicate=predicate)
        # Create contact if it doesn't already exist or it's in a 'removed' state.
        if len(existing_contacts) == 0 or existing_contacts[-1].IsRemoved():
            if len(existing_contacts) != 0:
                # Delete the 'removed' contact.
                validator.ValidateDeleteDBObject(
                    Contact, DBKey(user_id, existing_contacts[-1].sort_key))
            validator.ValidateCreateContact(**contact_dict)
        return contact_dict['contact_id']
Exemple #2
0
    def testMergeWithContacts(self):
        """Test merge in which another user has the source user as a contact."""
        # Create user #1 contacts for user #2 and user #3.
        exp_contacts = []
        for user, identity in zip(self._users[1:], self._identities[1:]):
            contact_dict = Contact.CreateContactDict(self._user.user_id,
                                                     [(identity.key, None)],
                                                     util._TEST_TIME,
                                                     Contact.GMAIL)
            exp_contacts.append({
                'contact_id':
                contact_dict['contact_id'],
                'contact_source':
                contact_dict['contact_source'],
                'identities': [{
                    'identity': identity.key,
                    'user_id': 3
                }]
            })
            self._UpdateOrAllocateDBObject(Contact, **contact_dict)

        # Merge user #2 into user #3. Contact's user id should be updated.
        self._tester.MergeAccounts(self._cookie3,
                                   source_user_cookie=self._confirmed_cookie2)
        self.assertEqual(
            sorted(self._tester.QueryContacts(self._cookie)['contacts']),
            sorted(exp_contacts))

        # Remove cookie so that base class won't try to validate its user's assets (and fail).
        self._cookies.remove(self._cookie2)
Exemple #3
0
  def testRegisterProspectiveContact(self):
    """Register an identity that is the target of a contact (that is still a prospective user)."""
    for user_id in [self._user.user_id, self._user2.user_id]:
      # Create several contacts.
      identity_key = 'Email:%s' % self._prospective_user.email
      contact_dict = Contact.CreateContactDict(user_id,
                                               [(identity_key, None)],
                                               util._TEST_TIME,
                                               Contact.GMAIL,
                                               name='Mr. John')
      self._UpdateOrAllocateDBObject(Contact, **contact_dict)

    # Register the prospective user.
    user, device_id = self._tester.RegisterViewfinderUser(self._register_user_dict)

    # Expect friend & contact notifications.
    response_dict = self._tester.QueryNotifications(self._cookie, 2, scan_forward=False)
    self.assertEqual([notify_dict['name'] for notify_dict in response_dict['notifications']],
                     ['register friend', 'first register contact'])

    # Expect only contact notification.
    response_dict = self._tester.QueryNotifications(self._cookie2, 1, scan_forward=False)
    self.assertEqual([notify_dict['name'] for notify_dict in response_dict['notifications']],
                     ['first register contact'])

    # Expect only friend notification.
    cookie = self._GetSecureUserCookie(self._prospective_user, self._prospective_user.webapp_dev_id)
    response_dict = self._tester.QueryNotifications(cookie, 2, scan_forward=False)
    self.assertEqual([notify_dict['name'] for notify_dict in response_dict['notifications']],
                     ['register friend', 'share_new'])
 def _CreateSimpleContacts(self):
   """Create multiple unbound contacts for user #1 and user #2."""
   for user_id in [self._user.user_id, self._user2.user_id]:
     for identity_key in ['Local:identity1', 'Local:identity2']:
       contact_dict = Contact.CreateContactDict(user_id,
                                                [('Phone:+13191234567', 'mobile'), (identity_key, None)],
                                                util._TEST_TIME,
                                                Contact.GMAIL)
       self._UpdateOrAllocateDBObject(Contact, **contact_dict)
Exemple #5
0
    def testUnlinkContacts(self):
        """Test unlinking identity that is referenced by contacts."""
        for i in xrange(3):
            contact_dict = Contact.CreateContactDict(
                self._users[i].user_id, [('FacebookGraph:100', None)],
                util._TEST_TIME,
                Contact.FACEBOOK,
                rank=i)
            self._UpdateOrAllocateDBObject(Contact, **contact_dict)

        self._tester.LinkFacebookUser({'id': 100}, user_cookie=self._cookie)
        response_dict = self._tester.QueryContacts(
            self._cookie2,
            start_key=Contact.CreateSortKey(None, util._TEST_TIME))
        self.assertEqual(len(response_dict['contacts']), 1)

        # Now unlink the identity and make sure contacts are updated.
        util._TEST_TIME += 1
        self._tester.UnlinkIdentity(self._cookie, 'FacebookGraph:100')
        response_dict = self._tester.QueryContacts(
            self._cookie2,
            start_key=Contact.CreateSortKey(None, util._TEST_TIME))
        self.assertEqual(len(response_dict['contacts']), 1)

        # Now repeat, but with older contacts.
        util._TEST_TIME += 1
        timestamp = time.time() - 100
        for i in xrange(3):
            contact_dict = Contact.CreateContactDict(
                self._users[i].user_id, [('FacebookGraph:101', None)],
                timestamp,
                Contact.FACEBOOK,
                rank=i)
            contact = self._UpdateOrAllocateDBObject(Contact, **contact_dict)

        self._tester.LinkFacebookUser({'id': 101}, user_cookie=self._cookie)
        self._tester.UnlinkIdentity(self._cookie, 'FacebookGraph:101')
        response_dict = self._tester.QueryContacts(
            self._cookie3,
            start_key=Contact.CreateSortKey(None, util._TEST_TIME))
        self.assertEqual(len(response_dict['contacts']), 1)
    def testTerminateWithContact(self):
        """Terminate user account to which a contact was linked."""
        # Create contact for user #1
        identity_key = 'Email:[email protected]'
        contact_dict = Contact.CreateContactDict(
            self._user.user_id, [('Email:[email protected]', None)],
            util._TEST_TIME, Contact.GMAIL)
        self._UpdateOrAllocateDBObject(Contact, **contact_dict)

        self._tester.TerminateAccount(self._cookie3)
        response_dict = self._tester.QueryNotifications(self._cookie,
                                                        1,
                                                        scan_forward=False)
        self.assertEqual(response_dict['notifications'][0]['name'],
                         'unlink_identity')

        # Remove cookie so that base class won't try to validate its user's assets (and fail).
        self._cookies.remove(self._cookie3)
Exemple #7
0
  def testRegisterContact(self):
    """Register an identity that is the target of a contact, which will
    be bound to a user_id as a result.
    """
    # Create a contact.
    user_dict = {'name': 'Andrew Kimball', 'email': '*****@*****.**', 'verified_email': True}
    identity_key = 'Email:%s' % user_dict['email']
    contact_dict = Contact.CreateContactDict(self._user.user_id,
                                             [(identity_key, None)],
                                             util._TEST_TIME,
                                             Contact.GMAIL,
                                             name=user_dict['name'])
    self._UpdateOrAllocateDBObject(Contact, **contact_dict)

    # Register the new user.
    user, device_id = self._tester.RegisterGoogleUser(user_dict)
    response_dict = self._tester.QueryNotifications(self._cookie, 1, scan_forward=False)
    self.assertEqual([notify_dict['name'] for notify_dict in response_dict['notifications']],
                     ['first register contact'])
Exemple #8
0
    def _CreateContact(self,
                       identities_properties,
                       no_identity=False,
                       **kwargs):
        if not no_identity:
            for identity_properties in identities_properties:
                contact_user_id = identity_properties[2] if len(
                    identity_properties) > 2 else None
                self._UpdateOrAllocateDBObject(Identity,
                                               key=Identity.Canonicalize(
                                                   identity_properties[0]),
                                               user_id=contact_user_id)

        contact_identities_properties = []
        for identity_properties in identities_properties:
            contact_identities_properties.append(identity_properties[:2])

        contact_dict = Contact.CreateContactDict(
            self._user.user_id, contact_identities_properties, util._TEST_TIME,
            Contact.GMAIL, **kwargs)
        self._UpdateOrAllocateDBObject(Contact, **contact_dict)
Exemple #9
0
    def testLinkWithContacts(self):
        """Test link of an identity which another user has as a contact."""
        # Create contact for user #1
        identity_key = 'Email:[email protected]'
        contact_dict = Contact.CreateContactDict(self._user.user_id,
                                                 [(identity_key, None)],
                                                 util._TEST_TIME,
                                                 Contact.GMAIL)
        self._UpdateOrAllocateDBObject(Contact, **contact_dict)

        # Link the identity to user #2 and verify that user #1 is notified.
        source_identity_dict = self._TestGenerateMergeToken(
            identity_key, user_cookie=self._cookie2)
        self._tester.MergeAccounts(self._cookie2,
                                   source_identity_dict=source_identity_dict)

        response_dict = self._tester.QueryNotifications(self._cookie,
                                                        1,
                                                        scan_forward=False)
        self.assertEqual(response_dict['notifications'][0]['name'],
                         'link identity')
    def _Check(self):
        """Check and prepare for update.
    Query for all of the existing contacts of the user so that any non-removed matches can be skipped and removed
      matches can be replaced.
    Complete construction of the contact dict.
    Check that the upload won't cause the max number of contacts to be exceeded.
    """
        existing_contacts_dict, self._contacts_to_delete = \
            yield UploadContactsOperation._GetAllContactsWithDedup(self._client, self._user_id)

        # Total count of non-removed contacts.  Excludes contacts which will be deleted during update phase.
        total_contact_count = 0
        for existing_contact in existing_contacts_dict.itervalues():
            if not existing_contact.IsRemoved():
                total_contact_count += 1

        # Complete construction of contact dict and sort out which contacts should be deleted/inserted/skipped.
        for contact in self._request_contacts:
            request_contact = Contact.CreateContactDict(
                user_id=self._user_id,
                timestamp=self._notify_timestamp,
                **contact)
            existing_contact = existing_contacts_dict.get(
                request_contact['contact_id'], None)
            if existing_contact is None:
                # No sign of this contact on the server, so we'll insert it.
                self._contact_dicts_to_insert.append((request_contact, None))
                total_contact_count += 1
            elif existing_contact.IsRemoved():
                # If it's removed, we'll replace it.
                self._contact_dicts_to_insert.append(
                    (request_contact, existing_contact))
                # Bump total contact count because this contact is transitioning from removed to present.
                total_contact_count += 1
            # else case is no-op because this contact is already present (non-removed).

        # Check if we're exceeding any limits with this upload.
        if total_contact_count > Contact.MAX_CONTACTS_LIMIT:
            raise LimitExceededError(UPLOAD_CONTACTS_EXCEEDS_LIMIT)
  def testSupportMultipleIdentitiesPerContact(self):
    """Ensure that the SUPPORT_MULTIPLE_IDENTITIES_PER_CONTACT migration works correctly."""
    identity_key = 'Email:' + self._user2.email

    # Create an identity to exercise the 'contact_user_id' field of the down-level response.
    self._UpdateOrAllocateDBObject(Identity, key=identity_key, user_id=21)

    # This contact is for a registered user.
    contact_dict = Contact.CreateContactDict(user_id=self._user.user_id,
                                             identities_properties=[(identity_key, 'work'),
                                                                    ('Email:' + self._user3.email, 'home'),
                                                                    ('Phone:+13191234567', 'mobile')],
                                             timestamp=1,
                                             contact_source=Contact.GMAIL,
                                             name='Mike Purtell',
                                             given_name='Mike',
                                             family_name='Purtell',
                                             rank=3)
    self._UpdateOrAllocateDBObject(Contact, **contact_dict)

    # This contact has been removed and shouldn't show up in down-level client queries.
    contact_dict = Contact.CreateContactDict(user_id=self._user.user_id,
                                             identities_properties=None,
                                             timestamp=1,
                                             contact_source=Contact.GMAIL,
                                             contact_id='gm:onetwothree',
                                             sort_key=Contact.CreateSortKey('gm:onetwothree', 1),
                                             labels=[Contact.REMOVED])
    self._UpdateOrAllocateDBObject(Contact, **contact_dict)

    # This contact has unknown identities.
    contact_dict = Contact.CreateContactDict(user_id=self._user.user_id,
                                             identities_properties=[('Email:[email protected]', 'work'),
                                                                    ('Email:[email protected]', 'home'),
                                                                    ('Phone:+13191234567', 'mobile')],
                                             timestamp=1,
                                             contact_source=Contact.GMAIL,
                                             name='Some One',
                                             given_name='Some',
                                             family_name='Body',
                                             rank=5)
    self._UpdateOrAllocateDBObject(Contact, **contact_dict)

    # This contact has just a phone number and shouldn't show up in down-level client queries.
    contact_dict = Contact.CreateContactDict(user_id=self._user.user_id,
                                             identities_properties=[('Phone:+13191234567', 'mobile')],
                                             timestamp=1,
                                             contact_source=Contact.GMAIL,
                                             name='Some One with just a phone',
                                             given_name='Some',
                                             family_name='Body',
                                             rank=42)
    self._UpdateOrAllocateDBObject(Contact, **contact_dict)

    # This contact has no identities and shouldn't show up in down-level client queries.
    contact_dict = Contact.CreateContactDict(user_id=self._user.user_id,
                                             identities_properties=[],
                                             timestamp=1,
                                             contact_source=Contact.GMAIL,
                                             name='Some One with just a phone',
                                             given_name='Some',
                                             family_name='Body',
                                             rank=42)
    self._UpdateOrAllocateDBObject(Contact, **contact_dict)

    response = self._SendRequest('query_contacts', self._cookie, {}, version=Message.SUPPRESS_BLANK_COVER_PHOTO)

    # Verify response is what we expect for down-level client.
    self.assertEqual(response['headers'], {'version': Message.SUPPRESS_BLANK_COVER_PHOTO})
    self.assertEqual(response['num_contacts'], 2)
    response_contact = response['contacts'][1]
    self.assertEqual(response_contact['name'], 'Mike Purtell')
    self.assertEqual(response_contact['given_name'], 'Mike')
    self.assertEqual(response_contact['family_name'], 'Purtell')
    self.assertEqual(response_contact['rank'], 3)
    self.assertEqual(response_contact['contact_user_id'], 21)
    self.assertEqual(response_contact['identity'], identity_key)
    self.assertFalse('identities' in response_contact)
    self.assertFalse('contact_id' in response_contact)
    self.assertFalse('contact_source' in response_contact)
    self.assertFalse('labels' in response_contact)

    response_contact = response['contacts'][0]
    self.assertEqual(response_contact['name'], 'Some One')
    self.assertEqual(response_contact['given_name'], 'Some')
    self.assertEqual(response_contact['family_name'], 'Body')
    self.assertEqual(response_contact['rank'], 5)
    self.assertEqual(response_contact['identity'], 'Email:[email protected]')
    self.assertFalse('contact_user_id' in response_contact)
    self.assertFalse('identities' in response_contact)
    self.assertFalse('contact_id' in response_contact)
    self.assertFalse('contact_source' in response_contact)
    self.assertFalse('labels' in response_contact)
Exemple #12
0
    def testAlerts(self):
        """Test that correct alerts are sent for various operations."""
        # Start with share to user #2.
        vp_id, ep_ids = self._tester.ShareNew(
            self._cookie, [(self._episode_id, self._photo_ids)],
            [self._user2.user_id])

        notification = TestService.Instance().GetNotifications('device2')[0]
        self.assertEqual(
            notification, {
                'sound': 'default',
                'expiry': None,
                'badge': 1,
                'extra': {
                    'v': vp_id
                },
                'alert': u'user1 shared 2 photos'
            })

        # Now share again to user #2 (same viewpoint).
        self._tester.ShareExisting(self._cookie, vp_id,
                                   [(self._episode_id2, self._photo_ids2[:1])])
        notification = TestService.Instance().GetNotifications('device2')[1]
        self.assertEqual(
            notification, {
                'sound': None,
                'expiry': None,
                'badge': 2,
                'extra': {
                    'v': vp_id
                },
                'alert': u'user1 shared 1 photo'
            })

        # Now share again to user #2 (different viewpoint).
        vp_id2, ep_ids2 = self._tester.ShareNew(
            self._cookie, [(self._episode_id2, self._photo_ids2)],
            [self._user2.user_id],
            title='A title')
        notification = TestService.Instance().GetNotifications('device2')[2]
        self.assertEqual(
            notification, {
                'sound': 'default',
                'expiry': None,
                'badge': 3,
                'extra': {
                    'v': vp_id2
                },
                'alert': u'user1 started a conversation: "A title"'
            })

        # Update user #2's viewed_seq on first viewpoint, and then post comment.
        self._tester.UpdateFollower(self._cookie2, vp_id, viewed_seq=2)
        self._tester.PostComment(self._cookie, vp_id, 'a comment')
        notification = TestService.Instance().GetNotifications('device2')[3]
        self.assertEqual(
            notification, {
                'sound': 'default',
                'expiry': None,
                'badge': 4,
                'extra': {
                    'v': vp_id
                },
                'alert': u'user1: a comment'
            })

        # Register a contact.
        contact_dict = Contact.CreateContactDict(
            self._user.user_id, [('Email:[email protected]', None)],
            util._TEST_TIME,
            Contact.GMAIL,
            name='Andy')
        self._UpdateOrAllocateDBObject(Contact, **contact_dict)

        user_dict = {
            'email': '*****@*****.**',
            'name': 'Andy Kimball',
            'given_name': 'Andy'
        }
        self._tester.RegisterViewfinderUser(user_dict)

        notification = TestService.Instance().GetNotifications('device1')[0]
        self.assertEqual(
            notification, {
                'sound': 'default',
                'expiry': None,
                'badge': None,
                'extra': None,
                'alert': 'Andy Kimball has joined Viewfinder'
            })