Create user under project_id passed in request
Currently when user is created, its taking the project_id parameter from the user who is creating the request. However, given root users are expected to be ablet to create users for all projects this patch modifies the behaviour and ensure that the user creation is always under the project_id parameter that is passed in. Functional test for create call is added. However, function test coverage is not complete. It needs to be addressed as a separate commit, tacked in issue: 1674287 Closes Bug: 1666695 Partial-Bug: 1674287 Parent: Ie5fac9ef4c305ff7e67fe32855ca8100a8adfa82 Change-Id: I19fb901ad41edeeb0a92f41264867a768a207fce
This commit is contained in:
parent
9ddf2c4cd5
commit
5f0e8d7622
|
@ -5,7 +5,6 @@ from oslo_utils import uuidutils
|
|||
from craton.api import v1
|
||||
from craton.api.v1 import base
|
||||
from craton import db as dbapi
|
||||
from craton import util
|
||||
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
@ -41,12 +40,14 @@ class Users(base.Resource):
|
|||
@base.http_codes
|
||||
def post(self, context, request_data):
|
||||
"""Create a new user. Requires project admin privileges."""
|
||||
json = util.copy_project_id_into_json(context, request_data)
|
||||
project_id = json["project_id"]
|
||||
# NOTE(sulo): Instead of using context project_id from
|
||||
# header, here we always ensure, user create gets project_id
|
||||
# from request param.
|
||||
project_id = request_data["project_id"]
|
||||
dbapi.projects_get_by_id(context, project_id)
|
||||
api_key = uuidutils.generate_uuid()
|
||||
request_data["api_key"] = api_key
|
||||
user_obj = dbapi.users_create(context, json)
|
||||
user_obj = dbapi.users_create(context, request_data)
|
||||
|
||||
location = v1.api.url_for(
|
||||
UserById, id=user_obj.id, _external=True
|
||||
|
|
|
@ -399,6 +399,7 @@ DefinitionUser = {
|
|||
DefinitionUserCreate = {
|
||||
"required": [
|
||||
"username",
|
||||
"project_id",
|
||||
],
|
||||
"type": "object",
|
||||
"additionalProperties": False,
|
||||
|
|
|
@ -9,6 +9,8 @@ import testtools
|
|||
import threading
|
||||
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
@ -266,6 +268,22 @@ class TestCase(testtools.TestCase):
|
|||
self.assertJSON(resp)
|
||||
return resp
|
||||
|
||||
def create_project(self, name, headers=None, variables=None):
|
||||
url = self.url + '/v1/projects'
|
||||
payload = {'name': name}
|
||||
if variables:
|
||||
payload['variables'] = variables
|
||||
response = self.post(url, headers=headers, data=payload)
|
||||
self.assertEqual(201, response.status_code)
|
||||
self.assertIn('Location', response.headers)
|
||||
project = response.json()
|
||||
self.assertTrue(uuidutils.is_uuid_like(project['id']))
|
||||
self.assertEqual(
|
||||
response.headers['Location'],
|
||||
"{}/{}".format(url, project['id'])
|
||||
)
|
||||
return project
|
||||
|
||||
def create_cloud(self, name, variables=None):
|
||||
url = self.url + '/v1/clouds'
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import copy
|
||||
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from craton.tests import functional
|
||||
from craton.tests.functional.test_variable_calls import \
|
||||
APIV1ResourceWithVariablesTestCase
|
||||
|
@ -20,29 +18,13 @@ class ProjectTests(functional.TestCase):
|
|||
def tearDown(self):
|
||||
super(ProjectTests, self).tearDown()
|
||||
|
||||
def create_project(self, name, variables=None):
|
||||
url = self.url + '/v1/projects'
|
||||
payload = {'name': name}
|
||||
if variables:
|
||||
payload['variables'] = variables
|
||||
response = self.post(url, headers=self.root_headers, data=payload)
|
||||
self.assertEqual(201, response.status_code)
|
||||
self.assertIn('Location', response.headers)
|
||||
project = response.json()
|
||||
self.assertTrue(uuidutils.is_uuid_like(project['id']))
|
||||
self.assertEqual(
|
||||
response.headers['Location'],
|
||||
"{}/{}".format(url, project['id'])
|
||||
)
|
||||
|
||||
return project
|
||||
|
||||
|
||||
class TestPaginationOfProjects(ProjectTests):
|
||||
def setUp(self):
|
||||
super(TestPaginationOfProjects, self).setUp()
|
||||
self.projects = [
|
||||
self.create_project('project-{}'.format(i))
|
||||
self.create_project('project-{}'.format(i),
|
||||
headers=self.root_headers)
|
||||
for i in range(0, 61)
|
||||
]
|
||||
|
||||
|
@ -56,7 +38,7 @@ class TestPaginationOfProjects(ProjectTests):
|
|||
self.assertEqual(30, len(projects))
|
||||
|
||||
def test_lists_projects_with_the_same_name(self):
|
||||
self.create_project('project-0')
|
||||
self.create_project('project-0', headers=self.root_headers)
|
||||
|
||||
response = self.get(self.url + '/v1/projects',
|
||||
name='project-0',
|
||||
|
@ -73,19 +55,22 @@ class APIV1ProjectTest(ProjectTests, APIV1ResourceWithVariablesTestCase):
|
|||
def test_project_create_with_variables(self):
|
||||
variables = {'a': 'b'}
|
||||
project_name = 'test'
|
||||
project = self.create_project(project_name, variables=variables)
|
||||
project = self.create_project(project_name,
|
||||
headers=self.root_headers,
|
||||
variables=variables)
|
||||
self.assertEqual(project_name, project['name'])
|
||||
self.assertEqual(variables, project['variables'])
|
||||
|
||||
def test_create_project_supports_vars_ops(self):
|
||||
project = self.create_project('test', {'a': 'b'})
|
||||
project = self.create_project('test', headers=self.root_headers,
|
||||
variables={'a': 'b'})
|
||||
self.assert_vars_get_expected(project['id'], {'a': 'b'})
|
||||
self.assert_vars_can_be_set(project['id'])
|
||||
self.assert_vars_can_be_deleted(project['id'])
|
||||
|
||||
def test_project_create_with_duplicate_name_works(self):
|
||||
project_name = 'test'
|
||||
self.create_project(project_name)
|
||||
self.create_project(project_name, headers=self.root_headers)
|
||||
url = self.url + '/v1/projects'
|
||||
payload = {'name': project_name}
|
||||
project = self.post(url, headers=self.root_headers, data=payload)
|
||||
|
@ -94,9 +79,9 @@ class APIV1ProjectTest(ProjectTests, APIV1ResourceWithVariablesTestCase):
|
|||
def test_project_get_all_with_name_filter(self):
|
||||
proj1 = 'test1'
|
||||
proj2 = 'test2'
|
||||
self.create_project(proj2)
|
||||
self.create_project(proj2, headers=self.root_headers)
|
||||
for i in range(3):
|
||||
self.create_project(proj1)
|
||||
self.create_project(proj1, headers=self.root_headers)
|
||||
url = self.url + '/v1/projects?name={}'.format(proj1)
|
||||
resp = self.get(url, headers=self.root_headers)
|
||||
projects = resp.json()['projects']
|
||||
|
@ -107,14 +92,15 @@ class APIV1ProjectTest(ProjectTests, APIV1ResourceWithVariablesTestCase):
|
|||
def test_get_project_details(self):
|
||||
project_name = 'test'
|
||||
project_vars = {"who": "that"}
|
||||
project = self.create_project(project_name, variables=project_vars)
|
||||
project = self.create_project(project_name, headers=self.root_headers,
|
||||
variables=project_vars)
|
||||
url = self.url + '/v1/projects/{}'.format(project['id'])
|
||||
project_with_detail = self.get(url, headers=self.root_headers)
|
||||
self.assertEqual(project_name, project_with_detail.json()['name'])
|
||||
self.assertEqual(project_vars, project_with_detail.json()['variables'])
|
||||
|
||||
def test_project_delete(self):
|
||||
project1 = self.create_project('test1')
|
||||
project1 = self.create_project('test1', headers=self.root_headers)
|
||||
url = self.url + '/v1/projects'
|
||||
projects = self.get(url, headers=self.root_headers)
|
||||
# NOTE(thomasem): Have to include the default project created by
|
||||
|
@ -129,7 +115,7 @@ class APIV1ProjectTest(ProjectTests, APIV1ResourceWithVariablesTestCase):
|
|||
|
||||
def test_project_variables_update(self):
|
||||
project_name = 'test'
|
||||
project = self.create_project(project_name)
|
||||
project = self.create_project(project_name, headers=self.root_headers)
|
||||
variables = {"bumbleywump": "cucumberpatch"}
|
||||
|
||||
put_url = self.url + '/v1/projects/{}/variables'.format(project['id'])
|
||||
|
@ -149,6 +135,7 @@ class APIV1ProjectTest(ProjectTests, APIV1ResourceWithVariablesTestCase):
|
|||
expected_vars = {'foo': 'bar'}
|
||||
variables.update(expected_vars)
|
||||
|
||||
project = self.create_project(project_name, variables=variables)
|
||||
project = self.create_project(project_name, headers=self.root_headers,
|
||||
variables=variables)
|
||||
self.assert_vars_get_expected(project['id'], variables)
|
||||
self.assert_vars_can_be_deleted(project['id'])
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
import copy
|
||||
|
||||
from craton.tests import functional
|
||||
|
||||
|
||||
class UserTests(functional.TestCase):
|
||||
def setUp(self):
|
||||
super(UserTests, self).setUp()
|
||||
self.root_headers = copy.deepcopy(self.session.headers)
|
||||
self.root_headers[functional.HEADER_USERNAME] = \
|
||||
functional.FAKE_DATA_GEN_BOOTSTRAP_USERNAME
|
||||
self.root_headers[functional.HEADER_TOKEN] = \
|
||||
functional.FAKE_DATA_GEN_BOOTSTRAP_TOKEN
|
||||
|
||||
def tearDown(self):
|
||||
super(UserTests, self).tearDown()
|
||||
|
||||
def test_create_user(self):
|
||||
project = self.create_project('test', headers=self.root_headers)
|
||||
url = self.url + '/v1/users'
|
||||
payload = {'username': 'testuser', 'project_id': project['id']}
|
||||
user = self.post(url, data=payload)
|
||||
self.assertEqual(201, user.status_code)
|
||||
self.assertEqual(payload['username'], user.json()['username'])
|
||||
self.assertEqual(payload['project_id'], user.json()['project_id'])
|
||||
|
||||
def test_create_user_with_admin_priv(self):
|
||||
project = self.create_project('test', headers=self.root_headers)
|
||||
url = self.url + '/v1/users'
|
||||
payload = {'username': 'testuser', 'project_id': project['id'],
|
||||
'is_admin': True}
|
||||
user = self.post(url, headers=self.root_headers, data=payload)
|
||||
self.assertEqual(201, user.status_code)
|
||||
self.assertEqual(payload['username'], user.json()['username'])
|
||||
self.assertEqual(payload['is_admin'], user.json()['is_admin'])
|
||||
|
||||
def test_create_user_with_no_project_id_fails(self):
|
||||
url = self.url + '/v1/users'
|
||||
payload = {'username': 'testuser'}
|
||||
user = self.post(url, headers=self.root_headers, data=payload)
|
||||
self.assertEqual(400, user.status_code)
|
|
@ -1241,7 +1241,8 @@ class APIV1UsersTest(APIV1Test):
|
|||
def test_create_users(self, mock_project, mock_user):
|
||||
mock_project.return_value = {'id': project_id1, 'name': 'project1'}
|
||||
mock_user.return_value = fake_resources.USER1
|
||||
data = {'username': 'user1', 'is_admin': False}
|
||||
data = {'username': 'user1', 'is_admin': False,
|
||||
'project_id': project_id1}
|
||||
resp = self.post('v1/users', data=data)
|
||||
self.assertEqual(resp.status_code, 201)
|
||||
self.assertEqual(resp.json['id'], 1)
|
||||
|
|
Loading…
Reference in New Issue