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
Example #3
0
    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
Example #5
0
    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)
Example #6
0
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 {}
Example #7
0
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,
            ))
Example #10
0
 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')
    )
Example #14
0
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))
Example #15
0
    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')
Example #16
0
    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')
Example #17
0
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)
    )
Example #18
0
    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}
Example #19
0
    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()
Example #21
0
    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
        )
Example #22
0
 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
Example #23
0
 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
Example #25
0
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 {}
Example #26
0
    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)
Example #27
0
    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
Example #30
0
    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}
Example #31
0
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 {}
Example #32
0
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 {}
Example #33
0
    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}
Example #34
0
    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}
Example #35
0
    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')
Example #36
0
    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,
        )
Example #37
0
    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,
        )
Example #38
0
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
Example #40
0
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
Example #41
0
    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')
Example #42
0
    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}
Example #43
0
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
Example #44
0
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()
Example #45
0
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()
Example #46
0
    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.',
        }
Example #47
0
    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.',
        }
Example #48
0
def get_targets():
    return ExternalAccount.find(
        Q("provider", "eq", "dataverse") & (Q("display_name", "eq", OLD_HOST) | Q("oauth_key", "eq", OLD_HOST))
    )
Example #49
0
 def tearDown(self):
     ExternalAccount.remove()
     self.user.remove()
     super(TestExternalProviderOAuth1, self).tearDown()
Example #50
0
 def tearDown(self):
     ExternalAccount._clear_caches()
     ExternalAccount.remove()
     self.user.remove()
     super(TestExternalProviderOAuth2, self).tearDown()
Example #51
0
 def tearDown(self):
     super(TestBoxMigration, self).tearDown()
     BoxUserSettings.remove()
     ExternalAccount.remove()
Example #52
0
 def tearDown(self):
     super(TestRefreshTokens, self).tearDown()
     ExternalAccount.remove()
Example #53
0
 def tearDown(self):
     ExternalAccount._clear_caches()
     ExternalAccount.remove()
     self.user.remove()
     super(TestExternalAccount, self).tearDown()
 def tearDown(self):
     super(TestRefreshTokens, self).tearDown()
     ExternalAccount.remove()
Example #55
0
 def tearDown(self):
     ExternalAccount.remove()
     self.user.remove()
     super(TestExternalProviderOAuth1, self).tearDown()