diff --git a/refstack/api/controllers/results.py b/refstack/api/controllers/results.py index 19b3f07e..35727634 100644 --- a/refstack/api/controllers/results.py +++ b/refstack/api/controllers/results.py @@ -149,6 +149,18 @@ class ResultsController(validation.BaseRestControllerWithValidation): 'upload your key.') test_['meta'][const.USER] = pubkey.openid + if test.get('cpid'): + version = db.get_product_version_by_cpid( + test['cpid'], allowed_keys=['id', 'product_id']) + # Only auto-associate if there is a single product version + # with the given cpid. + if len(version) == 1: + is_foundation = api_utils.check_user_is_foundation_admin( + pubkey.openid) + is_product_admin = api_utils.check_user_is_product_admin( + version[0]['product_id'], pubkey.openid) + if is_foundation or is_product_admin: + test_['product_version_id'] = version[0]['id'] test_id = db.store_results(test_) return {'test_id': test_id, 'url': parse.urljoin(CONF.ui_url, diff --git a/refstack/api/utils.py b/refstack/api/utils.py index 2af24cc7..9c1d75f1 100644 --- a/refstack/api/utils.py +++ b/refstack/api/utils.py @@ -342,25 +342,25 @@ def verify_openid_request(request): return True -def check_user_is_foundation_admin(): +def check_user_is_foundation_admin(user_id=None): """Check is user in foundation group or not.""" - user = get_user_id() + user = user_id if user_id else get_user_id() org_users = db.get_foundation_users() return user in org_users -def check_user_is_vendor_admin(vendor_id): +def check_user_is_vendor_admin(vendor_id, user_id=None): """Check is user in vendor group or not.""" - user = get_user_id() + user = user_id if user_id else get_user_id() org_users = db.get_organization_users(vendor_id) return user in org_users -def check_user_is_product_admin(product_id): +def check_user_is_product_admin(product_id, user_id=None): """Check if the current user is in the vendor group for a product.""" product = db.get_product(product_id) vendor_id = product['organization_id'] - return check_user_is_vendor_admin(vendor_id) + return check_user_is_vendor_admin(vendor_id, user_id=user_id) def decode_token(request): diff --git a/refstack/db/api.py b/refstack/db/api.py index 8e5b2adf..a509f4f3 100644 --- a/refstack/db/api.py +++ b/refstack/db/api.py @@ -269,6 +269,11 @@ def get_product_version(product_version_id, allowed_keys=None): allowed_keys=allowed_keys) +def get_product_version_by_cpid(cpid, allowed_keys=None): + """Get a product version given a cloud provider id.""" + return IMPL.get_product_version_by_cpid(cpid, allowed_keys=allowed_keys) + + def get_product_versions(product_id, allowed_keys=None): """Get all versions for a product.""" return IMPL.get_product_versions(product_id, allowed_keys=allowed_keys) diff --git a/refstack/db/sqlalchemy/api.py b/refstack/db/sqlalchemy/api.py index 8ce709f3..d1e02e51 100644 --- a/refstack/db/sqlalchemy/api.py +++ b/refstack/db/sqlalchemy/api.py @@ -116,6 +116,7 @@ def store_results(results): test.id = test_id test.cpid = results.get('cpid') test.duration_seconds = results.get('duration_seconds') + test.product_version_id = results.get('product_version_id') session = get_session() with session.begin(): for result in results.get('results', []): @@ -669,6 +670,16 @@ def get_product_version(product_version_id, allowed_keys=None): return _to_dict(version, allowed_keys=allowed_keys) +def get_product_version_by_cpid(cpid, allowed_keys=None): + """Get a product version given a cloud provider id.""" + session = get_session() + version = ( + session.query(models.ProductVersion) + .filter_by(cpid=cpid).all() + ) + return _to_dict(version, allowed_keys=allowed_keys) + + def get_product_versions(product_id, allowed_keys=None): """Get all versions for a product.""" session = get_session() diff --git a/refstack/tests/unit/test_api.py b/refstack/tests/unit/test_api.py index deb21b15..ecbf4fcb 100644 --- a/refstack/tests/unit/test_api.py +++ b/refstack/tests/unit/test_api.py @@ -160,25 +160,34 @@ class ResultsControllerTestCase(BaseControllerTestCase): self.assertEqual(self.mock_response.status, 201) mock_store_results.assert_called_once_with({'answer': 42}) + @mock.patch('refstack.api.utils.check_user_is_foundation_admin') + @mock.patch('refstack.api.utils.check_user_is_product_admin') + @mock.patch('refstack.db.get_product_version_by_cpid') @mock.patch('refstack.db.store_results') @mock.patch('refstack.db.get_pubkey') - def test_post_with_sign(self, mock_get_pubkey, mock_store_results): - self.mock_request.body = '{"answer": 42}' + def test_post_with_sign(self, mock_get_pubkey, mock_store_results, + mock_get_version, mock_check, mock_foundation): + self.mock_request.body = '{"answer": 42, "cpid": "123"}' self.mock_request.headers = { 'X-Signature': 'fake-sign', 'X-Public-Key': 'ssh-rsa Zm9vIGJhcg==' } mock_get_pubkey.return_value.openid = 'fake_openid' - + mock_get_version.return_value = [{'id': 'ver1', + 'product_id': 'prod1'}] + mock_check.return_value = True + mock_foundation.return_value = False mock_store_results.return_value = 'fake_test_id' result = self.controller.post() self.assertEqual(result, {'test_id': 'fake_test_id', 'url': self.test_results_url % 'fake_test_id'}) self.assertEqual(self.mock_response.status, 201) + mock_check.assert_called_once_with('prod1', 'fake_openid') mock_store_results.assert_called_once_with( - {'answer': 42, 'meta': {const.USER: 'fake_openid'}} + {'answer': 42, 'cpid': '123', 'product_version_id': 'ver1', + 'meta': {const.USER: 'fake_openid'}} ) @mock.patch('refstack.db.get_test')