def migration_restore(request, domain, case_id): """Restore endpoint used in bulk case migrations Accepts the provided case_id and returns a restore for the user containing: * Registration block * The passed in case and its full network of cases """ domain_obj = Domain.get_by_name(domain) restore_user = request.couch_user restore_params = RestoreParams(device_id="case_migration", version=V2) restore_state = RestoreState(domain_obj, restore_user.to_ota_restore_user(domain), restore_params) restore_state.start_sync() timing_context = TimingContext('migration-restore-{}-{}'.format( domain, restore_user.username)) case_ids = get_related_case_ids(domain, case_id) with RestoreContent(restore_user.username) as content: content.append(get_registration_element(restore_user)) sync_payload = CleanOwnerSyncPayload(timing_context, case_ids, restore_state) sync_payload.extend_response(content) payload = content.get_fileobj() restore_state.finish_sync() return RestoreResponse(payload).get_http_response()
def get_response(user, created): if created: text = "Thanks for registering! Your username is %s" % user.username else: text = "Thanks for updating your information, %s." % user.username nature = ResponseNature.SUBMIT_USER_REGISTERED if created else \ ResponseNature.SUBMIT_USER_UPDATED response = receiver_xml.get_response_element(text, nature=nature) response.append(phone_xml.get_registration_element(user.to_casexml_user())) return phone_xml.tostring(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 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_response(user, created): if created: text = "Thanks for registering! Your username is %s" % user.username else: text = "Thanks for updating your information, %s." % user.username nature = ResponseNature.SUBMIT_USER_REGISTERED if created else \ ResponseNature.SUBMIT_USER_UPDATED response = receiver_xml.get_response_element(text, nature=nature) response.append(phone_xml.get_registration_element(user.to_casexml_user())) return phone_xml.tostring(response)
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 migration_restore(request, domain, case_id): """Restore endpoint used in bulk case migrations Accepts the provided case_id and returns a restore for the user containing: * Registration block * The passed in case and its full network of cases """ restore_user = request.couch_user with RestoreContent(restore_user.username) as content: content.append(get_registration_element(restore_user)) for case in get_case_and_descendants(domain, case_id): # Formplayer will be creating these cases for the first time, so # include create blocks content.append(get_case_element(case, ('create', 'update'), V2)) payload = content.get_fileobj() return RestoreResponse(payload).get_http_response()
def get_elements(self, restore_state): yield xml.get_registration_element(restore_state.restore_user)
def get_registration_xml(restore_user): return xml.tostring(xml.get_registration_element(restore_user))
def get_elements(self, restore_state): yield xml.get_registration_element(restore_state.restore_user)
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_registration_xml(restore_user): return xml.tostring(xml.get_registration_element(restore_user)).decode('utf-8')
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)