def migrate_to_external_account(user_settings_document): user_info = utils.get_user_info( access_key=user_settings_document['access_key'], secret_key=user_settings_document['secret_key']) user = User.load(user_settings_document['owner']) if not user_info: return (None, None, None) new = False try: external_account = ExternalAccount.find_one( Q('provider_id', 'eq', user_info.id)) logger.info( 'Duplicate account use found: s3usersettings {0} with id {1}'. format(user_settings_document['_id'], user._id)) except NoResultsFound: new = True external_account = ExternalAccount( provider=PROVIDER, provider_name=PROVIDER_NAME, provider_id=user_info.id, oauth_key=user_settings_document['access_key'], oauth_secret=user_settings_document['secret_key'], display_name=user_info.display_name, ) external_account.save() user.external_accounts.append(external_account) user.save() return external_account, user, new
def migrate_to_external_account(user_settings_document): user_info = utils.get_user_info(access_key=user_settings_document['access_key'], secret_key=user_settings_document['secret_key']) user = User.load(user_settings_document['owner']) if not user_info: return (None, None, None) new = False try: external_account = ExternalAccount.find_one(Q('provider_id', 'eq', user_info.id)) logger.info('Duplicate account use found: s3usersettings {0} with id {1}'.format(user_settings_document['_id'], user._id)) except NoResultsFound: new = True external_account = ExternalAccount( provider=PROVIDER, provider_name=PROVIDER_NAME, provider_id=user_info.id, oauth_key=user_settings_document['access_key'], oauth_secret=user_settings_document['secret_key'], display_name=user_info.display_name, ) external_account.save() user.external_accounts.append(external_account) user.save() return external_account, user, new
def test_dataverse_add_external_account_existing(self, mock_connection): mock_connection.return_value = create_mock_connection() host = 'myfakehost.data.verse' token = 'dont-use-this-token-in-other-tests' display_name = 'loaded_version' # Save an existing version external_account = ExternalAccount( provider='dataverse', provider_name='Dataverse', display_name=display_name, oauth_key=host, oauth_secret=token, provider_id=token, ) external_account.save() url = api_url_for('dataverse_add_user_account') params = {'host': host, 'api_token': token} self.app.post_json(url, params, auth=self.user.auth) self.user.reload() assert_equal(len(self.user.external_accounts), 1) external_account = self.user.external_accounts[0] assert_equal(external_account.provider, 'dataverse') assert_equal(external_account.oauth_key, host) assert_equal(external_account.oauth_secret, token) # Ensure we got the loaded version assert_equal(external_account.display_name, display_name)
def migrate_to_external_account(user_settings_document): if not user_settings_document.get('access_token'): return (None, None, None) new = False user = User.load(user_settings_document['owner']) try: external_account = ExternalAccount.find( Q('provider_id', 'eq', user_settings_document['dropbox_id']))[0] logger.info( 'Duplicate account use found: User {0} with dropbox_id {1}'.format( user.username, user_settings_document['dropbox_id'])) except IndexError: new = True external_account = ExternalAccount( provider=PROVIDER, provider_name=PROVIDER_NAME, provider_id=user_settings_document['dropbox_id'], oauth_key=user_settings_document['access_token'], display_name=user_settings_document['dropbox_info'].get( 'display_name', None) if user_settings_document.get( 'dropbox_info', None) else None, ) external_account.save() # generate pk for external accountc user.external_accounts.append(external_account) user.save() return external_account, user, new
def test_dataverse_add_external_account_existing(self, mock_connection): mock_connection.return_value = create_mock_connection() host = 'myfakehost.data.verse' token = 'dont-use-this-token-in-other-tests' display_name = 'loaded_version' # Save an existing version external_account = ExternalAccount( provider='dataverse', provider_name='Dataverse', display_name=display_name, oauth_key=host, oauth_secret=token, provider_id=token, ) external_account.save() url = api_url_for('dataverse_add_user_account') params = {'host': host, 'api_token': token} self.app.post_json(url, params, auth=self.user.auth) self.user.reload() assert_equal(len(self.user.external_accounts), 1) external_account = self.user.external_accounts[0] assert_equal(external_account.provider, 'dataverse') assert_equal(external_account.oauth_key, host) assert_equal(external_account.oauth_secret, token) # Ensure we got the loaded version assert_equal(external_account.display_name, display_name)
def s3_add_user_account(auth, **kwargs): """Verifies new external account credentials and adds to user's list""" try: access_key = request.json['access_key'] secret_key = request.json['secret_key'] except KeyError: raise HTTPError(httplib.BAD_REQUEST) if not (access_key and secret_key): return { 'message': 'All the fields above are required.' }, httplib.BAD_REQUEST user_info = utils.get_user_info(access_key, secret_key) if not user_info: return { 'message': ('Unable to access account.\n' 'Check to make sure that the above credentials are valid, ' 'and that they have permission to list buckets.') }, httplib.BAD_REQUEST if not utils.can_list(access_key, secret_key): return { 'message': ('Unable to list buckets.\n' 'Listing buckets is required permission that can be changed via IAM' ) }, httplib.BAD_REQUEST account = None try: account = ExternalAccount( provider=SHORT_NAME, provider_name=FULL_NAME, oauth_key=access_key, oauth_secret=secret_key, provider_id=user_info.id, display_name=user_info.display_name, ) account.save() except KeyExistsException: # ... or get the old one account = ExternalAccount.find_one( Q('oauth_key', 'eq', access_key) & Q('oauth_secret', 'eq', secret_key)) assert account is not None if account not in auth.user.external_accounts: auth.user.external_accounts.append(account) # Ensure S3 is enabled. auth.user.get_or_add_addon('s3', auth=auth) auth.user.save() return {}
def s3_add_user_account(auth, **kwargs): """Verifies new external account credentials and adds to user's list""" try: access_key = request.json['access_key'] secret_key = request.json['secret_key'] except KeyError: raise HTTPError(httplib.BAD_REQUEST) if not (access_key and secret_key): return { 'message': 'All the fields above are required.' }, httplib.BAD_REQUEST user_info = utils.get_user_info(access_key, secret_key) if not user_info: return { 'message': ('Unable to access account.\n' 'Check to make sure that the above credentials are valid, ' 'and that they have permission to list buckets.') }, httplib.BAD_REQUEST if not utils.can_list(access_key, secret_key): return { 'message': ('Unable to list buckets.\n' 'Listing buckets is required permission that can be changed via IAM') }, httplib.BAD_REQUEST account = None try: account = ExternalAccount( provider=SHORT_NAME, provider_name=FULL_NAME, oauth_key=access_key, oauth_secret=secret_key, provider_id=user_info.id, display_name=user_info.display_name, ) account.save() except KeyExistsException: # ... or get the old one account = ExternalAccount.find_one( Q('provider', 'eq', SHORT_NAME) & Q('provider_id', 'eq', user_info.id) ) assert account is not None if account not in auth.user.external_accounts: auth.user.external_accounts.append(account) # Ensure S3 is enabled. auth.user.get_or_add_addon('s3', auth=auth) auth.user.save() return {}
def do_migration(records): database['googledrivenodesettings'].update({'user_settings': { '$type': 2 }}, {'$rename': { 'user_settings': 'foreign_user_settings' }}, multi=True) for user_addon in records: user = user_addon.owner old_account = user_addon.oauth_settings logger.info('Record found for user {}'.format(user._id)) # Create/load external account and append to user try: account = ExternalAccount( provider='googledrive', provider_name='Google Drive', display_name=old_account.username, oauth_key=old_account.access_token, refresh_token=old_account.refresh_token, provider_id=old_account.user_id, expires_at=old_account.expires_at, ) account.save() except KeyExistsException: # ... or get the old one account = ExternalAccount.find_one( Q('provider', 'eq', 'googledrive') & Q('provider_id', 'eq', old_account.user_id)) assert account is not None user.external_accounts.append(account) user.save() # Remove oauth_settings from user settings object user_addon.oauth_settings = None user_addon.save() logger.info('Added external account {0} to user {1}'.format( account._id, user._id, )) # Add external account to authorized nodes for node in GoogleDriveNodeSettings.find(): if node.foreign_user_settings is None: continue logger.info('Migrating user_settings for googledrive {}'.format( node._id)) node.user_settings = node.foreign_user_settings node.save()
def do_migration(records): host = 'dataverse.harvard.edu' for user_addon in records: user = user_addon.owner api_token = user_addon.api_token logger.info('Record found for user {}'.format(user._id)) # Modified from `dataverse_add_user_account` # Create/load external account and append to user try: account = ExternalAccount( provider='dataverse', provider_name='Dataverse', display_name=host, oauth_key=host, oauth_secret=api_token, provider_id=api_token, ) account.save() except KeyExistsException: # ... or get the old one account = ExternalAccount.find_one( Q('provider', 'eq', 'dataverse') & Q('provider_id', 'eq', api_token)) assert account is not None user.external_accounts.append(account) user.save() # Remove api_token from user settings object user_addon.api_token = None user_addon.save() logger.info('Added external account {0} to user {1}'.format( account._id, user._id, )) ####### BROKEN ####### # Field user_addon needed to be user_addon._id for lookup. # # Add external account to authorized nodes for node_addon in get_authorized_node_settings(user_addon): node_addon.set_auth(account, user) logger.info('Added external account {0} to node {1}'.format( account._id, node_addon.owner._id, ))
def test_migrate_to_external_account(self): assert_equal(ExternalAccount.find().count(), 0) user_settings_document = self.unlinked_user_settings[0] external_account, user, new = migration.migrate_to_external_account( user_settings_document) assert_true(new) assert_equal(ExternalAccount.find().count(), 1) assert_is_not_none(external_account) assert_equal(user_settings_document['owner'], user._id) assert_equal(external_account.provider, 's3') assert_equal(external_account.provider_name, 'Amazon S3') assert_equal(external_account.oauth_key, user_settings_document['access_key']) assert_is_not_none(external_account.display_name)
def do_migration(records): host = 'dataverse.harvard.edu' for user_addon in records: user = user_addon.owner api_token = user_addon.api_token logger.info('Record found for user {}'.format(user._id)) # Modified from `dataverse_add_user_account` # Create/load external account and append to user try: account = ExternalAccount( provider='dataverse', provider_name='Dataverse', display_name=host, oauth_key=host, oauth_secret=api_token, provider_id=api_token, ) account.save() except KeyExistsException: # ... or get the old one account = ExternalAccount.find_one( Q('provider', 'eq', 'dataverse') & Q('provider_id', 'eq', api_token) ) assert account is not None user.external_accounts.append(account) user.save() # Remove api_token from user settings object user_addon.api_token = None user_addon.save() logger.info('Added external account {0} to user {1}'.format( account._id, user._id, )) ####### BROKEN ####### # Field user_addon needed to be user_addon._id for lookup. # # Add external account to authorized nodes for node_addon in get_authorized_node_settings(user_addon): node_addon.set_auth(account, user) logger.info('Added external account {0} to node {1}'.format( account._id, node_addon.owner._id, ))
def test_migrate_to_external_account(self): assert_equal(ExternalAccount.find().count(), 0) user_settings_document = self.unlinked_user_settings[0] external_account, user, new = migration.migrate_to_external_account(user_settings_document) assert_true(new) assert_equal(ExternalAccount.find().count(), 1) assert_is_not_none(external_account) assert_equal(user_settings_document['owner'], user._id) assert_equal(external_account.provider, 's3') assert_equal(external_account.provider_name, 'Amazon S3') assert_equal( external_account.oauth_key, user_settings_document['access_key'] ) assert_is_not_none(external_account.display_name)
def get_targets(delta): # NOTE: expires_at is the access_token's expiration date, # NOT the refresh token's return ExternalAccount.find( Q('expires_at', 'lt', datetime.datetime.utcnow() - delta) & Q('provider', 'eq', 'box') )
def get_targets(delta, addon_short_name): # NOTE: expires_at is the access_token's expiration date, # NOT the refresh token's return ExternalAccount.find( Q('date_last_refreshed', 'lt', datetime.datetime.utcnow() - delta) & Q('provider', 'eq', addon_short_name))
def test_callback(self): # Exchange temporary credentials for permanent credentials # Mock the exchange of the code for an access token _prepare_mock_oauth2_handshake_response() user = UserFactory() # Fake a request context for the callback with self.app.app.test_request_context( path="/oauth/callback/mock2/", query_string="code=mock_code&state=mock_state" ): # make sure the user is logged in authenticate(user=self.user, access_token=None, response=None) session = get_session() session.data['oauth_states'] = { self.provider.short_name: { 'state': 'mock_state', }, } session.save() # do the key exchange self.provider.auth_callback(user=user) account = ExternalAccount.find_one() assert_equal(account.oauth_key, 'mock_access_token') assert_equal(account.provider_id, 'mock_provider_id')
def test_callback(self): # Exchange temporary credentials for permanent credentials # Mock the exchange of the code for an access token _prepare_mock_oauth2_handshake_response() user = UserFactory() # Fake a request context for the callback with self.app.app.test_request_context( path="/oauth/callback/mock2/", query_string="code=mock_code&state=mock_state"): # make sure the user is logged in authenticate(user=self.user, access_token=None, response=None) session.data['oauth_states'] = { self.provider.short_name: { 'state': 'mock_state', }, } session.save() # do the key exchange self.provider.auth_callback(user=user) account = ExternalAccount.find_one() assert_equal(account.oauth_key, 'mock_access_token') assert_equal(account.provider_id, 'mock_provider_id')
def get_targets(delta, addon_short_name): # NOTE: expires_at is the access_token's expiration date, # NOT the refresh token's return ExternalAccount.find( Q('expires_at', 'lt', datetime.datetime.utcnow() - delta) & Q('provider', 'eq', addon_short_name) )
def add_user_auth(self, node_addon, user, external_account_id): external_account = ExternalAccount.load(external_account_id) if external_account not in user.external_accounts: raise HTTPError(http.FORBIDDEN) try: node_addon.set_auth(external_account, user) except PermissionsError: raise HTTPError(http.FORBIDDEN) node = node_addon.owner node.add_log( action='dataverse_node_authorized', params={ 'project': node.parent_id, 'node': node._id, }, auth=Auth(user=user), ) result = self.serializer( node_settings=node_addon, user_settings=user.get_addon('dataverse'), ).serialized_node_settings return {'result': result}
def test_multiple_users_associated(self): # Create only one ExternalAccount for multiple OSF users # # For some providers (ex: GitHub), the act of completing the OAuth flow # revokes previously generated credentials. In addition, there is often no # way to know the user's id on the external service until after the flow # has completed. # # Having only one ExternalAccount instance per account on the external # service means that connecting subsequent OSF users to the same external # account will not invalidate the credentials used by the OSF for users # already associated. user_a = UserFactory() external_account = ExternalAccountFactory( provider='mock2', provider_id='mock_provider_id', provider_name='Mock Provider', ) user_a.external_accounts.append(external_account) user_a.save() user_b = UserFactory() # Mock the exchange of the code for an access token _prepare_mock_oauth2_handshake_response() # Fake a request context for the callback with self.app.app.test_request_context( path="/oauth/callback/mock2/", query_string="code=mock_code&state=mock_state" ) as ctx: # make sure the user is logged in authenticate(user=user_b, access_token=None, response=None) session = get_session() session.data['oauth_states'] = { self.provider.short_name: { 'state': 'mock_state', }, } session.save() # do the key exchange self.provider.auth_callback(user=user_b) user_a.reload() user_b.reload() external_account.reload() assert_equal( user_a.external_accounts, user_b.external_accounts, ) assert_equal( ExternalAccount.find().count(), 1 )
def do_migration(records): database['googledrivenodesettings'].update({'user_settings': {'$type': 2}}, {'$rename': { 'user_settings': 'foreign_user_settings'}}, multi=True) for user_addon in records: user = user_addon.owner old_account = user_addon.oauth_settings logger.info('Record found for user {}'.format(user._id)) # Create/load external account and append to user try: account = ExternalAccount( provider='googledrive', provider_name='Google Drive', display_name=old_account.username, oauth_key=old_account.access_token, refresh_token=old_account.refresh_token, provider_id=old_account.user_id, expires_at=old_account.expires_at, ) account.save() except KeyExistsException: # ... or get the old one account = ExternalAccount.find_one( Q('provider', 'eq', 'googledrive') & Q('provider_id', 'eq', old_account.user_id) ) assert account is not None user.external_accounts.append(account) user.save() # Remove oauth_settings from user settings object user_addon.oauth_settings = None user_addon.save() logger.info('Added external account {0} to user {1}'.format( account._id, user._id, )) # Add external account to authorized nodes for node in GoogleDriveNodeSettings.find(): if node.foreign_user_settings is None: continue logger.info('Migrating user_settings for googledrive {}'.format(node._id)) node.user_settings = node.foreign_user_settings node.save()
def test_multiple_users_associated(self): # Create only one ExternalAccount for multiple OSF users # # For some providers (ex: GitHub), the act of completing the OAuth flow # revokes previously generated credentials. In addition, there is often no # way to know the user's id on the external service until after the flow # has completed. # # Having only one ExternalAccount instance per account on the external # service means that connecting subsequent OSF users to the same external # account will not invalidate the credentials used by the OSF for users # already associated. user_a = UserFactory() external_account = ExternalAccountFactory( provider='mock2', provider_id='mock_provider_id', provider_name='Mock Provider', ) user_a.external_accounts.append(external_account) user_a.save() user_b = UserFactory() # Mock the exchange of the code for an access token _prepare_mock_oauth2_handshake_response() # Fake a request context for the callback with self.app.app.test_request_context( path="/oauth/callback/mock2/", query_string="code=mock_code&state=mock_state" ) as ctx: # make sure the user is logged in authenticate(user=user_b, access_token=None, response=None) session.data['oauth_states'] = { self.provider.short_name: { 'state': 'mock_state', }, } session.save() # do the key exchange self.provider.auth_callback(user=user_b) user_a.reload() user_b.reload() external_account.reload() assert_equal( user_a.external_accounts, user_b.external_accounts, ) assert_equal( ExternalAccount.find().count(), 1 )
def get_account_or_error(self, addon_name, external_account_id, auth): external_account = ExternalAccount.load(external_account_id) if not external_account: raise exceptions.NotFound('Unable to find requested account.') if external_account not in auth.user.external_accounts: raise exceptions.PermissionDenied('Requested action requires account ownership.') if external_account.provider != addon_name: raise Conflict('Cannot authorize the {} addon with an account for {}'.format(addon_name, external_account.provider)) return external_account
def get_account_or_error(self, addon_name, external_account_id, auth): external_account = ExternalAccount.load(external_account_id) if not external_account: raise exceptions.NotFound('Unable to find requested account.') if external_account not in auth.user.external_accounts: raise exceptions.PermissionDenied('Requested action requires account ownership.') if external_account.provider != addon_name: raise Conflict('Cannot authorize the {} addon with an account for {}'.format(addon_name, external_account.provider)) return external_account
def migrate_to_external_account(user_settings_document, oauth_settings_document): if not oauth_settings_document.get('oauth_access_token'): return (None, None, None) try: user_info = GitHubClient( access_token=oauth_settings_document['oauth_access_token']).user() except (GitHubError, ApiError): user_id = oauth_settings_document['github_user_id'] profile_url = None display_name = oauth_settings_document['github_user_name'] else: user_id = user_info.id profile_url = user_info.html_url display_name = user_info.login new = False user = User.load(user_settings_document['owner']) try: external_account = ExternalAccount.find(Q('provider_id', 'eq', user_id))[0] logger.info( 'Duplicate account use found: User {0} with github_user_id {1}'. format(user.username, user_id)) except IndexError: new = True external_account = ExternalAccount( provider=PROVIDER, provider_name=PROVIDER_NAME, provider_id=user_id, profile_url=profile_url, oauth_key=oauth_settings_document['oauth_access_token'], display_name=display_name, ) external_account.save() if not profile_url: invalid_oauth_creds[external_account._id] = ( user_settings_document['_id'], oauth_settings_document['_id']) logger.info( "Created ExternalAccount<_id:{0}> with invalid oauth credentials." .format(external_account._id)) user.external_accounts.append(external_account) user.save() return external_account, user, new
def dataverse_add_user_account(auth, **kwargs): """Verifies new external account credentials and adds to user's list""" user = auth.user provider = DataverseProvider() host = request.json.get('host').rstrip('/') api_token = request.json.get('api_token') # Verify that credentials are valid client.connect_or_error(host, api_token) # Note: `DataverseSerializer` expects display_name to be a URL try: provider.account = ExternalAccount( provider=provider.short_name, provider_name=provider.name, display_name=host, # no username; show host oauth_key=host, # hijacked; now host oauth_secret=api_token, # hijacked; now api_token provider_id=api_token, # Change to username if Dataverse allows ) provider.account.save() except KeyExistsException: # ... or get the old one provider.account = ExternalAccount.find_one( Q('provider', 'eq', provider.short_name) & Q('provider_id', 'eq', api_token) ) assert provider.account is not None if provider.account not in user.external_accounts: user.external_accounts.append(provider.account) user_addon = auth.user.get_addon('dataverse') if not user_addon: user.add_addon('dataverse') user.save() # Need to ensure that the user has dataverse enabled at this point user.get_or_add_addon('dataverse', auth=auth) user.save() return {}
def test_disconnect(self): # Disconnect an external account from a user external_account = ExternalAccountFactory( provider='mock2', provider_id='mock_provider_id', provider_name='Mock Provider', ) self.user.external_accounts.append(external_account) self.user.save() # If the external account isn't attached, this test has no meaning assert_equal(ExternalAccount.find().count(), 1) assert_in( external_account, self.user.external_accounts, ) response = self.app.delete( api_url_for('oauth_disconnect', external_account_id=external_account._id), auth=self.user.auth ) # Request succeeded assert_equal( response.status_code, http.OK, ) self.user.reload() # external_account.reload() # External account has been disassociated with the user assert_not_in( external_account, self.user.external_accounts, ) # External account is still in the database assert_equal(ExternalAccount.find().count(), 1)
def test_disconnect(self): # Disconnect an external account from a user external_account = ExternalAccountFactory( provider='mock2', provider_id='mock_provider_id', provider_name='Mock Provider', ) self.user.external_accounts.append(external_account) self.user.save() # If the external account isn't attached, this test has no meaning assert_equal(ExternalAccount.find().count(), 1) assert_in( external_account, self.user.external_accounts, ) response = self.app.delete( api_url_for('oauth_disconnect', external_account_id=external_account._id), auth=self.user.auth ) # Request succeeded assert_equal( response.status_code, http.OK, ) self.user.reload() # external_account.reload() # External account has been disassociated with the user assert_not_in( external_account, self.user.external_accounts, ) # External account is still in the database assert_equal(ExternalAccount.find().count(), 1)
def migrate_to_external_account(user_settings_document): if not user_settings_document.get('access_token'): return (None, None, None) new = False user = User.load(user_settings_document['owner']) try: external_account = ExternalAccount.find(Q('provider_id', 'eq', user_settings_document['dropbox_id']))[0] logger.info('Duplicate account use found: User {0} with dropbox_id {1}'.format(user.username, user_settings_document['dropbox_id'])) except IndexError: new = True external_account = ExternalAccount( provider=PROVIDER, provider_name=PROVIDER_NAME, provider_id=user_settings_document['dropbox_id'], oauth_key=user_settings_document['access_token'], display_name=user_settings_document['dropbox_info'].get('display_name', None) if user_settings_document.get('dropbox_info', None) else None, ) external_account.save() # generate pk for external accountc user.external_accounts.append(external_account) user.save() return external_account, user, new
def migrate_to_external_account(user_settings_document, oauth_settings_document): if not oauth_settings_document.get('oauth_access_token'): return (None, None, None) try: user_info = GitHubClient(access_token=oauth_settings_document['oauth_access_token']).user() except (GitHubError, ApiError): user_id = oauth_settings_document['github_user_id'] profile_url = None display_name = oauth_settings_document['github_user_name'] else: user_id = user_info.id profile_url = user_info.html_url display_name = user_info.login new = False user = User.load(user_settings_document['owner']) try: external_account = ExternalAccount.find(Q('provider_id', 'eq', user_id))[0] logger.info('Duplicate account use found: User {0} with github_user_id {1}'.format(user.username, user_id)) except IndexError: new = True external_account = ExternalAccount( provider=PROVIDER, provider_name=PROVIDER_NAME, provider_id=user_id, profile_url=profile_url, oauth_key=oauth_settings_document['oauth_access_token'], display_name=display_name, ) external_account.save() if not profile_url: invalid_oauth_creds[external_account._id] = (user_settings_document['_id'], oauth_settings_document['_id']) logger.info("Created ExternalAccount<_id:{0}> with invalid oauth credentials.".format( external_account._id )) user.external_accounts.append(external_account) user.save() return external_account, user, new
def add_user_auth(self, node_addon, user, external_account_id): external_account = ExternalAccount.load(external_account_id) if external_account not in user.external_accounts: raise HTTPError(http.FORBIDDEN) try: node_addon.set_auth(external_account, user) except PermissionsError: raise HTTPError(http.FORBIDDEN) result = self.serialize_settings(node_addon, user) return {'result': result}
def owncloud_add_user_account(auth, **kwargs): """ Verifies new external account credentials and adds to user's list This view expects `host`, `username` and `password` fields in the JSON body of the request. """ # Ensure that ownCloud uses https host_url = request.json.get('host') host = furl() host.host = host_url.rstrip('/').replace('https://', '').replace('http://', '') host.scheme = 'https' username = request.json.get('username') password = request.json.get('password') try: oc = owncloud.Client(host.url, verify_certs=settings.USE_SSL) oc.login(username, password) oc.logout() except requests.exceptions.ConnectionError: return { 'message': 'Invalid ownCloud server.' }, http.BAD_REQUEST except owncloud.owncloud.HTTPResponseError: return { 'message': 'ownCloud Login failed.' }, http.UNAUTHORIZED provider = OwnCloudProvider(account=None, host=host.url, username=username, password=password) try: provider.account.save() except KeyExistsException: # ... or get the old one provider.account = ExternalAccount.find_one( Q('provider', 'eq', provider.short_name) & Q('provider_id', 'eq', '{}:{}'.format(host.url, username).lower()) ) user = auth.user if provider.account not in user.external_accounts: user.external_accounts.append(provider.account) user.get_or_add_addon('owncloud', auth=auth) user.save() return {}
def owncloud_add_user_account(auth, **kwargs): """ Verifies new external account credentials and adds to user's list This view expects `host`, `username` and `password` fields in the JSON body of the request. """ # Ensure that ownCloud uses https host_url = request.json.get('host') host = furl() host.host = host_url.rstrip('/').replace('https://', '').replace('http://', '') host.scheme = 'https' username = request.json.get('username') password = request.json.get('password') try: oc = owncloud.Client(host.url, verify_certs=settings.USE_SSL) oc.login(username, password) oc.logout() except requests.exceptions.ConnectionError: return {'message': 'Invalid ownCloud server.'}, http.BAD_REQUEST except owncloud.owncloud.HTTPResponseError: return {'message': 'ownCloud Login failed.'}, http.UNAUTHORIZED provider = OwnCloudProvider(account=None, host=host.url, username=username, password=password) try: provider.account.save() except KeyExistsException: # ... or get the old one provider.account = ExternalAccount.find_one( Q('provider', 'eq', provider.short_name) & Q('provider_id', 'eq', '{}:{}'.format(host.url, username).lower())) user = auth.user if provider.account not in user.external_accounts: user.external_accounts.append(provider.account) user.get_or_add_addon('owncloud', auth=auth) user.save() return {}
def add_user_auth(self, node_addon, user, external_account_id): external_account = ExternalAccount.load(external_account_id) if external_account not in user.external_accounts: raise HTTPError(http.FORBIDDEN) try: node_addon.set_auth(external_account, user) except PermissionsError: raise HTTPError(http.FORBIDDEN) result = self.serializer( node_settings=node_addon, user_settings=user.get_addon(self.provider_name), ).serialized_node_settings return {'result': result}
def add_user_auth(self, node_addon, user, external_account_id): external_account = ExternalAccount.load(external_account_id) if external_account not in user.external_accounts: raise HTTPError(http.FORBIDDEN) try: node_addon.set_auth(external_account, user) except PermissionsError: raise HTTPError(http.FORBIDDEN) result = self.serializer( node_settings=node_addon, user_settings=user.get_addon(self.provider_name), ).serialized_node_settings result['validCredentials'] = self.check_credentials(node_addon) return {'result': result}
def test_callback(self): # Exchange temporary credentials for permanent credentials # mock a successful call to the provider to exchange temp keys for # permanent keys httpretty.register_uri( httpretty.POST, 'http://mock1a.com/callback', body=( 'oauth_token=perm_token' '&oauth_token_secret=perm_secret' '&oauth_callback_confirmed=true' ), ) user = UserFactory() # Fake a request context for the callback ctx = self.app.app.test_request_context( path='/oauth/callback/mock1a/', query_string='oauth_token=temp_key&oauth_verifier=mock_verifier', ) with ctx: # make sure the user is logged in authenticate(user=user, access_token=None, response=None) session = get_session() session.data['oauth_states'] = { self.provider.short_name: { 'token': 'temp_key', 'secret': 'temp_secret', }, } session.save() # do the key exchange self.provider.auth_callback(user=user) account = ExternalAccount.find_one() assert_equal(account.oauth_key, 'perm_token') assert_equal(account.oauth_secret, 'perm_secret') assert_equal(account.provider_id, 'mock_provider_id') assert_equal(account.provider_name, 'Mock OAuth 1.0a Provider')
def test_disconnect_with_multiple_connected(self): # Disconnect an account connected to multiple users from one user external_account = ExternalAccountFactory( provider='mock2', provider_id='mock_provider_id', provider_name='Mock Provider', ) self.user.external_accounts.append(external_account) self.user.save() other_user = UserFactory() other_user.external_accounts.append(external_account) other_user.save() response = self.app.delete( api_url_for('oauth_disconnect', external_account_id=external_account._id), auth=self.user.auth ) # Request succeeded assert_equal( response.status_code, http.OK, ) self.user.reload() # External account has been disassociated with the user assert_not_in( external_account, self.user.external_accounts, ) # External account is still in the database assert_equal(ExternalAccount.find().count(), 1) other_user.reload() # External account is still associated with the other user assert_in( external_account, other_user.external_accounts, )
def test_disconnect_with_multiple_connected(self): # Disconnect an account connected to multiple users from one user external_account = ExternalAccountFactory( provider='mock2', provider_id='mock_provider_id', provider_name='Mock Provider', ) self.user.external_accounts.append(external_account) self.user.save() other_user = UserFactory() other_user.external_accounts.append(external_account) other_user.save() response = self.app.delete( api_url_for('oauth_disconnect', external_account_id=external_account._id), auth=self.user.auth ) # Request succeeded assert_equal( response.status_code, http.OK, ) self.user.reload() # External account has been disassociated with the user assert_not_in( external_account, self.user.external_accounts, ) # External account is still in the database assert_equal(ExternalAccount.find().count(), 1) other_user.reload() # External account is still associated with the other user assert_in( external_account, other_user.external_accounts, )
def oauth_disconnect(external_account_id, auth): account = ExternalAccount.load(external_account_id) user = auth.user if account is None: HTTPError(http.NOT_FOUND) if account not in user.external_accounts: HTTPError(http.FORBIDDEN) # iterate AddonUserSettings for addons for user_settings in user.get_oauth_addons(): user_settings.revoke_oauth_access(account) user_settings.save() # ExternalAccount.remove_one(account) # # only after all addons have been dealt with can we remove it from the user user.external_accounts.remove(account) user.save()
def creds_are_valid(ea_id): logger.warn('Validating credentials for externalaccount {}'.format(ea_id)) ea = ExternalAccount.load(ea_id) if ea.provider == 'github': try: GitHubClient(external_account=ea).user() except (GitHubError, IndexError): logger.info('Invalid creds: {}'.format(ea_id)) return False elif ea.provider == 'dropbox': try: DropboxClient(ea.oauth_key).account_info() except (ValueError, IndexError, ErrorResponse): logger.info('Invalid creds: {}'.format(ea_id)) return False else: raise Exception('Unexpected provider: {}'.format(ea.provider)) logger.info('Valid creds: {}'.format(ea_id)) return True
def creds_are_valid(ea_id): logger.warn('Validating credentials for externalaccount {}'.format(ea_id)) ea = ExternalAccount.load(ea_id) if ea.provider == 'github': try: GitHubClient(external_account=ea).user() except (GitHubError, IndexError): logger.info('Invalid creds: {}'.format(ea_id)) return False elif ea.provider == 'dropbox': try: DropboxClient(ea.oauth_key).account_info() except (ValueError, IndexError, ErrorResponse): logger.info('Invalid creds: {}'.format(ea_id)) return False else: raise Exception('Unexpected provider: {}'.format(ea.provider)) logger.info('Valid creds: {}'.format(ea_id)) return True
def test_callback(self): # Exchange temporary credentials for permanent credentials # mock a successful call to the provider to exchange temp keys for # permanent keys httpretty.register_uri( httpretty.POST, 'http://mock1a.com/callback', body=( 'oauth_token=perm_token' '&oauth_token_secret=perm_secret' '&oauth_callback_confirmed=true' ), ) user = UserFactory() # Fake a request context for the callback ctx = self.app.app.test_request_context( path='/oauth/callback/mock1a/', query_string='oauth_token=temp_key&oauth_verifier=mock_verifier', ) with ctx: # make sure the user is logged in authenticate(user=user, access_token=None, response=None) session.data['oauth_states'] = { self.provider.short_name: { 'token': 'temp_key', 'secret': 'temp_secret', }, } session.save() # do the key exchange self.provider.auth_callback(user=user) account = ExternalAccount.find_one() assert_equal(account.oauth_key, 'perm_token') assert_equal(account.oauth_secret, 'perm_secret') assert_equal(account.provider_id, 'mock_provider_id') assert_equal(account.provider_name, 'Mock OAuth 1.0a Provider')
def add_user_auth(self, node_addon, user, external_account_id): """Adds authorization to a node if the user has authorization to grant""" external_account = ExternalAccount.load(external_account_id) if external_account not in user.external_accounts: raise HTTPError(http.FORBIDDEN) try: node_addon.set_auth(external_account, user) except PermissionsError: raise HTTPError(http.FORBIDDEN) result = self.serializer( node_settings=node_addon, user_settings=user.get_addon(self.provider_name), ).serialized_node_settings result['validCredentials'] = self.check_credentials(node_addon) return {'result': result}
def googledrive_import_user_auth(auth, node_addon, **kwargs): """ Import googledrive credentials from the currently logged-in user to a node. """ user = auth.user external_account_id = request.get_json().get('external_account_id') external_account = ExternalAccount.load(external_account_id) if external_account not in user.external_accounts: raise HTTPError(http.FORBIDDEN) try: node_addon.set_auth(external_account, user) except PermissionsError: raise HTTPError(http.FORBIDDEN) result = GoogleDriveSerializer( node_settings=node_addon, user_settings=user.get_addon('googledrive'), ).serialize_settings(node_addon, user) return result
def oauth_disconnect(external_account_id, auth): account = ExternalAccount.load(external_account_id) user = auth.user if account is None: HTTPError(http.NOT_FOUND) if account not in user.external_accounts: HTTPError(http.FORBIDDEN) # iterate AddonUserSettings for addons for user_settings in user.get_oauth_addons(): user_settings.revoke_oauth_access(account) user_settings.save() # ExternalAccount.remove_one(account) # # only after all addons have been dealt with can we remove it from the user user.external_accounts.remove(account) user.save()
def oauth_disconnect(external_account_id, auth): account = ExternalAccount.load(external_account_id) user = auth.user if account is None: raise HTTPError(http.NOT_FOUND) if not user.external_accounts.filter(id=account.id).exists(): raise HTTPError(http.FORBIDDEN) # iterate AddonUserSettings for addons for user_settings in user.get_oauth_addons(): if user_settings.oauth_provider.short_name == account.provider: user_settings.revoke_oauth_access(account) user_settings.save() # ExternalAccount.remove_one(account) # # only after all addons have been dealt with can we remove it from the user user.external_accounts.remove(account) user.save()
def _import_auth(auth, node_addon, user_addon, **kwargs): """Import add-on credentials from the currently logged-in user to a node. """ external_account = ExternalAccount.load( request.json['external_account_id']) if external_account not in user_addon.external_accounts: raise HTTPError(http.FORBIDDEN) try: node_addon.set_auth(external_account, user_addon.owner) except PermissionsError: raise HTTPError(http.FORBIDDEN) node_addon.save() return { 'result': Serializer().serialize_settings(node_addon, auth.user), 'message': 'Successfully imported access token from profile.', }
def _import_auth(auth, node_addon, user_addon, **kwargs): """Import add-on credentials from the currently logged-in user to a node. """ external_account = ExternalAccount.load( request.json['external_account_id'] ) if external_account not in user_addon.external_accounts: raise HTTPError(http.FORBIDDEN) try: node_addon.set_auth(external_account, user_addon.owner) except PermissionsError: raise HTTPError(http.FORBIDDEN) node_addon.save() return { 'result': Serializer().serialize_settings(node_addon, auth.user), 'message': 'Successfully imported access token from profile.', }
def get_targets(): return ExternalAccount.find( Q("provider", "eq", "dataverse") & (Q("display_name", "eq", OLD_HOST) | Q("oauth_key", "eq", OLD_HOST)) )
def tearDown(self): ExternalAccount.remove() self.user.remove() super(TestExternalProviderOAuth1, self).tearDown()
def tearDown(self): ExternalAccount._clear_caches() ExternalAccount.remove() self.user.remove() super(TestExternalProviderOAuth2, self).tearDown()
def tearDown(self): super(TestBoxMigration, self).tearDown() BoxUserSettings.remove() ExternalAccount.remove()
def tearDown(self): super(TestRefreshTokens, self).tearDown() ExternalAccount.remove()
def tearDown(self): ExternalAccount._clear_caches() ExternalAccount.remove() self.user.remove() super(TestExternalAccount, self).tearDown()
def tearDown(self): super(TestRefreshTokens, self).tearDown() ExternalAccount.remove()
def tearDown(self): ExternalAccount.remove() self.user.remove() super(TestExternalProviderOAuth1, self).tearDown()