def get_fixtures(request, domain, user_id, fixture_id=None): try: user = CommCareUser.get_by_user_id(user_id) except CouchUser.AccountTypeError: err = ("You can't use case sharing or fixtures as a %s. " "Login as a mobile worker and try again." ) % settings.WEB_USER_TERM, return HttpResponse(err, status=412, content_type="text/plain") if not user: raise Http404 assert user.is_member_of(domain) casexml_user = user.to_casexml_user() if not fixture_id: ret = ElementTree.Element("fixtures") for fixture in generator.get_fixtures(casexml_user, version=V2): ret.append(fixture) return HttpResponse(ElementTree.tostring(ret), content_type="text/xml") else: for fixture in generator.get_fixtures(casexml_user, version=V2): if fixture.attrib.get("id") == fixture_id: assert len(fixture.getchildren()) == 1 return HttpResponse(ElementTree.tostring( fixture.getchildren()[0]), content_type="text/xml") raise Http404
def get_fixtures(request, domain, user_id, fixture_id=None): try: user = CommCareUser.get_by_user_id(user_id) except CouchUser.AccountTypeError: err = ("You can't use case sharing or fixtures as a %s. " "Login as a mobile worker and try again.") % settings.WEB_USER_TERM, return HttpResponse(err, status=412, content_type="text/plain") if not user: raise Http404 assert user.is_member_of(domain) casexml_user = user.to_casexml_user() if not fixture_id: ret = ElementTree.Element("fixtures") for fixture in generator.get_fixtures(casexml_user, version=V2): ret.append(fixture) return HttpResponse(ElementTree.tostring(ret), content_type="text/xml") else: for fixture in generator.get_fixtures(casexml_user, version=V2): if fixture.attrib.get("id") == fixture_id: assert len(fixture.getchildren()) == 1, 'fixture {} expected 1 child but found {}'.format( fixture_id, len(fixture.getchildren()) ) return HttpResponse(ElementTree.tostring(fixture.getchildren()[0]), content_type="text/xml") raise Http404
def test_fixtures_by_group(self): fixture_xml = generator.get_fixtures(self.casexml_user, version=V2, group='case') self.assertEqual(list(fixture_xml), []) fixture_xml = generator.get_fixtures(self.casexml_user, version=V2, group='standalone') self._check_fixture(fixture_xml, item_lists=[SA_PROVINCES, FR_PROVINCES])
def get_fixtures(request, domain, user_id, fixture_id=None): try: user = CommCareUser.get_by_user_id(user_id) except CouchUser.AccountTypeError: err = ("You can't use case sharing or fixtures as a %s. " "Login as a mobile worker and try again." ) % settings.WEB_USER_TERM, return HttpResponse(err, status=412, content_type="text/plain") if not user: raise Http404 assert user.is_member_of(domain) restore_user = user.to_ota_restore_user() if not fixture_id: ret = ElementTree.Element("fixtures") for fixture in generator.get_fixtures(restore_user): ret.append(fixture) return HttpResponse(ElementTree.tostring(ret), content_type="text/xml") else: fixture = generator.get_fixture_by_id(fixture_id, restore_user) if not fixture: raise Http404 assert len(fixture.getchildren() ) == 1, 'fixture {} expected 1 child but found {}'.format( fixture_id, len(fixture.getchildren())) return HttpResponse(ElementTree.tostring(fixture.getchildren()[0]), content_type="text/xml")
def get_elements(self, restore_state): # fixture block for fixture in generator.get_fixtures( restore_state.user, restore_state.version, restore_state.last_sync_log ): yield fixture
def get_payload(self): user = self.user last_sync = self.sync_log self.validate() cached_payload = self.get_cached_payload() if cached_payload: return cached_payload sync_operation = user.get_case_updates(last_sync) case_xml_elements = [ xml.get_case_element(op.case, op.required_updates, self.version) for op in sync_operation.actual_cases_to_sync ] commtrack_elements = self.get_stock_payload(sync_operation) last_seq = str(get_db().info()["update_seq"]) # create a sync log for this previous_log_id = last_sync.get_id if last_sync else None synclog = SyncLog( user_id=user.user_id, last_seq=last_seq, owner_ids_on_phone=user.get_owner_ids(), date=datetime.utcnow(), previous_log_id=previous_log_id, cases_on_phone=[CaseState.from_case(c) for c in sync_operation.actual_owned_cases], dependent_cases_on_phone=[CaseState.from_case(c) for c in sync_operation.actual_extended_cases], ) synclog.save(**get_safe_write_kwargs()) # start with standard response response = get_response_element( "Successfully restored account %s!" % user.username, ResponseNature.OTA_RESTORE_SUCCESS ) # add sync token info response.append(xml.get_sync_element(synclog.get_id)) # registration block response.append(xml.get_registration_element(user)) # fixture block for fixture in generator.get_fixtures(user, self.version, last_sync): response.append(fixture) # case blocks for case_elem in case_xml_elements: response.append(case_elem) for ct_elem in commtrack_elements: response.append(ct_elem) if self.items: response.attrib["items"] = "%d" % len(response.getchildren()) resp = xml.tostring(response) self.set_cached_payload_if_enabled(resp) return resp
def get_fixtures(request, domain, user_id, fixture_id=None): user = CommCareUser.get_by_user_id(user_id) if not user: raise Http404 assert user.is_member_of(domain) casexml_user = user.to_casexml_user() if not fixture_id: ret = ElementTree.Element("fixtures") for fixture in generator.get_fixtures(casexml_user, version=V2): ret.append(fixture) return HttpResponse(ElementTree.tostring(ret), content_type="text/xml") else: for fixture in generator.get_fixtures(casexml_user, version=V2): if fixture.attrib.get("id") == fixture_id: assert len(fixture.getchildren()) == 1 return HttpResponse(ElementTree.tostring(fixture.getchildren()[0]), content_type="text/xml") raise Http404
def get_payload(self): """ This function currently returns either a full string payload or a string name of a file that contains the contents of the payload. If FILE_RESTORE toggle is enabled, then this will return the filename, otherwise it will return the full string payload """ user = self.user last_synclog = self.sync_log self.validate() cached_response = self.get_cached_payload() if cached_response.exists(): return cached_response start_time = datetime.utcnow() last_seq = str(get_db().info()["update_seq"]) # create a sync log for this previous_log_id = last_synclog.get_id if last_synclog else None new_synclog = SyncLog( user_id=user.user_id, last_seq=last_seq, owner_ids_on_phone=user.get_owner_ids(), date=datetime.utcnow(), previous_log_id=previous_log_id ) new_synclog.save(**get_safe_write_kwargs()) # start with standard response with get_restore_class(user)(user.username, items=self.items) as response: # add sync token info response.append(xml.get_sync_element(new_synclog.get_id)) # registration block response.append(xml.get_registration_element(user)) # fixture block for fixture in generator.get_fixtures(user, self.version, last_synclog): response.append(fixture) case_response, self.num_batches = get_case_payload_batched( self.domain, self.stock_settings, self.version, user, last_synclog, new_synclog ) combined_response = response + case_response case_response.close() combined_response.finalize() duration = datetime.utcnow() - start_time new_synclog.duration = duration.seconds new_synclog.save() self.set_cached_payload_if_necessary(combined_response, duration) return combined_response
def get_payload(self): user = self.user last_sync = self.sync_log self.validate() cached_payload = self.get_cached_payload() if cached_payload: return cached_payload start_time = datetime.utcnow() last_seq = str(get_db().info()["update_seq"]) # create a sync log for this previous_log_id = last_sync.get_id if last_sync else None synclog = SyncLog( user_id=user.user_id, last_seq=last_seq, owner_ids_on_phone=user.get_owner_ids(), date=datetime.utcnow(), previous_log_id=previous_log_id ) synclog.save(**get_safe_write_kwargs()) # start with standard response batch_enabled = BATCHED_RESTORE.enabled(self.user.domain) or BATCHED_RESTORE.enabled(self.user.username) logger.debug('Batch restore enabled: %s', batch_enabled) if batch_enabled: response = StringRestoreResponse(user.username, items=self.items) else: response = EtreeRestoreResponse(user.username, items=self.items) # add sync token info response.append(xml.get_sync_element(synclog.get_id)) # registration block response.append(xml.get_registration_element(user)) # fixture block for fixture in generator.get_fixtures(user, self.version, last_sync): response.append(fixture) payload_fn = self._get_case_payload_batched if batch_enabled else self._get_case_payload response = payload_fn(response, user, last_sync, synclog) resp = str(response) duration = datetime.utcnow() - start_time synclog.duration = duration.seconds synclog.save() add_custom_parameter('restore_response_size', response.num_items) self.set_cached_payload_if_necessary(resp, duration) return resp
def test_fixture_gen_v1(self): fixture_xml = generator.get_fixtures(self.casexml_user, version=V1) self.assertEqual(fixture_xml, [])
def test_basic_fixture_generation(self): fixture_xml = generator.get_fixtures(self.restore_user, version=V2) self._check_fixture(fixture_xml, item_lists=[SA_PROVINCES, FR_PROVINCES])
def test_fixture_gen_v1(self): fixture_xml = generator.get_fixtures(self.restore_user, version=V1) self.assertEqual(list(fixture_xml), [])
sync_operation.actual_owned_cases], dependent_cases_on_phone=[CaseState.from_case(c) for c in \ sync_operation.actual_extended_cases]) synclog.save(**get_safe_write_kwargs()) # start with standard response response = get_response_element( "Successfully restored account %s!" % user.username, ResponseNature.OTA_RESTORE_SUCCESS) # add sync token info response.append(xml.get_sync_element(synclog.get_id)) # registration block response.append(xml.get_registration_element(user)) # fixture block for fixture in generator.get_fixtures(user, self.version, last_sync): response.append(fixture) # case blocks for case_elem in case_xml_elements: response.append(case_elem) for ct_elem in commtrack_elements: response.append(ct_elem) if self.items: response.attrib['items'] = '%d' % len(response.getchildren()) resp = xml.tostring(response) self.set_cached_payload_if_enabled(resp) return resp def get_response(self):
def generate_restore_payload(user, restore_id="", version="1.0", state_hash=""): """ Gets an XML payload suitable for OTA restore. If you need to do something other than find all cases matching user_id = user.user_id then you have to pass in a user object that overrides the get_case_updates() method. It should match the same signature as models.user.get_case_updates(): user: who the payload is for. must implement get_case_updates restore_id: sync token version: the CommCare version returns: the xml payload of the sync operation """ check_version(version) last_sync = None if restore_id: try: last_sync = SyncLog.get(restore_id) except Exception: logging.error("Request for bad sync log %s by %s, ignoring..." % (restore_id, user)) if last_sync and state_hash: parsed_hash = CaseStateHash.parse(state_hash) if last_sync.get_state_hash() != parsed_hash: raise BadStateException(expected=last_sync.get_state_hash(), actual=parsed_hash, case_ids=last_sync.get_footprint_of_cases_on_phone()) sync_operation = user.get_case_updates(last_sync) case_xml_elements = [xml.get_case_element(op.case, op.required_updates, version) \ for op in sync_operation.actual_cases_to_sync] last_seq = get_db().info()["update_seq"] # create a sync log for this previous_log_id = last_sync.get_id if last_sync else None synclog = SyncLog(user_id=user.user_id, last_seq=last_seq, owner_ids_on_phone=user.get_owner_ids(), date=datetime.utcnow(), previous_log_id=previous_log_id, cases_on_phone=[CaseState.from_case(c) for c in \ sync_operation.actual_owned_cases], dependent_cases_on_phone=[CaseState.from_case(c) for c in \ sync_operation.actual_extended_cases]) synclog.save() # start with standard response response = get_response_element( "Successfully restored account %s!" % user.username, ResponseNature.OTA_RESTORE_SUCCESS) # add sync token info response.append(xml.get_sync_element(synclog.get_id)) # registration block response.append(xml.get_registration_element(user)) # fixture block for fixture in generator.get_fixtures(user, version, last_sync): response.append(fixture) # case blocks for case_elem in case_xml_elements: response.append(case_elem) return xml.tostring(response)
def test_basic_fixture_generation(self): fixture_xml = generator.get_fixtures(self.casexml_user, version=V2) self._check_fixture(fixture_xml, item_lists=[SA_PROVINCES, FR_PROVINCES])
def test_basic_fixture_generation(self): fixture_xml = list(generator.get_fixtures(self.restore_user, version=V2)) self.assertEqual(len(fixture_xml), 1) self.assertEqual(fixture_xml[0].findall('./groups/group'), [])