From 88713cce119c5f6a9f5b943de7cec49092cfebd4 Mon Sep 17 00:00:00 2001 From: Lance Bragstad Date: Wed, 20 Apr 2016 00:16:10 +0000 Subject: [PATCH] Separate protocol schema Currently, the protocol entity is validated using the same schema regardless of the request creating or updating a protocol. All other schemas in keystone break the schemas into create and update schemas. This applies that same convention to the federated protocol entities. Change-Id: Ic6f481cdb4147c2068c4378cf9e398a3db6eeb63 --- keystone/federation/controllers.py | 4 +- keystone/federation/schema.py | 18 ++++++--- keystone/tests/unit/test_validation.py | 51 +++++++++++++++++++++----- 3 files changed, 57 insertions(+), 16 deletions(-) diff --git a/keystone/federation/controllers.py b/keystone/federation/controllers.py index 5746e46837..6dc9de1ed4 100644 --- a/keystone/federation/controllers.py +++ b/keystone/federation/controllers.py @@ -178,7 +178,7 @@ class FederationProtocol(_ControllerBase): return {cls.member_name: ref} @controller.protected() - @validation.validated(schema.federation_protocol_schema, 'protocol') + @validation.validated(schema.protocol_create, 'protocol') def create_protocol(self, context, idp_id, protocol_id, protocol): ref = self._normalize_dict(protocol) ref = self.federation_api.create_protocol(idp_id, protocol_id, ref) @@ -186,7 +186,7 @@ class FederationProtocol(_ControllerBase): return wsgi.render_response(body=response, status=('201', 'Created')) @controller.protected() - @validation.validated(schema.federation_protocol_schema, 'protocol') + @validation.validated(schema.protocol_update, 'protocol') def update_protocol(self, context, idp_id, protocol_id, protocol): ref = self._normalize_dict(protocol) ref = self.federation_api.update_protocol(idp_id, protocol_id, diff --git a/keystone/federation/schema.py b/keystone/federation/schema.py index 6cdfd1f58c..0159d39780 100644 --- a/keystone/federation/schema.py +++ b/keystone/federation/schema.py @@ -104,12 +104,20 @@ identity_provider_update = { 'additionalProperties': False } -federation_protocol_schema = { +_protocol_properties = { + 'mapping_id': parameter_types.mapping_id_string +} + +protocol_create = { 'type': 'object', - 'properties': { - 'mapping_id': parameter_types.mapping_id_string - }, - # `mapping_id` is the property that cannot be ignored + 'properties': _protocol_properties, + 'required': ['mapping_id'], + 'additionalProperties': False +} + +protocol_update = { + 'type': 'object', + 'properties': _protocol_properties, 'minProperties': 1, 'additionalProperties': False } diff --git a/keystone/tests/unit/test_validation.py b/keystone/tests/unit/test_validation.py index bbe4472d60..f4764629aa 100644 --- a/keystone/tests/unit/test_validation.py +++ b/keystone/tests/unit/test_validation.py @@ -2050,26 +2050,26 @@ class FederationProtocolValidationTestCase(unit.BaseTestCase): def setUp(self): super(FederationProtocolValidationTestCase, self).setUp() - schema = federation_schema.federation_protocol_schema - # create protocol and update protocol have the same shema definition, - # combine them together, no need to validate separately. - self.protocol_validator = validators.SchemaValidator(schema) + create = federation_schema.protocol_create + update = federation_schema.protocol_update + self.create_protocol_validator = validators.SchemaValidator(create) + self.update_protocol_validator = validators.SchemaValidator(update) def test_validate_protocol_request_succeeds(self): """Test that we validate a protocol request successfully.""" request_to_validate = {'mapping_id': uuid.uuid4().hex} - self.protocol_validator.validate(request_to_validate) + self.create_protocol_validator.validate(request_to_validate) def test_validate_protocol_request_succeeds_with_nonuuid_mapping_id(self): """Test that we allow underscore in mapping_id value.""" request_to_validate = {'mapping_id': 'my_mapping_id'} - self.protocol_validator.validate(request_to_validate) + self.create_protocol_validator.validate(request_to_validate) def test_validate_protocol_request_fails_with_invalid_params(self): """Exception raised when unknown parameter is found.""" request_to_validate = {'bogus': uuid.uuid4().hex} self.assertRaises(exception.SchemaValidationError, - self.protocol_validator.validate, + self.create_protocol_validator.validate, request_to_validate) def test_validate_protocol_request_no_parameters(self): @@ -2077,16 +2077,49 @@ class FederationProtocolValidationTestCase(unit.BaseTestCase): request_to_validate = {} # 'mapping_id' is required. self.assertRaises(exception.SchemaValidationError, - self.protocol_validator.validate, + self.create_protocol_validator.validate, request_to_validate) def test_validate_protocol_request_fails_with_invalid_mapping_id(self): """Exception raised when mapping_id is not string.""" request_to_validate = {'mapping_id': 12334} self.assertRaises(exception.SchemaValidationError, - self.protocol_validator.validate, + self.create_protocol_validator.validate, request_to_validate) + def test_validate_protocol_request_succeeds_on_update(self): + """Test that we validate a protocol update request successfully.""" + request_to_validate = {'mapping_id': uuid.uuid4().hex} + self.update_protocol_validator.validate(request_to_validate) + + def test_validate_update_protocol_request_succeeds_with_nonuuid_id(self): + """Test that we allow underscore in mapping_id value when updating.""" + request_to_validate = {'mapping_id': 'my_mapping_id'} + self.update_protocol_validator.validate(request_to_validate) + + def test_validate_update_protocol_request_fails_with_invalid_params(self): + """Exception raised when unknown parameter in protocol update.""" + request_to_validate = {'bogus': uuid.uuid4().hex} + self.assertRaises(exception.SchemaValidationError, + self.update_protocol_validator.validate, + request_to_validate) + + def test_validate_update_protocol_with_no_parameters_fails(self): + """Test that updating a protocol requires at least one attribute.""" + request_to_validate = {} + # 'mapping_id' is required. + self.assertRaises(exception.SchemaValidationError, + self.update_protocol_validator.validate, + request_to_validate) + + def test_validate_update_protocol_request_fails_with_invalid_id(self): + """Test that updating a protocol with a non-string mapping_id fail.""" + for bad_mapping_id in [12345, True]: + request_to_validate = {'mapping_id': bad_mapping_id} + self.assertRaises(exception.SchemaValidationError, + self.update_protocol_validator.validate, + request_to_validate) + class OAuth1ValidationTestCase(unit.BaseTestCase): """Test for V3 Identity OAuth1 API validation."""