def test_gracefully_handle_new_namespace(db, api_client): new_namespace = Namespace() new_account = GenericAccount() new_account.password = '******' new_namespace.account = new_account db.session.add(new_namespace) db.session.add(new_account) db.session.commit() cursor = get_cursor(api_client, int(time.time()), new_namespace) url = url_concat('/n/{}/delta/streaming'.format(new_namespace.public_id), {'timeout': .1, 'cursor': cursor}) r = api_client.get_raw(url) assert r.status_code == 200
def make_default_account(db, config): import platform from inbox.models.backends.gmail import GmailAccount from inbox.models.backends.gmail import GmailAuthCredentials from inbox.auth.gmail import OAUTH_SCOPE from inbox.models import Namespace ns = Namespace() account = GmailAccount(sync_host='{}:{}'.format(platform.node(), 0), email_address='*****@*****.**') account.namespace = ns account.create_emailed_events_calendar() account.refresh_token = 'faketoken' auth_creds = GmailAuthCredentials() auth_creds.client_id = config.get_required('GOOGLE_OAUTH_CLIENT_ID') auth_creds.client_secret = \ config.get_required('GOOGLE_OAUTH_CLIENT_SECRET') auth_creds.refresh_token = 'faketoken' auth_creds.g_id_token = 'foo' auth_creds.created_at = datetime.utcnow() auth_creds.updated_at = datetime.utcnow() auth_creds.gmailaccount = account auth_creds.scopes = OAUTH_SCOPE db.session.add(account) db.session.add(auth_creds) db.session.commit() return account
def test_canonical_tags_created_for_namespace(db): new_namespace = Namespace() db.session.add(new_namespace) db.session.commit() tags = db.session.query(Tag).filter(Tag.namespace_id == new_namespace.id).all() assert {tag.name for tag in tags} == CANONICAL_TAG_NAMES
def add_fake_account(db_session, email_address='*****@*****.**'): from inbox.models import Account, Namespace namespace = Namespace() account = Account(email_address=email_address, namespace=namespace) db_session.add(account) db_session.commit() return account
def create_account(self, db_session, email_address, response): try: account = db_session.query(GenericAccount).filter_by( email_address=email_address).one() except sqlalchemy.orm.exc.NoResultFound: namespace = Namespace() account = GenericAccount(namespace=namespace) account.email_address = response['email'] account.password = response['password'] account.date = datetime.datetime.utcnow() provider_name = self.provider_name account.provider = provider_name if provider_name == 'custom': account.imap_endpoint = (response['imap_server_host'], response['imap_server_port']) account.smtp_endpoint = (response['smtp_server_host'], response['smtp_server_port']) # Hack to ensure that account syncs get restarted if they were stopped # because of e.g. invalid credentials and the user re-auths. # TODO(emfree): remove after status overhaul. if account.sync_state != 'running': account.sync_state = None return account
def create_account(self, db_session, email_address, response): try: account = db_session.query(GenericAccount).filter_by( email_address=email_address).one() except sqlalchemy.orm.exc.NoResultFound: namespace = Namespace() account = GenericAccount(namespace=namespace) account.email_address = response['email'] if response.get('name'): account.name = response['name'] account.password = response['password'] account.date = datetime.datetime.utcnow() provider_name = self.provider_name account.provider = provider_name if provider_name == 'custom': account.imap_endpoint = (response['imap_server_host'], response['imap_server_port']) account.smtp_endpoint = (response['smtp_server_host'], response['smtp_server_port']) # Ensure account has sync enabled after authing. account.enable_sync() return account
def create_account(self, db_session, email_address, response): email_address = response.get('emails')['account'] try: account = db_session.query(OutlookAccount).filter_by( email_address=email_address).one() except sqlalchemy.orm.exc.NoResultFound: namespace = Namespace() account = OutlookAccount(namespace=namespace) account.refresh_token = response['refresh_token'] account.date = datetime.datetime.utcnow() tok = response.get('access_token') expires_in = response.get('expires_in') token_manager.cache_token(account, tok, expires_in) account.scope = response.get('scope') account.email_address = email_address account.o_id_token = response.get('user_id') account.o_id = response.get('id') account.name = response.get('name') account.gender = response.get('gender') account.link = response.get('link') account.locale = response.get('locale') # Ensure account has sync enabled. account.enable_sync() return account
def create_account(db_session, email_address, response): # See if the account exists in db, otherwise create it try: account = db_session.query(GmailAccount) \ .filter_by(email_address=email_address).one() except NoResultFound: namespace = Namespace() account = GmailAccount(namespace=namespace) tok = response.get('access_token') expires_in = response.get('expires_in') account.set_access_token(tok, expires_in) account.refresh_token = response.get('refresh_token') account.scope = response.get('scope') account.email_address = response.get('email') account.family_name = response.get('family_name') account.given_name = response.get('given_name') account.name = response.get('name') account.gender = response.get('gender') account.g_id = response.get('id') account.g_user_id = response.get('user_id') account.g_id_token = response.get('id_token') account.link = response.get('link') account.locale = response.get('locale') account.picture = response.get('picture') account.home_domain = response.get('hd') account.client_id = response.get('client_id') account.client_secret = response.get('client_secret') return account
def create_account(self, account_data): namespace = Namespace() account = GenericAccount(namespace=namespace) account.provider = "custom" account.create_emailed_events_calendar() account.sync_should_run = False return self.update_account(account, account_data)
def create_account(self, email_address, response): # This method assumes that the existence of an account for the # provider and email_address has been checked by the caller; # callers may have different methods of performing the check # (redwood auth versus get_account()) namespace = Namespace() account = GenericAccount(namespace=namespace) # The server endpoints can ONLY be set at account creation and # CANNOT be subsequently changed in order to prevent MITM attacks. account.provider = self.provider_name if self.provider_name == 'custom': account.imap_endpoint = (response['imap_server_host'], response['imap_server_port']) account.smtp_endpoint = (response['smtp_server_host'], response['smtp_server_port']) # Shim for back-compatability with legacy auth # The old API does NOT send these but authentication now uses them # so set them (included here, set in update_account()). for username in ['imap_username', 'smtp_username']: if username not in response: response[username] = email_address for password in ['imap_password', 'smtp_password']: if password not in response: response[password] = response['password'] return self.update_account(account, response)
def test_namespace_limiting(db, test_client): dt = datetime.datetime.utcnow() subject = dt.isoformat() db.session.add(Namespace()) db.session.commit() namespaces = db.session.query(Namespace).all() assert len(namespaces) > 1 for ns in namespaces: thread = Thread(namespace=ns, subjectdate=dt, recentdate=dt, subject=subject) add_fake_message(db.session, ns.id, thread, received_date=dt, subject=subject) db.session.add(Block(namespace=ns, filename=subject)) db.session.commit() for ns in namespaces: r = json.loads( test_client.get('/n/{}/threads?subject={}'.format( ns.public_id, subject)).data) assert len(r) == 1 r = json.loads( test_client.get('/n/{}/messages?subject={}'.format( ns.public_id, subject)).data) assert len(r) == 1 r = json.loads( test_client.get('/n/{}/files?filename={}'.format( ns.public_id, subject)).data) assert len(r) == 1
def test_generic_grouping(db, default_account): thread = add_fake_thread(db.session, default_account.namespace.id) message = add_fake_message(db.session, default_account.namespace.id, thread, subject="Golden Gate Park next Sat") folder = Folder(account=default_account, name='Inbox', canonical_name='inbox') ImapUid(message=message, account_id=default_account.id, msg_uid=2222, folder=folder) thread = add_fake_thread(db.session, default_account.namespace.id) new_namespace = Namespace() db.session.add(new_namespace) db.session.commit() message = add_fake_message(db.session, new_namespace.id, thread, subject="Golden Gate Park next Sat") thread = fetch_corresponding_thread(db.session, default_account.namespace.id, message) assert thread is None, ("fetch_similar_threads should " "heed namespace boundaries")
def add_fake_gmail_account( db_session, email_address="*****@*****.**", refresh_token="tearsofgold", password="******", ): import platform from inbox.models import Namespace from inbox.models.backends.gmail import GmailAccount with db_session.no_autoflush: namespace = Namespace() account = GmailAccount( email_address=email_address, refresh_token=refresh_token, sync_host=platform.node(), namespace=namespace, ) account.imap_password = password account.smtp_password = password db_session.add(account) db_session.commit() return account
def create_account(self, email_address, response): # This method assumes that the existence of an account for the # provider and email_address has been checked by the caller; # callers may have different methods of performing the check # (redwood auth versus get_account()) namespace = Namespace() account = GenericAccount(namespace=namespace) return self.update_account(account, response)
def create_account(self, email_address, response): # This method assumes that the existence of an account for the # provider and email_address has been checked by the caller; # callers may have different methods of performing the check # (redwood auth versus bin/inbox-auth) namespace = Namespace() account = GmailAccount(namespace=namespace) account.create_emailed_events_calendar() return self.update_account(account, response)
def create_account(self, db_session, email_address, response): email_address = response.get('email') # See if the account exists in db, otherwise create it try: account = db_session.query(GmailAccount) \ .filter_by(email_address=email_address).one() except NoResultFound: namespace = Namespace() account = GmailAccount(namespace=namespace) # We only get refresh tokens on initial login (or failed credentials) # otherwise, we don't force the login screen and therefore don't get a # refresh token back from google. new_refresh_token = response.get('refresh_token') if new_refresh_token: account.refresh_token = new_refresh_token else: if not account.refresh_token or account.sync_state == 'invalid': # We got a new auth without a refresh token, so we need to back # out and force the auth flow, since we don't already have # a refresh (or the one we have doesn't work.) raise OAuthError("Missing refresh token") tok = response.get('access_token') expires_in = response.get('expires_in') token_manager.cache_token(account, tok, expires_in) account.scope = response.get('scope') account.email_address = email_address account.family_name = response.get('family_name') account.given_name = response.get('given_name') account.name = response.get('name') account.gender = response.get('gender') account.g_id = response.get('id') account.g_user_id = response.get('user_id') account.g_id_token = response.get('id_token') account.link = response.get('link') account.locale = response.get('locale') account.picture = response.get('picture') account.home_domain = response.get('hd') account.client_id = response.get('client_id') account.client_secret = response.get('client_secret') account.sync_contacts = response.get('contacts', True) account.sync_events = response.get('events', True) try: self.verify_config(account) except GmailSettingError as e: raise UserRecoverableConfigError(e) # Hack to ensure that account syncs get restarted if they were stopped # because of e.g. invalid credentials and the user re-auths. # TODO(emfree): remove after status overhaul. if account.sync_state != 'running': account.sync_state = None return account
def test_gracefully_handle_new_namespace(db, streaming_test_client): new_namespace = Namespace() db.session.add(new_namespace) db.session.commit() cursor = get_cursor(streaming_test_client, int(time.time()), new_namespace) url = url_concat('/n/{}/delta/streaming'.format(new_namespace.public_id), { 'timeout': .1, 'cursor': cursor }) r = streaming_test_client.get(url) assert r.status_code == 200
def add_fake_imap_account(db_session, provider, email_address, password): from inbox.models import Namespace from inbox.models.backends.generic import GenericAccount namespace = Namespace() account = GenericAccount(namespace=namespace, provider=provider, email_address=email_address, password=password) db_session.add(account) db_session.commit() return account
def make_imap_account(db_session, email_address): import platform from inbox.models.backends.generic import GenericAccount from inbox.models import Namespace account = GenericAccount(email_address=email_address, sync_host=platform.node(), provider='custom') account.password = '******' account.namespace = Namespace() db_session.add(account) db_session.commit() return account
def add_fake_yahoo_account(db_session, email_address='*****@*****.**'): import platform from inbox.models.backends.generic import GenericAccount from inbox.models import Namespace account = GenericAccount(email_address=email_address, sync_host=platform.node(), provider='yahoo') account.imap_password = '******' account.smtp_password = '******' account.namespace = Namespace() db_session.add(account) db_session.commit() return account
def generic_account(db): import platform from inbox.models.backends.generic import GenericAccount from inbox.models import Namespace ns = Namespace() account = GenericAccount(email_address='*****@*****.**', sync_host=platform.node(), provider='custom') account.namespace = ns account.create_emailed_events_calendar() account.password = '******' db.session.add(account) db.session.commit() return account
def add_generic_imap_account(db_session, email_address='*****@*****.**'): import platform from inbox.models.backends.generic import GenericAccount from inbox.models import Namespace account = GenericAccount(email_address=email_address, sync_host=platform.node(), provider='custom') account.imap_endpoint = ('imap.custom.com', 993) account.smtp_endpoint = ('smtp.custom.com', 587) account.imap_password = '******' account.smtp_password = '******' account.namespace = Namespace() db_session.add(account) db_session.commit() return account
def add_account_with_different_namespace_id(db_session, email_address='*****@*****.**'): import platform from inbox.models.backends.generic import GenericAccount from inbox.models import Namespace account = GenericAccount(id=11, email_address=email_address, sync_host=platform.node(), provider='yahoo') account.imap_password = '******' account.smtp_password = '******' account.namespace = Namespace() db_session.add(account) db_session.commit() assert account.namespace.id != account.id return account
def create_account(self, email_address, response): # This method assumes that the existence of an account for the # provider and email_address has been checked by the caller; # callers may have different methods of performing the check # (redwood auth versus get_account()) namespace = Namespace() account = GenericAccount(namespace=namespace) # Verification for legacy auth account creation attempts. for username in ['imap_username', 'smtp_username']: if username not in response: response[username] = email_address for password in ['imap_password', 'smtp_password']: if password not in response: response[password] = response['password'] return self.update_account(account, response)
def gmail_account(db): import platform from inbox.models import Namespace from inbox.models.backends.gmail import GmailAccount account = db.session.query(GmailAccount).first() if account is None: with db.session.no_autoflush: namespace = Namespace() account = GmailAccount(email_address='*****@*****.**', refresh_token='tearsofgold', sync_host=platform.node(), namespace=namespace) account.password = '******' db.session.add(account) db.session.commit() return account
def create_account(db_session, email_address, response): provider_name = provider_from_address(email_address) if provider_name == "unknown": raise NotSupportedError('Inbox does not support the email provider.') try: account = db_session.query(GenericAccount).filter_by( email_address=email_address).one() except sqlalchemy.orm.exc.NoResultFound: namespace = Namespace() account = GenericAccount(namespace=namespace) account.email_address = response['email'] account.password = response['password'] account.date = datetime.datetime.utcnow() account.provider = provider_name return account
def make_default_account(db, config): import platform from inbox.models import Namespace from inbox.models.backends.gmail import GmailAccount ns = Namespace() account = GmailAccount( sync_host="{}:{}".format(platform.node(), 0), email_address="*****@*****.**", ) account.namespace = ns account.client_id = config.get_required("GOOGLE_OAUTH_CLIENT_ID") account.create_emailed_events_calendar() account.refresh_token = "faketoken" db.session.add(account) db.session.commit() return account
def add_fake_gmail_account(db_session, email_address='*****@*****.**', refresh_token='tearsofgold', password='******'): from inbox.models import Account, Namespace from inbox.models.backends.gmail import GmailAccount import platform with db_session.no_autoflush: namespace = Namespace() account = GmailAccount(email_address=email_address, refresh_token=refresh_token, sync_host=platform.node(), namespace=namespace) account.password = password db_session.add(account) db_session.commit() return account
def create_account(self, db_session, email_address, response): # Override create_account to persist the 'login hint' email_address # rather than the canonical email that is contained in response. # This allows us to trigger errors by authing with addresses of the # format: # [email protected] # Since verify_config throws an Exception if no specific case is # triggered, this account is never committed. namespace = Namespace() account = GmailAccount(namespace=namespace) account.email_address = email_address try: self.verify_config(account) except GmailSettingError as e: print e raise UserRecoverableConfigError(e) return account
def test_stealing_limited_by_host(db, config): host = platform.node() config['DATABASE_HOSTS'][0]['SHARDS'][0]['SYNC_HOSTS'] = [host] config['DATABASE_HOSTS'][0]['SHARDS'][1]['SYNC_HOSTS'] = ['otherhost'] purge_other_accounts() ss = SyncService(cpu_id=0, total_cpus=1) for key in (0, 1): with session_scope_by_shard_id(key) as db_session: acc = Account() acc.namespace = Namespace() db_session.add(acc) db_session.commit() ss.accounts_to_start() with session_scope_by_shard_id(0) as db_session: acc = db_session.query(Account).first() assert acc.sync_host == host with session_scope_by_shard_id(1) as db_session: acc = db_session.query(Account).first() assert acc.sync_host is None
def test_accounts_started_on_all_shards(db, default_account, config): config['SYNC_STEAL_ACCOUNTS'] = True purge_other_accounts(default_account) default_account.sync_host = None db.session.commit() ss = SyncService(cpu_id=0, total_cpus=1) ss.host = 'localhost' account_ids = {default_account.id} for key in (0, 1): with session_scope_by_shard_id(key) as db_session: acc = Account() acc.namespace = Namespace() db_session.add(acc) db_session.commit() account_ids.add(acc.id) assert len(account_ids) == 3 assert set(ss.accounts_to_start()) == account_ids for id_ in account_ids: with session_scope(id_) as db_session: acc = db_session.query(Account).get(id_) assert acc.sync_host == 'localhost'