def get(self): """Function is called by cron to build a contact index Call with a key to build index for this entity. """ if not users.is_current_user_admin(): logging.critical("UpdateIndex called by non-admin") self.error(500) return key = self.request.get("key", None) logging.info("Update index tables.") if key: con = Contact.get(Key(key)) if con: update_index(con) # update dependant take2 entries for t2 in Take2.all().filter("contact_ref =", con): update_index(t2) # update parent login_user user = LoginUser.all().filter("me =", con).get() if user: update_index(user) return else: t2 = Take2.get(Key(key)) if t2: update_index(t2) return logging.info("Could not find key: %s" % (key)) return # Go through the tables which contribute to the index for table in [LoginUser,Contact,Address]: batch = [] for obj in table.all(): res = update_index(obj, batch=True) if res: batch.extend(res) # bulk db operation db.put(batch) logging.info("%d updates." % (len(batch))) self.response.headers['Content-Type'] = "text/plain" self.response.out.write("/index done.")
def encode_take2(contact, include_attic=False): """Encodes the contact's take2 property objects Returns a dictionary with the property's name as the key and a list of properties as values. """ restypes = {} for take2 in [Email,Web,Address,Mobile,Other]: restypes[take2.class_name().lower()] = [] q_obj = Take2.all() q_obj.filter("contact_ref =", contact) q_obj.order('-timestamp') for obj in q_obj: # do only enclose non-attic take2 properties unless attic parameter is set if obj.attic and not include_attic: continue res = {} res['key'] = str(obj.key()) res['type'] = obj.class_name().lower() res['timestamp'] = obj.timestamp.isoformat() res['attic'] = obj.attic if obj.class_name() == "Email": res['email'] = obj.email elif obj.class_name() == "Web": res['web'] = obj.web elif obj.class_name() == "Address": if obj.location: res['location_lat'] = obj.location.lat res['location_lon'] = obj.location.lon res['adr'] = obj.adr if obj.landline_phone: res['landline_phone'] = obj.landline_phone if obj.country: res['country'] = obj.country.country if obj.adr_zoom: res['adr_zoom'] = obj.adr_zoom elif obj.class_name() == "Mobile": res['mobile'] = obj.mobile elif obj.class_name() == "Other": res['tag'] = obj.tag.tag res['text'] = obj.text else: assert True, "Invalid class name: %s" % obj.class_name() restypes[obj.class_name().lower()].append(res) return restypes
def deattic_take2(self, login_user=None, template_values={}): instance = self.request.get("instance", "") key = self.request.get("key", "") t2 = Take2.get(key) # consistency checks assert t2.class_name() == instance.title(), "Edit class name %s does not fit with object %s" % (instance,key) contact = t2.contact_ref assert contact.class_name() in ['Person','Contact'], "Object %s key: %s is not a Contact" % (contact.class_name(),str(contact.key())) # access check if not write_access(contact, login_user): self.error(500) return logging.debug("De-attic: %s instance: %s key: %s" % (contact.name,instance,key)) t2.attic = False; t2.put(); if t2.class_name() == 'Address': update_index(t2) self.redirect('/editcontact?key=%s' % str(contact.key()))
def encode_contact(contact, login_user, include_attic=False, include_privacy=False): """Factory to encode data into view classes which can easily be rendered 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. If include_privacy is set, it will include the privacy setting for contacts this user owns: private, restricted or public """ result = None # do only enclose non-attic contacts unless attic parameter is set if contact.attic and not include_attic: return None result = ContactView(contact) if contact.class_name() == "Person": if contact.lastname: result.lastname = contact.lastname if login_user: # Birthday if contact.class_name() == "Person": if contact.birthday.has_year(): result.birthyear = contact.birthday.year if contact.birthday.has_month(): result.birthmonth = calendar.month_name[contact.birthday.month] if contact.birthday.has_day(): result.birthday = contact.birthday.day # nickname if contact.nickname: result.nickname = contact.nickname # A user can see their own data, obviously if login_user and login_user.key() == contact.owned_by.key(): # introduction/relation to this person result.relation = contact.introduction if contact.introduction else "" # Relation back to the middleman if contact.middleman_ref: result.middleman = contact.middleman_ref.name result.middleman_ref = str(contact.middleman_ref.key()) # Relation(s) going out from this person towards others result.contacts = [] # for con in Contact.all().filter("middleman_ref =", contact): for con in contact.affix: if not con.attic or include_attic: result.append_take2(con) # can I edit the contact data? if login_user: if contact.owned_by.key() == login_user.key(): result.can_edit = True # Is this the contact data for the logged in user (myself)? if login_user and login_user.me: if contact.key() == login_user.me.key(): result.is_myself = True # # encode contact's data # q_obj = Take2.all() q_obj.filter("contact_ref =", contact) q_obj.order('-timestamp') for obj in q_obj: # do only enclose non-attic take2 properties unless attic parameter is set if obj.attic and not include_attic: continue if include_privacy: # look for an entry in the SharedTake2 table priv = SharedTake2.all().filter("contact_ref =", contact).filter("take2_ref =", obj).get() if priv: if priv.class_name() == "PublicTake2": # add privacy property to obj on the fly obj.privacy = 'public' elif priv.class_name() == "RestrictedTake2": obj.privacy = 'restricted' result.append_take2(obj) else: result.relation = "(You cannot see this person's data.)" # user does not own the contact, but let's check whether the privacy settings # allow us to see something q_priv = SharedTake2.all().filter("contact_ref =", contact) for priv in q_priv: # public objects if priv.class_name() == 'PublicTake2': obj = priv.take2_ref # do only enclose non-attic take2 properties unless attic parameter is set if obj.attic and not include_attic: continue result.append_take2(obj) result.relation = "(This person shares some data.)" return result
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.")