def get(self): login_user = get_login_user() # bbox is in GeoJson notation [minlon,minlat,maxlon,maxlat] bbox = self.request.get('bbox',"0,0,0,0").split(',') minlat = float(bbox[1]) minlon = float(bbox[0]) maxlat = float(bbox[3]) maxlon = float(bbox[2]) geojson = {"type": "FeatureCollection"} geojson['features'] = [] box = geo.geotypes.Box(maxlat,maxlon,minlat,minlon) for geoix in GeoIndex.bounding_box_fetch(GeoIndex.all(), box, max_results=111): try: con = geocode_contact(geoix.contact_ref, include_attic=False, login_user=login_user) if con: # geoconding successful geojson['features'].extend(con) else: nongeo.append(encode_contact(contact_ref, login_user, include_attic=False)) except db.ReferencePropertyResolveError: logging.critical("AttributeError while encoding") geojson["bbox"] = bbox logging.debug("Return %s objects" % (len(geojson['features']))) # encode and return # self.response.headers['Content-Type'] = "application/json" self.response.headers['Content-Type'] = "text/plain" self.response.out.write(json.dumps(geojson))
def get(self): if not users.is_current_user_admin(): logging.critical("PurgeIndex called by non-admin") self.error(500) return logging.info("Purge index tables.") alldata = [] for data in SearchIndex.all(): alldata.append(data.key()) db.delete(alldata) logging.info("%d datasets deleted in SearchIndex." % (len(alldata))) alldata = [] for data in GeoIndex.all(): alldata.append(data.key()) db.delete(alldata) logging.info("%d datasets deleted in GeoIndex." % (len(alldata))) self.response.headers['Content-Type'] = "text/plain" self.response.out.write("/indexpurge done.")
def geocode_contact(contact, login_user, include_attic=False, include_privacy=False): """Encode data as a GeoJSON feature dictionary structure The function takes into account the access rights and encodes only elements which the user is allowed to see. signed_in is set to True if the user is signed in If include_attic=True, data will include the complete history and also archived data. """ features = [] # lookup coordinates for this point q_geo = GeoIndex.all() q_geo.filter("contact_ref =", contact) if not include_attic: q_geo.filter("attic =", False) for geo in q_geo: if geo.location.lat != 0.0 and geo.location.lon != 0.0: feature = {} feature['type'] = "Feature" # make position worse if user is not logged in or does not have access rights random.seed(contact.key().id_or_name()) if login_user: if login_user.key() == contact.owned_by.key(): mlat = 0.0 mlon = 0.0 else: margin = 0.005 mlat = random.random()*margin+0.5*margin mlon = random.random()*margin+0.5*margin else: margin = 0.02 mlat = random.random()*margin+0.5*margin mlon = random.random()*margin+0.5*margin feature['geometry'] = {"type": "Point", "coordinates": [geo.location.lon+mlon,geo.location.lat+mlat]} properties = {} properties['name'] = contact.name if login_user and login_user.key() == contact.owned_by.key(): properties['key'] = str(contact.key()) if login_user and contact.class_name() == 'Person': properties['lastname'] = contact.lastname else: properties['lastname'] = "" # For Addresses add place information if geo.data_ref.key().kind() == 'Take2' and geo.data_ref.class_name() == 'Address': properties['place'] = ", ".join(geo.data_ref.adr_zoom[:2]) properties["zoom"] = geo.data_ref.map_zoom else: properties['place'] = "(last known standpoint)" properties["zoom"] = 11 if login_user and login_user.key() == contact.owned_by.key(): properties["popupContent"] = "<p><strong><a href=\"/editcontact?key=%s\">%s %s</a></strong></p><p>%s</p>" % (properties['key'],properties['name'],properties['lastname'],properties['place']) else: properties["popupContent"] = "<p><strong>%s %s</strong></p><p><em>This user does not share contact information.</em></p><p>%s</p>" % (properties['name'],properties['lastname'],properties['place']) feature['properties'] = properties feature['id'] = 'display' features.append(feature) if not features: # no geodata available for this contact. Encode it simply without feature = {} feature['type'] = "Feature" properties = {} properties['name'] = contact.name if login_user and login_user.key() == contact.owned_by.key(): properties['key'] = str(contact.key()) if login_user and contact.class_name() == 'Person': properties['lastname'] = contact.lastname else: properties['lastname'] = "" properties['place'] = "" # this will be filtered out on the client side feature['geometry'] = {"type": "Point", "coordinates": [0.0,0.0]} properties["popupContent"] = "<p><strong>%s %s</strong></p><p><em>This user does not share contact information.</em></p>" % (properties['name'],properties['lastname']) feature['properties'] = properties feature['id'] = 'hide' features.append(feature) return features
def update_index(obj, batch=False): """Updates SearchIndex and GeoIndex tables with obj-related keywords and locations for the contact to which obj belongs. If obj indices are already in the SearchIndex, their content is updated. If obj is new, it is added. Index keywords are: - name (name: Contact) - nickname (nickname: Person) - last name (lastname: Person) - place (adr_zoom: Address) """ # # generate the keys and find the contact reference # new_keys = None new_location = None contact_ref = None attic = False res = [] try: obj_class = obj.class_name() except AttributeError: # for non poly model objects obj_class = obj.key().kind() if obj_class in ['Person','Contact','Company']: contact = obj new_keys = plainify(contact.name) if contact.class_name() == "Person": if contact.lastname: new_keys.extend(plainify(contact.lastname)) if contact.nickname: new_keys.extend(plainify(contact.nickname)) attic = obj.attic or contact.attic elif obj_class in ['Address']: try: contact = obj.contact_ref except db.ReferencePropertyResolveError: logging.warning("Address has invalid reference to contact %s" % (str(obj.key()))) return None # use the elements as search keys (should be town and neighborhood or similar) new_keys = plainify(" ".join(obj.adr_zoom[:2])) if obj.location: new_location = obj.location attic = obj.attic or contact.attic elif obj_class in ['LoginUser']: try: contact = obj.me except db.ReferencePropertyResolveError: logging.warning("Address has invalid reference to contact %s" % (str(obj.key()))) return None if obj.location: new_location = obj.location else: logging.debug("update_index(): class %s is not considered here" % (obj_class)) return None if new_location: logging.debug("Update %s class %s with location: %f %f" % (contact.name,obj_class,new_location.lat,new_location.lon)) if new_keys: logging.debug("Update %s class %s with keys: %s" % (contact.name,obj_class,new_keys)) if new_keys: # read SearchIndex dataset with reference to obj data = SearchIndex.all().filter("data_ref =", obj).get() if data: # update existing dataset data.keys = new_keys data.attic = attic else: if batch: logging.warning("A new search index was created in batch for dataset: %d" % (obj.key().id())) data = SearchIndex(keys=new_keys, attic=attic, data_ref=obj, contact_ref=contact) if batch: res.append(data) else: data.put() if new_location: # read GeoIndex dataset with reference to obj geo = GeoIndex.all().filter("data_ref =", obj).get() if geo: # update existing dataset geo.location = new_location geo.attic = attic # update geo reference field geo.update_location() else: if batch: logging.warning("A new geo index was created in batch for dataset: %d" % (obj.key().id())) geo = GeoIndex(location=new_location, attic=attic, data_ref=obj, contact_ref=contact) geo.update_location() if batch: res.append(geo) else: geo.put() return res
def get(self): if not users.is_current_user_admin(): logging.critical("UpdateIndex called by non-admin") self.error(500) return fix = True if self.request.get("fix", "False") == "True" else False # look for LoginUser with invalid Person attached logging.info("Check LoginUser") err = False for obj in LoginUser.all(): try: if not obj.me: logging.critical("LoginUser %d has no Person attached" % ((obj.key().id()))) err = True except db.ReferencePropertyResolveError: logging.critical("LoginUser %d has invalid Person reference" % ((obj.key().id()))) err = True if err: # check for dependent datasets count = Contact.all().filter("owned_by =", obj).count() logging.critical("LoginUser %d has %d dependant datasets" % (obj.key().id(),count)) if fix: obj.delete() logging.info("%d deleted" % obj.key().id()) err = False logging.info("Check Contact") err = False for obj in Contact.all(): try: if not obj.owned_by: logging.critical("Contact '%s' %d has no reference to owner" % (obj.name,obj.key().id())) err = True except db.ReferencePropertyResolveError: logging.critical("Contact '%s' %d has invalid reference to owner" % (obj.name,obj.key().id())) count = LoginUser.all().filter("me =", obj).count() if count: logging.critical("... but owner has reference!") err = True if err: # check for dependent datasets count = Take2.all().filter("contact_ref =", obj).count() logging.critical("Contact '%s' has %d dependent datasets" % (obj.name, count)) if fix: obj.delete() logging.info("%d deleted" % obj.key().id()) err = False logging.info("Check Take2") err = False for obj in Take2.all(): try: if not obj.contact_ref: logging.critical("Take2 has no reference to owner %s" % (obj.key().id())) err = True except db.ReferencePropertyResolveError: logging.critical("Take2 has invalid reference to owner %s" % (obj.key().id())) err = True if err: if fix: obj.delete() logging.info("%d deleted" % obj.key().id()) # location in address shall be set to default if obj.class_name() == 'Address' and not obj.location: logging.error("Address has null location %s. Fixed." % (obj.key().id())) obj.location=db.GeoPt(lon=0.0, lat=0.0) obj.put() err = False logging.info("Check SearchIndex") err = False for obj in SearchIndex.all(): try: if not obj.contact_ref: logging.critical("SearchIndex %d has no reference to owner" % (obj.key().id())) err = True except db.ReferencePropertyResolveError: logging.critical("SearchIndex %d has invalid reference to owner" % (obj.key().id())) err = True if err: if fix: obj.delete() logging.info("%d deleted" % obj.key().id()) err = False logging.info("Check GeoIndex") err = False for obj in GeoIndex.all(): try: if not obj.contact_ref: logging.critical("GeoIndex %d has no reference to owner" % (obj.key().id())) err = True except db.ReferencePropertyResolveError: logging.critical("GeoIndex %d has invalid reference to owner" % (obj.key().id())) err = True if err: if fix: obj.delete() logging.info("%d deleted" % obj.key().id()) err = False self.response.headers['Content-Type'] = "text/plain" self.response.out.write("/fix done.")