コード例 #1
0
    def test_synced_before_and_after_bug_resolution_200(self):
        before = SimplifiedSyncLog(
            user_id=self.restore_user.user_id,
            date=datetime(2016, 7, 19, 18,
                          0)  # synced before bug was introduced
        )
        before.save()
        restore_config = RestoreConfig(project=self.project,
                                       restore_user=self.restore_user,
                                       params=RestoreParams(
                                           sync_log_id=before._id,
                                           version="2.0",
                                       ),
                                       cache_settings=RestoreCacheSettings())
        response = restore_config.get_response()
        self.assertEqual(response.status_code, 200)

        after = SimplifiedSyncLog(
            user_id=self.restore_user.user_id,
            previous_log_id=before._id,
            date=datetime(2016, 7, 21, 19, 0)  # after resolution
        )
        after.save()

        restore_config = RestoreConfig(project=self.project,
                                       restore_user=self.restore_user,
                                       params=RestoreParams(
                                           sync_log_id=after._id,
                                           version="2.0",
                                       ),
                                       cache_settings=RestoreCacheSettings())
        response = restore_config.get_response()
        self.assertEqual(response.status_code, 200)
コード例 #2
0
    def test_synced_during_and_after_bug_resolution_returns_200(self):
        during = SimplifiedSyncLog(
            user_id=self.restore_user.user_id,
            date=datetime(2016, 7, 19, 20, 0)  # during bug
        )
        during.save()

        after = SimplifiedSyncLog(
            user_id=self.restore_user.user_id,
            previous_log_id=during._id,
            date=datetime(2016, 7, 21, 19, 0)  # after resolution
        )
        after.save()

        restore_config = RestoreConfig(
            project=self.project,
            restore_user=self.restore_user,
            params=RestoreParams(
                sync_log_id=after._id,
                version="2.0",
            ),
            cache_settings=RestoreCacheSettings()
        )
        response = restore_config.get_response()
        self.assertEqual(response.status_code, 200)
コード例 #3
0
    def handle(self, *args, **options):
        username = options['username']
        if not username:
            print "You need a username!"
            print "Usage: ./manage.py mem_profile_restore --username [email protected]"
            return

        couch_user = CommCareUser.get_by_username(username)
        project = couch_user.project

        restore_config = RestoreConfig(
            project=project,
            restore_user=couch_user.to_ota_restore_user(),
            params=RestoreParams(
                version=V2,
                include_item_count=True,
            ),
            cache_settings=RestoreCacheSettings(
                force_cache=True,
                cache_timeout=1,
                overwrite_cache=False,
            ))

        with resident_set_size():
            restore_config.get_payload()
コード例 #4
0
ファイル: views.py プロジェクト: ekush/commcare-hq
def get_restore_response(domain, couch_user, since=None, version='1.0',
                         state=None, items=False, force_cache=False,
                         cache_timeout=None, overwrite_cache=False,
                         force_restore_mode=None):
    # not a view just a view util
    if not couch_user.is_commcare_user():
        return HttpResponse("No linked chw found for %s" % couch_user.username,
                            status=401)  # Authentication Failure
    elif domain != couch_user.domain:
        return HttpResponse("%s was not in the domain %s" % (couch_user.username, domain),
                            status=401)

    project = Domain.get_by_name(domain)
    restore_config = RestoreConfig(
        project=project,
        user=couch_user.to_casexml_user(),
        params=RestoreParams(
            sync_log_id=since,
            version=version,
            state_hash=state,
            include_item_count=items,
            force_restore_mode=force_restore_mode,
        ),
        cache_settings=RestoreCacheSettings(
            force_cache=force_cache,
            cache_timeout=cache_timeout,
            overwrite_cache=overwrite_cache
        ),
    )
    return restore_config.get_response()
コード例 #5
0
    def test_old_then_new_sync(self):
        restore_config = RestoreConfig(self.project, user=self.user)
        case = CaseFactory(domain=self.project.name,
                           case_defaults={
                               'owner_id': self.user_id
                           }).create_case()
        restore_payload = restore_config.get_payload().as_string()
        self.assertTrue(case._id in restore_payload)
        sync_log = synclog_from_restore_payload(restore_payload)
        self.assertEqual(SyncLog, type(sync_log))
        restore_config = RestoreConfig(
            self.project,
            user=self.user,
            params=RestoreParams(sync_log_id=sync_log._id))
        original_payload_back = restore_config.get_payload().as_string()
        self.assertFalse(case._id in original_payload_back)
        self.assertEqual(
            SyncLog, type(synclog_from_restore_payload(original_payload_back)))

        OWNERSHIP_CLEANLINESS_RESTORE.set(self.domain,
                                          enabled=True,
                                          namespace='domain')
        restore_config = RestoreConfig(
            self.project,
            user=self.user,
            params=RestoreParams(sync_log_id=sync_log._id),
            cache_settings=RestoreCacheSettings(overwrite_cache=True))
        migrated_payload_back = restore_config.get_payload().as_string()
        self.assertFalse(case._id in migrated_payload_back)
        self.assertEqual(
            SimplifiedSyncLog,
            type(synclog_from_restore_payload(migrated_payload_back)))
        OWNERSHIP_CLEANLINESS_RESTORE.set(self.domain,
                                          enabled=False,
                                          namespace='domain')
コード例 #6
0
def generate_restore_payload(project, user, restore_id="", version=V1, state_hash="",
                             items=False, overwrite_cache=False, force_cache=False):
    """
    Gets an XML payload suitable for OTA restore.

        user:          who the payload is for
        restore_id:    last sync token for this user
        version:       the restore API version

        returns: the xml payload of the sync operation
    """
    config = RestoreConfig(
        project=project,
        user=user,
        params=RestoreParams(
            sync_log_id=restore_id,
            version=version,
            state_hash=state_hash,
            include_item_count=items
        ),
        cache_settings=RestoreCacheSettings(
            overwrite_cache=overwrite_cache,
            force_cache=force_cache,
        )
    )
    return config.get_payload().as_string()
コード例 #7
0
ファイル: utils.py プロジェクト: tstalka/commcare-hq
def get_restore_config(project,
                       user,
                       restore_id="",
                       version=V1,
                       state_hash="",
                       items=False,
                       overwrite_cache=False,
                       force_cache=False,
                       device_id=None,
                       case_sync=None,
                       app=None):
    from casexml.apps.phone.restore import (RestoreCacheSettings,
                                            RestoreConfig, RestoreParams)

    return RestoreConfig(project=project,
                         restore_user=user,
                         case_sync=case_sync,
                         params=RestoreParams(
                             sync_log_id=restore_id,
                             version=version,
                             state_hash=state_hash,
                             include_item_count=items,
                             device_id=device_id,
                             app=app,
                         ),
                         cache_settings=RestoreCacheSettings(
                             overwrite_cache=overwrite_cache,
                             force_cache=force_cache,
                         ))
コード例 #8
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,
                         force_restore_mode=None,
                         as_user=None,
                         device_id=None,
                         has_data_cleanup_privelege=False,
                         openrosa_version=OPENROSA_DEFAULT_VERSION):
    # not a view just a view util
    is_permitted, message = is_permitted_to_restore(
        domain,
        couch_user,
        as_user,
        has_data_cleanup_privelege,
    )
    if not is_permitted:
        return HttpResponse(message, status=401), None

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

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

    project = Domain.get_by_name(domain)
    app = get_app(domain, app_id) if app_id else None
    async_restore_enabled = (toggles.ASYNC_RESTORE.enabled(domain) 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,
        ),
        cache_settings=RestoreCacheSettings(force_cache=force_cache
                                            or async_restore_enabled,
                                            cache_timeout=cache_timeout,
                                            overwrite_cache=overwrite_cache),
        async=async_restore_enabled)
    return restore_config.get_response(), restore_config.timing_context
コード例 #9
0
 def _restore_config(self, is_async=True, sync_log_id='', overwrite_cache=False):
     restore_config = RestoreConfig(
         project=self.project,
         restore_user=self.user,
         params=RestoreParams(sync_log_id=sync_log_id, version=V2),
         cache_settings=RestoreCacheSettings(
             overwrite_cache=overwrite_cache
         ),
         is_async=is_async
     )
     self.addCleanup(get_redis_default_cache().clear)
     return restore_config
コード例 #10
0
 def test_return_412_between_bug_dates(self):
     log = SimplifiedSyncLog(user_id=self.restore_user.user_id,
                             date=datetime(2016, 7, 19, 19, 20))
     log.save()
     restore_config = RestoreConfig(project=self.project,
                                    restore_user=self.restore_user,
                                    params=RestoreParams(
                                        sync_log_id=log._id,
                                        version="2.0",
                                    ),
                                    cache_settings=RestoreCacheSettings())
     response = restore_config.get_response()
     self.assertEqual(response.status_code, 412)
コード例 #11
0
def get_restore_config(project, user, restore_id="", version=V1, state_hash="",
                       items=False, overwrite_cache=False, force_cache=False, device_id=None):
    return RestoreConfig(
        project=project,
        restore_user=user,
        params=RestoreParams(
            sync_log_id=restore_id,
            version=version,
            state_hash=state_hash,
            include_item_count=items,
            device_id=device_id,
        ),
        cache_settings=RestoreCacheSettings(
            overwrite_cache=overwrite_cache,
            force_cache=force_cache,
        )
    )
コード例 #12
0
    def handle(self, username, **options):
        couch_user = CommCareUser.get_by_username(username)
        project = couch_user.project

        restore_config = RestoreConfig(
            project=project,
            restore_user=couch_user.to_ota_restore_user(),
            params=RestoreParams(
                version=V2,
                include_item_count=True,
            ),
            cache_settings=RestoreCacheSettings(
                force_cache=True,
                cache_timeout=1,
                overwrite_cache=False,
            ))

        with resident_set_size():
            restore_config.get_payload()
コード例 #13
0
ファイル: tasks.py プロジェクト: zbidi/commcare-hq
def prime_restore(username_or_id, domain, version, cache_timeout_hours,
                  overwrite_cache, check_cache_only):
    couch_user = get_user(username_or_id, domain)

    try:
        project = couch_user.project
        restore_config = RestoreConfig(
            project=project,
            restore_user=couch_user.to_ota_restore_user(),
            params=RestoreParams(
                version=version,
                include_item_count=True,
            ),
            cache_settings=RestoreCacheSettings(
                force_cache=True,
                cache_timeout=cache_timeout_hours * 60 * 60,
                overwrite_cache=overwrite_cache
            )
        )

        if check_cache_only:
            cached_payload = _get_cached_payload(restore_config)
            ret = u'Restore cache {} for user: {}'.format(
                'EXISTS' if cached_payload else 'does not exist',
                couch_user.human_friendly_name,
            )
        else:
            restore_config.get_payload()

            cached_payload = _get_cached_payload(restore_config)
            if cached_payload:
                ret = u'Restore cached successfully for user: {}'.format(
                    couch_user.human_friendly_name,
                )
            else:
                raise PrimeRestoreException(u"Restore completed by cache still empty")

    except Exception as e:
        raise PrimeRestoreException(u'Error processing user: {}. Error was: {}'.format(
            couch_user.human_friendly_name, str(e)
        ))

    return {"messages": ret}
コード例 #14
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):
    """
    :param domain: Domain being restored from
    :param couch_user: User performing restore
    :param app_id: App ID of the app making the request
    :param since: ID of current sync log used to generate incremental sync
    :param version: Version of the sync response required
    :param state: Hash value of the current database of cases on the device for consistency checking
    :param items: Include item count if True
    :param force_cache: Force response to be cached
    :param cache_timeout: Override the default cache timeout of 1 hour.
    :param overwrite_cache: Ignore cached response if True
    :param as_user: Username of user to generate restore for (if different from current user)
    :param device_id: ID of device performing restore
    :param user_id: ID of user performing restore (used in case of deleted user with same username)
    :param openrosa_version:
    :param case_sync: Override default case sync algorithm
    :return: Tuple of (http response, timing context or 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 = _('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

    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']))

    app = get_app_cached(domain, app_id) if app_id else None
    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),
        is_async=async_restore_enabled,
        case_sync=case_sync,
    )
    return restore_config.get_response(), restore_config.timing_context
コード例 #15
0
    def tearDownClass(cls):
        cls.project.delete()
        delete_all_cases()
        delete_all_sync_logs()
        delete_all_users()
        super(BaseAsyncRestoreTest, cls).tearDownClass()

    def _restore_config(self,
                        async=True,
                        sync_log_id='',
                        overwrite_cache=False):
        restore_config = RestoreConfig(
            project=self.project,
            restore_user=self.user,
            params=RestoreParams(sync_log_id=sync_log_id, version=V2),
            cache_settings=RestoreCacheSettings(
                overwrite_cache=overwrite_cache),
            is_async=async)
        self.addCleanup(get_redis_default_cache().clear)
        return restore_config


class AsyncRestoreTestCouchOnly(BaseAsyncRestoreTest):
    @mock.patch('casexml.apps.phone.restore.get_async_restore_payload')
    def test_regular_restore_doesnt_start_task(self, task):
        """
        when the feature flag is off, the celery task does not get called
        """
        self._restore_config(async=False).get_payload()
        self.assertFalse(task.delay.called)

    @mock.patch('casexml.apps.phone.restore.get_async_restore_payload')
コード例 #16
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,
                         force_restore_mode=None,
                         as_user=None,
                         device_id=None,
                         user_id=None,
                         has_data_cleanup_privelege=False,
                         openrosa_version=OPENROSA_DEFAULT_VERSION):

    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

    # not a view just a view util
    is_permitted, message = is_permitted_to_restore(
        domain,
        couch_user,
        as_user,
        has_data_cleanup_privelege,
    )
    if not is_permitted:
        return HttpResponse(message, status=401), None

    is_demo_restore = couch_user.is_commcare_user() and couch_user.is_demo_user
    is_enikshay = toggles.ENIKSHAY.enabled(domain)
    if is_enikshay:
        couch_restore_user = couch_user
        if not is_demo_restore and as_user is not None:
            couch_restore_user = CouchUser.get_by_username(as_user)
        update_device_id(couch_restore_user, device_id)

    if is_demo_restore:
        # if user is in demo-mode, return demo restore
        return demo_user_restore_response(couch_user), None

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

    project = Domain.get_by_name(domain)
    app = get_app(domain, app_id) if app_id else None
    async_restore_enabled = (toggles.ASYNC_RESTORE.enabled(domain) 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,
        ),
        cache_settings=RestoreCacheSettings(force_cache=force_cache
                                            or async_restore_enabled,
                                            cache_timeout=cache_timeout,
                                            overwrite_cache=overwrite_cache),
        async=async_restore_enabled)
    return restore_config.get_response(), restore_config.timing_context
コード例 #17
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 = _('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

    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']))

    app = get_app_cached(domain, app_id) if app_id else None
    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
コード例 #18
0
ファイル: tasks.py プロジェクト: ekush/commcare-hq
def prime_restore(domain, usernames_or_ids, version=V1, cache_timeout_hours=None,
                  overwrite_cache=False, check_cache_only=False):
    """
    Task to generate and cache a restore payload for each user passed in.

    :param domain:              The domain name for the users
    :param usernames_or_ids:    List of usernames or user IDs
    :param version:             Restore format version
    :param cache_timeout_hours: Hours to cache the payload
    :param overwrite_cache:     If True overwrite any existing cache
    :param check_cache_only:    Don't generate the payload, just check if it is already cached
    """
    total = len(usernames_or_ids)
    DownloadBase.set_progress(prime_restore, 0, total)

    ret = {'messages': []}
    for i, username_or_id in enumerate(usernames_or_ids):
        couch_user = get_user(username_or_id, domain)
        if not couch_user:
            ret['messages'].append('WARNING: User not found: {}'.format(username_or_id))
            continue
        elif couch_user.domain != domain:
            ret['messages'].append("WARNING: User '{}' not from domain '{}'".format(
                username_or_id,
                domain
            ))
            continue

        try:
            project = couch_user.project
            restore_config = RestoreConfig(
                project=project,
                user=couch_user.to_casexml_user(),
                params=RestoreParams(
                    version=version,
                    include_item_count=True,
                ),
                cache_settings=RestoreCacheSettings(
                    force_cache=True,
                    cache_timeout=cache_timeout_hours * 60 * 60,
                    overwrite_cache=overwrite_cache
                )
            )

            if check_cache_only:
                cached_payload = _get_cached_payload(restore_config)
                ret['messages'].append(u'Restore cache {} for user: {}'.format(
                    'EXISTS' if cached_payload else 'does not exist',
                    couch_user.human_friendly_name,
                ))
            else:
                restore_config.get_payload()

                cached_payload = _get_cached_payload(restore_config)
                if cached_payload:
                    ret['messages'].append('SUCCESS: Restore cached successfully for user: {}'.format(
                        couch_user.human_friendly_name,
                    ))
                else:
                    ret['messages'].append('ERROR: Restore completed by cache still empty for user: {}'.format(
                        couch_user.human_friendly_name,
                    ))
        except Exception as e:
            ret['messages'].append('ERROR: Error processing user: {}'.format(str(e)))

        DownloadBase.set_progress(prime_restore, i + 1, total)

    return ret