def test_merge_device_app_meta_last_is_none(self):
        m1 = DeviceAppMeta(
            last_submission=datetime.utcnow(),
        )
        m2 = DeviceAppMeta(
            last_sync=datetime.utcnow(),
        )

        m1.merge(m2)
        self.assertEqual(m1.last_sync, m2.last_sync)
Пример #2
0
    def test_merge_device_app_meta_last_is_none(self):
        m1 = DeviceAppMeta(
            last_submission=datetime.utcnow(),
        )
        m2 = DeviceAppMeta(
            last_sync=datetime.utcnow(),
        )

        m1.merge(m2)
        self.assertEqual(m1.last_sync, m2.last_sync)
Пример #3
0
def mark_last_synclog(domain,
                      user,
                      app_id,
                      build_id,
                      sync_date,
                      device_id,
                      save=True):
    version = None
    if build_id:
        version = get_version_from_build_id(domain, build_id)

    local_save = update_last_sync(user, app_id, sync_date, version)
    if version:
        local_save |= update_latest_builds(user, app_id, sync_date, version)

    app_meta = None
    if device_id:
        if app_id:
            app_meta = DeviceAppMeta(app_id=app_id,
                                     build_id=build_id,
                                     last_sync=sync_date)
        local_save |= update_device_meta(user,
                                         device_id,
                                         device_app_meta=app_meta,
                                         save=False)

    if local_save and save:
        user.save(fire_signals=False)
    return local_save
Пример #4
0
def mark_latest_submission(domain, user_id, app_id, build_id, version, metadata, received_on):
    user = CouchUser.get_by_user_id(user_id, domain)

    if not user or user.is_deleted():
        return

    try:
        received_on_datetime = string_to_utc_datetime(received_on)
    except ValueError:
        return

    last_submission = filter_by_app(user.reporting_metadata.last_submissions, app_id)

    if metadata and metadata.get('appVersion'):
        if not isinstance(metadata['appVersion'], str):
            metadata = format_form_meta_for_es(metadata)

    app_version_info = get_app_version_info(
        domain,
        build_id,
        version,
        metadata
    )

    if _last_submission_needs_update(last_submission,
                                     received_on_datetime,
                                     app_version_info.build_version,
                                     app_version_info.commcare_version):

        if last_submission is None:
            last_submission = LastSubmission()
            user.reporting_metadata.last_submissions.append(last_submission)

        last_submission.submission_date = received_on_datetime
        device_id = metadata.get('deviceID')
        last_submission.device_id = device_id
        last_submission.app_id = app_id
        last_submission.build_id = build_id
        last_submission.build_version = app_version_info.build_version
        last_submission.commcare_version = app_version_info.commcare_version

        if app_version_info.build_version:
            update_latest_builds(user, app_id, received_on_datetime, app_version_info.build_version)

        if _last_submission_needs_update(user.reporting_metadata.last_submission_for_user,
                                         received_on_datetime,
                                         app_version_info.build_version,
                                         app_version_info.commcare_version,
                                         False):

            user.reporting_metadata.last_submission_for_user = last_submission

        app_meta = DeviceAppMeta(
            app_id=app_id,
            build_id=build_id,
            last_submission=received_on_datetime,
        )
        update_device_meta(user, device_id, app_version_info.commcare_version, app_meta, save=False)

        user.save()
Пример #5
0
    def process_change(self, change):
        synclog = change.get_document()
        if not synclog:
            return

        version = None
        app_id = None
        try:
            sync_date = string_to_utc_datetime(synclog.get('date'))
        except (ValueError, AttributeError):
            return
        build_id = synclog.get('build_id')
        if build_id:
            version, app_id = get_version_and_app_from_build_id(synclog.get('domain'), build_id)
        user_id = synclog.get('user_id')

        if user_id:
            user = CouchUser.get_by_user_id(user_id)
            save = update_last_sync(user, app_id, sync_date, version)
            if version:
                save |= update_latest_builds(user, app_id, sync_date, version)

            app_meta = None
            device_id = synclog.get('device_id')
            if device_id:
                if app_id:
                    app_meta = DeviceAppMeta(app_id=app_id, build_id=build_id, last_sync=sync_date)
                save |= update_device_meta(user, device_id, device_app_meta=app_meta, save=False)

            if save:
                user.save(fire_signals=False)
Пример #6
0
    def process_change(self, change):
        synclog = change.get_document()
        if not synclog:
            return

        user_id = synclog.get('user_id')
        domain = synclog.get('domain')

        if not user_id or not domain:
            return

        try:
            sync_date = string_to_utc_datetime(synclog.get('date'))
        except (ValueError, AttributeError):
            return

        build_id = synclog.get('build_id')
        device_id = synclog.get('device_id')
        app_id = synclog.get('app_id')

        # WebApps syncs do not provide the app_id.
        # For those syncs we go ahead and mark the last synclog synchronously.
        if app_id and settings.USER_REPORTING_METADATA_BATCH_ENABLED:
            UserReportingMetadataStaging.add_sync(domain, user_id, app_id, build_id, sync_date, device_id)
        else:
            user = CouchUser.get_by_user_id(user_id)
            if not user:
                return

            device_app_meta = None
            if device_id and app_id:
                device_app_meta = DeviceAppMeta(app_id=app_id, build_id=build_id, last_sync=sync_date)
            mark_last_synclog(domain, user, app_id, build_id, sync_date, sync_date, device_id, device_app_meta)
Пример #7
0
 def test_update_app_metadata(self):
     user = CommCareUser()
     app_meta = DeviceAppMeta(app_id='123',
                              build_id='build1',
                              build_version=1,
                              last_submission=datetime.utcnow(),
                              num_unsent_forms=1)
     user.update_device_id_last_used('device', device_app_meta=app_meta)
     device = user.get_device('device')
     app_meta = device.get_meta_for_app('123')
     self.assertIsNotNone(app_meta)
Пример #8
0
def update_user_reporting_data(app_build_id, app_id, couch_user, request):
    def _safe_int(val):
        try:
            return int(val)
        except:
            pass

    app_version = _safe_int(request.GET.get('app_version', ''))
    device_id = request.GET.get('device_id', '')
    last_sync_time = request.GET.get('last_sync_time', '')
    num_unsent_forms = _safe_int(request.GET.get('num_unsent_forms', ''))
    num_quarantined_forms = _safe_int(
        request.GET.get('num_quarantined_forms', ''))
    commcare_version = request.GET.get('cc_version', '')
    save_user = False
    # if mobile cannot determine app version it sends -1
    if app_version and app_version > 0:
        save_user = update_latest_builds(couch_user, app_id, datetime.utcnow(),
                                         app_version)
    try:
        last_sync = adjust_text_to_datetime(last_sync_time)
    except iso8601.ParseError:
        try:
            last_sync = string_to_utc_datetime(last_sync_time)
        except (ValueError, OverflowError):
            last_sync = None
    else:
        save_user |= update_last_sync(couch_user, app_id, last_sync,
                                      app_version)
    app_meta = DeviceAppMeta(app_id=app_id,
                             build_id=app_build_id,
                             build_version=app_version,
                             last_heartbeat=datetime.utcnow(),
                             last_sync=last_sync,
                             num_unsent_forms=num_unsent_forms,
                             num_quarantined_forms=num_quarantined_forms)
    save_user |= update_device_meta(couch_user,
                                    device_id,
                                    commcare_version=commcare_version,
                                    device_app_meta=app_meta,
                                    save=False)
    if save_user:
        couch_user.save(fire_signals=False)
Пример #9
0
    def test_merge_device_app_meta(self):
        m1 = DeviceAppMeta(build_id='build1',
                           build_version=1,
                           last_submission=datetime.utcnow(),
                           num_unsent_forms=1)
        m2 = DeviceAppMeta(
            build_id='build2',
            build_version=2,
            last_submission=datetime.utcnow(),
        )

        m2.merge(m1)
        self.assertNotEqual(m2.build_id, m1.build_id)
        self.assertNotEqual(m2.build_version, m1.build_version)
        self.assertNotEqual(m2.last_submission, m1.last_submission)
        self.assertIsNone(m2.num_unsent_forms)

        m1.merge(m2)
        self.assertEqual(m1.build_id, m2.build_id)
        self.assertEqual(m1.build_version, m2.build_version)
        self.assertEqual(m1.last_submission, m2.last_submission)
        self.assertEqual(m1.num_unsent_forms, 1)
Пример #10
0
    def test_merge_device_app_meta(self):
        m1 = DeviceAppMeta(
            build_id='build1',
            build_version=1,
            last_submission=datetime.utcnow(),
            num_unsent_forms=1
        )
        m2 = DeviceAppMeta(
            build_id='build2',
            build_version=2,
            last_submission=datetime.utcnow(),
        )

        m2.merge(m1)
        self.assertNotEqual(m2.build_id, m1.build_id)
        self.assertNotEqual(m2.build_version, m1.build_version)
        self.assertNotEqual(m2.last_submission, m1.last_submission)
        self.assertIsNone(m2.num_unsent_forms)

        m1.merge(m2)
        self.assertEqual(m1.build_id, m2.build_id)
        self.assertEqual(m1.build_version, m2.build_version)
        self.assertEqual(m1.last_submission, m2.last_submission)
        self.assertEqual(m1.num_unsent_forms, 1)
Пример #11
0
def get_restore_response(domain, couch_user, app_id=None, since=None, version='1.0',
                         state=None, items=False, force_cache=False,
                         cache_timeout=None, overwrite_cache=False,
                         as_user=None, device_id=None, user_id=None,
                         openrosa_version=None,
                         case_sync=None):

    if user_id and user_id != couch_user.user_id:
        # sync with a user that has been deleted but a new
        # user was created with the same username and password
        from couchforms.openrosa_response import get_simple_response_xml
        from couchforms.openrosa_response import ResponseNature
        response = get_simple_response_xml(
            'Attempt to sync with invalid user.',
            ResponseNature.OTA_RESTORE_ERROR
        )
        return HttpResponse(response, content_type="text/xml; charset=utf-8", status=412), None

    is_demo_restore = couch_user.is_commcare_user() and couch_user.is_demo_user
    if is_demo_restore:
        # if user is in demo-mode, return demo restore
        return demo_user_restore_response(couch_user), None

    uses_login_as = bool(as_user)
    as_user_obj = CouchUser.get_by_username(as_user) if uses_login_as else None
    if uses_login_as and not as_user_obj:
        msg = _(u'Invalid restore as user {}').format(as_user)
        return HttpResponse(msg, status=401), None
    is_permitted, message = is_permitted_to_restore(
        domain,
        couch_user,
        as_user_obj,
    )
    if not is_permitted:
        return HttpResponse(message, status=401), None

    couch_restore_user = as_user_obj if uses_login_as else couch_user
    app = app_meta = None
    if app_id:
        app = get_app(domain, app_id)
        app_meta = DeviceAppMeta(
            app_id=app.master_id,
            build_id=app_id if app.copy_of else None,
            last_sync=datetime.utcnow(),
        )
    update_device_meta(couch_restore_user, device_id, device_app_meta=app_meta)

    restore_user = get_restore_user(domain, couch_user, as_user_obj)
    if not restore_user:
        return HttpResponse('Could not find user', status=404), None

    project = Domain.get_by_name(domain)
    async_restore_enabled = (
        toggles.ASYNC_RESTORE.enabled(domain)
        and openrosa_version
        and LooseVersion(openrosa_version) >= LooseVersion(OPENROSA_VERSION_MAP['ASYNC_RESTORE'])
    )
    restore_config = RestoreConfig(
        project=project,
        restore_user=restore_user,
        params=RestoreParams(
            sync_log_id=since,
            version=version,
            state_hash=state,
            include_item_count=items,
            app=app,
            device_id=device_id,
            openrosa_version=openrosa_version,
        ),
        cache_settings=RestoreCacheSettings(
            force_cache=force_cache or async_restore_enabled,
            cache_timeout=cache_timeout,
            overwrite_cache=overwrite_cache
        ),
        async=async_restore_enabled,
        case_sync=case_sync,
    )
    return restore_config.get_response(), restore_config.timing_context