Moved the validation code to _validate_input_edit.
Updated relevant tests.
Change-Id: I0666f28e1f06585f3648b0a88812f7348c622d86
Signed-off-by: Frank Bryden <frank.bryden@etsi.org>
input = super()._validate_input_new(input, force)
return self._obtain_url(input, True)
- def _validate_input_edit(self, input, force=False):
- input = super()._validate_input_edit(input, force)
+ def _validate_input_edit(self, input, content, force=False):
+ input = super()._validate_input_edit(input, content, force)
return self._obtain_url(input, False)
if kwargs:
BaseTopic._update_input_with_kwargs(indata, kwargs)
try:
- indata = self._validate_input_edit(indata, force=session["force"])
-
if not content:
content = self.show(session, _id)
+ indata = self._validate_input_edit(indata, content, force=session["force"])
self.check_conflict_on_edit(session, content, indata, _id=_id)
# self.format_on_edit(content, indata)
if kwargs:
BaseTopic._update_input_with_kwargs(indata, kwargs)
try:
- indata = self._validate_input_edit(indata, force=session["force"])
-
if not content:
content = self.show(session, _id)
+ indata = self._validate_input_edit(indata, content, force=session["force"])
self.check_conflict_on_edit(session, content, indata, _id=_id)
self.format_on_edit(content, indata)
return input
- def _validate_input_edit(self, input, force=False):
+ def _validate_input_edit(self, input, content, force=False):
"""
Validates input user content for updating an entry.
if kwargs:
self._update_input_with_kwargs(indata, kwargs)
try:
- indata = self._validate_input_edit(indata, force=session["force"])
if not content:
content = self.show(session, _id)
+ indata = self._validate_input_edit(indata, content, force=session["force"])
deep_update_rfc7396(content, indata)
self.check_conflict_on_edit(session, content, indata, _id=_id)
self.format_on_edit(content, indata)
validate_input(input, self.schema_new)
return input
- def _validate_input_edit(self, input, force=False):
+ def _validate_input_edit(self, input, content, force=False):
"""
Validates input user content for an edition. It uses jsonschema. Some overrides will use pyangbind
:param input: user input content for the new topic
if indata and session.get("set_project"):
raise EngineException("Cannot edit content and set to project (query string SET_PROJECT) at same time",
HTTPStatus.UNPROCESSABLE_ENTITY)
- indata = self._validate_input_edit(indata, force=session["force"])
-
+
# TODO self._check_edition(session, indata, _id, force)
if not content:
content = self.show(session, _id)
+
+ indata = self._validate_input_edit(indata, content, force=session["force"])
+
deep_update_rfc7396(content, indata)
# To allow project addressing by name AS WELL AS _id. Get the _id, just in case the provided one is a name
raise EngineException("Error in pyangbind validation: {}".format(str(e)),
http_code=HTTPStatus.UNPROCESSABLE_ENTITY)
+ def _validate_input_edit(self, indata, content, force=False):
+ # not needed to validate with pyangbind becuase it will be validated at check_conflict_on_edit
+ if "_id" in indata:
+ indata.pop("_id")
+ if "_admin" not in indata:
+ indata["_admin"] = {}
+
+ if "operationalState" in indata:
+ if indata["operationalState"] in ("ENABLED", "DISABLED"):
+ indata["_admin"]["operationalState"] = indata.pop("operationalState")
+ else:
+ raise EngineException("State '{}' is not a valid operational state"
+ .format(indata["operationalState"]),
+ http_code=HTTPStatus.BAD_REQUEST)
+
+ # In the case of user defined data, we need to put the data in the root of the object
+ # to preserve current expected behaviour
+ if "userDefinedData" in indata:
+ data = indata.pop("userDefinedData")
+ if type(data) == dict:
+ indata["_admin"]["userDefinedData"] = data
+ else:
+ raise EngineException("userDefinedData should be an object, but is '{}' instead"
+ .format(type(data)),
+ http_code=HTTPStatus.BAD_REQUEST)
+
+ if ("operationalState" in indata["_admin"] and
+ content["_admin"]["operationalState"] == indata["_admin"]["operationalState"]):
+ raise EngineException("operationalState already {}".format(content["_admin"]["operationalState"]),
+ http_code=HTTPStatus.CONFLICT)
+
+ return indata
+
class VnfdTopic(DescriptorTopic):
topic = "vnfds"
http_code=HTTPStatus.UNPROCESSABLE_ENTITY)
return indata
- def _validate_input_edit(self, indata, force=False):
- # not needed to validate with pyangbind becuase it will be validated at check_conflict_on_edit
- return indata
-
def _validate_package_folders(self, storage_params, folder, file=None):
if not storage_params or not storage_params.get("pkg-dir"):
return False
http_code=HTTPStatus.UNPROCESSABLE_ENTITY)
return indata
- def _validate_input_edit(self, indata, force=False):
+ def _validate_input_edit(self, indata, content, force=False):
# not needed to validate with pyangbind becuase it will be validated at check_conflict_on_edit
+ """
+ indata looks as follows:
+ - In the new case (conformant)
+ {'nsdOperationalState': 'DISABLED', 'userDefinedData': {'id': 'string23',
+ '_id': 'c6ddc544-cede-4b94-9ebe-be07b298a3c1', 'name': 'simon46'}}
+ - In the old case (backwards-compatible)
+ {'id': 'string23', '_id': 'c6ddc544-cede-4b94-9ebe-be07b298a3c1', 'name': 'simon46'}
+ """
+ if "_admin" not in indata:
+ indata["_admin"] = {}
+
+ if "nsdOperationalState" in indata:
+ if indata["nsdOperationalState"] in ("ENABLED", "DISABLED"):
+ indata["_admin"]["operationalState"] = indata.pop("nsdOperationalState")
+ else:
+ raise EngineException("State '{}' is not a valid operational state"
+ .format(indata["nsdOperationalState"]),
+ http_code=HTTPStatus.BAD_REQUEST)
+
+ # In the case of user defined data, we need to put the data in the root of the object
+ # to preserve current expected behaviour
+ if "userDefinedData" in indata:
+ data = indata.pop("userDefinedData")
+ if type(data) == dict:
+ indata["_admin"]["userDefinedData"] = data
+ else:
+ raise EngineException("userDefinedData should be an object, but is '{}' instead"
+ .format(type(data)),
+ http_code=HTTPStatus.BAD_REQUEST)
+ if ("operationalState" in indata["_admin"] and
+ content["_admin"]["operationalState"] == indata["_admin"]["operationalState"]):
+ raise EngineException("nsdOperationalState already {}".format(content["_admin"]["operationalState"]),
+ http_code=HTTPStatus.CONFLICT)
return indata
def _check_descriptor_dependencies(self, session, descriptor):
clean_indata = clean_indata['nst:nst'][0]
return clean_indata
- def _validate_input_edit(self, indata, force=False):
- # TODO validate with pyangbind, serialize
- return indata
-
def _validate_input_new(self, indata, storage_params, force=False):
indata = self.pyangbind_validation("nsts", indata, force)
return indata.copy()
new_name = "other-user-name"
new_prms = [{}]
self.auth.get_role_list.side_effect = [[user], []]
+ self.auth.get_user_list.side_effect = [[user]]
with self.assertRaises(EngineException, msg="Accepted wrong project-role mappings") as e:
self.topic.edit(self.fake_session, uid, {"username": new_name, "project_role_mappings": new_prms})
self.assertEqual(e.exception.http_code, HTTPStatus.UNPROCESSABLE_ENTITY, "Wrong HTTP status code")
self.assertEqual(operation["detailed-status"], "", "Wrong operation detailed status info")
self.assertIsNone(operation["operationParams"], "Wrong operation parameters")
with self.subTest(i=2):
+ self.db.get_one.side_effect = [cvws]
with self.assertRaises(EngineException, msg="Accepted wrong property") as e:
self.topic.edit(self.fake_session, str(uuid4()), {"name": "new-name", "extra_prop": "anything"})
self.assertEqual(e.exception.http_code, HTTPStatus.UNPROCESSABLE_ENTITY, "Wrong HTTP status code")