Esempio n. 1
0
    def testGetUserWithUserConflict(self):
        """
        A L{DuplicateUserError} exception is raised if a L{User} with the same
        username as the Twitter user's screen name already exists, but is not
        associated with the Twitter UID.
        """
        UserAPI().create([
            (u'consumer', 'secret', u'Consumer', u'*****@*****.**'),
            (u'john', 'secret', u'John', u'*****@*****.**')])
        self.store.commit()

        self.agent._connect = self._connect
        authentication = 'OAuth oauth_consumer_key="...", ...'
        consumer = getUser(u'consumer')
        provider = ServiceProvider(self.agent, 'https://example.com/verify')
        delegator = Delegator(self.transact)
        deferred = delegator.getUser(consumer, provider, authentication)

        [(request, responseDeferred)] = self.protocol.requests
        response = FakeResponse(ResponseDone(), dumps({'id': 1984245,
                                                       'screen_name': u'john',
                                                       'name': u'John Doe'}))
        responseDeferred.callback(response)
        error = yield self.assertFailure(deferred, DuplicateUserError)
        self.assertEqual([u'john'], list(error.usernames))
Esempio n. 2
0
    def testVerifyCredentialsUnpacksSuccessfulResponse(self):
        """
        L{ServiceProvider.verifyCredentials} returns a C{Deferred} that
        fires with the user object returned by Twitter, as a C{dict}, when
        credentials are successfully verified.
        """
        self.agent._connect = self._connect
        authentication = 'OAuth oauth_consumer_key="...", ...'
        provider = ServiceProvider(self.agent, 'https://example.com/verify')
        deferred = provider.verifyCredentials(authentication)

        [(request, responseDeferred)] = self.protocol.requests
        response = FakeResponse(ResponseDone(), dumps({'id': 1984245}))
        responseDeferred.callback(response)
        user = yield deferred
        self.assertEqual(1984245, user['id'])
Esempio n. 3
0
    def testGetUserWithNewUserAndMixedCaseTwitterScreenName(self):
        """
        A new L{User} is created if L{Delegator.getUser} verifies the
        L{TwitterUser} but can't find a user matching the Twitter screen name.
        The Twitter user's screen name should be lowercased to make the
        new Fluidinfo username.
        """
        UserAPI().create([
            (u'consumer', 'secret', u'Consumer', u'*****@*****.**')])
        consumer = getUser(u'consumer')
        OAuthConsumerAPI().register(consumer)
        self.store.commit()

        self.agent._connect = self._connect
        authentication = 'OAuth oauth_consumer_key="...", ...'
        provider = ServiceProvider(self.agent, 'https://example.com/verify')
        delegator = Delegator(self.transact)
        deferred = delegator.getUser(u'consumer', provider, authentication)

        [(request, responseDeferred)] = self.protocol.requests
        response = FakeResponse(ResponseDone(),
                                dumps({'id': 1984245,
                                       'screen_name': u'MixedCaseName',
                                       'name': u'John Doe'}))
        responseDeferred.callback(response)
        result = yield deferred
        self.assertTrue(result['new-user'])
        user = TwitterUserAPI().get(1984245)
        self.assertEqual(u'mixedcasename', user.username)
Esempio n. 4
0
    def testGetUserWithNoPassword(self):
        """
        If a L{User} returned by L{Delegator.getUser} doesn't have a password,
        a C{missing-password} value is added to the result.
        """
        UserAPI().create([
            (u'consumer', 'secret', u'Consumer', u'*****@*****.**'),
            (u'user', None, u'User', u'*****@*****.**')])
        TwitterUserAPI().create(u'user', 1984245)
        consumer = getUser(u'consumer')
        OAuthConsumerAPI().register(consumer)
        self.store.commit()

        self.agent._connect = self._connect
        authentication = 'OAuth oauth_consumer_key="...", ...'
        provider = ServiceProvider(self.agent, 'https://example.com/verify')
        delegator = Delegator(self.transact)
        deferred = delegator.getUser(u'consumer', provider, authentication)

        [(request, responseDeferred)] = self.protocol.requests
        response = FakeResponse(ResponseDone(), dumps({'id': 1984245}))
        responseDeferred.callback(response)
        result = yield deferred
        self.assertTrue(result['access-token'])
        self.assertTrue(result['renewal-token'])
        del result['access-token']
        del result['renewal-token']
        self.assertEqual({'username': u'user',
                          'new-user': False,
                          'missing-password': True,
                          'uid': 1984245,
                          'data': {u'id': 1984245}},
                         result)
Esempio n. 5
0
    def testGetUser(self):
        """
        L{Delegator.getUser} returns a C{(User, data)} 2-tuple when the
        service provider successfully verifies credentials and a mapping
        between a Fluidinfo L{User} and the L{TwitterUser} being verified
        exists.
        """
        UserAPI().create([
            (u'consumer', 'secret', u'Consumer', u'*****@*****.**'),
            (u'user', 'secret', u'User', u'*****@*****.**')])
        TwitterUserAPI().create(u'user', 1984245)
        consumer = getUser(u'consumer')
        OAuthConsumerAPI().register(consumer)
        self.store.commit()

        self.agent._connect = self._connect
        authentication = 'OAuth oauth_consumer_key="...", ...'
        provider = ServiceProvider(self.agent, 'https://example.com/verify')
        delegator = Delegator(self.transact)
        deferred = delegator.getUser(u'consumer', provider, authentication)

        [(request, responseDeferred)] = self.protocol.requests
        response = FakeResponse(ResponseDone(), dumps({'id': 1984245}))
        responseDeferred.callback(response)
        result = yield deferred
        self.assertTrue(result['access-token'])
        self.assertTrue(result['renewal-token'])
        del result['access-token']
        del result['renewal-token']
        self.assertEqual({'username': u'user',
                          'new-user': False,
                          'missing-password': False,
                          'uid': 1984245,
                          'data': {u'id': 1984245}},
                         result)
Esempio n. 6
0
    def testVerifyCredentialsWithUnsuccessfulResponseCode(self):
        """
        L{ServiceProvider.verifyCredentials} fires an errback with a
        L{ServiceProviderError} exception if the service provider returns a
        code other than C{200 OK}.  The exception contains the HTTP status
        code and the payload, if any, that was sent by the service provider.
        """
        self.agent._connect = self._connect
        authentication = 'OAuth oauth_consumer_key="...", ...'
        provider = ServiceProvider(self.agent, 'https://example.com/verify')
        deferred = provider.verifyCredentials(authentication)

        [(request, responseDeferred)] = self.protocol.requests
        response = FakeResponse(ResponseDone(), 'Something bad happened',
                                code=BAD_REQUEST)
        responseDeferred.callback(response)
        error = yield self.assertFailure(deferred, ServiceProviderError)
        self.assertEqual(BAD_REQUEST, error.code)
        self.assertEqual('Something bad happened', error.payload)
Esempio n. 7
0
    def testVerifyCredentialsPassesOAuthEchoHeadersWithRequest(self):
        """
        L{ServiceProvider.verifyCredentials} makes a request to Twitter
        to verify credentials for the consumer, as part of the OAuth Echo
        process.  It includes an C{Authentication} response header with the
        OAuth Echo credentials provided by the consumer.
        """
        self.agent._connect = self._connect
        authentication = 'OAuth oauth_consumer_key="...", ...'
        provider = ServiceProvider(self.agent, 'https://example.com/verify')
        provider.verifyCredentials(authentication)

        [(request, responseDeferred)] = self.protocol.requests
        self.assertIsInstance(request, Request)
        self.assertEqual('GET', request.method)
        self.assertEqual('/verify', request.uri)
        self.assertEqual(Headers({'Authorization': [authentication],
                                  'Host': ['example.com']}),
                         request.headers)
Esempio n. 8
0
    def render_GET(self, request):
        """Handle an OAuth Echo request.

        Call the original service provider's endpoint to verify credentials
        (at least that's what Twitter calls it) and return the result, along
        with appropriate Fluidinfo-specific headers.  The client invoking this
        method is the consumer, Fluidinfo is the delegator and Twitter is the
        service provider, in the OAuth Echo process.

        A C{deferred} attribute is set on the instance for testing purposes.
        It will fire with the result of a call to L{Delegator.getUser}.

        @param request: The HTTP request.
        @return: Either an empty string (in the case of an error), or
            C{NOT_DONE_YET} to indicate processing is ongoing.
        """
        def succeeded(result):
            """
            Handle successful credentials verification with the
            L{ServiceProvider}.
            """
            # FIXME UTF-8 encode and base64 the username.
            username = result['username']
            if result['new-user']:
                request.setHeader('X-FluidDB-New-User', 'true')
            if result['missing-password']:
                request.setHeader('X-FluidDB-Missing-Password', 'true')
            encodedUsername = b64encode(username.encode('utf-8'))
            request.setHeader('X-FluidDB-Username', encodedUsername)
            request.setHeader('X-FluidDB-Access-Token', result['access-token'])
            request.setHeader('X-FluidDB-Renewal-Token',
                              result['renewal-token'])
            request.write(dumps(result['data']))
            request.setResponseCode(OK)
            request.finish()
            return result

        def failed(failure):
            """
            Handle a failure that occurred while attempting to verify
            credentials with the L{ServiceProvider}.
            """
            if failure.check(DuplicateUserError):
                logging.warning('Could not authenticate duplicate user:'******'utf-8'))
                request.setHeader('X-FluidDB-Username', encodedUsername)
                request.setHeader('X-FluidDB-Error-Class', 'UsernameConflict')
                request.setResponseCode(CONFLICT)
            else:
                logging.warning('Could not complete OAuth Echo request:')
                logging.exception(failure.value)
                request.setResponseCode(SERVICE_UNAVAILABLE)
            request.setHeader('X-FluidDB-Request-Id', self._session.id)
            request.finish()

        def crashed(failure):
            """
            Handle an unexpected failure that occurred while attempting to
            handle this request.
            """
            logging.error('Unexpected error handling OAuth Echo request:')
            logging.exception(failure.value)
            request.setResponseCode(INTERNAL_SERVER_ERROR)
            request.finish()

        try:
            url, authorization = self._getParameters(request)
        except OAuthEchoRequestError as error:
            request.setResponseCode(BAD_REQUEST)
            request.setHeader('X-FluidDB-Request-Id', self._session.id)
            request.setHeader('X-FluidDB-Error-Class', error.errorClass)
            if error.badHeader:
                request.setHeader('X-FluidDB-Header', error.badHeader)
            return ''
        else:
            consumerUsername = self._session.auth.username
            provider = ServiceProvider(self._agent, url)
            delegator = Delegator(self._session.transact)
            self.deferred = delegator.getUser(consumerUsername, provider,
                                              authorization)
            self.deferred.addCallbacks(succeeded, failed)
            self.deferred.addErrback(crashed)
            return NOT_DONE_YET