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))
def testRenderWithUserConflict(self): """ A C{CONFLICT} HTTP status code is returned if the authorization is successfully verified by the service provider, but the username clashes with an existing L{User} that isn't linked to the Twitter UID. The offending username is returned UTF-8 and base64 encoded. """ username = u'john\N{HIRAGANA LETTER A}' UserAPI().create([(username, 'secret', u'John', u'*****@*****.**')]) self.store.commit() self.agent._connect = self._connect headers = { 'X-Verify-Credentials-Authorization': ['OAuth ...'], 'X-Auth-Service-Provider': [TWITTER_URL] } request = FakeRequest(headers=Headers(headers)) with login(u'anon', self.anonymous.objectID, self.transact) as session: resource = OAuthEchoResource(session, self.agent) self.assertEqual(NOT_DONE_YET, resource.render_GET(request)) [(_, responseDeferred)] = self.protocol.requests data = {'id': 1984245, 'screen_name': username, 'name': u'John'} response = FakeResponse(ResponseDone(), dumps(data)) responseDeferred.callback(response) yield resource.deferred self.assertEqual(CONFLICT, request.code) headers = dict(request.responseHeaders.getAllRawHeaders()) encodedUsername = b64encode(username.encode('utf-8')) self.assertEqual( { 'X-Fluiddb-Error-Class': ['UsernameConflict'], 'X-Fluiddb-Username': [encodedUsername], 'X-Fluiddb-Request-Id': [session.id] }, headers)
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)
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)
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)
def testRenderWithNewUser(self): """ Missing L{User}s are created automatically and linked to L{TwitterUser}s for authorized UIDs. """ self.assertNotIn(u'john', UserAPI().get([u'john'])) self.store.commit() self.agent._connect = self._connect headers = { 'X-Verify-Credentials-Authorization': ['OAuth ...'], 'X-Auth-Service-Provider': [TWITTER_URL] } request = FakeRequest(headers=Headers(headers)) with login(u'anon', self.anonymous.objectID, self.transact) as session: resource = OAuthEchoResource(session, self.agent) self.assertEqual(NOT_DONE_YET, resource.render_GET(request)) [(_, responseDeferred)] = self.protocol.requests data = {'id': 1984245, 'screen_name': u'john', 'name': u'John'} response = FakeResponse(ResponseDone(), dumps(data)) responseDeferred.callback(response) result = yield resource.deferred self.assertTrue(result['access-token']) self.assertTrue(result['renewal-token']) del result['access-token'] del result['renewal-token'] self.assertEqual( { 'username': u'john', 'new-user': True, 'missing-password': True, 'data': data, 'uid': 1984245 }, result) self.assertEqual(OK, request.code) self.assertEqual(data, loads(request.written.getvalue())) headers = dict(request.responseHeaders.getAllRawHeaders()) self.assertTrue(headers['X-Fluiddb-Access-Token']) self.assertTrue(headers['X-Fluiddb-Renewal-Token']) del headers['X-Fluiddb-Access-Token'] del headers['X-Fluiddb-Renewal-Token'] self.assertEqual( { 'X-Fluiddb-New-User': ['true'], 'X-Fluiddb-Missing-Password': ['true'], 'X-Fluiddb-Username': ['am9obg=='] }, # username is in base64. headers) self.store.rollback() self.assertIn(u'john', UserAPI().get([u'john']))
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'])
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)
def testRenderWithSuccessfulVerification(self): """ An C{OK} HTTP status code is returned if the authorization is successfully verified by the service provider. The results of the call to the service provider to verify credentials are returned to the user. """ UserAPI().create([(u'john', 'secret', u'John', u'*****@*****.**')]) TwitterUserAPI().create(u'john', 1984245) self.store.commit() self.agent._connect = self._connect headers = { 'X-Verify-Credentials-Authorization': ['OAuth ...'], 'X-Auth-Service-Provider': [TWITTER_URL] } request = FakeRequest(headers=Headers(headers)) with login(u'anon', self.anonymous.objectID, self.transact) as session: resource = OAuthEchoResource(session, self.agent) self.assertEqual(NOT_DONE_YET, resource.render_GET(request)) [(_, responseDeferred)] = self.protocol.requests data = {'id': 1984245, 'screen_name': u'john', 'name': u'John'} response = FakeResponse(ResponseDone(), dumps(data)) responseDeferred.callback(response) result = yield resource.deferred self.assertTrue(result['access-token']) self.assertTrue(result['renewal-token']) del result['access-token'] del result['renewal-token'] self.assertEqual( { 'username': u'john', 'new-user': False, 'missing-password': False, 'data': data, 'uid': 1984245 }, result) self.assertEqual(OK, request.code) self.assertEqual(data, loads(request.written.getvalue()))
def testRenderWithFailingServiceProviderCall(self): """ A C{SERVICE_UNAVAILABLE} HTTP status code is returned if an error occurs while communicating with the L{ServiceProvider}. """ UserAPI().create([(u'user', 'secret', u'User', u'*****@*****.**')]) TwitterUserAPI().create(u'user', 1984245) self.store.commit() self.agent._connect = self._connect headers = { 'X-Verify-Credentials-Authorization': ['OAuth ...'], 'X-Auth-Service-Provider': [TWITTER_URL] } request = FakeRequest(headers=Headers(headers)) with login(u'anon', self.anonymous.objectID, self.transact) as session: resource = OAuthEchoResource(session, self.agent) self.assertEqual(NOT_DONE_YET, resource.render_GET(request)) [(_, responseDeferred)] = self.protocol.requests response = FakeResponse(RuntimeError(), None) responseDeferred.callback(response) yield resource.deferred self.assertEqual(SERVICE_UNAVAILABLE, request.code)