Skip to content

Commit da22c80

Browse files
committed
Fix data source configuration resource
obj_get raised tastypie's NotFound, which get_detail does not catch, so a GET for an unknown id returned a 500 rather than a 404. The obj_update change is a refactor with no behavior change: put_detail already answered 404 once it stopped echoing the exception message. It replaces the duplicated Http404 conversion with the couch mixin helper.
1 parent eb59c04 commit da22c80

3 files changed

Lines changed: 38 additions & 14 deletions

File tree

corehq/apps/api/resources/__init__.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,14 @@ def detail_uri_kwargs(self, bundle_or_obj):
359359

360360
def get_document_for_update(self, doc_id, domain):
361361
"""
362-
Converts ``ObjectDoesNotExist`` into ``tastypie.NotFound``
362+
Converts ``ObjectDoesNotExist`` into ``tastypie.NotFound``.
363+
364+
Converting only here makes ``NotFound`` mean exactly "the object
365+
addressed by this URL does not exist", which is what
366+
``HqBaseResource.put_detail`` turns into a 404. Tastypie's own
367+
``ModelResource.obj_update`` does the same conversion in the same
368+
place; couch resources need this because they are not
369+
``ModelResource`` subclasses.
363370
"""
364371
try:
365372
return get_object_or_not_exist(self._meta.object_class, doc_id, domain)

corehq/apps/api/resources/v0_5.py

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
from corehq.apps.api.util import (
6868
django_date_filter,
6969
get_obj,
70+
get_object_or_not_exist,
7071
make_date_filter,
7172
parse_str_to_date,
7273
cursor_based_query_for_datasource
@@ -1022,13 +1023,7 @@ def _ensure_toggle_enabled(self, request):
10221023

10231024
def obj_get(self, bundle, **kwargs):
10241025
self._ensure_toggle_enabled(bundle.request)
1025-
domain = kwargs['domain']
1026-
pk = kwargs['pk']
1027-
try:
1028-
data_source = get_document_or_404(DataSourceConfiguration, domain, pk)
1029-
except Http404 as e:
1030-
raise NotFound(str(e))
1031-
return data_source
1026+
return get_object_or_not_exist(DataSourceConfiguration, kwargs['pk'], kwargs['domain'])
10321027

10331028
def obj_get_list(self, bundle, **kwargs):
10341029
self._ensure_toggle_enabled(bundle.request)
@@ -1037,12 +1032,7 @@ def obj_get_list(self, bundle, **kwargs):
10371032

10381033
def obj_update(self, bundle, **kwargs):
10391034
self._ensure_toggle_enabled(bundle.request)
1040-
domain = kwargs['domain']
1041-
pk = kwargs['pk']
1042-
try:
1043-
data_source = get_document_or_404(DataSourceConfiguration, domain, pk)
1044-
except Http404 as e:
1045-
raise NotFound(str(e))
1035+
data_source = self.get_document_for_update(kwargs['pk'], kwargs['domain'])
10461036
allowed_update_fields = [
10471037
'display_name',
10481038
'configured_filter',
@@ -1075,6 +1065,7 @@ def detail_uri_kwargs(self, bundle_or_obj):
10751065

10761066
class Meta(CustomResourceMeta):
10771067
resource_name = 'ucr_data_source'
1068+
object_class = DataSourceConfiguration
10781069
list_allowed_methods = ['get']
10791070
detail_allowed_methods = ['get', 'put']
10801071
always_return_data = True

corehq/apps/api/tests/test_ucr_resources.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,12 @@ class TestDataSourceConfigurationResource(APIResourceTest):
167167
resource = v0_5.DataSourceConfigurationResource
168168
api_name = "v0.5"
169169

170+
@flag_enabled('USER_CONFIGURABLE_REPORTS')
171+
def test_cant_get_missing_data_source(self):
172+
response = self._assert_auth_get_resource(self.single_endpoint(uuid.uuid4().hex))
173+
174+
assert response.status_code == 404, response.content
175+
170176
@flag_enabled('USER_CONFIGURABLE_REPORTS')
171177
def test_cant_update_missing_data_source(self):
172178
response = self._assert_auth_post_resource(
@@ -180,6 +186,26 @@ def test_cant_update_missing_data_source(self):
180186
# detail, and get_document_or_404 even embeds a traceback
181187
assert response.content == b""
182188

189+
@flag_enabled('USER_CONFIGURABLE_REPORTS')
190+
def test_cant_update_data_source_in_another_domain(self):
191+
not_my_data_source = DataSourceConfiguration(
192+
domain='not-my-project',
193+
referenced_doc_type="XFormInstance",
194+
table_id=uuid.uuid4().hex,
195+
display_name="theirs",
196+
)
197+
not_my_data_source.save()
198+
self.addCleanup(not_my_data_source.delete)
199+
200+
response = self._assert_auth_post_resource(
201+
self.single_endpoint(not_my_data_source._id),
202+
json.dumps({"display_name": "mine now"}),
203+
method="PUT",
204+
)
205+
206+
assert response.status_code == 404, response.content
207+
assert DataSourceConfiguration.get(not_my_data_source._id).display_name == "theirs"
208+
183209

184210
class TestConfigurableReportDataResource(APIResourceTest):
185211
resource = v0_5.ConfigurableReportDataResource

0 commit comments

Comments
 (0)