def test_update_cache_version_associations_removed_wp(self): waypoint1 = Waypoint(waypoint_type='summit') waypoint2 = Waypoint(waypoint_type='summit') waypoint3 = Waypoint(waypoint_type='summit') waypoint_unrelated = Waypoint(waypoint_type='summit') self.session.add_all( [waypoint1, waypoint2, waypoint3, waypoint_unrelated]) self.session.flush() update_cache_version_associations([], [{ 'parent_id': waypoint1.document_id, 'parent_type': WAYPOINT_TYPE, 'child_id': waypoint2.document_id, 'child_type': WAYPOINT_TYPE }, { 'parent_id': waypoint3.document_id, 'parent_type': WAYPOINT_TYPE, 'child_id': waypoint1.document_id, 'child_type': WAYPOINT_TYPE }]) cache_version1 = self.session.query(CacheVersion).get( waypoint1.document_id) cache_version2 = self.session.query(CacheVersion).get( waypoint2.document_id) cache_version3 = self.session.query(CacheVersion).get( waypoint3.document_id) cache_version_untouched = self.session.query(CacheVersion).get( waypoint_unrelated.document_id) self.assertEqual(cache_version1.version, 2) self.assertEqual(cache_version2.version, 2) self.assertEqual(cache_version3.version, 2) self.assertEqual(cache_version_untouched.version, 1)
def collection_post(self): association = schema_association.objectify(self.request.validated) association.parent_document_type = \ self.request.validated['parent_document_type'] association.child_document_type = \ self.request.validated['child_document_type'] if exists_already(association): raise HTTPBadRequest( 'association (or its back-link) exists already') DBSession.add(association) DBSession.add( association.get_log(self.request.authenticated_userid)) update_cache_version_associations( [{'parent_id': association.parent_document_id, 'parent_type': association.parent_document_type, 'child_id': association.child_document_id, 'child_type': association.child_document_type}], []) notify_es_syncer_if_needed(association, self.request) update_feed_association_update( association.parent_document_id, association.parent_document_type, association.child_document_id, association.child_document_type, self.request.authenticated_userid) return {}
def collection_post(self): association = schema_association.objectify(self.request.validated) association.parent_document_type = \ self.request.validated['parent_document_type'] association.child_document_type = \ self.request.validated['child_document_type'] if exists_already(association): raise HTTPBadRequest( 'association (or its back-link) exists already') DBSession.add(association) DBSession.add(association.get_log(self.request.authenticated_userid)) update_cache_version_associations( [{ 'parent_id': association.parent_document_id, 'parent_type': association.parent_document_type, 'child_id': association.child_document_id, 'child_type': association.child_document_type }], []) notify_es_syncer_if_needed(association, self.request) update_feed_association_update(association.parent_document_id, association.parent_document_type, association.child_document_id, association.child_document_type, self.request.authenticated_userid) return {}
def test_update_cache_version_associations_removed_wp_route(self): waypoint1 = Waypoint(waypoint_type='summit') waypoint2 = Waypoint(waypoint_type='summit') waypoint3 = Waypoint(waypoint_type='summit') waypoint_unrelated = Waypoint(waypoint_type='summit') route = Route(activities=['skitouring']) self.session.add_all( [waypoint1, waypoint2, waypoint3, waypoint_unrelated, route]) self.session.flush() self.session.add(Association.create(waypoint2, waypoint1)) self.session.add(Association.create(waypoint3, waypoint2)) self.session.flush() update_cache_version_associations([], [ {'parent_id': waypoint1.document_id, 'parent_type': WAYPOINT_TYPE, 'child_id': route.document_id, 'child_type': ROUTE_TYPE} ]) cache_version1 = self.session.query(CacheVersion).get( waypoint1.document_id) cache_version2 = self.session.query(CacheVersion).get( waypoint2.document_id) cache_version3 = self.session.query(CacheVersion).get( waypoint3.document_id) cache_version_route = self.session.query(CacheVersion).get( route.document_id) cache_version_untouched = self.session.query(CacheVersion).get( waypoint_unrelated.document_id) self.assertEqual(cache_version1.version, 2) self.assertEqual(cache_version2.version, 2) self.assertEqual(cache_version3.version, 2) self.assertEqual(cache_version_route.version, 2) self.assertEqual(cache_version_untouched.version, 1)
def test_update_cache_version_associations_removed_wp(self): waypoint1 = Waypoint(waypoint_type='summit') waypoint2 = Waypoint(waypoint_type='summit') waypoint3 = Waypoint(waypoint_type='summit') waypoint_unrelated = Waypoint(waypoint_type='summit') self.session.add_all( [waypoint1, waypoint2, waypoint3, waypoint_unrelated]) self.session.flush() update_cache_version_associations([], [ {'parent_id': waypoint1.document_id, 'parent_type': WAYPOINT_TYPE, 'child_id': waypoint2.document_id, 'child_type': WAYPOINT_TYPE}, {'parent_id': waypoint3.document_id, 'parent_type': WAYPOINT_TYPE, 'child_id': waypoint1.document_id, 'child_type': WAYPOINT_TYPE} ]) cache_version1 = self.session.query(CacheVersion).get( waypoint1.document_id) cache_version2 = self.session.query(CacheVersion).get( waypoint2.document_id) cache_version3 = self.session.query(CacheVersion).get( waypoint3.document_id) cache_version_untouched = self.session.query(CacheVersion).get( waypoint_unrelated.document_id) self.assertEqual(cache_version1.version, 2) self.assertEqual(cache_version2.version, 2) self.assertEqual(cache_version3.version, 2) self.assertEqual(cache_version_untouched.version, 1)
def _create_document(self, document_in, schema, before_add=None, after_add=None, allow_anonymous=False): if allow_anonymous and document_in.get('anonymous') and \ self.request.registry.anonymous_user_id: user_id = self.request.registry.anonymous_user_id else: user_id = self.request.authenticated_userid document = schema.objectify(document_in) document.document_id = None if before_add: before_add(document, user_id) DBSession.add(document) DBSession.flush() DocumentRest.create_new_version(document, user_id) if document.type != AREA_TYPE: update_areas_for_document(document, reset=False) if document.type != MAP_TYPE: update_maps_for_document(document, reset=False) if after_add: after_add(document, user_id=user_id) if document_in.get('associations', None): check_association = association_permission_checker( self.request, skip_outing_check=document.type == OUTING_TYPE) added_associations = create_associations( document, document_in['associations'], user_id, check_association=check_association) update_cache_version_associations(added_associations, [], document.document_id) update_feed_document_create(document, user_id) notify_es_syncer(self.request.registry.queue_config) return document
def test_update_cache_version_associations_removed_route_outing(self): waypoint1 = Waypoint(waypoint_type='summit') waypoint2 = Waypoint(waypoint_type='summit') waypoint3 = Waypoint(waypoint_type='summit') waypoint_unrelated = Waypoint(waypoint_type='summit') route = Route(activities=['skitouring']) outing = Outing(activities=['skitouring'], date_start=datetime.date(2016, 2, 1), date_end=datetime.date(2016, 2, 1)) self.session.add_all([ waypoint1, waypoint2, waypoint3, waypoint_unrelated, route, outing ]) self.session.flush() self.session.add(Association.create(waypoint1, route)) self.session.add(Association.create(waypoint2, waypoint1)) self.session.add(Association.create(waypoint3, waypoint2)) self.session.flush() update_cache_version_associations([], [{ 'parent_id': route.document_id, 'parent_type': ROUTE_TYPE, 'child_id': outing.document_id, 'child_type': OUTING_TYPE }]) cache_version1 = self.session.query(CacheVersion).get( waypoint1.document_id) cache_version2 = self.session.query(CacheVersion).get( waypoint2.document_id) cache_version3 = self.session.query(CacheVersion).get( waypoint3.document_id) cache_version_route = self.session.query(CacheVersion).get( route.document_id) cache_version_outing = self.session.query(CacheVersion).get( outing.document_id) cache_version_untouched = self.session.query(CacheVersion).get( waypoint_unrelated.document_id) self.assertEqual(cache_version1.version, 2) self.assertEqual(cache_version2.version, 2) self.assertEqual(cache_version3.version, 2) self.assertEqual(cache_version_route.version, 2) self.assertEqual(cache_version_outing.version, 2) self.assertEqual(cache_version_untouched.version, 1)
def test_update_cache_version_associations_removed_route_outing(self): waypoint1 = Waypoint(waypoint_type='summit') waypoint2 = Waypoint(waypoint_type='summit') waypoint3 = Waypoint(waypoint_type='summit') waypoint_unrelated = Waypoint(waypoint_type='summit') route = Route(activities=['skitouring']) outing = Outing( activities=['skitouring'], date_start=datetime.date(2016, 2, 1), date_end=datetime.date(2016, 2, 1)) self.session.add_all( [waypoint1, waypoint2, waypoint3, waypoint_unrelated, route, outing]) self.session.flush() self.session.add(Association.create(waypoint1, route)) self.session.add(Association.create(waypoint2, waypoint1)) self.session.add(Association.create(waypoint3, waypoint2)) self.session.flush() update_cache_version_associations([], [ {'parent_id': route.document_id, 'parent_type': ROUTE_TYPE, 'child_id': outing.document_id, 'child_type': OUTING_TYPE} ]) cache_version1 = self.session.query(CacheVersion).get( waypoint1.document_id) cache_version2 = self.session.query(CacheVersion).get( waypoint2.document_id) cache_version3 = self.session.query(CacheVersion).get( waypoint3.document_id) cache_version_route = self.session.query(CacheVersion).get( route.document_id) cache_version_outing = self.session.query(CacheVersion).get( outing.document_id) cache_version_untouched = self.session.query(CacheVersion).get( waypoint_unrelated.document_id) self.assertEqual(cache_version1.version, 2) self.assertEqual(cache_version2.version, 2) self.assertEqual(cache_version3.version, 2) self.assertEqual(cache_version_route.version, 2) self.assertEqual(cache_version_outing.version, 2) self.assertEqual(cache_version_untouched.version, 1)
def collection_delete(self): association_in = schema_association.objectify(self.request.validated) association = self._load(association_in) if association is None: # also accept {parent_document_id: y, child_document_id: x} when # for an association {parent_document_id: x, child_document_id: x} association_in = Association( parent_document_id=association_in.child_document_id, child_document_id=association_in.parent_document_id) association = self._load(association_in) if association is None: raise HTTPBadRequest('association does not exist') _check_required_associations(association) check_permission_for_association_removal(self.request, association) log = association.get_log(self.request.authenticated_userid, is_creation=False) DBSession.delete(association) DBSession.add(log) update_cache_version_associations( [], [{ 'parent_id': association.parent_document_id, 'parent_type': association.parent_document_type, 'child_id': association.child_document_id, 'child_type': association.child_document_type }]) notify_es_syncer_if_needed(association, self.request) update_feed_association_update(association.parent_document_id, association.parent_document_type, association.child_document_id, association.child_document_type, self.request.authenticated_userid) return {}
def _create_document( self, document_in, schema, before_add=None, after_add=None): user_id = self.request.authenticated_userid document = schema.objectify(document_in) document.document_id = None if before_add: before_add(document, user_id) DBSession.add(document) DBSession.flush() DocumentRest.create_new_version(document, user_id) if document.type != AREA_TYPE: update_areas_for_document(document, reset=False) if document.type != MAP_TYPE: update_maps_for_document(document, reset=False) if after_add: after_add(document, user_id=user_id) if document_in.get('associations', None): check_association = association_permission_checker( self.request, skip_outing_check=document.type == OUTING_TYPE) added_associations = create_associations( document, document_in['associations'], user_id, check_association=check_association) update_cache_version_associations( added_associations, [], document.document_id) update_feed_document_create(document, user_id) notify_es_syncer(self.request.registry.queue_config) return document
def test_update_cache_version_associations_removed_wp_route(self): waypoint1 = Waypoint(waypoint_type='summit') waypoint2 = Waypoint(waypoint_type='summit') waypoint3 = Waypoint(waypoint_type='summit') waypoint_unrelated = Waypoint(waypoint_type='summit') route = Route(activities=['skitouring']) self.session.add_all( [waypoint1, waypoint2, waypoint3, waypoint_unrelated, route]) self.session.flush() self.session.add(Association.create(waypoint2, waypoint1)) self.session.add(Association.create(waypoint3, waypoint2)) self.session.flush() update_cache_version_associations([], [{ 'parent_id': waypoint1.document_id, 'parent_type': WAYPOINT_TYPE, 'child_id': route.document_id, 'child_type': ROUTE_TYPE }]) cache_version1 = self.session.query(CacheVersion).get( waypoint1.document_id) cache_version2 = self.session.query(CacheVersion).get( waypoint2.document_id) cache_version3 = self.session.query(CacheVersion).get( waypoint3.document_id) cache_version_route = self.session.query(CacheVersion).get( route.document_id) cache_version_untouched = self.session.query(CacheVersion).get( waypoint_unrelated.document_id) self.assertEqual(cache_version1.version, 2) self.assertEqual(cache_version2.version, 2) self.assertEqual(cache_version3.version, 2) self.assertEqual(cache_version_route.version, 2) self.assertEqual(cache_version_untouched.version, 1)
def collection_delete(self): association_in = schema_association.objectify(self.request.validated) association = self._load(association_in) if association is None: # also accept {parent_document_id: y, child_document_id: x} when # for an association {parent_document_id: x, child_document_id: x} association_in = Association( parent_document_id=association_in.child_document_id, child_document_id=association_in.parent_document_id) association = self._load(association_in) if association is None: raise HTTPBadRequest('association does not exist') _check_required_associations(association) check_permission_for_association_removal(self.request, association) log = association.get_log( self.request.authenticated_userid, is_creation=False) DBSession.delete(association) DBSession.add(log) update_cache_version_associations( [], [{'parent_id': association.parent_document_id, 'parent_type': association.parent_document_type, 'child_id': association.child_document_id, 'child_type': association.child_document_type}]) notify_es_syncer_if_needed(association, self.request) update_feed_association_update( association.parent_document_id, association.parent_document_type, association.child_document_id, association.child_document_type, self.request.authenticated_userid) return {}
def update_document(document, document_in, request, before_update=None, after_update=None, manage_versions=None): user_id = request.authenticated_userid # remember the current version numbers of the document old_versions = document.get_versions() if before_update: before_update(document, document_in) # update the document with the input document document.update(document_in) if manage_versions: manage_versions(document, old_versions) try: DBSession.flush() except StaleDataError: raise HTTPConflict('concurrent modification') # when flushing the session, SQLAlchemy automatically updates the # version numbers in case attributes have changed. by comparing with # the old version numbers, we can check if only figures or only locales # have changed. (update_types, changed_langs) = document.get_update_type(old_versions) if update_types: # A new version needs to be created and persisted DocumentRest.update_version(document, user_id, request.validated['message'], update_types, changed_langs) if document.type != AREA_TYPE and UpdateType.GEOM in update_types: update_areas_for_document(document, reset=True) if document.type != MAP_TYPE and UpdateType.GEOM in update_types: update_maps_for_document(document, reset=True) if after_update: after_update(document, update_types, user_id=user_id) update_cache_version(document) associations = request.validated.get('associations', None) if associations: check_association_add = \ association_permission_checker(request) check_association_remove = \ association_permission_removal_checker(request) added_associations, removed_associations = \ synchronize_associations( document, associations, user_id, check_association_add=check_association_add, check_association_remove=check_association_remove) if update_types or associations: # update search index notify_es_syncer(request.registry.queue_config) update_feed_document_update(document, user_id, update_types) if associations and (removed_associations or added_associations): update_cache_version_associations(added_associations, removed_associations) return update_types
def _put( self, clazz, schema, clazz_locale=None, before_update=None, after_update=None): user_id = self.request.authenticated_userid id = self.request.validated['id'] document_in = \ schema.objectify(self.request.validated['document']) self._check_document_id(id, document_in.document_id) # get the current version of the document document = self._get_document(clazz, id, clazz_locale=clazz_locale) if document.redirects_to: raise HTTPBadRequest('can not update merged document') if document.protected and not self.request.has_permission('moderator'): raise HTTPForbidden('No permission to change a protected document') self._check_versions(document, document_in) # remember the current version numbers of the document old_versions = document.get_versions() # update the document with the input document document.update(document_in) if before_update: before_update(document, document_in, user_id=user_id) try: DBSession.flush() except StaleDataError: raise HTTPConflict('concurrent modification') # when flushing the session, SQLAlchemy automatically updates the # version numbers in case attributes have changed. by comparing with # the old version numbers, we can check if only figures or only locales # have changed. (update_types, changed_langs) = document.get_update_type(old_versions) if update_types: # A new version needs to be created and persisted self._update_version( document, user_id, self.request.validated['message'], update_types, changed_langs) if document.type != AREA_TYPE and UpdateType.GEOM in update_types: update_areas_for_document(document, reset=True) if document.type != MAP_TYPE and UpdateType.GEOM in update_types: update_maps_for_document(document, reset=True) if after_update: after_update(document, update_types, user_id=user_id) update_cache_version(document) associations = self.request.validated.get('associations', None) if associations: check_association_add = \ association_permission_checker(self.request) check_association_remove = \ association_permission_removal_checker(self.request) added_associations, removed_associations = \ synchronize_associations( document, associations, user_id, check_association_add=check_association_add, check_association_remove=check_association_remove) if update_types or associations: # update search index notify_es_syncer(self.request.registry.queue_config) update_feed_document_update(document, user_id, update_types) if associations and (removed_associations or added_associations): update_cache_version_associations( added_associations, removed_associations) return {}
def _put( self, clazz, schema, clazz_locale=None, before_update=None, after_update=None): user_id = self.request.authenticated_userid id = self.request.validated['id'] document_in = \ schema.objectify(self.request.validated['document']) self._check_document_id(id, document_in.document_id) # get the current version of the document document = self._get_document(clazz, id, clazz_locale=clazz_locale) if document.redirects_to: raise HTTPBadRequest('can not update merged document') if document.protected and not self.request.has_permission('moderator'): raise HTTPForbidden('No permission to change a protected document') self._check_versions(document, document_in) # remember the current version numbers of the document old_versions = document.get_versions() # update the document with the input document document.update(document_in) if before_update: before_update(document, document_in, user_id=user_id) try: DBSession.flush() except StaleDataError: raise HTTPConflict('concurrent modification') # when flushing the session, SQLAlchemy automatically updates the # version numbers in case attributes have changed. by comparing with # the old version numbers, we can check if only figures or only locales # have changed. (update_types, changed_langs) = document.get_update_type(old_versions) if update_types: # A new version needs to be created and persisted DocumentRest.update_version( document, user_id, self.request.validated['message'], update_types, changed_langs) if document.type != AREA_TYPE and UpdateType.GEOM in update_types: update_areas_for_document(document, reset=True) if document.type != MAP_TYPE and UpdateType.GEOM in update_types: update_maps_for_document(document, reset=True) if after_update: after_update(document, update_types, user_id=user_id) update_cache_version(document) associations = self.request.validated.get('associations', None) if associations: check_association_add = \ association_permission_checker(self.request) check_association_remove = \ association_permission_removal_checker(self.request) added_associations, removed_associations = \ synchronize_associations( document, associations, user_id, check_association_add=check_association_add, check_association_remove=check_association_remove) if update_types or associations: # update search index notify_es_syncer(self.request.registry.queue_config) update_feed_document_update(document, user_id, update_types) if associations and (removed_associations or added_associations): update_cache_version_associations( added_associations, removed_associations) return {}