def upload_profile() -> Response: try: form = request.form.to_dict() identifier = form['ID'] meta = form['meta'] profile = form['profile'] identifier = ID.parse(identifier=identifier) # save meta if meta is None: meta = g_facebook.meta(identifier=identifier) if meta is None: raise LookupError('meta not found: %s' % identifier) else: meta = Meta.parse(meta=json.loads(meta)) if not g_facebook.save_meta(meta=meta, identifier=identifier): raise ValueError('meta not acceptable: %s' % identifier) # save profile if profile is None: raise ValueError('profile empty: %s' % identifier) else: profile = Document.parse(document=json.loads(profile)) if not g_facebook.save_document(document=profile): raise ValueError('profile not acceptable: %s' % identifier) # OK return user(identifier) except Exception as error: res = { 'code': 500, 'name': 'Internal Server Error', 'message': '%s' % error } xml = render_template('error.xml', result=res) return respond_xml(xml)
def do_profile(self, name: str): if self.client is None: self.info('login first') return facebook = g_messenger.facebook user = facebook.current_user profile = None if name is None: identifier = user.identifier elif name.startswith('{') and name.endswith('}'): identifier = user.identifier profile = json_decode(data=utf8_encode(string=name)) else: identifier = ID.parse(identifier=name) if identifier is None: self.info('I don\'t understand.') return if profile: private_key = facebook.private_key_for_signature(identifier=identifier) assert private_key is not None, 'failed to get private key for client: %s' % self.client # create new profile and set all properties tai = Document.create(doc_type=Document.VISA, identifier=identifier) for key in profile: tai.set_property(key, profile.get(key)) tai.sign(private_key=private_key) cmd = DocumentCommand.response(identifier=identifier, document=tai) else: cmd = DocumentCommand.query(identifier=identifier) self.client.send_command(cmd=cmd)
def check_document(self, document: Document) -> bool: """ Checking document :param document: entity document :return: True on accepted """ identifier = document.identifier if identifier is None: return False # NOTICE: if this is a group profile, # verify it with each member's meta.key # else (this is a user profile) # verify it with the user's meta.key if identifier.is_group: # check by each member members = self.members(identifier=identifier) if members is not None: for item in members: meta = self.meta(identifier=item) if meta is None: # FIXME: meta not found for this member continue if document.verify(public_key=meta.key): return True # DISCUSS: what to do about assistants? # check by owner owner = self.owner(identifier=identifier) if owner is None: if identifier.type == NetworkType.POLYLOGUE: # NOTICE: if this is a polylogue profile # verify it with the founder's meta.key # (which equals to the group's meta.key) meta = self.meta(identifier=identifier) else: # FIXME: owner not found for this group return False elif owner in members: # already checked return False else: meta = self.meta(identifier=owner) else: meta = self.meta(identifier=identifier) if meta is not None: return document.verify(public_key=meta.key)
def register_document_factories(): Document.register(doc_type='*', factory=GeneralDocumentFactory(doc_type='*')) Document.register(doc_type=Document.VISA, factory=GeneralDocumentFactory(doc_type=Document.VISA)) Document.register( doc_type=Document.PROFILE, factory=GeneralDocumentFactory(doc_type=Document.PROFILE)) Document.register( doc_type=Document.BULLETIN, factory=GeneralDocumentFactory(doc_type=Document.BULLETIN))
def save_document(self, document: Document) -> bool: if not document.valid: identifier = document.identifier if identifier is None: return False meta = self.meta(identifier=identifier) if meta is None: return False if not document.verify(public_key=meta.key): return False return self.__document_table.save_document(document=document)
def load_station(identifier: Union[ID, str], facebook: CommonFacebook) -> Station: """ Load station info from 'etc' directory :param identifier - station ID :param facebook - social network data source :return station with info from 'dims/etc/{address}/*' """ identifier = ID.parse(identifier=identifier) # check meta meta = facebook.meta(identifier=identifier) if meta is None: # load from 'etc' directory meta = Meta.parse(meta=load_station_info(identifier=identifier, filename='meta.js')) if meta is None: raise LookupError('failed to get meta for station: %s' % identifier) elif not facebook.save_meta(meta=meta, identifier=identifier): raise ValueError('meta error: %s' % meta) # check private key private_key = facebook.private_key_for_signature(identifier=identifier) if private_key is None: # load from 'etc' directory private_key = PrivateKey.parse(key=load_station_info(identifier=identifier, filename='secret.js')) if private_key is None: pass elif not facebook.save_private_key(key=private_key, identifier=identifier): raise AssertionError('failed to save private key for ID: %s, %s' % (identifier, private_key)) # check profile profile = load_station_info(identifier=identifier, filename='profile.js') if profile is None: raise LookupError('failed to get profile for station: %s' % identifier) Log.info('station profile: %s' % profile) name = profile.get('name') host = profile.get('host') port = profile.get('port') # create station if private_key is None: # remote station station = Station(identifier=identifier, host=host, port=port) else: # create profile profile = Document.create(doc_type=Document.PROFILE, identifier=identifier) profile.set_property('name', name) profile.set_property('host', host) profile.set_property('port', port) profile.sign(private_key=private_key) if not facebook.save_document(document=profile): raise AssertionError('failed to save profile: %s' % profile) # local station station = Station(identifier=identifier, host=host, port=port) facebook.cache_user(user=station) Log.info('station loaded: %s' % station) return station
def is_expired_document(self, document: Document, reset: bool = True) -> bool: # check expired time now = time.time() expires = document.get(self.EXPIRES_KEY) if expires is None: # set expired time document[self.EXPIRES_KEY] = now + self.EXPIRES return False if now > expires: if reset: # update expired time document[self.EXPIRES_KEY] = now + self.EXPIRES return True
def load_user(identifier: str, facebook: CommonFacebook) -> User: identifier = ID.parse(identifier=identifier) # check meta try: meta = facebook.meta(identifier=identifier) except AssertionError: meta = None if meta is None: # load from 'etc' directory meta = Meta.parse(meta=load_robot_info(identifier=identifier, filename='meta.js')) if meta is None: raise LookupError('failed to get meta for robot: %s' % identifier) elif not facebook.save_meta(meta=meta, identifier=identifier): raise ValueError('meta error: %s' % meta) # check private key private_key = facebook.private_key_for_signature(identifier=identifier) if private_key is None: # load from 'etc' directory private_key = PrivateKey.parse(key=load_robot_info(identifier=identifier, filename='secret.js')) if private_key is None: raise AssertionError('private key not found for ID: %s' % identifier) elif not facebook.save_private_key(key=private_key, identifier=identifier): raise AssertionError('failed to save private key for ID: %s, %s' % (identifier, private_key)) # check profile profile = load_robot_info(identifier=identifier, filename='profile.js') if profile is None: raise LookupError('failed to get profile for robot: %s' % identifier) Log.info('robot profile: %s' % profile) name = profile.get('name') avatar = profile.get('avatar') # create profile profile = Document.create(doc_type=Document.VISA, identifier=identifier) profile.set_property('name', name) profile.set_property('avatar', avatar) profile.sign(private_key=private_key) if not facebook.save_document(document=profile): raise AssertionError('failed to save profile: %s' % profile) # create local user return facebook.user(identifier=identifier)
def __load_profile(self, filename: str) -> Optional[Document]: profile = Document.parse(document=load_resource_file( filename=filename)) assert profile is not None, 'failed to load profile: %s' % filename # copy 'name' name = profile.get('name') if name is None: names = profile.get('names') if names is not None and len(names) > 0: profile.set_property('name', names[0]) else: profile.set_property('name', name) # copy 'avatar' avatar = profile.get('avatar') if avatar is None: photos = profile.get('photos') if photos is not None and len(photos) > 0: profile.set_property('avatar', photos[0]) else: profile.set_property('avatar', avatar) # sign self.__sign_profile(profile=profile) return profile
def document(self, identifier: ID, doc_type: Optional[str]='*') -> Optional[Document]: # 1. try from memory cache info = self.__caches.get(identifier) if info is None: # 2. try from local storage path = self.__path(identifier=identifier) self.info('Loading document from: %s' % path) dictionary = self.read_json(path=path) if dictionary is not None: data = dictionary.get('data') if data is None: # compatible with v1.0 data = dictionary.get('profile') signature = dictionary.get('signature') info = Document.create(doc_type=doc_type, identifier=identifier, data=data, signature=signature) if info is None: # 2.1. place an empty meta for cache info = self.__empty # 3. store into memory cache self.__caches[identifier] = info if info is not self.__empty: return info self.info('document not found: %s' % identifier)
def is_empty_document(document: Document) -> bool: if document is None: return True json = document.get('data') return json is None or len(json) == 0
def __sign_profile(self, profile: Document) -> bytes: identifier = profile.identifier key = self.private_key_for_signature(identifier) if key is not None: return profile.sign(private_key=key)