def test_form_extras_override_defaults(self): domain = uuid.uuid4().hex LOOSE_SYNC_TOKEN_VALIDATION.set(domain, True, namespace='domain') token_id = uuid.uuid4().hex factory = CaseFactory(domain=domain, form_extras={'last_sync_token': token_id}) [case] = factory.create_or_update_case(CaseStructure(), form_extras={'last_sync_token': 'differenttoken'}) form = XFormInstance.get(case.xform_ids[0]) self.assertEqual('differenttoken', form.last_sync_token)
def test_form_extras(self): domain = uuid.uuid4().hex LOOSE_SYNC_TOKEN_VALIDATION.set(domain, True, namespace='domain') token_id = uuid.uuid4().hex factory = CaseFactory(domain=domain) [case] = factory.create_or_update_case(CaseStructure(), form_extras={'last_sync_token': token_id}) form = FormProcessorInterface(domain).xform_model.get(case.xform_ids[0]) self.assertEqual(token_id, form.last_sync_token)
def test_form_extras_override_defaults(self): domain = uuid.uuid4().hex LOOSE_SYNC_TOKEN_VALIDATION.set(domain, True, namespace="domain") token_id = uuid.uuid4().hex factory = CaseFactory(domain=domain, form_extras={"last_sync_token": token_id}) [case] = factory.create_or_update_case(CaseStructure(), form_extras={"last_sync_token": "differenttoken"}) form = FormAccessors(domain).get_form(case.xform_ids[0]) self.assertEqual("differenttoken", form.last_sync_token)
def test_form_extras(self): domain = uuid.uuid4().hex LOOSE_SYNC_TOKEN_VALIDATION.set(domain, True, namespace='domain') token_id = uuid.uuid4().hex factory = CaseFactory(domain=domain) [case] = factory.create_or_update_case( CaseStructure(), form_extras={'last_sync_token': token_id}) form = FormAccessors(domain).get_form(case.xform_ids[0]) self.assertEqual(token_id, form.last_sync_token)
def test_form_extras_default(self): domain = uuid.uuid4().hex # have to enable loose sync token validation for the domain or create actual SyncLog documents. # this is the easier path. LOOSE_SYNC_TOKEN_VALIDATION.set(domain, True, namespace='domain') token_id = uuid.uuid4().hex factory = CaseFactory(domain=domain, form_extras={'last_sync_token': token_id}) case = factory.create_case() form = XFormInstance.get(case.xform_ids[0]) self.assertEqual(token_id, form.last_sync_token)
def test_form_extras_override_defaults(self): domain = uuid.uuid4().hex LOOSE_SYNC_TOKEN_VALIDATION.set(domain, True, namespace='domain') token_id = uuid.uuid4().hex factory = CaseFactory(domain=domain, form_extras={'last_sync_token': token_id}) [case] = factory.create_or_update_case( CaseStructure(), form_extras={'last_sync_token': 'differenttoken'}) form = XFormInstance.get(case.xform_ids[0]) self.assertEqual('differenttoken', form.last_sync_token)
def test_form_extras_default(self): domain = uuid.uuid4().hex # have to enable loose sync token validation for the domain or create actual SyncLog documents. # this is the easier path. LOOSE_SYNC_TOKEN_VALIDATION.set(domain, True, namespace='domain') token_id = uuid.uuid4().hex factory = CaseFactory(domain=domain, form_extras={'last_sync_token': token_id}) case = factory.create_case() form = FormAccessors(domain).get_form(case.xform_ids[0]) self.assertEqual(token_id, form.last_sync_token)
def process_cases_with_casedb(xforms, case_db, config=None): config = config or CaseProcessingConfig() case_processing_result = _get_or_update_cases(xforms, case_db) cases = case_processing_result.cases xform = xforms[0] # attach domain and export tag domain = xform.domain def attach_extras(case): case.domain = domain if domain: assert hasattr(case, 'type') case['#export_tag'] = ["domain", "type"] return case cases = [attach_extras(case) for case in cases] # handle updating the sync records for apps that use sync mode try: relevant_log = xform.get_sync_token() except ResourceNotFound: if LOOSE_SYNC_TOKEN_VALIDATION.enabled(xform.domain): relevant_log = None else: raise if relevant_log: # in reconciliation mode, things can be unexpected relevant_log.strict = config.strict_asserts from casexml.apps.case.util import update_sync_log_with_checks update_sync_log_with_checks(relevant_log, xform, cases, case_db, case_id_blacklist=config.case_id_blacklist) try: cases_received.send(sender=None, xform=xform, cases=cases) except Exception as e: # don't let the exceptions in signals prevent standard case processing notify_exception( None, 'something went wrong sending the cases_received signal ' 'for form %s: %s' % (xform._id, e) ) for case in cases: ActionsUpdateStrategy(case).reconcile_actions_if_necessary(xform) case_db.mark_changed(case) action_xforms = {action.xform_id for action in case.actions if action.xform_id} mismatched_forms = action_xforms ^ set(case.xform_ids) if mismatched_forms: logging.warning( "CASE XFORM MISMATCH /a/{},{}".format( domain, case.case_id ) ) case_processing_result.set_cases(cases) return case_processing_result
def test_submission_with_bad_log_toggle_enabled(self): domain = 'submission-domain-with-toggle' def _test(): post_case_blocks( [CaseBlock(create=True, case_id='bad-log-toggle-enabled', version=V2).as_xml()], form_extras={"last_sync_token": 'not-a-valid-synclog-id'}, domain=domain, ) LOOSE_SYNC_TOKEN_VALIDATION.set(domain, False, namespace='domain') with self.assertRaises(ResourceNotFound): _test() LOOSE_SYNC_TOKEN_VALIDATION.set(domain, True, namespace='domain') # this is just asserting that an exception is not raised after the toggle is set _test()
def process_cases_with_casedb(xform, case_db, config=None): config = config or CaseProcessingConfig() cases = get_or_update_cases(xform, case_db).values() if config.reconcile: for c in cases: c.reconcile_actions(rebuild=True) # attach domain and export tag domain = xform.domain def attach_extras(case): case.domain = domain if domain: assert hasattr(case, 'type') case['#export_tag'] = ["domain", "type"] return case cases = [attach_extras(case) for case in cases] # handle updating the sync records for apps that use sync mode try: relevant_log = xform.get_sync_token() except ResourceNotFound: if LOOSE_SYNC_TOKEN_VALIDATION.enabled(xform.domain): relevant_log = None else: raise if relevant_log: # in reconciliation mode, things can be unexpected relevant_log.strict = config.strict_asserts from casexml.apps.case.util import update_sync_log_with_checks update_sync_log_with_checks(relevant_log, xform, cases, case_db, case_id_blacklist=config.case_id_blacklist) if config.reconcile and relevant_log.reconcile_cases(): relevant_log.save() try: cases_received.send(sender=None, xform=xform, cases=cases) except Exception as e: # don't let the exceptions in signals prevent standard case processing notify_exception( None, 'something went wrong sending the cases_received signal ' 'for form %s: %s' % (xform._id, e) ) for case in cases: if not case.check_action_order(): try: case.reconcile_actions(rebuild=True, xforms={xform._id: xform}) except ReconciliationError: pass case_db.mark_changed(case) return cases
def test_restore_with_bad_log_toggle_enabled(self): domain = 'restore-domain-with-toggle' def _test(): RestoreConfig( self.user, version=V2, restore_id='not-a-valid-synclog-id', domain=Domain(name=domain), ).get_payload() LOOSE_SYNC_TOKEN_VALIDATION.set(domain, False, namespace='domain') with self.assertRaises(ResourceNotFound): _test() LOOSE_SYNC_TOKEN_VALIDATION.set(domain, True, namespace='domain') # when the toggle is set the exception should be an HttpException instead with self.assertRaises(HttpException): _test()
def validate(self): try: self.restore_state.validate_state() except InvalidSyncLogException, e: if LOOSE_SYNC_TOKEN_VALIDATION.enabled(self.domain): # This exception will get caught by the view and a 412 will be returned to the phone for resync raise RestoreException(e) else: # This exception will fail hard and we'll get a 500 error message raise
def _update_sync_logs(xform, case_db, config, cases): # handle updating the sync records for apps that use sync mode try: relevant_log = xform.get_sync_token() except ResourceNotFound: if LOOSE_SYNC_TOKEN_VALIDATION.enabled(xform.domain): relevant_log = None else: raise if relevant_log: # in reconciliation mode, things can be unexpected relevant_log.strict = config.strict_asserts from casexml.apps.case.util import update_sync_log_with_checks update_sync_log_with_checks(relevant_log, xform, cases, case_db, case_id_blacklist=config.case_id_blacklist)
def sync_log(self): if self.restore_id: try: sync_log = SyncLog.get(self.restore_id) except ResourceNotFound: # if we are in loose mode, return an HTTP 412 so that the phone will # just force a fresh sync if LOOSE_SYNC_TOKEN_VALIDATION.enabled(self.domain): raise HttpException(412) else: raise if sync_log.user_id == self.user.user_id \ and sync_log.doc_type == 'SyncLog': return sync_log else: raise HttpException(412) else: return None
def process_cases_with_casedb(xforms, case_db, config=None): config = config or CaseProcessingConfig() case_processing_result = _get_or_update_cases(xforms, case_db) cases = case_processing_result.cases xform = xforms[0] # handle updating the sync records for apps that use sync mode try: relevant_log = xform.get_sync_token() except ResourceNotFound: if LOOSE_SYNC_TOKEN_VALIDATION.enabled(xform.domain): relevant_log = None else: raise if relevant_log: # in reconciliation mode, things can be unexpected relevant_log.strict = config.strict_asserts from casexml.apps.case.util import update_sync_log_with_checks update_sync_log_with_checks(relevant_log, xform, cases, case_db, case_id_blacklist=config.case_id_blacklist) try: cases_received.send(sender=None, xform=xform, cases=cases) except Exception as e: # don't let the exceptions in signals prevent standard case processing notify_exception( None, 'something went wrong sending the cases_received signal ' 'for form %s: %s' % (xform.form_id, e) ) for case in cases: case_db.post_process_case(case, xform) case_db.mark_changed(case) case_processing_result.set_cases(cases) return case_processing_result
domain = xform.domain def attach_extras(case): case.domain = domain if domain: assert hasattr(case, 'type') case['#export_tag'] = ["domain", "type"] return case cases = [attach_extras(case) for case in cases] # handle updating the sync records for apps that use sync mode try: relevant_log = xform.get_sync_token() except ResourceNotFound: if LOOSE_SYNC_TOKEN_VALIDATION.enabled(xform.domain): relevant_log = None else: raise if relevant_log: # in reconciliation mode, things can be unexpected relevant_log.strict = config.strict_asserts from casexml.apps.case.util import update_sync_log_with_checks update_sync_log_with_checks(relevant_log, xform, cases, case_db, case_id_blacklist=config.case_id_blacklist) try: