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)
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
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()
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)
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)
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)
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)
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)
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)
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