diff --git a/microsetta_private_api/api/_sample.py b/microsetta_private_api/api/_sample.py index d83549e24..31f6cd1b1 100644 --- a/microsetta_private_api/api/_sample.py +++ b/microsetta_private_api/api/_sample.py @@ -137,9 +137,13 @@ def update_sample_association(account_id, source_id, sample_id, body, except ValueError: raise BadRequest("Invalid sample_datetime") curdate = datetime.now(sample_datetime.tzinfo) - lower_limit = curdate + relativedelta(years=-10) + lower_limit = curdate + relativedelta(years=-1) upper_limit = curdate + relativedelta(months=+1) - if sample_datetime < lower_limit or sample_datetime > upper_limit: + is_admin = token_grants_admin_access(token_info) + + # Allow admins to bypass the back-dating/forward-dating limits + if (sample_datetime < lower_limit or sample_datetime > upper_limit)\ + and not is_admin: raise BadRequest('Invalid sample date') # sample_site will not be present if its environmental. this will # default to None if the key is not present @@ -151,7 +155,6 @@ def update_sample_association(account_id, source_id, sample_id, body, body["sample_notes"] ) - is_admin = token_grants_admin_access(token_info) sample_repo.update_info(account_id, source_id, sample_info, override_locked=is_admin) diff --git a/microsetta_private_api/api/tests/test_api.py b/microsetta_private_api/api/tests/test_api.py index 1bfb4a8bf..d4333dc88 100644 --- a/microsetta_private_api/api/tests/test_api.py +++ b/microsetta_private_api/api/tests/test_api.py @@ -920,7 +920,7 @@ def test_account_scrub_success(self): sample_body = {'sample_site': 'Stool', "sample_notes": "foobar", - 'sample_datetime': "2017-07-21T17:32:28Z"} + 'sample_datetime': datetime.datetime.utcnow()} put_resp = self.client.put( '%s?%s' % (sample_url, self.default_lang_querystring), @@ -1016,10 +1016,13 @@ def test_account_scrub_success(self): self.assertEqual(response_obj['sample_site'], sample_body['sample_site']) - # strip the trailing "Z" which comes from the database... easier - # than loading into datetime - self.assertEqual(response_obj['sample_datetime'], - sample_body['sample_datetime'][:-1]) + response_ts = datetime.datetime.strptime( + response_obj['sample_datetime'], "%Y-%m-%dT%H:%M:%S.%f" + ) + self.assertEqual( + response_ts.strftime("%Y-%m-%d %H:%M:%S"), + sample_body['sample_datetime'].strftime("%Y-%m-%d %H:%M:%S") + ) # This test specifically verifies that the scenario in Private API # issue #492 - where a user takes an external survey, deletes the source, @@ -2353,7 +2356,7 @@ def test_update_sample_association_locked(self): sample_url = "{0}/{1}".format(base_url, MOCK_SAMPLE_ID) body = {'sample_site': 'Stool', "sample_notes": "", - 'sample_datetime': "2017-07-21T17:32:28Z"} + 'sample_datetime': datetime.datetime.utcnow()} put_resp = self.client.put( '%s?%s' % (sample_url, self.default_lang_querystring), @@ -2376,7 +2379,7 @@ def test_update_sample_association_locked(self): # attempt to modify the locked sample as the participant body = {'sample_site': 'Saliva', "sample_notes": "", - 'sample_datetime': "2017-07-21T17:32:28Z"} + 'sample_datetime': datetime.datetime.utcnow()} put_resp = self.client.put( '%s?%s' % (sample_url, self.default_lang_querystring),