def test_show(self): """Tests that GET /applicationsettings/id returns the JSON application settings object with id=id or a 404 status code depending on whether the id is valid or invalid/unspecified, respectively. """ # Invalid id id = 100000000000 response = self.app.get(url('applicationsetting', id=id), extra_environ=self.extra_environ_admin, status=404) assert json.loads(response.body)['error'] == u'There is no application settings with id %s' % id assert response.content_type == 'application/json' # No id response = self.app.get(url('applicationsetting', id=''), status=404, extra_environ=self.extra_environ_admin) assert json.loads(response.body)['error'] == \ 'The resource could not be found.' # Add the default application settings. application_settings = add_default_application_settings() application_settings = h.get_application_settings() application_settings_id = application_settings.id # Valid id response = self.app.get(url('applicationsetting', id=application_settings_id), extra_environ=self.extra_environ_admin) resp = json.loads(response.body) assert response.content_type == 'application/json' assert type(resp) == type({}) assert resp['object_language_name'] == \ application_settings.object_language_name assert resp['storage_orthography']['name'] == \ application_settings.storage_orthography.name
def delete(self, id): """Delete an existing orthography and return it. :URL: ``DELETE /orthographies/id`` :param str id: the ``id`` value of the orthography to be deleted. :returns: the deleted orthography model. .. note:: Contributors can only delete orthographies that are not used in the active application settings. """ orthography = Session.query(Orthography).get(id) if orthography: app_set = h.get_application_settings() if session['user'].role == u'administrator' or orthography not in ( app_set.storage_orthography, app_set.input_orthography, app_set.output_orthography): Session.delete(orthography) Session.commit() return orthography else: response.status = 403 return {'error': u'Only administrators are permitted to delete orthographies that are used in the active application settings.'} else: response.status_int = 404 return {'error': 'There is no orthography with id %s' % id}
def delete(self, id): """Delete an existing orthography and return it. :URL: ``DELETE /orthographies/id`` :param str id: the ``id`` value of the orthography to be deleted. :returns: the deleted orthography model. .. note:: Contributors can only delete orthographies that are not used in the active application settings. """ orthography = Session.query(Orthography).get(id) if orthography: app_set = h.get_application_settings() if session['user'].role == u'administrator' or orthography not in ( app_set.storage_orthography, app_set.input_orthography, app_set.output_orthography): Session.delete(orthography) Session.commit() return orthography else: response.status = 403 return { 'error': u'Only administrators are permitted to delete orthographies that are used in the active application settings.' } else: response.status_int = 404 return {'error': 'There is no orthography with id %s' % id}
def update(self, id): """Update an orthography and return it. :URL: ``PUT /orthographies/id`` :Request body: JSON object representing the orthography with updated attribute values. :param str id: the ``id`` value of the orthography to be updated. :returns: the updated orthography model. .. note:: Contributors can only update orthographies that are not used in the active application settings. """ orthography = Session.query(Orthography).get(int(id)) user = session['user'] if orthography: app_set = h.get_application_settings() if user.role == u'administrator' or orthography not in ( app_set.storage_orthography, app_set.input_orthography, app_set.output_orthography): try: schema = OrthographySchema() values = json.loads(unicode(request.body, request.charset)) state = h.get_state_object(values) state.id = id result = schema.to_python(values, state) orthography = update_orthography(orthography, result) # orthography will be False if there are no changes (cf. update_orthography). if orthography: Session.add(orthography) Session.commit() return orthography else: response.status_int = 400 return { 'error': u'The update request failed because the submitted data were not new.' } except h.JSONDecodeError: response.status_int = 400 return h.JSONDecodeErrorResponse except Invalid, e: response.status_int = 400 return {'errors': e.unpack_errors()} else: response.status = 403 return { 'error': u'Only administrators are permitted to update orthographies that are used in the active application settings.' }
def update(self, id): """Update an orthography and return it. :URL: ``PUT /orthographies/id`` :Request body: JSON object representing the orthography with updated attribute values. :param str id: the ``id`` value of the orthography to be updated. :returns: the updated orthography model. .. note:: Contributors can only update orthographies that are not used in the active application settings. """ orthography = Session.query(Orthography).get(int(id)) user = session['user'] if orthography: app_set = h.get_application_settings() if user.role == u'administrator' or orthography not in ( app_set.storage_orthography, app_set.input_orthography, app_set.output_orthography): try: schema = OrthographySchema() values = json.loads(unicode(request.body, request.charset)) state = h.get_state_object(values) state.id = id result = schema.to_python(values, state) orthography = update_orthography(orthography, result) # orthography will be False if there are no changes (cf. update_orthography). if orthography: Session.add(orthography) Session.commit() return orthography else: response.status_int = 400 return {'error': u'The update request failed because the submitted data were not new.'} except h.JSONDecodeError: response.status_int = 400 return h.JSONDecodeErrorResponse except Invalid, e: response.status_int = 400 return {'errors': e.unpack_errors()} else: response.status = 403 return {'error': u'Only administrators are permitted to update orthographies that are used in the active application settings.'}
def delete(self, id): """Delete an existing application settings and return it. :URL: ``DELETE /applicationsettings/id`` :param str id: the ``id`` value of the application settings to be deleted. :returns: the deleted application settings model. """ application_settings = h.eagerload_application_settings( Session.query(ApplicationSettings)).get(id) if application_settings: active_application_settings_id = getattr(h.get_application_settings(), 'id', None) to_be_deleted_application_settings_id = application_settings.id Session.delete(application_settings) Session.commit() if active_application_settings_id == to_be_deleted_application_settings_id: app_globals.application_settings = h.ApplicationSettings() return application_settings else: response.status_int = 404 return {'error': 'There is no application settings with id %s' % id}
def delete(self, id): """Delete an existing application settings and return it. :URL: ``DELETE /applicationsettings/id`` :param str id: the ``id`` value of the application settings to be deleted. :returns: the deleted application settings model. """ application_settings = h.eagerload_application_settings( Session.query(ApplicationSettings)).get(id) if application_settings: active_application_settings_id = getattr( h.get_application_settings(), 'id', None) to_be_deleted_application_settings_id = application_settings.id Session.delete(application_settings) Session.commit() if active_application_settings_id == to_be_deleted_application_settings_id: app_globals.application_settings = h.ApplicationSettings() return application_settings else: response.status_int = 404 return { 'error': 'There is no application settings with id %s' % id }
def test_delete(self): """Tests that DELETE /orthographies/id deletes the orthography with id=id.""" # Create an orthography to delete. params = self.orthography_create_params.copy() params.update({'name': u'orthography', 'orthography': u'a, b, c'}) params = json.dumps(params) response = self.app.post(url('orthographies'), params, self.json_headers, self.extra_environ_admin) resp = json.loads(response.body) orthography_count = Session.query(Orthography).count() assert resp['name'] == u'orthography' assert resp['orthography'] == u'a, b, c' assert resp['lowercase'] == False # default value from model/orthography.py assert resp['initial_glottal_stops'] == True # default value from model/orthography.py orthography_id = resp['id'] original_datetime_modified = resp['datetime_modified'] # Now delete the orthography response = self.app.delete(url('orthography', id=orthography_id), headers=self.json_headers, extra_environ=self.extra_environ_admin) resp = json.loads(response.body) new_orthography_count = Session.query(Orthography).count() assert new_orthography_count == orthography_count - 1 assert resp['id'] == orthography_id assert response.content_type == 'application/json' # Trying to get the deleted orthography from the db should return None deleted_orthography = Session.query(Orthography).get(orthography_id) assert deleted_orthography == None # Delete with an invalid id id = 9999999999999 response = self.app.delete(url('orthography', id=id), headers=self.json_headers, extra_environ=self.extra_environ_admin, status=404) assert u'There is no orthography with id %s' % id in json.loads(response.body)['error'] assert response.content_type == 'application/json' # Delete without an id response = self.app.delete(url('orthography', id=''), status=404, headers=self.json_headers, extra_environ=self.extra_environ_admin) assert json.loads(response.body)['error'] == 'The resource could not be found.' assert response.content_type == 'application/json' # Observe how deletions are restricted when an orthography is part of an # active application settings ... # Create an orthography to demonstrate. params = self.orthography_create_params.copy() params.update({'name': u'orthography', 'orthography': u'a, b, c'}) params = json.dumps(params) response = self.app.post(url('orthographies'), params, self.json_headers, self.extra_environ_admin) resp = json.loads(response.body) orthography_count = Session.query(Orthography).count() assert resp['name'] == u'orthography' assert resp['orthography'] == u'a, b, c' assert resp['lowercase'] == False # default value from model/orthography.py assert resp['initial_glottal_stops'] == True # default value from model/orthography.py orthography_id = resp['id'] # Create an application settings with the above orthography as the storage orthography app_set = h.generate_default_application_settings() app_set.storage_orthography = Session.query(Orthography).get(orthography_id) Session.add(app_set) Session.commit() # Now attempting to delete as a contributor should fail response = self.app.delete(url('orthography', id=orthography_id), headers=self.json_headers, extra_environ=self.extra_environ_contrib, status=403) resp = json.loads(response.body) assert resp['error'] == u'Only administrators are permitted to delete orthographies that are used in the active application settings.' assert response.content_type == 'application/json' # If we now remove the orthography from the application settings, the # contributor will be able to delete it. app_set = h.get_application_settings() app_set.storage_orthography = None Session.commit() response = self.app.delete(url('orthography', id=orthography_id), headers=self.json_headers, extra_environ=self.extra_environ_contrib) resp = json.loads(response.body) assert response.content_type == 'application/json' assert resp['orthography'] == u'a, b, c'
def test_update(self): """Tests that PUT /orthographies/id updates the orthography with id=id.""" # Create an orthography to update. params = self.orthography_create_params.copy() params.update({'name': u'orthography', 'orthography': u'a, b, c'}) params = json.dumps(params) response = self.app.post(url('orthographies'), params, self.json_headers, self.extra_environ_admin) resp = json.loads(response.body) orthography_count = Session.query(Orthography).count() assert resp['name'] == u'orthography' assert resp['orthography'] == u'a, b, c' assert resp['lowercase'] == False # default value from model/orthography.py assert resp['initial_glottal_stops'] == True # default value from model/orthography.py assert response.content_type == 'application/json' orthography_id = resp['id'] original_datetime_modified = resp['datetime_modified'] # Update the orthography sleep(1) # sleep for a second to ensure that MySQL registers a different datetime_modified for the update params = self.orthography_create_params.copy() params.update({'name': u'orthography', 'orthography': u'a, b, c, d'}) params = json.dumps(params) response = self.app.put(url('orthography', id=orthography_id), params, self.json_headers, self.extra_environ_admin) resp = json.loads(response.body) datetime_modified = resp['datetime_modified'] new_orthography_count = Session.query(Orthography).count() assert orthography_count == new_orthography_count assert datetime_modified != original_datetime_modified assert resp['orthography'] == u'a, b, c, d' assert response.content_type == 'application/json' # Attempt an update with no new input and expect to fail sleep(1) # sleep for a second to ensure that MySQL could register a different datetime_modified for the update response = self.app.put(url('orthography', id=orthography_id), params, self.json_headers, self.extra_environ_admin, status=400) resp = json.loads(response.body) orthography_count = new_orthography_count new_orthography_count = Session.query(Orthography).count() our_orthography_datetime_modified = Session.query(Orthography).get(orthography_id).datetime_modified assert our_orthography_datetime_modified.isoformat() == datetime_modified assert orthography_count == new_orthography_count assert resp['error'] == u'The update request failed because the submitted data were not new.' assert response.content_type == 'application/json' # Observe how updates are restricted when an orthography is part of an # active application settings ... app_set = h.generate_default_application_settings() app_set.storage_orthography = Session.query(Orthography).get(orthography_id) Session.add(app_set) Session.commit() # Now attempting a valid update as a contributor should fail params = self.orthography_create_params.copy() params.update({'name': u'orthography', 'orthography': u'a, b, c, d, e'}) params = json.dumps(params) response = self.app.put(url('orthography', id=orthography_id), params, self.json_headers, self.extra_environ_contrib, status=403) resp = json.loads(response.body) assert resp['error'] == u'Only administrators are permitted to update orthographies that are used in the active application settings.' assert response.content_type == 'application/json' # The same update as an admin should succeed. params = self.orthography_create_params.copy() params.update({'name': u'orthography', 'orthography': u'a, b, c, d, e'}) params = json.dumps(params) response = self.app.put(url('orthography', id=orthography_id), params, self.json_headers, self.extra_environ_admin) resp = json.loads(response.body) assert resp['name'] == u'orthography' assert resp['orthography'] == u'a, b, c, d, e' assert response.content_type == 'application/json' # If we now remove the orthography from the application settings, the # contributor will be able to edit it. app_set = h.get_application_settings() app_set.storage_orthography = None Session.commit() params = self.orthography_create_params.copy() params.update({'name': u'orthography', 'orthography': u'a, b, c, d, e, f'}) params = json.dumps(params) response = self.app.put(url('orthography', id=orthography_id), params, self.json_headers, self.extra_environ_contrib) resp = json.loads(response.body) assert response.content_type == 'application/json' assert resp['name'] == u'orthography' assert resp['orthography'] == u'a, b, c, d, e, f'
def test_delete(self): """Tests that DELETE /orthographies/id deletes the orthography with id=id.""" # Create an orthography to delete. params = self.orthography_create_params.copy() params.update({'name': u'orthography', 'orthography': u'a, b, c'}) params = json.dumps(params) response = self.app.post(url('orthographies'), params, self.json_headers, self.extra_environ_admin) resp = json.loads(response.body) orthography_count = Session.query(Orthography).count() assert resp['name'] == u'orthography' assert resp['orthography'] == u'a, b, c' assert resp[ 'lowercase'] == False # default value from model/orthography.py assert resp[ 'initial_glottal_stops'] == True # default value from model/orthography.py orthography_id = resp['id'] original_datetime_modified = resp['datetime_modified'] # Now delete the orthography response = self.app.delete(url('orthography', id=orthography_id), headers=self.json_headers, extra_environ=self.extra_environ_admin) resp = json.loads(response.body) new_orthography_count = Session.query(Orthography).count() assert new_orthography_count == orthography_count - 1 assert resp['id'] == orthography_id assert response.content_type == 'application/json' # Trying to get the deleted orthography from the db should return None deleted_orthography = Session.query(Orthography).get(orthography_id) assert deleted_orthography == None # Delete with an invalid id id = 9999999999999 response = self.app.delete(url('orthography', id=id), headers=self.json_headers, extra_environ=self.extra_environ_admin, status=404) assert u'There is no orthography with id %s' % id in json.loads( response.body)['error'] assert response.content_type == 'application/json' # Delete without an id response = self.app.delete(url('orthography', id=''), status=404, headers=self.json_headers, extra_environ=self.extra_environ_admin) assert json.loads( response.body)['error'] == 'The resource could not be found.' assert response.content_type == 'application/json' # Observe how deletions are restricted when an orthography is part of an # active application settings ... # Create an orthography to demonstrate. params = self.orthography_create_params.copy() params.update({'name': u'orthography', 'orthography': u'a, b, c'}) params = json.dumps(params) response = self.app.post(url('orthographies'), params, self.json_headers, self.extra_environ_admin) resp = json.loads(response.body) orthography_count = Session.query(Orthography).count() assert resp['name'] == u'orthography' assert resp['orthography'] == u'a, b, c' assert resp[ 'lowercase'] == False # default value from model/orthography.py assert resp[ 'initial_glottal_stops'] == True # default value from model/orthography.py orthography_id = resp['id'] # Create an application settings with the above orthography as the storage orthography app_set = h.generate_default_application_settings() app_set.storage_orthography = Session.query(Orthography).get( orthography_id) Session.add(app_set) Session.commit() # Now attempting to delete as a contributor should fail response = self.app.delete(url('orthography', id=orthography_id), headers=self.json_headers, extra_environ=self.extra_environ_contrib, status=403) resp = json.loads(response.body) assert resp[ 'error'] == u'Only administrators are permitted to delete orthographies that are used in the active application settings.' assert response.content_type == 'application/json' # If we now remove the orthography from the application settings, the # contributor will be able to delete it. app_set = h.get_application_settings() app_set.storage_orthography = None Session.commit() response = self.app.delete(url('orthography', id=orthography_id), headers=self.json_headers, extra_environ=self.extra_environ_contrib) resp = json.loads(response.body) assert response.content_type == 'application/json' assert resp['orthography'] == u'a, b, c'
def test_update(self): """Tests that PUT /orthographies/id updates the orthography with id=id.""" # Create an orthography to update. params = self.orthography_create_params.copy() params.update({'name': u'orthography', 'orthography': u'a, b, c'}) params = json.dumps(params) response = self.app.post(url('orthographies'), params, self.json_headers, self.extra_environ_admin) resp = json.loads(response.body) orthography_count = Session.query(Orthography).count() assert resp['name'] == u'orthography' assert resp['orthography'] == u'a, b, c' assert resp[ 'lowercase'] == False # default value from model/orthography.py assert resp[ 'initial_glottal_stops'] == True # default value from model/orthography.py assert response.content_type == 'application/json' orthography_id = resp['id'] original_datetime_modified = resp['datetime_modified'] # Update the orthography sleep( 1 ) # sleep for a second to ensure that MySQL registers a different datetime_modified for the update params = self.orthography_create_params.copy() params.update({'name': u'orthography', 'orthography': u'a, b, c, d'}) params = json.dumps(params) response = self.app.put(url('orthography', id=orthography_id), params, self.json_headers, self.extra_environ_admin) resp = json.loads(response.body) datetime_modified = resp['datetime_modified'] new_orthography_count = Session.query(Orthography).count() assert orthography_count == new_orthography_count assert datetime_modified != original_datetime_modified assert resp['orthography'] == u'a, b, c, d' assert response.content_type == 'application/json' # Attempt an update with no new input and expect to fail sleep( 1 ) # sleep for a second to ensure that MySQL could register a different datetime_modified for the update response = self.app.put(url('orthography', id=orthography_id), params, self.json_headers, self.extra_environ_admin, status=400) resp = json.loads(response.body) orthography_count = new_orthography_count new_orthography_count = Session.query(Orthography).count() our_orthography_datetime_modified = Session.query(Orthography).get( orthography_id).datetime_modified assert our_orthography_datetime_modified.isoformat( ) == datetime_modified assert orthography_count == new_orthography_count assert resp[ 'error'] == u'The update request failed because the submitted data were not new.' assert response.content_type == 'application/json' # Observe how updates are restricted when an orthography is part of an # active application settings ... app_set = h.generate_default_application_settings() app_set.storage_orthography = Session.query(Orthography).get( orthography_id) Session.add(app_set) Session.commit() # Now attempting a valid update as a contributor should fail params = self.orthography_create_params.copy() params.update({ 'name': u'orthography', 'orthography': u'a, b, c, d, e' }) params = json.dumps(params) response = self.app.put(url('orthography', id=orthography_id), params, self.json_headers, self.extra_environ_contrib, status=403) resp = json.loads(response.body) assert resp[ 'error'] == u'Only administrators are permitted to update orthographies that are used in the active application settings.' assert response.content_type == 'application/json' # The same update as an admin should succeed. params = self.orthography_create_params.copy() params.update({ 'name': u'orthography', 'orthography': u'a, b, c, d, e' }) params = json.dumps(params) response = self.app.put(url('orthography', id=orthography_id), params, self.json_headers, self.extra_environ_admin) resp = json.loads(response.body) assert resp['name'] == u'orthography' assert resp['orthography'] == u'a, b, c, d, e' assert response.content_type == 'application/json' # If we now remove the orthography from the application settings, the # contributor will be able to edit it. app_set = h.get_application_settings() app_set.storage_orthography = None Session.commit() params = self.orthography_create_params.copy() params.update({ 'name': u'orthography', 'orthography': u'a, b, c, d, e, f' }) params = json.dumps(params) response = self.app.put(url('orthography', id=orthography_id), params, self.json_headers, self.extra_environ_contrib) resp = json.loads(response.body) assert response.content_type == 'application/json' assert resp['name'] == u'orthography' assert resp['orthography'] == u'a, b, c, d, e, f'
def test_edit(self): """Tests that GET /applicationsettings/id/edit returns a JSON object for editing an existing application settings. The JSON object is of the form {application_settings: {...}, data: {...}} or {'error': '...'} (and a 404 status code) depending on whether the id is valid or invalid/unspecified, respectively. """ # Not logged in: expect 401 Unauthorized response = self.app.get( url('edit_applicationsetting', id=100000000000), status=401) resp = json.loads(response.body) assert resp['error'] == u'Authentication is required to access this resource.' assert response.content_type == 'application/json' # Invalid id: expect 404 Not Found id = 100000000000 response = self.app.get(url('edit_applicationsetting', id=id), extra_environ=self.extra_environ_admin, status=404) assert json.loads(response.body)['error'] == \ u'There is no application settings with id %s' % id assert response.content_type == 'application/json' # No id: expect 404 Not Found response = self.app.get(url('edit_applicationsetting', id=''), status=404, extra_environ=self.extra_environ_admin) assert json.loads(response.body)['error'] == \ 'The resource could not be found.' # Add the default application settings. application_settings = add_default_application_settings() application_settings = h.get_application_settings() application_settings_id = application_settings.id # Valid id response = self.app.get(url('edit_applicationsetting', id=application_settings_id), extra_environ=self.extra_environ_admin) resp = json.loads(response.body) assert response.content_type == 'application/json' assert type(resp) == type({}) assert resp['application_settings']['object_language_name'] == \ application_settings.object_language_name # Valid id with GET params. Param values are treated as strings, not # JSON. If any params are specified, the default is to return a JSON # array corresponding to store for the param. There are three cases # that will result in an empty JSON array being returned: # 1. the param is not specified # 2. the value of the specified param is an empty string # 3. the value of the specified param is an ISO 8601 UTC datetime # string that matches the most recent datetime_modified value of the # store in question. # Get the data currently in the db (see websetup.py for the test data). data = { 'languages': h.get_languages(), 'users': h.get_mini_dicts_getter('User')(), 'orthographies': h.get_mini_dicts_getter('Orthography')() } # JSON.stringify and then re-Python-ify the data. This is what the data # should look like in the response to a simulated GET request. data = json.loads(json.dumps(data, cls=h.JSONOLDEncoder)) params = { # Value is a non-empty string: 'users' will be in response. 'users': 'give me some users!', # Value is empty string: 'languages' will not be in response. 'languages': '', # Value is ISO 8601 UTC datetime string that does not match the most # recent Orthography.datetime_modified value: 'orthographies' *will* # be in the response. 'orthographies': datetime.datetime.utcnow().isoformat(), } response = self.app.get(url('edit_applicationsetting', id=application_settings_id), params, extra_environ=self.extra_environ_admin) resp = json.loads(response.body) assert resp['data']['users'] == data['users'] assert resp['data']['languages'] == [] assert resp['data']['orthographies'] == data['orthographies'] # Invalid id with GET params. It should still return a 404 Not Found. params = { # If id were valid, this would cause a users array to be returned also. 'users': 'True', } response = self.app.get( url('edit_applicationsetting', id=id), params, extra_environ=self.extra_environ_admin, status=404) assert json.loads(response.body)['error'] == \ u'There is no application settings with id %s' % id