Beispiel #1
0
    def testOtherUserUpdatesIndex(self):
        # create a parent and child case (with index) from one user
        parent_id = "other_updates_index_parent"
        case_id = "other_updates_index_child"
        self._createCaseStubs([parent_id])

        child = CaseBlock(
            create=True,
            case_id=case_id,
            user_id=USER_ID,
            owner_id=USER_ID,
            version=V2,
            index={'mother': ('mother', parent_id)}
        ).as_xml()
        self._postFakeWithSyncToken(child, self.sync_log.get_id)

        assert_user_doesnt_have_case(self, self.user, parent_id, restore_id=self.sync_log.get_id)
        assert_user_doesnt_have_case(self, self.user, case_id, restore_id=self.sync_log.get_id)
        
        # assign the parent case away from same user
        parent_update = CaseBlock(
            create=False, 
            case_id=parent_id,
            user_id=USER_ID, 
            owner_id=OTHER_USER_ID,
            update={"greeting": "hello"}, 
            version=V2).as_xml()
        self._postFakeWithSyncToken(parent_update, self.sync_log.get_id)
        
        self.sync_log = SyncLog.get(self.sync_log.get_id)
        
        # these tests added to debug another issue revealed by this test
        self.assertTrue(self.sync_log.phone_has_case(case_id))
        self.assertTrue(self.sync_log.phone_has_dependent_case(parent_id))
        self.assertTrue(self.sync_log.phone_is_holding_case(case_id))
        self.assertTrue(self.sync_log.phone_is_holding_case(parent_id))
        
        # original user syncs again
        # make sure there are no new changes
        assert_user_doesnt_have_case(self, self.user, parent_id, restore_id=self.sync_log.get_id,
                                     purge_restore_cache=True)
        assert_user_doesnt_have_case(self, self.user, case_id, restore_id=self.sync_log.get_id)

        assert_user_has_case(self, self.other_user, parent_id, restore_id=self.other_sync_log.get_id,
                             purge_restore_cache=True)
        # update the parent case from another user
        self.other_sync_log = SyncLog.last_for_user(OTHER_USER_ID)
        other_parent_update = CaseBlock(
            create=False,
            case_id=parent_id,
            user_id=OTHER_USER_ID,
            update={"greeting2": "hi"},
            version=V2
        ).as_xml()
        self._postFakeWithSyncToken(other_parent_update, self.other_sync_log.get_id)
        
        # make sure the indexed case syncs again
        self.sync_log = SyncLog.last_for_user(USER_ID)
        assert_user_has_case(self, self.user, parent_id, restore_id=self.sync_log.get_id,
                             purge_restore_cache=True)
Beispiel #2
0
    def testMultiUserEdits(self):
        # create a case from one user
        case_id = "multi_user_edits"
        self._createCaseStubs([case_id], owner_id=SHARED_ID)

        # both users syncs
        generate_restore_payload(self.user)
        generate_restore_payload(self.other_user)
        self.sync_log = SyncLog.last_for_user(USER_ID)
        self.other_sync_log = SyncLog.last_for_user(OTHER_USER_ID)

        # update case from same user
        my_change = CaseBlock(
            create=False,
            case_id=case_id,
            user_id=USER_ID,
            version=V2,
            update={'greeting': 'hello'}
        ).as_xml()
        self._postFakeWithSyncToken(
            my_change,
            self.sync_log.get_id
        )

        # update from another user
        their_change = CaseBlock(
            create=False,
            case_id=case_id,
            user_id=USER_ID,
            version=V2,
            update={'greeting_2': 'hello'}
        ).as_xml()
        self._postFakeWithSyncToken(
            their_change,
            self.other_sync_log.get_id
        )

        # original user syncs again
        # make sure updates both appear (and merge?)
        joint_change = CaseBlock(
            create=False,
            case_id=case_id,
            user_id=USER_ID,
            version=V2,
            update={
                'greeting': 'hello',
                'greeting_2': 'hello'
            },
            owner_id=SHARED_ID,
            case_name='',
            case_type='mother',
        ).as_xml()
        check_user_has_case(self, self.user, joint_change, restore_id=self.sync_log.get_id, version=V2)
        check_user_has_case(self, self.other_user, joint_change, restore_id=self.other_sync_log.get_id, version=V2)
Beispiel #3
0
 def testOtherUserEdits(self):
     # create a case by one user
     case_id = "other_user_edits"
     self._createCaseStubs([case_id], owner_id=SHARED_ID)
     
     # sync to the other's phone to be able to edit
     check_user_has_case(self, self.other_user, 
                         CaseBlock(case_id=case_id, version=V2).as_xml(), 
                         should_have=True, line_by_line=False,
                         restore_id=self.other_sync_log.get_id, version=V2)
     
     latest_sync = SyncLog.last_for_user(OTHER_USER_ID)
     # update from another
     self._postFakeWithSyncToken(
         CaseBlock(create=False, case_id=case_id, user_id=OTHER_USER_ID,
                   version=V2, update={'greeting': "Hello!"}
     ).as_xml(), latest_sync.get_id)
     
     # original user syncs again
     # make sure updates take
     updated_case = CaseBlock(create=False, case_id=case_id, user_id=USER_ID,
                              version=V2, update={'greeting': "Hello!"}).as_xml()
     match = check_user_has_case(self, self.user, updated_case, should_have=True,
                                 line_by_line=False, restore_id=self.sync_log.get_id,
                                 version=V2)
     self.assertTrue("Hello!" in ElementTree.tostring(match))
Beispiel #4
0
    def testOtherUserAddsIndex(self):
        # create a case from one user
        case_id = "other_user_adds_index"
        self._createCaseStubs([case_id], owner_id=SHARED_ID)

        # sync to the other's phone to be able to edit
        check_user_has_case(self, self.other_user,
            CaseBlock(case_id=case_id, version=V2).as_xml(),
            should_have=True, line_by_line=False,
            restore_id=self.other_sync_log.get_id, version=V2)

        latest_sync = SyncLog.last_for_user(OTHER_USER_ID)
        mother_id = "other_user_adds_index_mother"
        # parent case
        parent_case = CaseBlock(
            create=True,
            case_id=mother_id,
            user_id=OTHER_USER_ID,
            case_type=PARENT_TYPE,
            version=V2,
        ).as_xml()
             
        self._postFakeWithSyncToken(
            parent_case,
            latest_sync.get_id
        )
        # the original user should not get the parent case
        check_user_has_case(self, self.user, parent_case, should_have=False,
                            restore_id=self.sync_log.get_id, version=V2)
        
        # update the original case from another, adding an indexed case
        self._postFakeWithSyncToken(
            CaseBlock(
                create=False,
                case_id=case_id,
                user_id=OTHER_USER_ID,
                owner_id=USER_ID,
                version=V2,
                index={'mother': ('mother', mother_id)}
            ).as_xml(),
            latest_sync.get_id
        )

        # original user syncs again
        # make sure index updates take and indexed case also syncs
        expected_parent_case = CaseBlock(
            create=True,
            case_id=mother_id,
            user_id=OTHER_USER_ID,
            case_type=PARENT_TYPE,
            owner_id=OTHER_USER_ID,
            version=V2,
        ).as_xml()
        
        check_user_has_case(self, self.user, expected_parent_case, 
                            restore_id=self.sync_log.get_id, version=V2)
        orig = check_user_has_case(self, self.user, CaseBlock(case_id=case_id, version=V2).as_xml(),
                                   line_by_line=False, restore_id=self.sync_log.get_id, 
                                   version=V2)
        self.assertTrue("index" in ElementTree.tostring(orig))
Beispiel #5
0
    def testOtherUserUpdatesUnowned(self):
        # create a case from one user and assign ownership elsewhere
        case_id = "other_user_updates_unowned"
        self._createCaseStubs([case_id], owner_id=OTHER_USER_ID)

        # sync and update from another user
        assert_user_has_case(self,
                             self.other_user,
                             case_id,
                             restore_id=self.other_sync_log.get_id)

        self.other_sync_log = SyncLog.last_for_user(OTHER_USER_ID)
        update = CaseBlock(create=False,
                           case_id=case_id,
                           user_id=OTHER_USER_ID,
                           version=V2,
                           update={
                               'greeting': 'hello'
                           }).as_xml()
        self._postFakeWithSyncToken(update, self.other_sync_log.get_id)

        # original user syncs again
        # make sure there are no new changes
        assert_user_doesnt_have_case(self,
                                     self.user,
                                     case_id,
                                     restore_id=self.sync_log.get_id)
Beispiel #6
0
 def testOtherUserUpdatesUnowned(self):
     # create a case from one user and assign ownership elsewhere
     case_id = "other_user_updates_unowned"
     self._createCaseStubs([case_id], owner_id=OTHER_USER_ID)
     
     # sync and update from another user
     check_user_has_case(self, self.other_user,
         CaseBlock(case_id=case_id, version=V2).as_xml(),
         should_have=True, line_by_line=False,
         restore_id=self.other_sync_log.get_id, version=V2)
     
     self.other_sync_log = SyncLog.last_for_user(OTHER_USER_ID)
     update = CaseBlock(
         create=False,
         case_id=case_id,
         user_id=OTHER_USER_ID,
         version=V2,
         update={'greeting': 'hello'}
     ).as_xml()
     self._postFakeWithSyncToken(
         update,
         self.other_sync_log.get_id
     )
     
     # original user syncs again
     # make sure there are no new changes
     # sync and update from another user
     check_user_has_case(self, self.user, update, should_have=False, 
                         restore_id=self.sync_log.get_id, version=V2)
Beispiel #7
0
    def testOtherUserEdits(self):
        # create a case by one user
        case_id = "other_user_edits"
        self._createCaseStubs([case_id], owner_id=SHARED_ID)

        # sync to the other's phone to be able to edit
        assert_user_has_case(self,
                             self.other_user,
                             case_id,
                             restore_id=self.other_sync_log.get_id)

        latest_sync = SyncLog.last_for_user(OTHER_USER_ID)
        # update from another
        self._postFakeWithSyncToken(
            CaseBlock(create=False,
                      case_id=case_id,
                      user_id=OTHER_USER_ID,
                      version=V2,
                      update={
                          'greeting': "Hello!"
                      }).as_xml(), latest_sync.get_id)

        # original user syncs again
        # make sure updates take
        match = assert_user_has_case(self,
                                     self.user,
                                     case_id,
                                     restore_id=self.sync_log.get_id)
        self.assertTrue("Hello!" in ElementTree.tostring(match))
Beispiel #8
0
    def rows(self):
        rows = []

        user_ids = map(lambda user: user.user_id, self.users)
        user_xform_dicts_map = get_last_form_submissions_by_user(
            self.domain, user_ids, self.selected_app_id)

        for user in self.users:
            xform_dict = last_seen = last_sync = app_name = None

            if user_xform_dicts_map.get(user.user_id):
                xform_dict = user_xform_dicts_map[user.user_id][0]

            if xform_dict:
                last_seen = string_to_utc_datetime(
                    xform_dict.get('received_on'))

                if xform_dict.get('app_id'):
                    try:
                        app = get_app(self.domain, xform_dict.get('app_id'))
                    except ResourceNotFound:
                        pass
                    else:
                        app_name = app.name
                else:
                    app_name = get_meta_appversion_text(
                        xform_dict['form']['meta'])

                app_version_info = get_app_version_info(
                    self.domain,
                    xform_dict.get('build_id'),
                    xform_dict.get('version'),
                    xform_dict['form']['meta'],
                )
                build_html = _build_html(app_version_info)
                commcare_version = ('CommCare {}'.format(
                    app_version_info.commcare_version)
                                    if app_version_info.commcare_version else
                                    _("Unknown CommCare Version"))
                commcare_version_html = mark_safe(
                    '<span class="label label-info">{}</span>'.format(
                        commcare_version))
                app_name = app_name or _("Unknown App")
                app_name = format_html(u'{} {} {}', app_name,
                                       mark_safe(build_html),
                                       commcare_version_html)

            if app_name is None and self.selected_app_id:
                continue

            last_sync_log = SyncLog.last_for_user(user.user_id)
            if last_sync_log:
                last_sync = last_sync_log.date

            rows.append([
                user.username_in_report,
                _fmt_date(last_seen),
                _fmt_date(last_sync), app_name or "---"
            ])
        return rows
Beispiel #9
0
    def testOtherUserAddsIndex(self):
        time = datetime.utcnow()

        # create a case from one user
        case_id = "other_user_adds_index"
        self._createCaseStubs([case_id], owner_id=SHARED_ID)

        # sync to the other's phone to be able to edit
        assert_user_has_case(self, self.other_user, case_id, restore_id=self.other_sync_log.get_id)

        latest_sync = SyncLog.last_for_user(OTHER_USER_ID)
        mother_id = "other_user_adds_index_mother"

        parent_case = CaseBlock(
            create=True,
            date_modified=time,
            case_id=mother_id,
            user_id=OTHER_USER_ID,
            case_type=PARENT_TYPE,
            version=V2,
        ).as_xml(format_datetime=json_format_datetime)

        self._postFakeWithSyncToken(
            parent_case,
            latest_sync.get_id
        )
        # the original user should not get the parent case
        assert_user_doesnt_have_case(self, self.user, mother_id, restore_id=self.sync_log.get_id)

        # update the original case from another, adding an indexed case
        self._postFakeWithSyncToken(
            CaseBlock(
                create=False,
                case_id=case_id,
                user_id=OTHER_USER_ID,
                owner_id=USER_ID,
                version=V2,
                index={'mother': ('mother', mother_id)}
            ).as_xml(format_datetime=json_format_datetime),
            latest_sync.get_id
        )

        # original user syncs again
        # make sure index updates take and indexed case also syncs
        expected_parent_case = CaseBlock(
            create=True,
            date_modified=time,
            case_id=mother_id,
            user_id=OTHER_USER_ID,
            case_type=PARENT_TYPE,
            owner_id=OTHER_USER_ID,
            version=V2,
        ).as_xml(format_datetime=json_format_datetime)

        check_user_has_case(self, self.user, expected_parent_case,
                            restore_id=self.sync_log.get_id, version=V2,
                            purge_restore_cache=True)
        _, orig = assert_user_has_case(self, self.user, case_id, restore_id=self.sync_log.get_id)
        self.assertTrue("index" in ElementTree.tostring(orig))
Beispiel #10
0
    def rows(self):
        rows = []

        user_ids = map(lambda user: user.user_id, self.users)
        user_xform_dicts_map = get_last_form_submissions_by_user(self.domain, user_ids, self.selected_app_id)

        for user in self.users:
            xform_dict = last_seen = last_sync = app_name = None
            app_version_info_from_form = app_version_info_from_sync = None
            if user_xform_dicts_map.get(user.user_id):
                xform_dict = user_xform_dicts_map[user.user_id][0]

            if xform_dict:
                last_seen = string_to_utc_datetime(xform_dict.get('received_on'))

                if xform_dict.get('app_id'):
                    try:
                        app = get_app(self.domain, xform_dict.get('app_id'))
                    except ResourceNotFound:
                        pass
                    else:
                        app_name = app.name
                else:
                    app_name = get_meta_appversion_text(xform_dict['form']['meta'])

                app_version_info_from_form = get_app_version_info(
                    self.domain,
                    xform_dict.get('build_id'),
                    xform_dict.get('version'),
                    xform_dict['form']['meta'],
                )

            if app_name is None and self.selected_app_id:
                continue

            last_sync_log = SyncLog.last_for_user(user.user_id)
            if last_sync_log:
                last_sync = last_sync_log.date
                if last_sync_log.build_id:
                    build_version = get_version_from_build_id(self.domain, last_sync_log.build_id)
                    app_version_info_from_sync = AppVersionInfo(
                        build_version,
                        app_version_info_from_form.commcare_version if app_version_info_from_form else None,
                        BuildVersionSource.BUILD_ID
                    )

            app_version_info_to_use = _choose_latest_version(
                app_version_info_from_sync, app_version_info_from_form,
            )

            commcare_version = _get_commcare_version(app_version_info_to_use)
            build_version = _get_build_version(app_version_info_to_use)

            rows.append([
                user.username_in_report, _fmt_date(last_seen), _fmt_date(last_sync),
                app_name or "---", build_version, commcare_version
            ])
        return rows
Beispiel #11
0
    def rows(self):
        rows = []
        selected_app = self.request_params.get(SelectApplicationFilter.slug, None)

        user_ids = map(lambda user: user.user_id, self.users)
        user_xform_dicts_map = get_last_form_submissions_by_user(self.domain, user_ids, selected_app)

        for user in self.users:
            xform_dict = last_seen = last_sync = app_name = None

            if user_xform_dicts_map.get(user.user_id):
                xform_dict = user_xform_dicts_map[user.user_id][0]

            if xform_dict:
                last_seen = string_to_utc_datetime(xform_dict.get('received_on'))

                if xform_dict.get('app_id'):
                    try:
                        app = get_app(self.domain, xform_dict.get('app_id'))
                    except ResourceNotFound:
                        pass
                    else:
                        app_name = app.name
                else:
                    app_name = get_meta_appversion_text(xform_dict['form']['meta'])

                app_version_info = get_app_version_info(
                    self.domain,
                    xform_dict.get('build_id'),
                    xform_dict.get('version'),
                    xform_dict['form']['meta'],
                )
                build_html = _build_html(app_version_info)
                commcare_version = (
                    'CommCare {}'.format(app_version_info.commcare_version)
                    if app_version_info.commcare_version
                    else _("Unknown CommCare Version")
                )
                commcare_version_html = mark_safe('<span class="label label-info">{}</span>'.format(
                    commcare_version)
                )
                app_name = app_name or _("Unknown App")
                app_name = format_html(
                    u'{} {} {}', app_name, mark_safe(build_html), commcare_version_html
                )

            if app_name is None and selected_app:
                continue

            last_sync_log = SyncLog.last_for_user(user.user_id)
            if last_sync_log:
                last_sync = last_sync_log.date

            rows.append(
                [user.username_in_report, _fmt_date(last_seen), _fmt_date(last_sync), app_name or "---"]
            )
        return rows
Beispiel #12
0
    def rows(self):
        rows = []
        selected_app = self.request_params.get(SelectApplicationFilter.slug,
                                               '')

        for user in self.users:
            last_seen = last_sync = app_name = None

            key = make_form_couch_key(self.domain,
                                      user_id=user.user_id,
                                      app_id=selected_app or None)
            xform = XFormInstance.view(
                "reports_forms/all_forms",
                startkey=key + [{}],
                endkey=key,
                include_docs=True,
                descending=True,
                reduce=False,
                limit=1,
            ).first()

            if xform:
                last_seen = xform.received_on
                build_version, build_version_source = get_build_version(xform)

                if xform.app_id:
                    try:
                        app = get_app(self.domain, xform.app_id)
                    except ResourceNotFound:
                        pass
                    else:
                        app_name = app.name
                else:
                    app_name = get_meta_appversion_text(xform)

                build_html = _build_html(build_version, build_version_source)
                app_name = app_name or _("Unknown App")
                app_name = format_html(
                    u'{} {}',
                    app_name,
                    mark_safe(build_html),
                )

            if app_name is None and selected_app:
                continue

            last_sync_log = SyncLog.last_for_user(user.user_id)
            if last_sync_log:
                last_sync = last_sync_log.date

            rows.append([
                user.username_in_report,
                _fmt_date(last_seen),
                _fmt_date(last_sync), app_name or "---"
            ])
        return rows
Beispiel #13
0
 def setUp(self):
     super(MultiUserSyncTest, self).setUp()
     # the other user is an "owner" of the original users cases as well,
     # for convenience
     self.other_user = User(user_id=OTHER_USER_ID, username="******",
                            password="******", date_joined=datetime(2011, 6, 9),
                            additional_owner_ids=[SHARED_ID])
     
     # this creates the initial blank sync token in the database
     generate_restore_payload(self.other_user)
     self.other_sync_log = SyncLog.last_for_user(OTHER_USER_ID)
     
     self.assertTrue(SHARED_ID in self.other_sync_log.owner_ids_on_phone)
     self.assertTrue(OTHER_USER_ID in self.other_sync_log.owner_ids_on_phone)
     
     self.user.additional_owner_ids = [SHARED_ID]
     generate_restore_payload(self.user)
     self.sync_log = SyncLog.last_for_user(self.user.user_id)
     self.assertTrue(SHARED_ID in self.sync_log.owner_ids_on_phone)
     self.assertTrue(USER_ID in self.sync_log.owner_ids_on_phone)
Beispiel #14
0
 def testComplicatedGatesBug(self):
     # found this bug in the wild, used the real (test) forms to fix it
     # just running through this test used to fail hard, even though there
     # are no asserts
     self.assertEqual(0, len(CommCareCase.view("case/by_user", reduce=False).all()))
     folder_path = os.path.join("bugs", "dependent_case_conflicts")
     files = ["reg1.xml", "reg2.xml", "cf.xml", "close.xml"]
     for f in files:
         form = self._postWithSyncToken(os.path.join(folder_path, f), self.sync_log.get_id)
         form = XFormInstance.get(form.get_id)
         self.assertFalse(hasattr(form, "problem"))
         generate_restore_payload(self.user, version="2.0")
         self.sync_log = SyncLog.last_for_user(self.user.user_id)
Beispiel #15
0
    def rows(self):
        rows = []
        selected_app = self.request_params.get(SelectApplicationFilter.slug, '')

        for user in self.users:
            last_seen = last_sync = app_name = None

            key = make_form_couch_key(self.domain, user_id=user.user_id,
                                      app_id=selected_app or None)
            xform = XFormInstance.view(
                "reports_forms/all_forms",
                startkey=key+[{}],
                endkey=key,
                include_docs=True,
                descending=True,
                reduce=False,
                limit=1,
            ).first()

            if xform:
                last_seen = xform.received_on
                build_version, build_version_source = get_build_version(xform)

                if xform.app_id:
                    try:
                        app = get_app(self.domain, xform.app_id)
                    except ResourceNotFound:
                        pass
                    else:
                        app_name = app.name
                else:
                    app_name = get_meta_appversion_text(xform)

                build_html = _build_html(build_version, build_version_source)
                app_name = app_name or _("Unknown App")
                app_name = format_html(
                    u'{} {}', app_name, mark_safe(build_html),
                )

            if app_name is None and selected_app:
                continue

            last_sync_log = SyncLog.last_for_user(user.user_id)
            if last_sync_log:
                last_sync = last_sync_log.date

            rows.append(
                [user.username_in_report, _fmt_date(last_seen), _fmt_date(last_sync), app_name or "---"]
            )
        return rows
Beispiel #16
0
 def test_build_id(self):
     app = Application(domain=self.domain)
     app.save()
     config = RestoreConfig(
         project=self.project,
         restore_user=self.restore_user,
         params=RestoreParams(app=app, ),
     )
     config.get_payload()  # this generates the sync log
     sync_log = SyncLog.last_for_user(self.restore_user.user_id)
     self.assertEqual(self.restore_user.user_id, sync_log.user_id)
     self.assertEqual(self.restore_user.domain, sync_log.domain)
     self.assertEqual(app._id, sync_log.build_id)
     self.addCleanup(app.delete)
Beispiel #17
0
    def rows(self):
        rows = []
        selected_app = self.request_params.get(SelectApplicationFilter.slug, None)

        for user in self.users:
            last_seen = last_sync = app_name = None

            xform = get_last_form_submission_for_user_for_app(
                self.domain, user.user_id, selected_app)

            if xform:
                last_seen = xform.received_on

                if xform.app_id:
                    try:
                        app = get_app(self.domain, xform.app_id)
                    except ResourceNotFound:
                        pass
                    else:
                        app_name = app.name
                else:
                    app_name = get_meta_appversion_text(xform)

                app_version_info = get_app_version_info(xform)
                build_html = _build_html(app_version_info)
                commcare_version = (
                    'CommCare {}'.format(app_version_info.commcare_version)
                    if app_version_info.commcare_version
                    else _("Unknown CommCare Version")
                )
                commcare_version_html = mark_safe('<span class="label label-info">{}</span>'.format(
                    commcare_version)
                )
                app_name = app_name or _("Unknown App")
                app_name = format_html(
                    u'{} {} {}', app_name, mark_safe(build_html), commcare_version_html
                )

            if app_name is None and selected_app:
                continue

            last_sync_log = SyncLog.last_for_user(user.user_id)
            if last_sync_log:
                last_sync = last_sync_log.date

            rows.append(
                [user.username_in_report, _fmt_date(last_seen), _fmt_date(last_sync), app_name or "---"]
            )
        return rows
Beispiel #18
0
 def test_build_id(self):
     app = Application(domain=self.domain)
     app.save()
     config = RestoreConfig(
         project=self.project,
         restore_user=self.restore_user,
         params=RestoreParams(
             app=app,
         ),
     )
     config.get_payload()  # this generates the sync log
     sync_log = SyncLog.last_for_user(self.restore_user.user_id)
     self.assertEqual(self.restore_user.user_id, sync_log.user_id)
     self.assertEqual(self.restore_user.domain, sync_log.domain)
     self.assertEqual(app._id, sync_log.build_id)
     self.addCleanup(app.delete)
Beispiel #19
0
    def rows(self):
        rows = []
        selected_app = self.request_params.get(SelectApplicationFilter.slug, None)

        for user in self.users:
            last_seen = last_sync = app_name = None

            xform = get_last_form_submission_for_user_for_app(
                self.domain, user.user_id, selected_app)

            if xform:
                last_seen = xform.received_on
                build_version, build_version_source = get_build_version(xform)

                if xform.app_id:
                    try:
                        app = get_app(self.domain, xform.app_id)
                    except ResourceNotFound:
                        pass
                    else:
                        app_name = app.name
                else:
                    app_name = get_meta_appversion_text(xform)

                build_html = _build_html(build_version, build_version_source)
                app_name = app_name or _("Unknown App")
                app_name = format_html(
                    u'{} {}', app_name, mark_safe(build_html),
                )

            if app_name is None and selected_app:
                continue

            last_sync_log = SyncLog.last_for_user(user.user_id)
            if last_sync_log:
                last_sync = last_sync_log.date

            rows.append(
                [user.username_in_report, _fmt_date(last_seen), _fmt_date(last_sync), app_name or "---"]
            )
        return rows
Beispiel #20
0
    def testOtherUserCloses(self):
        # create a case from one user
        case_id = "other_user_closes"
        self._createCaseStubs([case_id], owner_id=SHARED_ID)

        # sync then close case from another user
        generate_restore_payload(self.other_user)
        self.other_sync_log = SyncLog.last_for_user(OTHER_USER_ID)
        close_block = CaseBlock(
            create=False,
            case_id=case_id,
            user_id=USER_ID,
            version=V2,
            close=True
        ).as_xml()
        self._postFakeWithSyncToken(
            close_block,
            self.other_sync_log.get_id
        )
        
        # original user syncs again
        # make sure close block appears
        check_user_has_case(self, self.user, close_block, line_by_line=False,
                            restore_id=self.sync_log.get_id, version=V2)
Beispiel #21
0
    def rows(self):
        rows = []
        selected_app = self.request_params.get(SelectApplicationFilter.slug,
                                               '')

        def _fmt_date(date):
            def _timedelta_class(delta):
                if delta > timedelta(days=7):
                    return "label label-important"
                elif delta > timedelta(days=3):
                    return "label label-warning"
                else:
                    return "label label-success"

            if not date:
                return self.table_cell(
                    -1, '<span class="label">{0}</span>'.format(_("Never")))
            else:
                return self.table_cell(
                    date.toordinal(),
                    '<span class="{cls}">{text}</span>'.format(
                        cls=_timedelta_class(datetime.utcnow() - date),
                        text=naturaltime(date),
                    ))

        for user in self.users:
            last_seen = last_sync = app_name = None

            key = make_form_couch_key(self.domain,
                                      user_id=user.user_id,
                                      app_id=selected_app or None)
            xform = XFormInstance.view(
                "reports_forms/all_forms",
                startkey=key + [{}],
                endkey=key,
                include_docs=True,
                descending=True,
                reduce=False,
                limit=1,
            ).first()

            if xform:
                last_seen = xform.received_on
                build_version, build_version_source = get_build_version(xform)

                if xform.app_id:
                    try:
                        app = get_app(self.domain, xform.app_id)
                    except ResourceNotFound:
                        pass
                    else:
                        app_name = app.name
                else:
                    app_name = get_meta_appversion_text(xform)

                build_html = _build_html(build_version, build_version_source)
                app_name = app_name or _("Unknown App")
                app_name = format_html(
                    u'{} {}',
                    app_name,
                    mark_safe(build_html),
                )

            if app_name is None and selected_app:
                continue

            last_sync_log = SyncLog.last_for_user(user.user_id)
            if last_sync_log:
                last_sync = last_sync_log.date

            rows.append([
                user.username_in_report,
                _fmt_date(last_seen),
                _fmt_date(last_sync), app_name or "---"
            ])
        return rows
Beispiel #22
0
 def test_basic_properties(self):
     # kick off a restore to generate the sync log
     generate_restore_payload(self.project, self.restore_user, items=True)
     sync_log = SyncLog.last_for_user(self.restore_user.user_id)
     self.assertEqual(self.restore_user.user_id, sync_log.user_id)
     self.assertEqual(self.restore_user.domain, sync_log.domain)
    def testOtherUserReassignsIndexed(self):
        # create a parent and child case (with index) from one user
        parent_id = "other_reassigns_index_parent"
        case_id = "other_reassigns_index_child"
        self._createCaseStubs([parent_id])
        child = CaseBlock(
            create=True,
            case_id=case_id,
            user_id=USER_ID,
            owner_id=SHARED_ID,
            version=V2,
            index={'mother': ('mother', parent_id)}
        ).as_xml()
        self._postFakeWithSyncToken(child, self.sync_log.get_id)
        
        
        # assign the parent case away from the same user
        parent_update = CaseBlock(
            create=False, 
            case_id=parent_id,
            user_id=USER_ID, 
            owner_id=OTHER_USER_ID,
            update={"greeting": "hello"}, 
            version=V2).as_xml()
        self._postFakeWithSyncToken(parent_update, self.sync_log.get_id)
        
        # sync cases to second user
        self.other_sync_log = synclog_from_restore_payload(generate_restore_payload(self.other_user))
        # change the child's owner from another user
        child_reassignment = CaseBlock(
            create=False,
            case_id=case_id,
            user_id=OTHER_USER_ID,
            owner_id=OTHER_USER_ID,
            version=V2,
            update={"childgreeting": "hi!"}, 
        ).as_xml()
        self._postFakeWithSyncToken(child_reassignment, self.other_sync_log.get_id)
        
        # also change the parent from the second user
        other_parent_update = CaseBlock(
            create=False, 
            case_id=parent_id,
            user_id=OTHER_USER_ID, 
            owner_id=OTHER_USER_ID,
            update={"other_greeting": "something new"}, 
            version=V2).as_xml()
        self._postFakeWithSyncToken(other_parent_update, self.other_sync_log.get_id)
        
        # original user syncs again
        self.sync_log = SyncLog.last_for_user(self.user.user_id)
        # both cases should sync to original user with updated ownership / edits
        assert_user_has_case(self, self.user, case_id, restore_id=self.sync_log.get_id)
        assert_user_has_case(self, self.user, parent_id, restore_id=self.sync_log.get_id)

        # Ghetto
        payload = generate_restore_payload(self.user, self.sync_log.get_id, 
                                           version=V2)
        self.assertTrue("something new" in payload)
        self.assertTrue("hi!" in payload)
        
        # change the parent again from the second user
        other_parent_update = CaseBlock(
            create=False, 
            case_id=parent_id,
            user_id=OTHER_USER_ID, 
            owner_id=OTHER_USER_ID,
            update={"other_greeting": "something different"}, 
            version=V2).as_xml()
        self._postFakeWithSyncToken(other_parent_update, self.other_sync_log.get_id)
        
        
        # original user syncs again
        self.sync_log = SyncLog.last_for_user(self.user.user_id)
        # should be no changes
        assert_user_doesnt_have_case(self, self.user, case_id, restore_id=self.sync_log.get_id)
        assert_user_doesnt_have_case(self, self.user, parent_id, restore_id=self.sync_log.get_id)

        # change the child again from the second user
        other_child_update = CaseBlock(
            create=False,
            case_id=case_id,
            user_id=OTHER_USER_ID,
            owner_id=OTHER_USER_ID,
            version=V2,
            update={"childgreeting": "hi changed!"}, 
        ).as_xml()
        self._postFakeWithSyncToken(other_child_update, self.other_sync_log.get_id)
        
        # original user syncs again
        self.sync_log = SyncLog.last_for_user(self.user.user_id)
        # should be no changes
        assert_user_doesnt_have_case(self, self.user, case_id, restore_id=self.sync_log.get_id)
        assert_user_doesnt_have_case(self, self.user, parent_id, restore_id=self.sync_log.get_id)

        # change owner of child back to orginal user from second user
        child_reassignment = CaseBlock(
            create=False,
            case_id=case_id,
            user_id=OTHER_USER_ID,
            owner_id=USER_ID,
            version=V2
        ).as_xml()
        self._postFakeWithSyncToken(child_reassignment, self.other_sync_log.get_id)
        
        # original user syncs again
        self.sync_log = SyncLog.last_for_user(self.user.user_id)
        # both cases should now sync
        assert_user_has_case(self, self.user, case_id, restore_id=self.sync_log.get_id)
        assert_user_has_case(self, self.user, parent_id, restore_id=self.sync_log.get_id)

        # ghetto
        payload = generate_restore_payload(self.user, self.sync_log.get_id, 
                                           version=V2)
        self.assertTrue("something different" in payload)
        self.assertTrue("hi changed!" in payload)
Beispiel #24
0
    def rows(self):
        rows = []
        selected_app = self.request_params.get(SelectApplicationFilter.slug, '')

        def _fmt_date(date):
            def _timedelta_class(delta):
                if delta > timedelta(days=7):
                    return "label label-important"
                elif delta > timedelta(days=3):
                    return "label label-warning"
                else:
                    return "label label-success"

            if not date:
                return self.table_cell(-1, '<span class="label">{0}</span>'.format(_("Never")))
            else:
                return self.table_cell(date.toordinal(), '<span class="{cls}">{text}</span>'.format(
                    cls=_timedelta_class(datetime.utcnow() - date),
                    text=naturaltime(date),
                ))

        for user in self.users:
            last_seen = last_sync = app_name = None

            key = make_form_couch_key(self.domain, user_id=user.user_id,
                                      app_id=selected_app or None)
            xform = XFormInstance.view(
                "reports_forms/all_forms",
                startkey=key+[{}],
                endkey=key,
                include_docs=True,
                descending=True,
                reduce=False,
                limit=1,
            ).first()

            if xform:
                last_seen = xform.received_on
                build_version, build_version_source = get_build_version(xform)

                if xform.app_id:
                    try:
                        app = get_app(self.domain, xform.app_id)
                    except ResourceNotFound:
                        pass
                    else:
                        app_name = app.name
                else:
                    app_name = get_meta_appversion_text(xform)

                build_html = _build_html(build_version, build_version_source)
                app_name = app_name or _("Unknown App")
                app_name = format_html(
                    u'{} {}', app_name, mark_safe(build_html),
                )

            if app_name is None and selected_app:
                continue

            last_sync_log = SyncLog.last_for_user(user.user_id)
            if last_sync_log:
                last_sync = last_sync_log.date

            rows.append(
                [user.username_in_report, _fmt_date(last_seen), _fmt_date(last_sync), app_name or "---"]
            )
        return rows
Beispiel #25
0
    def testOtherUserAddsIndex(self):
        time = datetime.now()

        # create a case from one user
        case_id = "other_user_adds_index"
        self._createCaseStubs([case_id], owner_id=SHARED_ID)

        # sync to the other's phone to be able to edit
        assert_user_has_case(self,
                             self.other_user,
                             case_id,
                             restore_id=self.other_sync_log.get_id)

        latest_sync = SyncLog.last_for_user(OTHER_USER_ID)
        mother_id = "other_user_adds_index_mother"

        parent_case = CaseBlock(
            create=True,
            date_modified=time,
            case_id=mother_id,
            user_id=OTHER_USER_ID,
            case_type=PARENT_TYPE,
            version=V2,
        ).as_xml(format_datetime=json_format_datetime)

        self._postFakeWithSyncToken(parent_case, latest_sync.get_id)
        # the original user should not get the parent case
        assert_user_doesnt_have_case(self,
                                     self.user,
                                     mother_id,
                                     restore_id=self.sync_log.get_id)

        # update the original case from another, adding an indexed case
        self._postFakeWithSyncToken(
            CaseBlock(create=False,
                      case_id=case_id,
                      user_id=OTHER_USER_ID,
                      owner_id=USER_ID,
                      version=V2,
                      index={
                          'mother': ('mother', mother_id)
                      }).as_xml(format_datetime=json_format_datetime),
            latest_sync.get_id)

        # original user syncs again
        # make sure index updates take and indexed case also syncs
        expected_parent_case = CaseBlock(
            create=True,
            date_modified=time,
            case_id=mother_id,
            user_id=OTHER_USER_ID,
            case_type=PARENT_TYPE,
            owner_id=OTHER_USER_ID,
            version=V2,
        ).as_xml(format_datetime=json_format_datetime)

        check_user_has_case(self,
                            self.user,
                            expected_parent_case,
                            restore_id=self.sync_log.get_id,
                            version=V2)
        orig = assert_user_has_case(self,
                                    self.user,
                                    case_id,
                                    restore_id=self.sync_log.get_id)
        self.assertTrue("index" in ElementTree.tostring(orig))
Beispiel #26
0
    def testOtherUserUpdatesIndex(self):
        # create a parent and child case (with index) from one user
        parent_id = "other_updates_index_parent"
        case_id = "other_updates_index_child"
        self._createCaseStubs([parent_id])
        parent = CaseBlock(case_id=parent_id, version=V2).as_xml()

        child = CaseBlock(create=True,
                          case_id=case_id,
                          user_id=USER_ID,
                          owner_id=USER_ID,
                          version=V2,
                          index={
                              'mother': ('mother', parent_id)
                          }).as_xml()
        self._postFakeWithSyncToken(child, self.sync_log.get_id)

        assert_user_doesnt_have_case(self,
                                     self.user,
                                     parent_id,
                                     restore_id=self.sync_log.get_id)
        assert_user_doesnt_have_case(self,
                                     self.user,
                                     case_id,
                                     restore_id=self.sync_log.get_id)

        # assign the parent case away from same user
        parent_update = CaseBlock(create=False,
                                  case_id=parent_id,
                                  user_id=USER_ID,
                                  owner_id=OTHER_USER_ID,
                                  update={
                                      "greeting": "hello"
                                  },
                                  version=V2).as_xml()
        self._postFakeWithSyncToken(parent_update, self.sync_log.get_id)

        self.sync_log = SyncLog.get(self.sync_log.get_id)

        # these tests added to debug another issue revealed by this test
        self.assertTrue(self.sync_log.phone_has_case(case_id))
        self.assertTrue(self.sync_log.phone_has_dependent_case(parent_id))
        self.assertTrue(self.sync_log.phone_is_holding_case(case_id))
        self.assertTrue(self.sync_log.phone_is_holding_case(parent_id))

        # original user syncs again
        # make sure there are no new changes
        assert_user_doesnt_have_case(self,
                                     self.user,
                                     parent_id,
                                     restore_id=self.sync_log.get_id)
        assert_user_doesnt_have_case(self,
                                     self.user,
                                     case_id,
                                     restore_id=self.sync_log.get_id)

        # update the parent case from another user
        assert_user_has_case(self,
                             self.other_user,
                             parent_id,
                             restore_id=self.other_sync_log.get_id)
        self.other_sync_log = SyncLog.last_for_user(OTHER_USER_ID)
        other_parent_update = CaseBlock(create=False,
                                        case_id=parent_id,
                                        user_id=OTHER_USER_ID,
                                        update={
                                            "greeting2": "hi"
                                        },
                                        version=V2).as_xml()
        self._postFakeWithSyncToken(other_parent_update,
                                    self.other_sync_log.get_id)

        # make sure the indexed case syncs again
        self.sync_log = SyncLog.last_for_user(USER_ID)
        assert_user_has_case(self,
                             self.user,
                             parent_id,
                             restore_id=self.sync_log.get_id)
Beispiel #27
0
    def testOtherUserReassignsIndexed(self):
        # create a parent and child case (with index) from one user
        parent_id = "other_reassigns_index_parent"
        case_id = "other_reassigns_index_child"
        self._createCaseStubs([parent_id])
        child = CaseBlock(create=True,
                          case_id=case_id,
                          user_id=USER_ID,
                          owner_id=SHARED_ID,
                          version=V2,
                          index={
                              'mother': ('mother', parent_id)
                          }).as_xml()
        self._postFakeWithSyncToken(child, self.sync_log.get_id)

        # assign the parent case away from the same user
        parent_update = CaseBlock(create=False,
                                  case_id=parent_id,
                                  user_id=USER_ID,
                                  owner_id=OTHER_USER_ID,
                                  update={
                                      "greeting": "hello"
                                  },
                                  version=V2).as_xml()
        self._postFakeWithSyncToken(parent_update, self.sync_log.get_id)

        # sync cases to second user
        self.other_sync_log = synclog_from_restore_payload(
            generate_restore_payload(self.other_user))
        # change the child's owner from another user
        child_reassignment = CaseBlock(
            create=False,
            case_id=case_id,
            user_id=OTHER_USER_ID,
            owner_id=OTHER_USER_ID,
            version=V2,
            update={
                "childgreeting": "hi!"
            },
        ).as_xml()
        self._postFakeWithSyncToken(child_reassignment,
                                    self.other_sync_log.get_id)

        # also change the parent from the second user
        other_parent_update = CaseBlock(create=False,
                                        case_id=parent_id,
                                        user_id=OTHER_USER_ID,
                                        owner_id=OTHER_USER_ID,
                                        update={
                                            "other_greeting": "something new"
                                        },
                                        version=V2).as_xml()
        self._postFakeWithSyncToken(other_parent_update,
                                    self.other_sync_log.get_id)

        # original user syncs again
        self.sync_log = SyncLog.last_for_user(self.user.user_id)
        # both cases should sync to original user with updated ownership / edits
        assert_user_has_case(self,
                             self.user,
                             case_id,
                             restore_id=self.sync_log.get_id)
        assert_user_has_case(self,
                             self.user,
                             parent_id,
                             restore_id=self.sync_log.get_id)

        # Ghetto
        payload = generate_restore_payload(self.user,
                                           self.sync_log.get_id,
                                           version=V2)
        self.assertTrue("something new" in payload)
        self.assertTrue("hi!" in payload)

        # change the parent again from the second user
        other_parent_update = CaseBlock(create=False,
                                        case_id=parent_id,
                                        user_id=OTHER_USER_ID,
                                        owner_id=OTHER_USER_ID,
                                        update={
                                            "other_greeting":
                                            "something different"
                                        },
                                        version=V2).as_xml()
        self._postFakeWithSyncToken(other_parent_update,
                                    self.other_sync_log.get_id)

        # original user syncs again
        self.sync_log = SyncLog.last_for_user(self.user.user_id)
        # should be no changes
        assert_user_doesnt_have_case(self,
                                     self.user,
                                     case_id,
                                     restore_id=self.sync_log.get_id)
        assert_user_doesnt_have_case(self,
                                     self.user,
                                     parent_id,
                                     restore_id=self.sync_log.get_id)

        # change the child again from the second user
        other_child_update = CaseBlock(
            create=False,
            case_id=case_id,
            user_id=OTHER_USER_ID,
            owner_id=OTHER_USER_ID,
            version=V2,
            update={
                "childgreeting": "hi changed!"
            },
        ).as_xml()
        self._postFakeWithSyncToken(other_child_update,
                                    self.other_sync_log.get_id)

        # original user syncs again
        self.sync_log = SyncLog.last_for_user(self.user.user_id)
        # should be no changes
        assert_user_doesnt_have_case(self,
                                     self.user,
                                     case_id,
                                     restore_id=self.sync_log.get_id)
        assert_user_doesnt_have_case(self,
                                     self.user,
                                     parent_id,
                                     restore_id=self.sync_log.get_id)

        # change owner of child back to orginal user from second user
        child_reassignment = CaseBlock(create=False,
                                       case_id=case_id,
                                       user_id=OTHER_USER_ID,
                                       owner_id=USER_ID,
                                       version=V2).as_xml()
        self._postFakeWithSyncToken(child_reassignment,
                                    self.other_sync_log.get_id)

        # original user syncs again
        self.sync_log = SyncLog.last_for_user(self.user.user_id)
        # both cases should now sync
        assert_user_has_case(self,
                             self.user,
                             case_id,
                             restore_id=self.sync_log.get_id)
        assert_user_has_case(self,
                             self.user,
                             parent_id,
                             restore_id=self.sync_log.get_id)

        # ghetto
        payload = generate_restore_payload(self.user,
                                           self.sync_log.get_id,
                                           version=V2)
        self.assertTrue("something different" in payload)
        self.assertTrue("hi changed!" in payload)
Beispiel #28
0
 def test_basic_properties(self):
     # kick off a restore to generate the sync log
     generate_restore_payload(self.project, self.restore_user, items=True)
     sync_log = SyncLog.last_for_user(self.restore_user.user_id)
     self.assertEqual(self.restore_user.user_id, sync_log.user_id)
     self.assertEqual(self.restore_user.domain, sync_log.domain)