From dbf101f69dcc0603f8746bdc357220634a562c26 Mon Sep 17 00:00:00 2001 From: Tin Lam Date: Fri, 29 Jul 2016 05:45:00 +0000 Subject: [PATCH] Add schema validation to v2 update tenant Partially implements: bp schema-validation-extent Change-Id: I57c29d1b988a44c031932f544f628d15f44954e6 --- keystone/resource/controllers.py | 9 +-- keystone/resource/core.py | 3 - keystone/resource/schema.py | 14 ++++ keystone/tests/unit/resource/test_backends.py | 14 ---- keystone/tests/unit/test_v2_validation.py | 73 +++++++++++++++++++ 5 files changed, 90 insertions(+), 23 deletions(-) diff --git a/keystone/resource/controllers.py b/keystone/resource/controllers.py index d639f6ecef..2523e8dee9 100644 --- a/keystone/resource/controllers.py +++ b/keystone/resource/controllers.py @@ -103,16 +103,13 @@ class Tenant(controller.V2Controller): @controller.v2_deprecated def update_project(self, request, tenant_id, tenant): + validation.lazy_validate(schema.tenant_update, tenant) self.assert_admin(request) self._assert_not_is_domain_project(tenant_id) - # Remove domain_id and is_domain if specified - a v2 api caller - # should not be specifying that - clean_tenant = tenant.copy() - clean_tenant.pop('domain_id', None) - clean_tenant.pop('is_domain', None) + initiator = notifications._get_request_audit_info(request.context_dict) tenant_ref = self.resource_api.update_project( - tenant_id, clean_tenant, initiator) + tenant_id, tenant, initiator) return {'tenant': self.v3_to_v2_project(tenant_ref)} @controller.v2_deprecated diff --git a/keystone/resource/core.py b/keystone/resource/core.py index d23a157195..abd4e89cc7 100644 --- a/keystone/resource/core.py +++ b/keystone/resource/core.py @@ -359,9 +359,6 @@ class Manager(manager.Manager): 'and will be removed in O.') ) - if 'enabled' in project: - project['enabled'] = clean.project_enabled(project['enabled']) - original_project_enabled = original_project.get('enabled', True) project_enabled = project.get('enabled', True) if not original_project_enabled and project_enabled: diff --git a/keystone/resource/schema.py b/keystone/resource/schema.py index ef1f5df260..865f567659 100644 --- a/keystone/resource/schema.py +++ b/keystone/resource/schema.py @@ -87,3 +87,17 @@ tenant_create = { }, 'additionalProperties': True } + +tenant_update = { + 'type': 'object', + 'properties': _tenant_properties, + 'not': { + 'anyOf': [ + {'required': ['is_domain']}, + {'required': ['domain_id']} + ] + }, + 'tenantId': validation.nullable(parameter_types.id_string), + 'minProperties': 1, + 'additionalProperties': True +} diff --git a/keystone/tests/unit/resource/test_backends.py b/keystone/tests/unit/resource/test_backends.py index e64f0121c5..a842b657e3 100644 --- a/keystone/tests/unit/resource/test_backends.py +++ b/keystone/tests/unit/resource/test_backends.py @@ -338,20 +338,6 @@ class ResourceTests(object): project['id'], project) - def test_update_project_invalid_enabled_type_string(self): - project = unit.new_project_ref( - domain_id=CONF.identity.default_domain_id) - self.resource_api.create_project(project['id'], project) - project_ref = self.resource_api.get_project(project['id']) - self.assertTrue(project_ref['enabled']) - - # Strings are not valid boolean values - project['enabled'] = "false" - self.assertRaises(exception.ValidationError, - self.resource_api.update_project, - project['id'], - project) - def test_create_project_invalid_domain_id(self): project = unit.new_project_ref(domain_id=uuid.uuid4().hex) self.assertRaises(exception.DomainNotFound, diff --git a/keystone/tests/unit/test_v2_validation.py b/keystone/tests/unit/test_v2_validation.py index 4e9c7b4da5..c89d1f93b9 100644 --- a/keystone/tests/unit/test_v2_validation.py +++ b/keystone/tests/unit/test_v2_validation.py @@ -78,8 +78,11 @@ class TenantValidationTestCase(unit.BaseTestCase): def setUp(self): super(TenantValidationTestCase, self).setUp() schema_tenant_create = resource_schema.tenant_create + schema_tenant_update = resource_schema.tenant_update self.create_validator = validators.SchemaValidator( schema_tenant_create) + self.update_validator = validators.SchemaValidator( + schema_tenant_update) def test_validate_tenant_create_success(self): request = { @@ -156,3 +159,73 @@ class TenantValidationTestCase(unit.BaseTestCase): self.assertRaises(exception.SchemaValidationError, self.create_validator.validate, request) + + def test_validate_tenant_update_success(self): + request = { + 'name': uuid.uuid4().hex, + 'description': 'Test tenant', + 'enabled': True + } + self.update_validator.validate(request) + + def test_validate_tenant_update_success_with_optional_ids(self): + request = { + 'name': uuid.uuid4().hex, + 'description': 'Test tenant', + 'enabled': True, + 'tenantId': uuid.uuid4().hex, + 'id': uuid.uuid4().hex + } + self.update_validator.validate(request) + + def test_validate_tenant_update_with_domain_id(self): + request = { + 'name': uuid.uuid4().hex, + 'domain_id': uuid.uuid4().hex + } + self.assertRaises(exception.SchemaValidationError, + self.update_validator.validate, + request) + + def test_validate_tenant_update_with_is_domain(self): + request = { + 'name': uuid.uuid4().hex, + 'is_domain': False + } + self.assertRaises(exception.SchemaValidationError, + self.update_validator.validate, + request) + + def test_validate_tenant_update_with_empty_request(self): + request = {} + self.assertRaises(exception.SchemaValidationError, + self.update_validator.validate, + request) + + def test_validate_tenant_update_fails_with_invalid_name(self): + """Exception when validating an update request with invalid `name`.""" + for invalid_name in _INVALID_NAMES: + request = {'name': invalid_name} + self.assertRaises(exception.SchemaValidationError, + self.update_validator.validate, + request) + + def test_validate_tenant_update_with_enabled(self): + """Validate `enabled` as boolean-like values.""" + for valid_enabled in _VALID_ENABLED_FORMATS: + request = { + 'name': uuid.uuid4().hex, + 'enabled': valid_enabled + } + self.update_validator.validate(request) + + def test_validate_tenant_update_with_invalid_enabled_fails(self): + """Exception is raised when `enabled` isn't a boolean-like value.""" + for invalid_enabled in _INVALID_ENABLED_FORMATS: + request = { + 'name': uuid.uuid4().hex, + 'enabled': invalid_enabled + } + self.assertRaises(exception.SchemaValidationError, + self.update_validator.validate, + request)