示例#1
0
    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))
示例#2
0
    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.")
示例#3
0
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
示例#4
0
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
示例#5
0
    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.")