Sanitize all entity names

Only allow string.letters, string.digits, "-" and "_".

Fixes-bug: #1295962
Change-Id: I582dfb20d146d7f4f67efe9b0ac33d1841a310a9
This commit is contained in:
Angus Salkeld
2014-05-07 11:20:04 +10:00
parent 91f1373407
commit 8d6de8ef26
14 changed files with 67 additions and 21 deletions

View File

@@ -110,7 +110,7 @@ class TestAssemblyController(base.TestCase):
def test_assemblies_put(self):
uuid, plan_uuid = self._create_assembly()
uri = "%s/v1/plans/%s" % (self.client.base_url, plan_uuid)
updated_data = {"name": "test_assembly updated",
updated_data = {"name": "test_assembly_updated",
"description": "A test to create assembly updated",
"plan_uri": uri,
"project_id": "project_id updated",
@@ -125,7 +125,7 @@ class TestAssemblyController(base.TestCase):
self._delete_assembly(uuid, plan_uuid)
def test_assemblies_put_not_found(self):
updated_data = {"name": "test_assembly updated",
updated_data = {"name": "test_assembly_updated",
"description": "A test to create assembly updated",
"plan_uri": 'fake_uri',
"project_id": "project_id updated",

View File

@@ -122,7 +122,7 @@ class TestComponentController(base.TestCase):
def test_components_put(self):
uuid, assembly_uuid, plan_uuid = self._create_component()
updated_data = {'name': 'test_service updated',
updated_data = {'name': 'test_service_updated',
'description': 'desc updated',
'plan_uri': "%s/v1/plans/%s" % (self.client.base_url,
plan_uuid),
@@ -135,7 +135,7 @@ class TestComponentController(base.TestCase):
self._delete_component(uuid, assembly_uuid, plan_uuid)
def test_components_put_not_found(self):
updated_data = {'name': 'test_service updated',
updated_data = {'name': 'test_service_updated',
'description': 'desc updated',
'plan_uri': "%s/v1/plans/%s" % (self.client.base_url,
'not_found'),

View File

@@ -120,7 +120,7 @@ class TestLanguagePackController(base.TestCase):
self.skipTest("Tags update not implemented yet in python-glanceclient")
# See http://goo.gl/vg9h6G
uuid = self._create_language_pack()
updated_data = {"name": "test_language_pack updated",
updated_data = {"name": "test_language_pack_updated",
"description": "A test to create language_pack update",
"language_pack_type": "python",
"language_implementation": "py",
@@ -145,7 +145,7 @@ class TestLanguagePackController(base.TestCase):
self._delete_language_pack(uuid)
def test_language_packs_put_not_found(self):
updated_data = {"name": "test_language_pack updated",
updated_data = {"name": "test_language_pack_updated",
"description": "A test to create language_pack update",
"language_pack_type": "python",
"language_implementation": "py",

View File

@@ -24,7 +24,7 @@ sample_data = {"name": "test_plan",
"user_id": "user_id",
"type": "plan",
"artifacts": [{
"name": "No deus",
"name": "No_deus",
"artifact_type": "application.heroku",
"content": {
"href": "https://example.com/git/a.git"
@@ -98,7 +98,7 @@ class TestPlanController(base.TestCase):
def test_plans_put(self):
uuid = self._create_plan()
updated_data = {"name": "test_plan updated",
updated_data = {"name": "test_plan_updated",
"description": "A test to create plan updated",
"type": "plan",
"artifacts": []}
@@ -110,7 +110,7 @@ class TestPlanController(base.TestCase):
self._delete_plan(uuid)
def test_plans_put_not_found(self):
updated_data = {"name": "test_plan updated",
updated_data = {"name": "test_plan_updated",
"description": "A test to create plan updated",
"type": "plan",
"artifacts": []}

View File

@@ -94,7 +94,7 @@ class TestServiceController(base.TestCase):
def test_services_put(self):
uuid = self._create_service()
updated_data = {"name": "test_service updated",
updated_data = {"name": "test_service_updated",
"description": "A test to create service updated",
"project_id": "project_id updated",
"user_id": "user_id updated",
@@ -108,7 +108,7 @@ class TestServiceController(base.TestCase):
self._delete_service(uuid)
def test_services_put_not_found(self):
updated_data = {"name": "test_service updated",
updated_data = {"name": "test_service_updated",
"description": "A test to create service updated",
"project_id": "project_id updated",
"user_id": "user_id updated",

View File

@@ -96,11 +96,11 @@ class Plan(api_types.Base):
@classmethod
def sample(cls):
return cls(uri='http://example.com/v1/plans/x1',
name='Example plan',
name='Example-plan',
type='plan',
tags=['small'],
artifacts=[{
'name': 'My python app',
'name': 'My-python-app',
'artifact_type': 'git_pull',
'content': {'href': 'git://example.com/project.git'},
'language_pack': str(uuid.uuid4()),
@@ -108,7 +108,7 @@ class Plan(api_types.Base):
'requirement_type': 'git_pull',
'fulfillment': 'id:build'}]}],
services=[{
'name': 'Build Service',
'name': 'Build-Service',
'id': 'build',
'characteristics': ['python_build_service']}],
project_id='1dae5a09ef2b4d8cbf3594b0eb4f6b94',

View File

@@ -12,10 +12,12 @@
# License for the specific language governing permissions and limitations
# under the License.
import string
import wsme
from wsme import types as wtypes
from solum.api.controllers import common_types
from solum.openstack.common.gettextutils import _
class Base(wtypes.Base):
@@ -27,7 +29,17 @@ class Base(wtypes.Base):
uuid = wtypes.text
"Unique Identifier of the resource"
name = wsme.wsattr(wtypes.text, mandatory=True)
def get_name(self):
return self.__name
def set_name(self, value):
allowed_chars = string.letters + string.digits + '-_'
for ch in value:
if ch not in allowed_chars:
raise ValueError(_('Names must only contain a-z,A-Z,0-9,-,_'))
self.__name = value
name = wtypes.wsproperty(str, get_name, set_name, mandatory=True)
"Name of the resource."
type = wtypes.text
@@ -45,6 +57,10 @@ class Base(wtypes.Base):
user_id = wtypes.text
"The user that owns this resource."
def __init__(self, **kwds):
self.__name = wsme.Unset
super(Base, self).__init__(**kwds)
@classmethod
def from_db_model(cls, m, host_url):
json = m.as_dict()

View File

@@ -114,7 +114,7 @@ class TestAssemblyAsDict(base.BaseTestCase):
('none', dict(data=None)),
('one', dict(data={'name': 'foo'})),
('full', dict(data={'uri': 'http://example.com/v1/assemblys/x1',
'name': 'Example assembly',
'name': 'Example-assembly',
'type': 'assembly',
'project_id': '1dae5a09ef2b4d8cbf3594b0eb4f6b94',
'user_id': '55f41cf46df74320b9486a35f5d28a11'}))

View File

@@ -161,7 +161,7 @@ class TestComponentAsDict(base.BaseTestCase):
('none', dict(data=None)),
('one', dict(data={'name': 'foo'})),
('full', dict(data={'uri': 'http://example.com/v1/components/x1',
'name': 'Example component',
'name': 'Example-component',
'type': 'component',
'tags': ['small'],
'project_id': '1dae5a09ef2b4d8cbf3594b0eb4f6b94',

View File

@@ -168,7 +168,7 @@ class TestOperationAsDict(base.BaseTestCase):
('none', dict(data=None)),
('one', dict(data={'name': 'foo'})),
('full', dict(data={'uri': 'http://example.com/v1/operations/x1',
'name': 'Example operation',
'name': 'Example-operation',
'type': 'operation',
'project_id': '1dae5a09ef2b4d8cbf3594b0eb4f6b94',
'user_id': '55f41cf46df74320b9486a35f5d28a11',

View File

@@ -149,7 +149,7 @@ class TestPlanAsDict(base.BaseTestCase):
('none', dict(data=None)),
('one', dict(data={'name': 'foo'})),
('full', dict(data={'uri': 'http://example.com/v1/plans/x1',
'name': 'Example plan',
'name': 'Example-plan',
'type': 'plan',
'project_id': '1dae5a09ef2b4d8cbf3594b0eb4f6b94',
'user_id': '55f41cf46df74320b9486a35f5d28a11'}))

View File

@@ -162,7 +162,7 @@ class TestServiceAsDict(base.BaseTestCase):
('none', dict(data=None)),
('one', dict(data={'name': 'foo'})),
('full', dict(data={'uri': 'http://example.com/v1/services/x1',
'name': 'Example service',
'name': 'Example-service',
'type': 'service',
'tags': ['small'],
'project_id': '1dae5a09ef2b4d8cbf3594b0eb4f6b94',

View File

@@ -73,3 +73,33 @@ class TestTypes(base.BaseTestCase):
obj = objects.registry.Component(**data)
c = component_api.Component.from_db_model(obj, 'http://test_host')
self.assertEqual(assembly_data['uuid'], c.assembly_uuid)
class TestTypeNames(base.BaseTestCase):
scenarios = [
('punct', dict(
in_value='.,', expect_ok=False)),
('-', dict(
in_value='a-b', expect_ok=True)),
('_', dict(
in_value='a_b', expect_ok=True)),
('spaces', dict(
in_value='look a space', expect_ok=False)),
('special', dict(
in_value='$-&', expect_ok=False)),
('upper', dict(
in_value='ALLGOOD', expect_ok=True)),
('lower', dict(
in_value='evenbetter', expect_ok=True)),
('numbers', dict(
in_value='12345', expect_ok=True)),
]
def test_name(self):
if self.expect_ok:
s = component_api.Component(name=self.in_value)
self.assertEqual(self.in_value, s.name)
else:
self.assertRaises(ValueError, component_api.Component,
name=self.in_value)

View File

@@ -54,7 +54,7 @@ class TestImageAsDict(base.BaseTestCase):
('none', dict(data=None)),
('one', dict(data={'name': 'foo'})),
('full', dict(data={'uri': 'http://example.com/v1/images/x1',
'name': 'Example image',
'name': 'Example-Image',
'type': 'image',
'tags': ['small'],
'project_id': '1dae5a09ef2b4d8cbf3594b0eb4f6b94',