diff options
8 files changed, 80 insertions, 8 deletions
diff --git a/testapi/opnfv_testapi/common/check.py b/testapi/opnfv_testapi/common/check.py index 1a66dd7..7f866dd 100644 --- a/testapi/opnfv_testapi/common/check.py +++ b/testapi/opnfv_testapi/common/check.py @@ -47,6 +47,20 @@ def is_authorized(method): return wrapper +def is_allowed(method): + @functools.wraps(method) + def wrapper(self, *args, **kwargs): + if self.table == 'projects': + query_data = {} + query_data['project_name'] = kwargs.get('query')['name'] + data = yield dbapi.db_find_one('testcases', query_data) + if data: + raises.Unauthorized(message.tied_with_resource()) + ret = yield gen.coroutine(method)(self, *args, **kwargs) + raise gen.Return(ret) + return wrapper + + def valid_token(method): @functools.wraps(method) def wrapper(self, *args, **kwargs): diff --git a/testapi/opnfv_testapi/common/message.py b/testapi/opnfv_testapi/common/message.py index c82d5dc..52cc2ad 100644 --- a/testapi/opnfv_testapi/common/message.py +++ b/testapi/opnfv_testapi/common/message.py @@ -60,3 +60,7 @@ def must_int(name): def no_permission(): return 'You do not have permission to perform this action' + + +def tied_with_resource(): + return 'Selected resource is associated with other resources' diff --git a/testapi/opnfv_testapi/handlers/base_handlers.py b/testapi/opnfv_testapi/handlers/base_handlers.py index 537077d..ed4aeb2 100644 --- a/testapi/opnfv_testapi/handlers/base_handlers.py +++ b/testapi/opnfv_testapi/handlers/base_handlers.py @@ -179,6 +179,7 @@ class GenericApiHandler(web.RequestHandler): @gen.coroutine @check.not_exist @check.is_authorized + @check.is_allowed def _delete(self, data, query=None): yield dbapi.db_delete(self.table, query) self.finish_request() @@ -189,6 +190,7 @@ class GenericApiHandler(web.RequestHandler): @check.not_exist @check.updated_one_not_exist @check.is_authorized + @check.is_allowed def _update(self, data, query=None, **kwargs): data = self.table_cls.from_dict(data) update_req = self._update_requests(data) diff --git a/testapi/opnfv_testapi/tests/unit/handlers/test_project.py b/testapi/opnfv_testapi/tests/unit/handlers/test_project.py index cbd1a4e..884dd68 100644 --- a/testapi/opnfv_testapi/tests/unit/handlers/test_project.py +++ b/testapi/opnfv_testapi/tests/unit/handlers/test_project.py @@ -12,6 +12,7 @@ import urllib from opnfv_testapi.common import message from opnfv_testapi.models import project_models +from opnfv_testapi.models import testcase_models as tcm from opnfv_testapi.tests.unit import executor from opnfv_testapi.tests.unit.handlers import test_base as base @@ -23,6 +24,9 @@ class TestProjectBase(base.TestBase): 'qtip-ssh test') self.req_e = project_models.ProjectCreateRequest('functest', 'functest test') + self.testcase_d = tcm.TestcaseCreateRequest.from_dict( + self.load_json('testcase_d')) + self.project = 'qtip' self.get_res = project_models.Project self.list_res = project_models.Projects self.update_res = project_models.Project @@ -150,6 +154,13 @@ class TestProjectUpdate(TestProjectBase): return self.req_d, self.req_d.name @executor.mock_valid_lfid() + @executor.update(httplib.UNAUTHORIZED, message.tied_with_resource()) + def test_updateNotAllowed(self): + self.create_help('/api/v1/projects/%s/cases', self.testcase_d, self.req_d.name) + req = project_models.ProjectUpdateRequest('apex', 'apex test') + return req, self.req_d.name + + @executor.mock_valid_lfid() @executor.update(httplib.OK, '_assert_update') def test_success(self): req = project_models.ProjectUpdateRequest('apex', 'apex test') @@ -178,6 +189,12 @@ class TestProjectDelete(TestProjectBase): return 'notFound' @executor.mock_valid_lfid() + @executor.delete(httplib.UNAUTHORIZED, message.tied_with_resource()) + def test_deleteNotAllowed(self): + self.create_help('/api/v1/projects/%s/cases', self.testcase_d, self.req_d.name) + return self.req_d.name + + @executor.mock_valid_lfid() @executor.delete(httplib.OK, '_assert_delete') def test_success(self): return self.req_d.name diff --git a/testapi/opnfv_testapi/ui/components/pods/podsController.js b/testapi/opnfv_testapi/ui/components/pods/podsController.js index 95e3571..38e084d 100644 --- a/testapi/opnfv_testapi/ui/components/pods/podsController.js +++ b/testapi/opnfv_testapi/ui/components/pods/podsController.js @@ -137,7 +137,6 @@ function batchDelete(){ var index; var checkedBox = []; - console.log(ctrl.checkBox) for(index in ctrl.checkBox){ if(!ctrl.showError){ if(ctrl.checkBox[index]){ @@ -153,7 +152,13 @@ * message */ function openBatchDeleteModal() { - confirmModal("Delete",ctrl.batchDelete); + var deleteObjects = [] + for(var index in ctrl.checkBox){ + if(ctrl.checkBox[index]){ + deleteObjects.push(ctrl.data.pods[index].name) + } + } + confirmModal("Delete", 'pods', ctrl.batchDelete, deleteObjects); } /** @@ -162,7 +167,7 @@ */ function openDeleteModal(name) { console.log(name) - confirmModal("Delete", ctrl.podDelete, name); + confirmModal("Delete", 'pod', ctrl.podDelete, name); } /** diff --git a/testapi/opnfv_testapi/ui/components/projects/projectsController.js b/testapi/opnfv_testapi/ui/components/projects/projectsController.js index 940c1e2..0d0ec99 100644 --- a/testapi/opnfv_testapi/ui/components/projects/projectsController.js +++ b/testapi/opnfv_testapi/ui/components/projects/projectsController.js @@ -204,7 +204,15 @@ * message */ function openBatchDeleteModal() { - confirmModal("Delete",ctrl.batchDelete); + var deleteObjects = [] + ctrl.checkBox.forEach(function(project, index){ + if(!ctrl.showError){ + if(project){ + deleteObjects.push(ctrl.data.projects[index].name) + } + } + }); + confirmModal("Delete", 'projects', ctrl.batchDelete, deleteObjects); } /** @@ -212,7 +220,7 @@ * message */ function openDeleteModal(name) { - confirmModal("Delete", ctrl.projectDelete, name); + confirmModal("Delete",'projects', ctrl.projectDelete, name); } ctrl.listProjects(); diff --git a/testapi/opnfv_testapi/ui/shared/alerts/confirmModal.html b/testapi/opnfv_testapi/ui/shared/alerts/confirmModal.html index e5397e0..417af37 100644 --- a/testapi/opnfv_testapi/ui/shared/alerts/confirmModal.html +++ b/testapi/opnfv_testapi/ui/shared/alerts/confirmModal.html @@ -10,7 +10,7 @@ </div> <div class="Delete" ng-class="{ 'hidden': confirmModal.data.text!='Delete' }"> <div class="form-group"> - <label for="confirmText"> You are about to delete.</label> + <label for="confirmText"> You are about to delete following {{confirmModal.data.resource}} : {{confirmModal.deleteObjects}} </label> <br> Do you want to proceed? </div> diff --git a/testapi/opnfv_testapi/ui/shared/alerts/confirmModalFactory.js b/testapi/opnfv_testapi/ui/shared/alerts/confirmModalFactory.js index 42cf873..c115a3c 100644 --- a/testapi/opnfv_testapi/ui/shared/alerts/confirmModalFactory.js +++ b/testapi/opnfv_testapi/ui/shared/alerts/confirmModalFactory.js @@ -11,7 +11,7 @@ * Opens confirm modal dialog with input textbox */ function confirmModal($uibModal) { - return function(text, successHandler, name) { + return function(text, resource, successHandler, name) { $uibModal.open({ templateUrl: 'testapi-ui/shared/alerts/confirmModal.html', controller: 'CustomConfirmModalController as confirmModal', @@ -20,8 +20,10 @@ data: function () { return { text: text, + resource: resource, successHandler: successHandler, name: name + }; } } @@ -44,8 +46,26 @@ ctrl.confirm = confirm; ctrl.cancel = cancel; - + ctrl.buildDeleteObjects = buildDeleteObjects; ctrl.data = angular.copy(data); + + function buildDeleteObjects(){ + ctrl.deleteObjects = ''; + if (typeof ctrl.data.name === 'string') { + ctrl.deleteObjects = ctrl.data.name + } + else{ + for(var index in ctrl.data.name){ + if(index==0){ + ctrl.deleteObjects += ctrl.data.name[index] + } + else{ + ctrl.deleteObjects += ", "+ ctrl.data.name[index] + } + + } + } + } /** * Initiate confirmation and call the success handler with the * input text. @@ -63,5 +83,7 @@ function cancel() { $uibModalInstance.dismiss('cancel'); } + + ctrl.buildDeleteObjects(); } })(); |