class GetFriendsSession(POSTSession): def __init__(self, global_context): self._users_engine = UsersEngine(global_context) self._access_rules = global_context.access_rules self._params = Params() def _init_session_params(self, query): self._params.parse(query) def _run_session(self): # Check user credentials self._access_rules.check_can_view_private_info(self._params.user_token, self._params.user_id) page = self._users_engine.get_friends(self._params.user_id, self._params.limit, self._params.cursor) relations = self._users_engine.get_relations_many( self._params.user_id, page.data) friends = list() # Retrieve aux data for i, user_id in enumerate(page.data): if relations[i] == None or not relations[i].is_friends: continue # FIXME use group request info = None try: info = self._users_engine.get_info(user_id) except: pass if info == None: logging.warning( 'Can\'t find user profile, id = {}'.format(user_id)) continue profile = { 'user_id': info.user_id, 'facebook_user_id': info.facebook_user_id, 'name': info.name, 'username': info.username, 'email': info.email, 'twilio_channel': relations[i].twilio_channel } friends.append(profile) result = { 'success': True, 'data': friends, 'paging': { 'cursor': page.cursor_code, 'has_next': page.has_next } } return result
class EMailAuthStage2Session(POSTSession): def __init__(self, global_context): self._auth_engine = AuthEngine() self._users_engine = UsersEngine(global_context) self._avatar_generator = global_context.avatar_generator self._params = Params() def _init_session_params(self, query): self._params.parse(query) def _run_session(self): email = self._auth_engine.auth_by_email_stage2(self._params.auth_code, self._params.auth_token) # Check user exists user_id = self._find_user(email) if user_id == None: user_id = self._create_new_user(email) result = { 'success': True, 'user_id': int(user_id), 'user_token': AccessToken.make_encoded(user_id) } return result def _find_user(self, email): user_id = self._users_engine.external_to_local_id(email) if user_id == None: return None try: info = self._users_engine.get_info(user_id) return info.user_id except: return None # TODO: move into users_engine def _create_new_user(self, email): info = UserInfo() info.name = '' info.email = email # Generate user id info.user_id = self._users_engine.gen_user_id(info) logging.info('create new profile, email = {}, user_id = {}'.format(email, info.user_id)) # Create profile self._users_engine.put_info(info) self._users_engine.put_external_link(info.user_id, email) picture = self._avatar_generator.generate(email) self._users_engine.put_picture(info.user_id, picture) return info.user_id
class MakeMessagingTokenSession(POSTSession): def __init__(self, global_context): self._users_engine = UsersEngine(global_context) self._twilio_connector = global_context.twilio_connector self._params = Params() def _init_session_params(self, query): self._params.parse(query) def _run_session(self): # Check user exists info = self._users_engine.get_info(self._params.user_id) token = self._twilio_connector.make_messaging_token( self._params.user_id, self._params.uuid) result = {'success': True, 'data': {'token': token}} return result
class UpdateProfileSession(POSTSession): def __init__(self, global_context): self._users_engine = UsersEngine(global_context) self._access_rules = global_context.access_rules self._params = Params() def _init_session_params(self, query): self._params.parse(query) def _run_session(self): user_id = self._params.user_token.user_id # Check user credentials self._access_rules.check_can_edit_user_info(self._params.user_token, user_id) user_info = self._users_engine.get_info(user_id) if user_info == None: raise APILogicalError('User not found') info_updated = False if self._params.name != None: user_info.name = self._params.name info_updated = True if self._params.username != None: user_info.username = self._params.username info_updated = True if self._params.email != None: user_info.email = self._params.email info_updated = True if info_updated: self._users_engine.put_info(user_info) if self._params.meta_blob: self._users_engine.put_meta(user_id, self._params.meta_blob) if self._params.picture_blob != None: self._users_engine.put_picture(user_id, self._params.picture_blob) result = {'success': True, 'user_token': self._params.user_token_str} return result
class GetProfileSession(POSTSession): def __init__(self, global_context): self._users_engine = UsersEngine(global_context) self._params = Params() def _init_session_params(self, query): self._params.parse(query) def _run_session(self): info = self._users_engine.get_info(self._params.user_id) if info == None: raise APILogicalError('User not found') # TODO remove facebook_access_token from result result = { 'user_id': info.user_id, 'facebook_user_id': info.facebook_user_id, 'facebook_access_token': info.facebook_access_token, 'name': info.name, 'username': info.username, 'email': info.email } if 'meta_blob' in self._params.properties: result['meta_blob'] = self._users_engine.get_meta( self._params.user_id) if 'picture_blob' in self._params.properties: result['picture_blob'] = self._users_engine.get_picture( self._params.user_id) if 'friends' in self._params.properties: facebook_user_id = result['facebook_user_id'] facebook_access_token = result['facebook_access_token'] if facebook_user_id != None and facebook_access_token != None: result['friends'] = self._get_friends_fb( info.user_id, facebook_user_id, facebook_access_token) else: result['friends'] = list() return result def _get_friends_fb(self, user_id, facebook_user_id, facebook_access_token): logging.info( '_get_friends_fb: Retrieve friends from facebook, facebook_user_id = {}' .format(facebook_user_id)) friends = list() next_page_uri = 'https://graph.facebook.com/{}/friends?access_token={}'.format( facebook_user_id, facebook_access_token) while next_page_uri: try: resp = requests.get(next_page_uri) # parse parsed = json.loads(resp.text) # take profiles data = parsed.get('data') for entry in data: facebook_user_id = entry.get('id') info = self._get_user_by_fb(facebook_user_id) if info == None: continue profile = { 'user_id': info.user_id, 'facebook_user_id': info.facebook_user_id, 'name': info.name, 'username': info.username, 'email': info.email } relation = self._users_engine.get_relations_many( user_id, [info.user_id])[0] if relation != None: profile['twilio_channel'] = relation.twilio_channel else: profile['twilio_channel'] = None friends.append(profile) # next page paging = parsed.get('paging') if paging: next_page_uri = paging.get('next') else: next_page_uri = None except Exception as ex: logging.error(ex) raise logging.info('_get_friends_fb: Got {} entries'.format(len(friends))) return friends def _get_user_by_fb(self, facebook_user_id): user_id = self._users_engine.external_to_local_id(facebook_user_id) if user_id == None: logging.warning('Can\'t find user by facebook user id') info = UserInfo() info.user_id = self._gen_user_id(info) info.facebook_user_id = facebook_user_id # Create profile self._users_engine.put_info(info.user_id, info) self._users_engine.put_external_link(info.user_id, facebook_user_id) else: info = self._users_engine.get_info(user_id) return info
class GetExternalFriendsSession(POSTSession): def __init__(self, global_context): self._users_engine = UsersEngine(global_context) self._access_rules = global_context.access_rules self._params = Params() def _init_session_params(self, query): self._params.parse(query) def _run_session(self): # Check user credentials self._access_rules.check_can_view_private_info(self._params.user_token, self._params.user_id) info = self._users_engine.get_info(self._params.user_id) if info == None: raise APILogicalError('User {} not found'.format( self._params.user_id)) friends = list() cursor = '' has_next = False if info.facebook_user_id != None and info.facebook_access_token != None: friends, cursor, has_next = self._get_fb_friends( info.facebook_user_id, info.facebook_access_token) result = { 'success': True, 'data': friends, 'paging': { 'cursor': cursor, 'has_next': has_next } } return result def _get_fb_friends(self, facebook_user_id, facebook_access_token): friends = list() page_uri = 'https://graph.facebook.com/{}/friends?access_token={}&limit={}&after={}'.format( facebook_user_id, facebook_access_token, self._params.limit, self._params.cursor) try: resp = requests.get(page_uri) # parse parsed = json.loads(resp.text) # check errors error = parsed.get('error') if error != None: logging.error('Facebook error: {}'.format( error.get('message'))) raise Exception('Can\'t get data from Facebook') # take profiles data = parsed.get('data') profiles = list() external_ids = list() for entry in data: profile = { 'facebook_user_id': entry.get('id'), 'name': entry.get('name') } profiles.append(profile) external_ids.append(entry.get('id')) local_ids = self._users_engine.external_to_local_id_many( external_ids) for i in range(len(local_ids) - 1, -1, -1): if local_ids[i] == None: del local_ids[i] del profiles[i] profiles[i]['user_id'] = local_ids[i] check_result = self._users_engine.check_friends_many( self._params.user_id, local_ids) for i in range(len(check_result)): if not check_result[i]: friends.append(profiles[i]) # paging cursor, has_next = self._parse_paging(parsed.get('paging')) except Exception as ex: logging.error(ex) raise return (friends, cursor, has_next) def _parse_paging(self, paging): cursor = '' has_next = False if paging == None: return (cursor, has_next) cursors = paging.get('cursors') if cursors != None: cursor = cursors.get('after', '') if 'next' in paging: has_next = True return (cursor, has_next)
class FacebookAuthSession(POSTSession): def __init__(self, global_context): self._users_engine = UsersEngine(global_context) self._avatar_generator = global_context.avatar_generator self._facebook_profile_uri = 'https://graph.facebook.com/me' self._timeout_sec = 1 self._params = Params() def _init_session_params(self, query): self._params.parse(query) def _run_session(self): facebook_prof = self._get_facebook_profile(self._params.access_token) facebook_user_id = facebook_prof['id'] facebook_name = facebook_prof.get('name') # Check fb user id if self._params.facebook_user_id != facebook_user_id: raise Exception('facebook_user_id mismatch') # Check user exists user_id = self._find_user(facebook_user_id) if user_id == None: user_id = self._create_new_user(facebook_name, facebook_user_id, self._params.access_token) result = { 'success': True, 'user_token': AccessToken.make_encoded(user_id), 'user_id': user_id } return result def _get_facebook_profile(self, access_token): url = '{}?access_token={}'.format(self._facebook_profile_uri, access_token) try: resp = requests.get(url, timeout=self._timeout_sec) except Exception as ex: logging.error(ex) raise Exception('Request to facebook failed') profile = json.loads(resp.text) if 'id' not in profile: logging.error('Facebook bad response: {}'.format(profile)) raise Exception('Request to facebook failed. Bad response.') return profile def _find_user(self, facebook_user_id): user_id = self._users_engine.external_to_local_id(facebook_user_id) if user_id == None: return None try: info = self._users_engine.get_info(user_id) return info.user_id except: return None def _create_new_user(self, name, facebook_user_id, facebook_access_token): info = UserInfo() info.facebook_user_id = facebook_user_id info.facebook_access_token = facebook_access_token info.name = name # Generate user id info.user_id = self._users_engine.gen_user_id(info) # Create profile self._users_engine.put_info(info) self._users_engine.put_external_link(info.user_id, facebook_user_id) picture = self._avatar_generator.generate(name) self._users_engine.put_picture(info.user_id, picture) return info.user_id