diff --git a/pillar/application/modules/blender_id.py b/pillar/application/modules/blender_id.py index 629b1e79..102b162b 100644 --- a/pillar/application/modules/blender_id.py +++ b/pillar/application/modules/blender_id.py @@ -4,7 +4,7 @@ import logging from pprint import pformat import requests -from flask import Blueprint, request, current_app, abort +from flask import Blueprint, request, current_app, abort, jsonify from eve.methods.post import post_internal from eve.methods.put import put_internal @@ -18,7 +18,7 @@ log = logging.getLogger(__name__) def store_subclient_token(): """Verifies & stores a user's subclient-specific token.""" - user_id = request.form['user_id'] + user_id = request.form['user_id'] # User ID at BlenderID scst = request.form['scst'] # Verify with Blender ID @@ -27,23 +27,28 @@ def store_subclient_token(): if user_info is None: log.warning('Unable to verify subclient token with Blender ID.') - return 'BLENDER ID ERROR', 403 + return jsonify({'status': 'fail', + 'error': 'BLENDER ID ERROR'}), 403 # Store the user info in MongoDB. log.info('Obtained user info from Blender ID: %s', user_info) db_user = find_user_in_db(user_id, scst, **user_info) - log.debug('Storing updated/created user:\n%s', pformat(db_user)) if '_id' in db_user: + # Update the existing user db_id = db_user['_id'] r, _, _, status = put_internal('users', remove_private_keys(db_user), _id=db_id) else: + # Create a new user r, _, _, status = post_internal('users', db_user) - if status != 200: + db_id = r['_id'] + + if status not in (200, 201): log.error('internal response: %r %r', status, r) return abort(500) - return 'OK', 200 + return jsonify({'status': 'success', + 'subclient_user_id': str(db_id)}), status def validate_subclient_token(user_id, scst): diff --git a/requirements.txt b/requirements.txt index 3270350a..b89cd648 100644 --- a/requirements.txt +++ b/requirements.txt @@ -26,3 +26,4 @@ zencoder==0.6.5 # development requirements httpretty==0.8.14 pytest==2.9.1 +responses==0.5.1 diff --git a/tests/common_test_class.py b/tests/common_test_class.py index d69d43d0..f516d8ba 100644 --- a/tests/common_test_class.py +++ b/tests/common_test_class.py @@ -3,6 +3,7 @@ import copy import sys import logging import os +import base64 from bson import ObjectId from eve.tests import TestMinimal @@ -101,3 +102,7 @@ class AbstractPillarTest(TestMinimal): 'status': 'success'}), content_type="application/json") + def make_header(self, username, password=''): + """Returns a Basic HTTP Authentication header value.""" + + return 'basic ' + base64.b64encode('%s:%s' % (username, password)) diff --git a/tests/test_auth.py b/tests/test_auth.py index 526d6704..bc0abafc 100644 --- a/tests/test_auth.py +++ b/tests/test_auth.py @@ -1,15 +1,8 @@ -import base64 import httpretty from common_test_class import AbstractPillarTest, TEST_EMAIL_USER, TEST_EMAIL_ADDRESS -def make_header(username, password=''): - """Returns a Basic HTTP Authentication header value.""" - - return 'basic ' + base64.b64encode('%s:%s' % (username, password)) - - class AuthenticationTests(AbstractPillarTest): def test_make_unique_username(self): from application.utils import authentication as auth @@ -36,7 +29,8 @@ class AuthenticationTests(AbstractPillarTest): from application.utils import authentication as auth self.htp_blenderid_validate_unhappy() - with self.app.test_request_context(headers={'Authorization': make_header('unknowntoken')}): + with self.app.test_request_context( + headers={'Authorization': self.make_header('unknowntoken')}): self.assertFalse(auth.validate_token()) @httpretty.activate @@ -46,5 +40,6 @@ class AuthenticationTests(AbstractPillarTest): from application.utils import authentication as auth self.htp_blenderid_validate_happy() - with self.app.test_request_context(headers={'Authorization': make_header('knowntoken')}): + with self.app.test_request_context( + headers={'Authorization': self.make_header('knowntoken')}): self.assertTrue(auth.validate_token()) diff --git a/tests/test_blender_id_subclient.py b/tests/test_blender_id_subclient.py new file mode 100644 index 00000000..7e252364 --- /dev/null +++ b/tests/test_blender_id_subclient.py @@ -0,0 +1,55 @@ +# -*- encoding: utf-8 -*- + +import responses +import json + +from bson import ObjectId + +from common_test_class import AbstractPillarTest + +TEST_FULL_NAME = u'врач Сергей' +TEST_EMAIL = 'jemoeder@example.com' +TEST_SUBCLIENT_TOKEN = 'my-subclient-token-for-pillar' +BLENDER_ID_TEST_USERID = 1896 +BLENDER_ID_USER_RESPONSE = {'status': 'success', + 'user': {'email': TEST_EMAIL, 'full_name': TEST_FULL_NAME}} + + +class BlenderIdSubclientTest(AbstractPillarTest): + @responses.activate + def test_store_scst_new_user(self): + self._common_user_test(201) + + @responses.activate + def test_store_scst_existing_user(self): + # Make sure the user exists in our database. + from application.utils.authentication import create_new_user + with self.app.test_request_context(): + create_new_user(TEST_EMAIL, 'apekoppie', BLENDER_ID_TEST_USERID) + + self._common_user_test(200) + + def _common_user_test(self, expected_status_code): + responses.add(responses.POST, + '%s/subclients/validate_token' % self.app.config['BLENDER_ID_ENDPOINT'], + json=BLENDER_ID_USER_RESPONSE, + status=200) + + resp = self.client.post('/blender_id/store_scst', + data={'user_id': BLENDER_ID_TEST_USERID, + 'scst': TEST_SUBCLIENT_TOKEN}) + self.assertEqual(expected_status_code, resp.status_code) + + user_info = json.loads(resp.data) # {'status': 'success', 'subclient_user_id': '...'} + self.assertEqual('success', user_info['status']) + # Check that the user was correctly updated + with self.app.test_request_context(): + users = self.app.data.driver.db['users'] + db_user = users.find_one(ObjectId(user_info['subclient_user_id'])) + self.assertIsNotNone(db_user, 'user %r not found' % user_info['subclient_user_id']) + + self.assertEqual(TEST_EMAIL, db_user['email']) + self.assertEqual(TEST_FULL_NAME, db_user['full_name']) + self.assertEqual(TEST_SUBCLIENT_TOKEN, db_user['auth'][0]['token']) + self.assertEqual(str(BLENDER_ID_TEST_USERID), db_user['auth'][0]['user_id']) + self.assertEqual('blender-id', db_user['auth'][0]['provider'])