Skip to content

Commit 96b2853

Browse files
author
Denis Papathanasiou
committed
Merge branch 'master' of github.com:SEL-Columbia/formhub into no_stathat so that we can deploy + test on dev before merging into master and deploying on formhub.org.
2 parents 805f78c + 309472c commit 96b2853

20 files changed

+389
-71
lines changed

api/tests/test_api.py

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
from django.contrib.auth.models import User
99
from django.contrib.auth.models import Permission
1010

11-
from utils.user_auth import set_api_permissions_for_user
12-
11+
from main.models import UserProfile
1312
from api.models import OrganizationProfile, Project
1413
from api.views import OrgProfileViewSet
1514
from api.views import ProjectViewSet
@@ -43,22 +42,25 @@ def _login_user_and_profile(self, extra_post_data={}):
4342
'home_page': 'bob.com',
4443
'twitter': 'boberama'
4544
}
46-
url = '/accounts/register/'
4745
post_data = dict(post_data.items() + extra_post_data.items())
48-
self.response = self.client.post(url, post_data)
49-
try:
50-
self.user = User.objects.get(username=post_data['username'])
51-
except User.DoesNotExist:
52-
pass
53-
else:
54-
self.user.is_active = True
55-
self.user.save()
56-
self.assertTrue(
57-
self.client.login(username=self.user.username,
58-
password='bobbob'))
59-
self.extra = {
60-
'HTTP_AUTHORIZATION': 'Token %s' % self.user.auth_token}
61-
set_api_permissions_for_user(self.user)
46+
user, created = User.objects.get_or_create(
47+
username=post_data['username'],
48+
first_name=post_data['name'],
49+
email=post_data['email'])
50+
user.set_password(post_data['password1'])
51+
user.save()
52+
new_profile, created = UserProfile.objects.get_or_create(
53+
user=user, name=post_data['name'],
54+
city=post_data['city'],
55+
country=post_data['country'],
56+
organization=post_data['organization'],
57+
home_page=post_data['home_page'],
58+
twitter=post_data['twitter'])
59+
self.user = user
60+
self.assertTrue(
61+
self.client.login(username=self.user.username, password='bobbob'))
62+
self.extra = {
63+
'HTTP_AUTHORIZATION': 'Token %s' % self.user.auth_token}
6264

6365
def _org_create(self):
6466
view = OrgProfileViewSet.as_view({

api/tests/test_data_api.py

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def test_form_list(self):
3434

3535
data = {
3636
u'_bamboo_dataset_id': u'',
37-
# u'_deleted_at': None,
37+
# u'_deleted_at': None,
3838
u'_attachments': [],
3939
u'_geolocation': [None, None],
4040
u'_xform_id_string': u'transportation_2011_07_25',
@@ -49,6 +49,53 @@ def test_form_list(self):
4949
self.assertIsInstance(response.data, dict)
5050
self.assertDictContainsSubset(data, response.data)
5151

52+
def test_data_with_query_parameter(self):
53+
view = DataViewSet.as_view({'get': 'list'})
54+
request = self.factory.get('/', **self.extra)
55+
formid = self.xform.pk
56+
dataid = self.xform.surveys.all()[0].pk
57+
response = view(request, owner='bob', formid=formid)
58+
self.assertEqual(response.status_code, 200)
59+
self.assertEqual(len(response.data), 4)
60+
query_str = '{"_id": "%s"}' % dataid
61+
request = self.factory.get('/?query=%s' % query_str, **self.extra)
62+
response = view(request, owner='bob', formid=formid)
63+
self.assertEqual(response.status_code, 200)
64+
self.assertEqual(len(response.data), 1)
65+
66+
def test_data_with_dataid_as_string(self):
67+
view = DataViewSet.as_view({'get': 'list'})
68+
request = self.factory.get('/', **self.extra)
69+
formid = self.xform.pk
70+
dataid = "random_string"
71+
request = self.factory.get('/', **self.extra)
72+
response = view(request, owner='bob', formid=formid, dataid=dataid)
73+
self.assertEqual(response.status_code, 200)
74+
self.assertEqual(len(response.data), 0)
75+
dataid = self.xform.surveys.all()[0].pk
76+
request = self.factory.get('/', **self.extra)
77+
response = view(request, owner='bob', formid=formid, dataid=dataid)
78+
self.assertEqual(response.status_code, 200)
79+
# a dict object instead of a list
80+
self.assertIsInstance(response.data, dict)
81+
82+
def test_data_with_formid_as_string(self):
83+
view = DataViewSet.as_view({'get': 'list'})
84+
request = self.factory.get('/', **self.extra)
85+
formid = "random_string"
86+
response = view(request, owner='bob', formid=formid)
87+
self.assertEqual(response.status_code, 404)
88+
formid = self.xform.id_string
89+
response = view(request, owner='bob', formid=formid)
90+
self.assertEqual(response.status_code, 200)
91+
self.assertEqual(len(response.data), 4)
92+
93+
def test_anon_form_list(self):
94+
view = DataViewSet.as_view({'get': 'list'})
95+
request = self.factory.get('/')
96+
response = view(request)
97+
self.assertEqual(response.status_code, 401)
98+
5299
def test_add_form_tag_propagates_to_data_tags(self):
53100
"""Test that when a tag is applied on an xform,
54101
it propagates to the instance submissions
@@ -77,3 +124,14 @@ def test_add_form_tag_propagates_to_data_tags(self):
77124
self.assertEqual(response.data, [])
78125
for i in self.xform.surveys.all():
79126
self.assertNotIn(u'hello', i.tags.names())
127+
view = DataViewSet.as_view({'get': 'labels'})
128+
request = self.factory.get('/', **self.extra)
129+
response = view(request, owner='bob', formid="random_string",
130+
dataid=i.pk)
131+
self.assertEqual(response.status_code, 404)
132+
response = view(request, owner='bob', formid=self.xform.pk,
133+
dataid="random")
134+
self.assertEqual(response.status_code, 404)
135+
response = view(request, owner='bob', formid=self.xform.pk,
136+
dataid=i.pk)
137+
self.assertEqual(response.status_code, 200)

api/views.py

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from django import forms
44
from django.db.models import Q
5+
from django.http import Http404
56
from django.shortcuts import get_object_or_404
67
from django.contrib.auth.models import User
78
from django.utils.translation import ugettext as _
@@ -23,7 +24,8 @@
2324
from api.signals import xform_tags_add, xform_tags_delete
2425
from api import tools as utils
2526

26-
from utils.user_auth import check_and_set_form_by_id
27+
from utils.user_auth import check_and_set_form_by_id, \
28+
check_and_set_form_by_id_string
2729
from main.models import UserProfile
2830

2931
from odk_logger.models import XForm, Instance
@@ -1031,7 +1033,7 @@ class DataViewSet(viewsets.ViewSet):
10311033
>
10321034
> HTTP 200 OK
10331035
"""
1034-
permission_classes = [permissions.IsAuthenticatedOrReadOnly, ]
1036+
permission_classes = [permissions.IsAuthenticated, ]
10351037
lookup_field = 'owner'
10361038
lookup_fields = ('owner', 'formid', 'dataid')
10371039
extra_lookup_fields = None
@@ -1092,27 +1094,41 @@ def list(self, request, owner=None, formid=None, dataid=None, **kwargs):
10921094
if not formid and not dataid and not tags:
10931095
data = self._get_formlist_data_points(request, owner)
10941096
if formid:
1095-
xform = check_and_set_form_by_id(int(formid), request)
1097+
try:
1098+
xform = check_and_set_form_by_id(int(formid), request)
1099+
except ValueError:
1100+
xform = check_and_set_form_by_id_string(formid, request)
10961101
if not xform:
10971102
raise exceptions.PermissionDenied(
10981103
_("You do not have permission to "
10991104
"view data from this form."))
1105+
else:
1106+
query = {}
1107+
query[ParsedInstance.USERFORM_ID] = \
1108+
u'%s_%s' % (xform.user.username, xform.id_string)
11001109
if xform and dataid and dataid == 'labels':
11011110
return Response(list(xform.tags.names()))
1102-
if xform and dataid:
1103-
query = {'_id': int(dataid)}
1111+
if dataid:
1112+
if query:
1113+
query.update({'_id': dataid})
1114+
else:
1115+
query = {'_id': dataid}
11041116
rquery = request.QUERY_PARAMS.get('query', None)
11051117
if rquery:
11061118
rquery = json.loads(rquery)
11071119
if query:
1108-
rquery.update(json.loads(query))
1120+
query.update(rquery)
1121+
else:
1122+
query = rquery
11091123
if tags:
11101124
query = query if query else {}
11111125
query['_tags'] = {'$all': tags.split(',')}
11121126
if xform:
11131127
data = self._get_form_data(xform, query=query)
11141128
if not xform and not data:
11151129
xforms = self._get_accessible_forms(owner)
1130+
if not query:
1131+
query = {}
11161132
query[ParsedInstance.USERFORM_ID] = {
11171133
'$in': [
11181134
u'%s_%s' % (form.user.username, form.id_string)
@@ -1130,13 +1146,21 @@ class TagForm(forms.Form):
11301146
tags = TagField()
11311147
if owner is None and not request.user.is_anonymous():
11321148
owner = request.user.username
1133-
xform = check_and_set_form_by_id(int(formid), request)
1149+
xform = None
1150+
try:
1151+
xform = check_and_set_form_by_id(int(formid), request)
1152+
except ValueError:
1153+
xform = check_and_set_form_by_id_string(formid, request)
11341154
if not xform:
11351155
raise exceptions.PermissionDenied(
11361156
_("You do not have permission to "
11371157
"view data from this form."))
11381158
status = 400
1139-
instance = get_object_or_404(ParsedInstance, instance__pk=int(dataid))
1159+
try:
1160+
instance = get_object_or_404(
1161+
ParsedInstance, instance__pk=int(dataid))
1162+
except ValueError:
1163+
raise Http404("No data with id %s" % dataid)
11401164
if request.method == 'POST':
11411165
form = TagForm(request.DATA)
11421166
if form.is_valid():

formhub/settings.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@
5151
('es', u'Español'),
5252
('it', u'Italiano'),
5353
('km', u'ភាសាខ្មែរ'),
54+
('ne', u'नेपाली'),
55+
('nl', u'Nederlands'),
56+
('zh', u'中文'),
5457
)
5558

5659
SITE_ID = 1
Binary file not shown.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<idChunk xmlns="http://opendatakit.org/submissions">
2+
<idList>
3+
<id>uuid:5b2cc313-fc09-437e-8149-fcd32f695d41</id>
4+
<id>uuid:9c6f3468-cfda-46e8-84c1-75458e72805d</id>
5+
<id>uuid:9f0a1508-c3b7-4c99-be00-9b237c26bcbf</id>
6+
</idList>
7+
<resumptionCursor>{{resumptionCursor}}</resumptionCursor>
8+
</idChunk>

main/tests/test_form_show.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,38 @@ def test_replace_xform(self):
321321
if e.name == u'preferred_means']) > 0
322322
self.assertTrue(is_updated_form)
323323

324+
def test_update_form_doesnt_truncate_to_50_chars(self):
325+
count = XForm.objects.count()
326+
xls_path = os.path.join(
327+
self.this_directory,
328+
"fixtures",
329+
"transportation",
330+
"transportation_with_long_id_string.xls")
331+
self._publish_xls_file_and_set_xform(xls_path)
332+
333+
# Update the form
334+
xform_update_url = reverse(update_xform, kwargs={
335+
'username': self.user.username,
336+
'id_string': self.xform.id_string
337+
})
338+
updated_xls_path = os.path.join(
339+
self.this_directory,
340+
"fixtures",
341+
"transportation",
342+
"transportation_with_long_id_string_updated.xls")
343+
with open(updated_xls_path, "r") as xls_file:
344+
post_data = {'xls_file': xls_file}
345+
self.client.post(xform_update_url, post_data)
346+
# Count should stay the same
347+
self.assertEqual(XForm.objects.count(), count + 1)
348+
self.xform = XForm.objects.order_by('id').reverse()[0]
349+
data_dictionary = self.xform.data_dictionary()
350+
# look for the preferred_means question
351+
# which is only in the updated xls
352+
is_updated_form = len([e.name for e in data_dictionary.survey_elements
353+
if e.name == u'preferred_means']) > 0
354+
self.assertTrue(is_updated_form)
355+
324356
def test_xform_delete(self):
325357
id_string = self.xform.id_string
326358
form_exists = XForm.objects.filter(

0 commit comments

Comments
 (0)