Exemplo n.º 1
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.add(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(
            list(user_a.external_accounts.values_list('pk', flat=True)),
            list(user_b.external_accounts.values_list('pk', flat=True)),
        )

        assert_equal(
            ExternalAccount.find().count(),
            1
        )
Exemplo n.º 2
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 not auth.user.external_accounts.filter(id=external_account.id).exists():
             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
Exemplo n.º 3
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.add(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.all(),
        )

        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.all(),
        )

        # External account is still in the database
        assert_equal(ExternalAccount.find().count(), 1)
Exemplo n.º 4
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 not auth.user.external_accounts.filter(
             id=external_account.id).exists():
         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
Exemplo n.º 5
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.add(external_account)
        self.user.save()

        other_user = UserFactory()
        other_user.external_accounts.add(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.all(),
        )

        # 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.all(),
        )
Exemplo n.º 6
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 not user.external_accounts.filter(id=external_account.id).all():
            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}
Exemplo n.º 7
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 not user.external_accounts.filter(id=external_account.id).all():
            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}