Skip to content

Conversation

@millerdev
Copy link
Contributor

The domain argument was removed from the following methods:

  • XFormInstance.objects.get_forms(form_ids)
  • XFormInstance.objects.iter_forms(form_ids)
  • CommCareCase.objects.get_cases(case_ids)
  • CommCareCase.objects.iter_cases(case_ids)

It was misleading to accept a domain argument because it falsely implied that only forms from that domain would be returned.

Safety Assurance

Safety story

In most places this was obviously safe since the domain check was enforced nearby when fetching form or case ids. In a few it was clearly not meant to be enforced. In some cases an additional check was added because it seemed like the code wanted it, or maybe out of paranoia because the domain check was distant and/or hard to verify quickly.

In any case, the code should be more conservative about domain membership in any place where a check was added.

Automated test coverage

Some.

QA Plan

No QA.

Rollback instructions

  • This PR can be reverted after deploy with no further considerations

XFormInstance.objects.iter_forms() indirectly ignored its domain argument.

It was misleading to accept a domain argument because it falsely
implied that only forms from that domain would be yielded.
XFormInstance.objects.get_forms() ignored its domain argument.

It was misleading to accept a domain argument because it falsely
implied that only forms from that domain would be returned.
CommCareCase.objects.iter_cases() indirectly ignored its domain argument.

It was misleading to accept a domain argument because it falsely
implied that only forms from that domain would be yielded.
CommCareCase.objects.get_cases() ignored its domain argument.

It was misleading to accept a domain argument because it falsely
implied that only forms from that domain would be returned.
@dimagimon dimagimon added reindex/migration Reindex or migration will be required during or before deploy Risk: High Change affects files that have been flagged as high risk. labels Dec 5, 2025
@millerdev millerdev added the product/invisible Change has no end-user visible impact label Dec 5, 2025

def inaccessible_forms_accessed(self, xform_ids, domain, couch_user):
xforms = XFormInstance.objects.get_forms(xform_ids, domain)
xforms = XFormInstance.objects.get_forms(xform_ids)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A domain check seemed incorrect for what this function is doing, so I didn't add one.

ids = case_ids
for case_id_chunk in chunked(ids, DEFAULT_CHUNK_SIZE):
case_chunk = CommCareCase.objects.get_cases(list(case_id_chunk), domain)
case_chunk = CommCareCase.objects.get_cases(list(case_id_chunk))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zandre-eng, this did not check the domain, and I think it's safe to not add an additional check here. Do you agree?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that is fine. We already filter for the case_ids by domain in process_batch() so it should be safe to not have an extra check here.

def _validate_payment_case_status(case, valid_statuses, operation):
def _validate_payment_case_status(case, domain, valid_statuses, operation):
if case.domain != domain:
raise PaymentRequestError(_("Case '{}' not in '{}' project").format(case.case_id, domain))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ajeety4, I added a domain check here as well as a new error. Does this seem right to you?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this looks correct to me.

def iter_documents(self, ids):
for wrapped_case in CommCareCase.objects.iter_cases(ids, self.domain):
"""NOTE: unlike iter_document_ids, this does not enforce domain membership"""
for wrapped_case in CommCareCase.objects.iter_cases(ids):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was the original inspiration for this PR. Pillow processors call iter_documents(ids) on a document store that has a domain, which was passed in here. That was very confusing because the ids are from many different domains, and the returned cases should not be filtered by domain.

for case_block in case_blocks:
case = db_case_dict[case_block['@case_id']]
if case_types and case.type not in case_types:
if case.domain != domain or (case_types and case.type not in case_types):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kaapstorm I had to update some tests that failed on account of this change. Do you think it's reasonable to add a domain check here?

@millerdev millerdev requested a review from gherceg December 5, 2025 16:03
@snopoke snopoke removed their request for review December 6, 2025 18:53
Copy link
Contributor

@AmitPhulera AmitPhulera left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good. Just one question, I see that in some places domain checks were skipped. I am sure you would have thought through the changes, just asked about the ones which I was not sure of.

def iter_forms(self, form_ids):
"""
:param form_ids: list of form_ids.
:param domain: See the same parameter of `get_forms`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: outdated docstring

Suggested change
:param domain: See the same parameter of `get_forms`.


for case in CommCareCase.objects.iter_cases(case_ids, domain_name):
for case in CommCareCase.objects.iter_cases(case_ids):
cc_case = CallCenterCase.from_case(case)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to have a domain check here?

errored_doc_ids = []
case_ids = [rec.doc_id for rec in records]
cases = {c.case_id: c for c in CommCareCase.objects.get_cases(case_ids, session.domain)}
cases = {c.case_id: c for c in CommCareCase.objects.get_cases(case_ids)}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we sure that the records can never have any cases from other domain?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

product/invisible Change has no end-user visible impact reindex/migration Reindex or migration will be required during or before deploy Risk: High Change affects files that have been flagged as high risk.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants