def purge_gid_links(self, destination, user): """ cleans abandoned account links """ # find all parents' [p]->destination:user # find all gids that feed the [p]->[destination:user] <- [gid] # if the gid is not in gids -- break the link parent -> gid # iterate over list of owners/parents of this destination:user account parents = self.get_linked_parents(S1.provider_root_key( destination, user), bag='dst') for parent in parents: # purge gid 2 gid links # this is now a manual process -- users can remove gid-gid links from the UI # self._purge_gid_gid(parent, gid) # check if destination:user is being fed by any of the parent's children # Note: parent will be listed as child of self children = self.get_linked_children(parent) child_links = set(self.get_bindings(destination, user)) if not len(child_links.intersection(children)): self.logger.info( 'Removing account linking: [{0}] --> [{1}]'.format( parent, S1.provider_root_key(destination, user))) self.remove_linked_account(parent, S1.provider_root_key( destination, user), bag='dst')
def add_linked_account(self, parent_gid, gid, bag=None): parent_key = S1.provider_root_key('parents', bag) if bag else 'parents' child_key = S1.provider_root_key('children', bag) if bag else 'children' self._append_hfield(S1.destination_key_fmt(parent_key), gid, parent_gid) self._append_hfield(S1.destination_key_fmt(child_key), parent_gid, gid)
def remove_linked_account(self, parent_gid, gid, bag=None): parent_key = S1.provider_root_key('parents', bag) if bag else 'parents' child_key = S1.provider_root_key('children', bag) if bag else 'children' self._delete_hfield_item(S1.destination_key_fmt(parent_key), gid, parent_gid) self._delete_hfield_item(S1.destination_key_fmt(child_key), parent_gid, gid)
def bind_user(self, master_gid, gid, destination, user): # bind to destination poller self.logger.info('Binding: [{0}] --> [{1}]:[{2}]'.format( gid, destination, user)) # store gid to gid relation self.add_linked_account(master_gid, gid) # store gid to destination user relation self.add_linked_account(master_gid, S1.provider_root_key(destination, user), bag='dst') # reset timestamps and errors self.reset_destination(gid, destination, user) # bind source and destination self.bind_destination(gid, destination, user) # carpet-notify GID destinations of updates self.flush_updates(gid) # append GID log self.add_log( master_gid, 'Success: Linked Google+ [{0}] --> [{1}:{2}]'.format( gid, destination, user)) self.logger.info('Success: Linked Google+ [{0}] --> [{1}:{2}]'.format( gid, destination, user))
def remove_binding(self, gid, destination, user, clean=False): """ clears binding created by bind_user() """ self.logger.info('Unbinding GID: [{0}] -/-> [{1}:{2}]'.format( gid, destination, user)) self.add_log( gid, 'Unbinding Google+ [{0}] -/-> [{1}:{2}]'.format( gid, destination, user)) # remove binding update option self.rc.hdel(S1.destination_option_key_fmt(destination), S1.destination_pair_fmt(gid, user, S1.updated_key())) # remove destination user id from list of destinations for this gid self._delete_hfield_item(S1.destination_key_fmt(destination), gid, user) # remove gid from list of sources for this destination user self._delete_hfield_item(S1.destination_source_key_fmt(destination), user, gid) # clean linked accounts # find the owner(s) of the destination:user pair self.purge_gid_links(destination, user) # the gid->destination:user link is broken # clear this relationship self.remove_linked_account(gid, S1.provider_root_key(destination, user), bag='dst') # remove destination binding if no bindings to this destination left bound_users = self.get_destination_users(gid, destination) if not (bound_users and len(bound_users)): self.logger.info('No links remain for [{0} --> {1}]'.format( gid, destination)) # remove destination from gid destination list self._delete_hfield_item( S1.destination_key_fmt(S1.destinations_key()), gid, destination) # keep message map for the destination:user -- user may re-bind later with new token # unless forced to clean all # keep filters unless forced to clean! if clean: self.filter.del_filter(destination, gid, user) self.filter.del_message_id_map(destination, user) # clear bound timestamp self.del_destination_param(gid, destination, user, S1.bound_key()) # check_orphan() will stop polling the gid if nothing is bound to it self.check_orphan(gid, 0)
def get_linked_users(self, gid, destination, user): """ yields a list of user gids who own gid->destination:user binding @param gid: gid of the source, not user gid @param destination: name of the destination i.e. "facebook" @param user: destination user id @return: yeilds gids of users who own gid->destination:user binding """ parents = self.get_linked_parents(gid) for parent in parents: children = self.get_linked_children(parent, bag='dst') if S1.provider_root_key(destination, user) in children: yield parent
def get_provider_error_count(self, provider, user): count_str = self.rc.hget(S1.provider_root_key(provider, user), S1.error_count_key()) return int(count_str) if count_str else 0
def set_provider_error_count(self, provider, user, count): self.rc.hset(S1.provider_root_key(provider, user), S1.error_count_key(), count)
def is_linked_account(self, gid, provider, user): return self.rc.sismember(S1.links_key(gid), S1.provider_root_key(provider, user))
def add_temp_account(self, gid, provider, user, data): self.rc.sadd(S1.links_temp_key(gid), S1.provider_root_key(provider, user)) self.rc.hset(S1.provider_root_key(provider, user), S1.ACCOUNT_KEY, data)
def get_linked_account(self, gid, provider, user): return self.rc.hget(S1.provider_root_key(provider, user), S1.ACCOUNT_KEY)
def link_provider_account(self, gid, provider, user, data=None): self.rc.sadd(S1.links_key(gid), S1.provider_root_key(provider, user)) if data: self.rc.hset(S1.provider_root_key(provider, user), S1.ACCOUNT_KEY, data)
def unlink_provider_account(self, gid, provider, user): self.rc.srem(S1.links_key(gid), S1.provider_root_key(provider, user))
def get_linked_children(self, gid, bag=None): child_key = S1.provider_root_key('children', bag) if bag else 'children' return self._get_hfield_list(S1.destination_key_fmt(child_key), gid)
def get_linked_parents(self, gid, bag=None): parent_key = S1.provider_root_key('parents', bag) if bag else 'parents' return self._get_hfield_list(S1.destination_key_fmt(parent_key), gid)