From 2e35a7e46f0929438c1c206e3116caa829f07dc6 Mon Sep 17 00:00:00 2001 From: Thomas Duval Date: Fri, 5 Oct 2018 16:54:37 +0200 Subject: Update code to 4.6 official version Change-Id: Ibd0da0e476e24b2685f54693efc11f7a58d40a62 --- moon_dashboard/Dockerfile | 10 +- moon_dashboard/moon/api/__init__.py | 0 moon_dashboard/moon/api/moon_api.py | 0 moon_dashboard/moon/static/moon/js/moon.module.js | 2 +- moon_dashboard/moon/static/moon/js/util.service.js | 8 +- .../moon/static/moon/model/model.controller.js | 150 ++++++++++++++------ moon_dashboard/moon/static/moon/model/model.html | 10 +- .../moon/static/moon/model/model.service.js | 5 + .../moon/static/moon/pdp/pdp.controller.js | 12 +- .../moon/static/moon/policy/policy.controller.js | 76 +++++++++-- moon_dashboard/moon/static/moon/policy/policy.html | 74 ++++++++-- .../moon/static/moon/policy/policy.service.js | 122 +++++++++++++++-- .../moon/static/moon/policy/policy.service.spec.js | 151 +++++++++++++++++++++ moon_dashboard/moon/static/moon/scss/moon.scss | 4 + moon_dashboard/run.sh | 38 ++++-- moon_dashboard/setup.cfg | 2 +- 16 files changed, 560 insertions(+), 104 deletions(-) create mode 100644 moon_dashboard/moon/api/__init__.py create mode 100644 moon_dashboard/moon/api/moon_api.py (limited to 'moon_dashboard') diff --git a/moon_dashboard/Dockerfile b/moon_dashboard/Dockerfile index 8f997fe1..790a2b21 100644 --- a/moon_dashboard/Dockerfile +++ b/moon_dashboard/Dockerfile @@ -8,19 +8,21 @@ LABEL Url="https://wiki.opnfv.org/display/moon/Moon+Project+Proposal" ENV MANAGER_HOST="127.0.0.1" ENV MANAGER_PORT=30001 ENV KEYSTONE_HOST="127.0.0.1" -ENV KEYSTONE_PORT=30005 +ENV KEYSTONE_PORT=5000 ENV OPENSTACK_HOST="127.0.0.1" -ENV OPENSTACK_KEYSTONE_URL="http://${KEYSTONE_HOST}:${KEYSTONE_PORT}/v2.0" +ENV OPENSTACK_KEYSTONE_URL="http://${KEYSTONE_HOST}:${KEYSTONE_PORT}/identity/v3" +ENV SERVER_IP_ADDR="0.0.0.0" USER root WORKDIR /root/ ADD . /root -RUN git clone https://git.openstack.org/openstack/horizon +RUN [ -d horizon ] || git clone https://git.openstack.org/openstack/horizon WORKDIR /root/horizon +# RUN pip install --no-cache-dir pip RUN pip install --no-cache-dir -c http://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt . RUN cp openstack_dashboard/local/local_settings.py.example openstack_dashboard/local/local_settings.py @@ -31,4 +33,6 @@ WORKDIR /root/ RUN cp -v moon/enabled/_32000_moon.py horizon/openstack_dashboard/local/enabled/_32000_moon.py RUN cp -rv moon/ horizon/openstack_dashboard/dashboards/ +EXPOSE 8000 + CMD ["/bin/sh", "/root/run.sh"] \ No newline at end of file diff --git a/moon_dashboard/moon/api/__init__.py b/moon_dashboard/moon/api/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/moon_dashboard/moon/api/moon_api.py b/moon_dashboard/moon/api/moon_api.py new file mode 100644 index 00000000..e69de29b diff --git a/moon_dashboard/moon/static/moon/js/moon.module.js b/moon_dashboard/moon/static/moon/js/moon.module.js index ed56ec2a..c8b86439 100755 --- a/moon_dashboard/moon/static/moon/js/moon.module.js +++ b/moon_dashboard/moon/static/moon/js/moon.module.js @@ -23,7 +23,7 @@ .module('moon', [ 'ngResource', ]).constant('moon.URI', { - API: 'http://{{MANAGER_HOST}}:{{MANAGER_PORT}}', + API: 'http://{{MANAGER_HOST}}:{{MANAGER_PORT}}', }) })(); diff --git a/moon_dashboard/moon/static/moon/js/util.service.js b/moon_dashboard/moon/static/moon/js/util.service.js index 18ae901d..29680a43 100755 --- a/moon_dashboard/moon/static/moon/js/util.service.js +++ b/moon_dashboard/moon/static/moon/js/util.service.js @@ -117,8 +117,12 @@ }, displayErrorFunction: function displayErrorFunction(message) { - return function() { - toast.add('error', gettext(message)); + return function(response) { + var text = gettext(message); + if (response && response.data && response.data.message) { + text += ' (' + response.data.message + ')' + } + toast.add('error', text); } }, diff --git a/moon_dashboard/moon/static/moon/model/model.controller.js b/moon_dashboard/moon/static/moon/model/model.controller.js index d6a7503b..99a7c7ed 100644 --- a/moon_dashboard/moon/static/moon/model/model.controller.js +++ b/moon_dashboard/moon/static/moon/model/model.controller.js @@ -17,13 +17,13 @@ link: function (scope, element, attrs) { element.bind('change', function (e) { - var onFileReadFn = $parse(attrs.onReadFile); + var onFileRead = $parse(attrs.onReadFile); var reader = new FileReader(); reader.onload = function () { var fileContents = reader.result; scope.$apply(function () { - onFileReadFn(scope, { + onFileRead(scope, { 'contents': fileContents }); }); @@ -65,8 +65,10 @@ modelService.initialize(); self.importData = function importData(text) { + horizon.modals.modal_spinner(gettext("Loading")) importService.importData(JSON.parse(text)).then(function () { modelService.initialize(); + horizon.modals.spinner.modal('hide'); }) } @@ -76,7 +78,8 @@ properties: { name: { type: "string", minLength: 2, title: gettext("Name") }, description: { type: "string", minLength: 2, title: gettext("Description") } - } + }, + required: ['name', 'description'] }; var model = { name: '', description: '' }; var config = { @@ -98,7 +101,8 @@ properties: { name: { type: "string", minLength: 2, title: gettext("Name") }, description: { type: "string", minLength: 2, title: gettext("Description") } - } + }, + required: ['name', 'description'] }; var config = { title: gettext('Update Model'), @@ -118,37 +122,73 @@ modelService.removeModel(model); } + self.createMetaRuleFunction = function createMetaRuleFunction(model, titleMap) { + return function () { + var schema = { + type: "object", + properties: { + name: { type: "string", minLength: 2, title: gettext("Name") }, + description: { type: "string", minLength: 2, title: gettext("Description") }, + }, + required: ['name', 'description'] + }; + var metaRule = { name: '', description: '' }; + var config = { + title: gettext('Create Meta Rule'), + schema: schema, + form: [ + 'name', + { key: 'description', type: 'textarea' } + ], + model: metaRule + }; + ModalFormService.open(config).then(submit); + + function submit(form) { + modelService.createMetaRule(form.model).then(function (metaRule) { + titleMap.push({ value: metaRule.id, name: metaRule.name }) + model.id = metaRule.id + }) + } + } + } + self.addMetaRule = function addMetaRule(model) { var schema = { type: "object", properties: { - name: { type: "string", minLength: 2, title: gettext("Name") }, - description: { type: "string", minLength: 2, title: gettext("Description") }, id: { type: "string", title: gettext("Select a Meta Rule:") } - } + }, + required: ['id'] }; - var metaRule = { name: '', description: '' }; var titleMap = util.arrayToTitleMap(modelService.metaRules) + var formModel = { id: null } var config = { title: gettext('Add Meta Rule'), schema: schema, - form: [{ key: 'id', type: 'select', titleMap: titleMap }, { type: 'help', helpvalue: gettext("Or create a new one:") }, 'name', { key: 'description', type: 'textarea' }], - model: metaRule + form: [ + { key: 'id', type: 'select', titleMap: titleMap }, + { + key: 'createButton', + type: 'button', + title: gettext('Create Meta Rule'), + icon: 'fa fa-plus', + onClick: self.createMetaRuleFunction(formModel, titleMap) + } + ], + model: formModel }; + if (modelService.metaRules.length == 1) { + formModel.id = modelService.metaRules[0].id + } + ModalFormService.open(config).then(submit); function submit(form) { - function addMetaRuleToModel(metaRule) { - var modelCopy = angular.copy(model); - modelCopy.meta_rules.push(metaRule); - modelService.updateModel(modelCopy); - } - - if (form.model.name) { - modelService.createMetaRule(form.model).then(addMetaRuleToModel) - } else if (form.model.id) { - addMetaRuleToModel(modelService.getMetaRule(form.model.id)); - } + var metaRule = modelService.getMetaRule(form.model.id); + var modelCopy = angular.copy(model); + modelCopy.meta_rules.push(metaRule); + modelService.updateModel(modelCopy); } } @@ -158,7 +198,8 @@ properties: { name: { type: "string", minLength: 2, title: gettext("Name") }, description: { type: "string", minLength: 2, title: gettext("Description") } - } + }, + required: ['name', 'description'] }; var metaRuleCopy = angular.copy(metaRule); var config = { @@ -188,38 +229,69 @@ } } + self.createCategoryFunction = function createCategoryFunction(type, formModel, titleMap) { + return function () { + var schema = { + type: "object", + properties: { + name: { type: "string", minLength: 2, title: gettext("Name") }, + description: { type: "string", minLength: 2, title: gettext("Description") }, + }, + required: ['name', 'description'] + }; + var metaRule = { name: '', description: '' }; + var config = { + title: gettext('Create Category'), + schema: schema, + form: [ + 'name', + { key: 'description', type: 'textarea' } + ], + model: metaRule + }; + ModalFormService.open(config).then(submit); + + function submit(form) { + modelService.createCategory(type, form.model).then(function (category) { + titleMap.push({ value: category.id, name: category.name }) + formModel.id = category.id + }) + } + } + } + self.addCategory = function addCategory(type, metaRule) { var typeValue = categoryMap[type]; var schema = { type: "object", properties: { - name: { type: "string", minLength: 2, title: gettext("Name") }, - description: { type: "string", minLength: 2, title: gettext("Description") }, id: { type: "string", title: gettext("Select a Category:") } - } + }, + required: ['id'] }; - var category = { name: '', description: '' }; var titleMap = util.arrayToTitleMap(modelService[typeValue.serviceListName]) + var formModel = { id: null } var config = { title: gettext(typeValue.addTitle), schema: schema, - form: [{ key: 'id', type: 'select', titleMap: titleMap }, { type: 'help', helpvalue: gettext("Or create a new one:") }, 'name', { key: 'description', type: 'textarea' }], - model: category + form: [ + { key: 'id', type: 'select', titleMap: titleMap }, + { + key: 'createButton', + type: 'button', + title: gettext('Create Category'), + icon: 'fa fa-plus', + onClick: self.createCategoryFunction(type, formModel, titleMap) + }], + model: formModel }; ModalFormService.open(config).then(submit); function submit(form) { - function addCategoryToMetaRule(category) { - var metaRuleCopy = angular.copy(metaRule); - metaRuleCopy[typeValue.listName].push(category); - modelService.updateMetaRule(metaRuleCopy) - } - - if (form.model.name) { - modelService.createCategory(type, form.model).then(addCategoryToMetaRule) - } else if (form.model.id) { - addCategoryToMetaRule(modelService.getCategory(type, form.model.id)); - } + var category = modelService.getCategory(type, form.model.id); + var metaRuleCopy = angular.copy(metaRule); + metaRuleCopy[typeValue.listName].push(category); + modelService.updateMetaRule(metaRuleCopy) } } diff --git a/moon_dashboard/moon/static/moon/model/model.html b/moon_dashboard/moon/static/moon/model/model.html index 98d64c75..97f08910 100644 --- a/moon_dashboard/moon/static/moon/model/model.html +++ b/moon_dashboard/moon/static/moon/model/model.html @@ -62,10 +62,6 @@ Import - @@ -115,19 +111,19 @@

- {$ category.name $} + {$ category.name $}

- {$ category.name $} + {$ category.name $}

- {$ category.name $} + {$ category.name $}

diff --git a/moon_dashboard/moon/static/moon/model/model.service.js b/moon_dashboard/moon/static/moon/model/model.service.js index 76c3da01..986eb6b1 100755 --- a/moon_dashboard/moon/static/moon/model/model.service.js +++ b/moon_dashboard/moon/static/moon/model/model.service.js @@ -205,6 +205,7 @@ return modelsMap[id]; }, createModel: function createModel(model) { + model.meta_rules = []; modelResource.create(null, model, success, util.displayErrorFunction('Unable to create model')); function success(data) { @@ -235,6 +236,10 @@ return metaRulesMap[id]; }, createMetaRule: function createMetaRule(metaRule) { + metaRule.subject_categories = []; + metaRule.object_categories = []; + metaRule.action_categories = []; + return metaRuleResource.create(null, metaRule).$promise.then(function (data) { util.displaySuccess('Meta Rule created'); return createMetaRuleInternal(data.meta_rules)[0]; diff --git a/moon_dashboard/moon/static/moon/pdp/pdp.controller.js b/moon_dashboard/moon/static/moon/pdp/pdp.controller.js index c57f3b28..1859b1f8 100644 --- a/moon_dashboard/moon/static/moon/pdp/pdp.controller.js +++ b/moon_dashboard/moon/static/moon/pdp/pdp.controller.js @@ -19,7 +19,8 @@ properties: { name: { type: "string", minLength: 2, title: gettext("Name") }, description: { type: "string", minLength: 2, title: gettext("Description") } - } + }, + required: ['name', 'description'] }; var pdp = { name: '', description: '' }; var config = { @@ -41,7 +42,8 @@ properties: { name: { type: "string", minLength: 2, title: gettext("Name") }, description: { type: "string", minLength: 2, title: gettext("Description") } - } + }, + required: ['name', 'description'] }; var config = { title: gettext('Update PDP'), @@ -66,7 +68,8 @@ type: "object", properties: { id: { type: "string", title: gettext("Select a Policy:") } - } + }, + required: ['id'] }; var titleMap = util.arrayToTitleMap(pdpService.policies) var config = { @@ -97,7 +100,8 @@ type: "object", properties: { id: { type: "string", title: gettext("Select a Project:") } - } + }, + required: ['id'] }; var model = {id : pdp.keystone_project_id}; diff --git a/moon_dashboard/moon/static/moon/policy/policy.controller.js b/moon_dashboard/moon/static/moon/policy/policy.controller.js index 6c6631cf..a3cc18f1 100644 --- a/moon_dashboard/moon/static/moon/policy/policy.controller.js +++ b/moon_dashboard/moon/static/moon/policy/policy.controller.js @@ -32,21 +32,23 @@ function createAddDataButton(type, index, category, config, policy) { config.form.push({ - "key": type + index + "Button", - "type": "button", - "title": "Add", - onClick: createDataFunction(type, category, policy) + key: type + index + "Button", + type: "button", + title: gettext("Create Data"), + icon: 'fa fa-plus', + onClick: createDataFunction(type, category, policy, config.model, type+index) }) } - function createDataFunction(type, category, policy) { + function createDataFunction(type, category, policy, formModel, key) { return function () { var schema = { type: "object", properties: { name: { type: "string", minLength: 2, title: gettext("Name") }, description: { type: "string", minLength: 2, title: gettext("Description") }, - } + }, + required: ['name', 'description'] }; var data = { name: '', description: '' }; var config = { @@ -61,6 +63,7 @@ policyService.createData(type, policy, category, form.model).then( function (data) { util.pushAll(dataTitleMaps[category.id], util.arrayToTitleMap(data)); + formModel[key] = data[0].id } ); } @@ -82,6 +85,7 @@ var titleMap = getOrCreateDataTitleMap(category, data, policy); config.schema.properties[type + i] = { type: "string", title: gettext('Select ' + type + ' data of ' + category.name + ' category') }; config.form.push({ key: type + i, type: 'select', titleMap: titleMap }); + config.schema.required.push(type + i); createAddDataButton(type, i, category, config, policy); } } @@ -102,7 +106,8 @@ description: { type: "string", minLength: 2, title: gettext("Description") }, genre: { type: "string", title: gettext("genre") }, model_id: { type: "string", title: gettext("Select a Model:") } - } + }, + required: ['name', 'description', 'genre', 'model_id'] }; var policy = { name: '', description: '', model_id: null, genre: '' }; var titleMap = util.arrayToTitleMap(modelService.models) @@ -126,7 +131,8 @@ name: { type: "string", minLength: 2, title: gettext("Name") }, description: { type: "string", minLength: 2, title: gettext("Description") }, genre: { type: "string", title: gettext("Genre") }, - } + }, + required: ['name', 'description', 'genre'] }; var config = { title: gettext('Update Policy'), @@ -146,7 +152,8 @@ type: "object", properties: { instructions: { type: "string", title: gettext("Instructions") } - } + }, + required: ['instructions'] }; var config = { @@ -179,11 +186,16 @@ } self.addRule = function addRule(policy) { + if (policy.model.meta_rules.length == 1) { + self.addRuleWithMetaRule(policy, policy.model.meta_rules[0]); + return; + } var schema = { type: "object", properties: { metaRuleId: { type: "string", title: gettext("Select a Metarule:") } - } + }, + required: ['metaRuleId'] }; var rule = { metaRuleId: null }; var titleMap = util.arrayToTitleMap(policy.model.meta_rules); @@ -201,7 +213,7 @@ } self.removePolicy = function removePolicy(policy) { - if (confirm(gettext('Are you sure to delete this Policy?'))) + if (confirm(gettext('Are you sure to delete this Policy? (Associated perimeter, data an PDP will be deleted too)'))) policyService.removePolicy(policy); } @@ -216,6 +228,7 @@ self.showRule = function showRule(rule) { self.selectedRule = rule; + self.currentData = null; } self.hideRule = function hideRule() { @@ -229,14 +242,22 @@ type: type, loading: true, perimeters: [], - assignments: [] + allPerimeters: [], + assignments: [], } policyService.loadPerimetersAndAssignments(type, policy).then(function (values) { var category = categoryMap[type]; self.currentData.loading = false; self.currentData.perimeters = values.perimeters; - for (var index = 0; index < values.assignments.length; index++) { + var index; + for (index = 0; index < values.allPerimeters.length; index++) { + var perimeter = values.allPerimeters[index]; + if (perimeter.policy_list.indexOf(policy.id) < 0) { + self.currentData.allPerimeters.push(perimeter); + } + } + for (index = 0; index < values.assignments.length; index++) { var assignment = values.assignments[index]; if (assignment.assignments.indexOf(data.id) >= 0) { var perimeter = values.perimetersMap[assignment[category.perimeterId]]; @@ -253,10 +274,12 @@ properties: { name: { type: "string", minLength: 2, title: gettext("Name") }, description: { type: "string", minLength: 2, title: gettext("Description") }, - } + }, + required: ['name', 'description'] }; if (type == 'subject') { schema.properties.email = { type: "email", "type": "string", "pattern": "^\\S+@\\S+$", title: gettext("Email") } + schema.required.push('email'); } var perimeter = { name: '', description: '' }; var config = { @@ -268,7 +291,7 @@ if (type == 'subject') { config.form.push('email'); } - + ModalFormService.open(config).then(submit); function submit(form) { @@ -278,6 +301,13 @@ } } + self.addPerimeter = function addPerimeter(type, policy, perimeter) { + policyService.addPerimeterToPolicy(type, policy, perimeter).then(function () { + self.currentData.allPerimeters.splice(self.currentData.allPerimeters.indexOf(perimeter), 1); + self.currentData.perimeters.push(perimeter); + }) + } + self.assign = function assign(type, policy, perimeter, data) { policyService.createAssignment(type, policy, perimeter, data).then(function () { self.currentData.assignments.push(perimeter); @@ -291,5 +321,21 @@ self.currentData.assignments.splice(self.currentData.assignments.indexOf(perimeter), 1); }) } + + self.removePerimeterFromPolicy = function removePerimeterFromPolicy(type, policy, perimeter) { + if (confirm(gettext('Are you sure to delete this Perimeter? (Associated assignments will be deleted too)'))) + policyService.removePerimeterFromPolicy(type, policy, perimeter).then(function () { + self.currentData.perimeters.splice(self.currentData.perimeters.indexOf(perimeter), 1); + perimeter.policy_list.splice(perimeter.policy_list.indexOf(policy.id), 1); + if (perimeter.policy_list.length > 0) { + self.currentData.allPerimeters.push(perimeter); + } + }) + } + + self.removeData = function removeData(type, policy, data) { + if (confirm(gettext('Are you sure to delete this Data? (Associated assignments and rules will be deleted too)'))) + policyService.removeData(type, policy, data) + } } })(); \ No newline at end of file diff --git a/moon_dashboard/moon/static/moon/policy/policy.html b/moon_dashboard/moon/static/moon/policy/policy.html index 70789fbb..ba13bec2 100644 --- a/moon_dashboard/moon/static/moon/policy/policy.html +++ b/moon_dashboard/moon/static/moon/policy/policy.html @@ -10,7 +10,7 @@
-
+

{$ policy.name $}

@@ -24,6 +24,46 @@ Genre: {$ policy.genre ? policy.genre : 'none' $} +
+ +

Warning!

+

+ Some data are unused, please check them and delete them if necessary. + Show unused data + Hide unused data +

+
+ +
+
+

Unused Subject data

+
+

{$ subject.name $}

+ +
+
+ +
+

Unused Object data

+
+

{$ object.name $}

+ +
+
+ +
+

Unused Action data

+
+

{$ action.name $}

+ +
+
+ +
+ +

Rules

@@ -85,7 +125,7 @@

- {$ data.name $} + {$ data.name $} + +

+

Click to add

+
+ +
+

Policy perimeters

- +
+ + {$ perimeter.name $} + + +
+

Click to assign

Assigned perimeters

- +

Click to unassign

diff --git a/moon_dashboard/moon/static/moon/policy/policy.service.js b/moon_dashboard/moon/static/moon/policy/policy.service.js index 87250b2e..3781156d 100755 --- a/moon_dashboard/moon/static/moon/policy/policy.service.js +++ b/moon_dashboard/moon/static/moon/policy/policy.service.js @@ -26,34 +26,55 @@ remove: { method: 'DELETE' } }); - var policySubjectDataResource = $resource(host + '/policies/' + ':policy_id' + '/subject_data/' + ':category_id', {}, { + var policySubjectDataResource = $resource(host + '/policies/' + ':policy_id' + '/subject_data/' + ':category_id' + '/' + ':data_id', {}, { query: {method: 'GET'}, create: { method: 'POST' }, + remove: { method: 'DELETE' } }) - var policyObjectDataResource = $resource(host + '/policies/' + ':policy_id' + '/object_data/' + ':category_id', {}, { + var policyObjectDataResource = $resource(host + '/policies/' + ':policy_id' + '/object_data/' + ':category_id' + '/' + ':data_id', {}, { query: {method: 'GET'}, create: { method: 'POST' }, + remove: { method: 'DELETE' } }) - var policyActionDataResource = $resource(host + '/policies/' + ':policy_id' + '/action_data/' + ':category_id', {}, { + var policyActionDataResource = $resource(host + '/policies/' + ':policy_id' + '/action_data/' + ':category_id' + '/' + ':data_id', {}, { query: {method: 'GET'}, create: { method: 'POST' }, + remove: { method: 'DELETE' } }) - var policySubjectPerimetersResource = $resource(host + '/policies/' + ':policy_id' + '/subjects', {}, { + var policySubjectPerimetersResource = $resource(host + '/policies/' + ':policy_id' + '/subjects/' + ':perimeter_id', {}, { query: {method: 'GET'}, create: { method: 'POST' }, + remove: { method: 'DELETE' } }) - var policyObjectPerimetersResource = $resource(host + '/policies/' + ':policy_id' + '/objects', {}, { + var policyObjectPerimetersResource = $resource(host + '/policies/' + ':policy_id' + '/objects/' + ':perimeter_id', {}, { query: {method: 'GET'}, create: { method: 'POST' }, + remove: { method: 'DELETE' } }) - var policyActionPerimetersResource = $resource(host + '/policies/' + ':policy_id' + '/actions', {}, { + var policyActionPerimetersResource = $resource(host + '/policies/' + ':policy_id' + '/actions/' + ':perimeter_id', {}, { query: {method: 'GET'}, create: { method: 'POST' }, + remove: { method: 'DELETE' } + }) + + var subjectPerimetersResource = $resource(host + '/subjects/' + ':perimeter_id', {}, { + query: {method: 'GET'}, + update: { method: 'PATCH' } + }) + + var objectPerimetersResource = $resource(host + '/objects/' + ':perimeter_id', {}, { + query: {method: 'GET'}, + update: { method: 'PATCH' } + }) + + var actionPerimetersResource = $resource(host + '/actions/' + ':perimeter_id', {}, { + query: {method: 'GET'}, + update: { method: 'PATCH' } }) var policySubjectAssignmentsResource = $resource(host + '/policies/' + ':policy_id' + '/subject_assignments/' + ':perimeter_id' + '/' + ':category_id' + '/' + ':data_id', {}, { @@ -81,30 +102,36 @@ arrayName: "subjectData", mapName: "subjectDataMap", responseName: "subject_data", - perimeterResource: policySubjectPerimetersResource, + policyPerimeterResource: policySubjectPerimetersResource, + perimeterResource: subjectPerimetersResource, assignmentResource: policySubjectAssignmentsResource, perimeterResponseName: "subjects", assignmentResponseName: "subject_assignments", + unusedArrayName: "unusedSubjectData", }, 'object': { resource: policyObjectDataResource, arrayName: "objectData", mapName: "objectDataMap", responseName: "object_data", - perimeterResource: policyObjectPerimetersResource, + policyPerimeterResource: policyObjectPerimetersResource, + perimeterResource: objectPerimetersResource, assignmentResource: policyObjectAssignmentsResource, perimeterResponseName: "objects", assignmentResponseName: "object_assignments", + unusedArrayName: "unusedObjectData", }, 'action': { resource: policyActionDataResource, arrayName: "actionData", mapName: "actionDataMap", responseName: "action_data", - perimeterResource: policyActionPerimetersResource, + policyPerimeterResource: policyActionPerimetersResource, + perimeterResource: actionPerimetersResource, assignmentResource: policyActionAssignmentsResource, perimeterResponseName: "actions", assignmentResponseName: "action_assignments", + unusedArrayName: "unusedActionData", } } @@ -149,6 +176,7 @@ function removeRuleInternal(policy, rule) { policy.rules.splice(policy.rules.indexOf(rule), 1); + updateUnusedData(policy); } function loadPolicyRule(policy) { @@ -161,11 +189,40 @@ } $q.all(queries).then(function (result) { - createRules(policy, result.rules, result.subjectData, result.objectData, result.actionData) + createRules(policy, result.rules, result.subjectData, result.objectData, result.actionData); + updateUnusedData(policy); }, util.displayErrorFunction('Unable to load rules')) } } + function updateUnusedData(policy) { + policy.unusedSubjectData.splice(0, policy.unusedSubjectData.length); + util.pushAll(policy.unusedSubjectData, policy.subjectData); + + policy.unusedObjectData.splice(0, policy.unusedObjectData.length); + util.pushAll(policy.unusedObjectData, policy.objectData); + + policy.unusedActionData.splice(0, policy.unusedActionData.length); + util.pushAll(policy.unusedActionData, policy.actionData); + + for (var i = 0; i < policy.rules.length; i++) { + var rule = policy.rules[i]; + removeUsedData(rule.subjectData, policy.unusedSubjectData); + removeUsedData(rule.objectData, policy.unusedObjectData); + removeUsedData(rule.actionData, policy.unusedActionData); + } + } + + function removeUsedData(list, orphanList) { + for (var j = 0; j < list.length; j++) { + var data = list[j]; + var notOrphanIndex = util.indexOf(orphanList, "id", data.id); + if (notOrphanIndex >= 0) { + orphanList.splice(notOrphanIndex, 1); + } + } + } + function createRules(policy, rulesData, subjectsData, objectsData, actionsData) { policy.rules = rulesData ? rulesData.rules.rules : []; policy.subjectDataMap = subjectsData.subject_data.length > 0 ? subjectsData.subject_data[0].data : []; @@ -174,6 +231,9 @@ policy.objectData = util.mapToArray(policy.objectDataMap); policy.actionDataMap = actionsData.action_data.length > 0 ? actionsData.action_data[0].data : []; policy.actionData = util.mapToArray(policy.actionDataMap); + policy.unusedSubjectData = []; + policy.unusedObjectData = []; + policy.unusedActionData = []; for (var i = 0; i < policy.rules.length; i++) { var rule = policy.rules[i]; populateRule(policy, rule); @@ -251,6 +311,7 @@ policy.rules.push(populateRule(policy, rule)) } util.displaySuccess('Rule created'); + updateUnusedData(policy); } }, removeRuleFromPolicy: function removeRuleFromPolicy(policy, rule) { @@ -267,14 +328,27 @@ function (data) { var result = util.createInternal(data[categoryValue.responseName].data, policy[categoryValue.arrayName], policy[categoryValue.mapName]); util.displaySuccess('Data created'); + util.pushAll(policy[categoryValue.unusedArrayName], result); return result; }, util.displayErrorFunction('Unable to create Data') ); }, + removeData: function removeData(type, policy, data) { + var categoryValue = categoryMap[type]; + return categoryValue.resource.remove({ policy_id: policy.id, category_id: data.category_id, data_id: data.id }).$promise.then( + function (data) { + policy[categoryValue.arrayName].splice(policy.subjectData.indexOf(data), 1); + policy[categoryValue.unusedArrayName].splice(policy.unusedSubjectData.indexOf(data), 1); + delete policy[categoryValue.mapName][data.id]; + util.displaySuccess('Data removed'); + }, + util.displayErrorFunction('Unable to remove Data') + ); + }, createPerimeter: function createPerimeter(type, policy, perimeter) { var categoryValue = categoryMap[type]; - return categoryValue.perimeterResource.create({ policy_id: policy.id }, perimeter).$promise.then( + return categoryValue.policyPerimeterResource.create({ policy_id: policy.id }, perimeter).$promise.then( function (data) { util.displaySuccess('Perimeter created'); return util.mapToArray(data[categoryValue.perimeterResponseName]); @@ -282,10 +356,33 @@ util.displayErrorFunction('Unable to create Perimeter') ); }, + removePerimeterFromPolicy: function removePerimeterFromPolicy(type, policy, perimeter) { + var categoryValue = categoryMap[type]; + + return categoryValue.policyPerimeterResource.remove({ policy_id: policy.id, perimeter_id: perimeter.id }, null).$promise.then( + function (data) { + util.displaySuccess('Perimeter removed'); + return perimeter; + }, + util.displayErrorFunction('Unable to remove Perimeter') + ) + }, + addPerimeterToPolicy: function addPerimeterToPolicy(type, policy, perimeter) { + var categoryValue = categoryMap[type]; + perimeter.policy_list.push(policy.id); + + return categoryValue.perimeterResource.update({ perimeter_id: perimeter.id }, perimeter).$promise.then( + function (data) { + util.displaySuccess('Perimeter added'); + }, + util.displayErrorFunction('Unable to add Perimeter') + ) + }, loadPerimetersAndAssignments: function loadPerimetersAndAssignments(type, policy) { var categoryValue = categoryMap[type]; var queries = { - perimeters: categoryValue.perimeterResource.query({ policy_id: policy.id }).$promise, + allPerimeters: categoryValue.perimeterResource.query().$promise, + perimeters: categoryValue.policyPerimeterResource.query({ policy_id: policy.id }).$promise, assignments: categoryValue.assignmentResource.query({ policy_id: policy.id }).$promise, } @@ -294,6 +391,7 @@ result.assignments = util.mapToArray(data.assignments[categoryValue.assignmentResponseName]); result.perimetersMap = data.perimeters[categoryValue.perimeterResponseName]; result.perimeters = util.mapToArray(result.perimetersMap); + result.allPerimeters = util.mapToArray(data.allPerimeters[categoryValue.perimeterResponseName]); return result; }, util.displayErrorFunction('Unable to load Perimeters')) diff --git a/moon_dashboard/moon/static/moon/policy/policy.service.spec.js b/moon_dashboard/moon/static/moon/policy/policy.service.spec.js index 045bf9b3..8d0ca8bf 100755 --- a/moon_dashboard/moon/static/moon/policy/policy.service.spec.js +++ b/moon_dashboard/moon/static/moon/policy/policy.service.spec.js @@ -329,6 +329,157 @@ }); + it('should create perimeter', function () { + var perimeterCreatedData = { + subjects: { + 'subjectId1': { name: 'subject1', description: 'sDescription1' }, + } + }; + + $httpBackend.expectPOST(URI.API + '/policies/policyId1/subjects').respond(200, perimeterCreatedData); + var type = 'subject'; + var policy = { id: 'policyId1' }; + var perimeter = { name: 'subject1', description: 'sDescription1' }; + + var promise = service.createPerimeter(type, policy, perimeter); + $httpBackend.flush(); + + promise.then(function (result) { + expect(result.length).toBe(1); + var perimeter = result[0]; + expect(perimeter.id).toBe('subjectId1'); + expect(perimeter.name).toBe('subject1'); + expect(perimeter.description).toBe('sDescription1'); + }) + }); + + it('should remove perimeter', function () { + $httpBackend.expectDELETE(URI.API + '/policies/policyId1/subjects/subjectId1').respond(200); + var type = 'subject'; + var policy = { id: 'policyId1' }; + var perimeter = { id: 'subjectId1' }; + + var promise = service.removePerimeterFromPolicy(type, policy, perimeter); + $httpBackend.flush(); + + promise.then(function (result) { + expect(result.id).toBe('subjectId1'); + }) + }); + + it('should load perimeters and assignments', function () { + var assignmentsData = { + subject_assignments: { + 'subjectAssignmentId1': { + id: 'subjectAssignmentId1', + policy_id: 'policyId1', + subject_id: 'subjectId1', + category_id: 'subjectCategoryId1', + assignments: ['subjectDataId1'] + }, + } + }; + + var perimetersData = { + subjects: { + 'subjectId1': { name: 'subject1', description: 'sDescription1' }, + } + }; + + var allPerimetersData = { + subjects: { + 'subjectId1': { name: 'subject1', description: 'sDescription1' }, + 'subjectId2': { name: 'subject2', description: 'sDescription2' }, + } + }; + + var type = 'subject'; + var policy = { id: 'policyId1' }; + $httpBackend.expectGET(URI.API + '/subjects').respond(200, allPerimetersData); + $httpBackend.expectGET(URI.API + '/policies/policyId1/subjects').respond(200, perimetersData); + $httpBackend.expectGET(URI.API + '/policies/policyId1/subject_assignments').respond(200, assignmentsData); + + var promise = service.loadPerimetersAndAssignments(type, policy); + + $httpBackend.flush(); + + promise.then(function (result) { + expect(result.perimeters.length).toBe(1); + var perimeter = result.perimeters[0]; + expect(perimeter.id).toBe('subjectId1'); + expect(perimeter.name).toBe('subject1'); + expect(perimeter.description).toBe('sDescription1'); + + expect(result.allPerimeters.length).toBe(2); + perimeter = result.allPerimeters[0]; + expect(perimeter.id).toBe('subjectId1'); + expect(perimeter.name).toBe('subject1'); + expect(perimeter.description).toBe('sDescription1'); + + perimeter = result.allPerimeters[1]; + expect(perimeter.id).toBe('subjectId2'); + expect(perimeter.name).toBe('subject2'); + expect(perimeter.description).toBe('sDescription2'); + + + expect(result.assignments.length).toBe(1); + var assignment = result.assignments[0]; + expect(assignment.id).toBe('subjectAssignmentId1'); + expect(assignment.policy_id).toBe('policyId1'); + expect(assignment.subject_id).toBe('subjectId1'); + expect(assignment.category_id).toBe('subjectCategoryId1'); + expect(assignment.assignments.length).toBe(1); + expect(assignment.assignments[0]).toBe('subjectDataId1'); + }) + + }); + + it('should create assignment', function () { + var assignmentCreatedData = { + subject_assignments: { + 'subjectAssignmentId1': { + id: 'subjectAssignmentId1', + policy_id: 'policyId1', + subject_id: 'subjectId1', + category_id: 'subjectCategoryId1', + assignments: ['subjectDataId1'] + }, + } + }; + + var type = 'subject'; + var policy = { id: 'policyId1' }; + var perimeter = { id: 'subjectId1' }; + var data = { id: 'subjectDataId1', category_id: 'subjectCategoryId1'}; + + $httpBackend.expectPOST(URI.API + '/policies/policyId1/subject_assignments').respond(200, assignmentCreatedData); + var promise = service.createAssignment(type, policy, perimeter, data); + + $httpBackend.flush(); + + promise.then(function (result) { + expect(result.length).toBe(1); + var assignment = result[0]; + expect(assignment.id).toBe('subjectAssignmentId1'); + expect(assignment.policy_id).toBe('policyId1'); + expect(assignment.subject_id).toBe('subjectId1'); + expect(assignment.category_id).toBe('subjectCategoryId1'); + expect(assignment.assignments.length).toBe(1); + expect(assignment.assignments[0]).toBe('subjectDataId1'); + }) + }); + + it('should remove assignment', function () { + var type = 'subject'; + var policy = { id: 'policyId1' }; + var perimeter = { id: 'subjectId1' }; + var data = { id: 'subjectDataId1', category_id: 'subjectCategoryId1'}; + + $httpBackend.expectDELETE(URI.API + '/policies/policyId1/subject_assignments/subjectId1/subjectCategoryId1/subjectDataId1').respond(200); + service.removeAssignment(type, policy, perimeter, data); + $httpBackend.flush(); + }); + }); diff --git a/moon_dashboard/moon/static/moon/scss/moon.scss b/moon_dashboard/moon/static/moon/scss/moon.scss index 20bf6c41..3cdbb6e3 100644 --- a/moon_dashboard/moon/static/moon/scss/moon.scss +++ b/moon_dashboard/moon/static/moon/scss/moon.scss @@ -51,4 +51,8 @@ details { .input-file { display: none !important; +} + +.overflow-hidden { + overflow: hidden; } \ No newline at end of file diff --git a/moon_dashboard/run.sh b/moon_dashboard/run.sh index bf18faa2..9a68ca6e 100644 --- a/moon_dashboard/run.sh +++ b/moon_dashboard/run.sh @@ -1,26 +1,42 @@ #!/bin/sh # sudo docker run -ti --rm -p 8000:8000 -e MANAGER_HOST=localhost -e MANAGER_PORT=30001 -e KEYSTONE_HOST=localhost -e KEYSTONE_PORT=30005 moonplatform/dashboard:dev +echo ----------------------------------- +export OPENSTACK_KEYSTONE_URL="http://${KEYSTONE_HOST}:${KEYSTONE_PORT}/identity/v3" +echo MANAGER_HOST=${MANAGER_HOST} +echo MANAGER_PORT=${MANAGER_PORT} +echo KEYSTONE_HOST=${KEYSTONE_HOST} +echo KEYSTONE_PORT=${KEYSTONE_PORT} +echo OPENSTACK_HOST=${OPENSTACK_HOST} +echo OPENSTACK_KEYSTONE_URL=${OPENSTACK_KEYSTONE_URL} +echo SERVER_IP_ADDR=${SERVER_IP_ADDR} +echo ----------------------------------- + CONSTANT_FILE=/root/horizon/openstack_dashboard/dashboards/moon/static/moon/js/moon.module.js -sed "s/{{MANAGER_HOST}}/$MANAGER_HOST/g" -i $CONSTANT_FILE -sed "s/{{MANAGER_PORT}}/$MANAGER_PORT/g" -i $CONSTANT_FILE -sed "s/{{KEYSTONE_HOST}}/$KEYSTONE_HOST/g" -i $CONSTANT_FILE -sed "s/{{KEYSTONE_PORT}}/$KEYSTONE_PORT/g" -i $CONSTANT_FILE +sed "s/{{MANAGER_HOST}}/${MANAGER_HOST}/g" -i ${CONSTANT_FILE} +sed "s/{{MANAGER_PORT}}/${MANAGER_PORT}/g" -i ${CONSTANT_FILE} +sed "s/{{KEYSTONE_HOST}}/${KEYSTONE_HOST}/g" -i ${CONSTANT_FILE} +sed "s/{{KEYSTONE_PORT}}/${KEYSTONE_PORT}/g" -i ${CONSTANT_FILE} cd /root/horizon LOCAL_SETTINGS=/root/horizon/openstack_dashboard/local/local_settings.py -sed "s/OPENSTACK_HOST = \"127.0.0.1\"/OPENSTACK_HOST = \"${OPENSTACK_HOST}\"/" -i $LOCAL_SETTINGS -sed "s#OPENSTACK_KEYSTONE_URL = \"http:\/\/%s:5000\/v2.0\" % OPENSTACK_HOST#OPENSTACK_KEYSTONE_URL = \"${OPENSTACK_KEYSTONE_URL}\"#" -i $LOCAL_SETTINGS + +sed "s/OPENSTACK_HOST = \"127.0.0.1\"/OPENSTACK_HOST = \"${OPENSTACK_HOST}\"/" -i ${LOCAL_SETTINGS} +sed "s#OPENSTACK_KEYSTONE_URL = \"http://%s:5000/v3\" % OPENSTACK_HOST#OPENSTACK_KEYSTONE_URL = \"${OPENSTACK_KEYSTONE_URL}\"#" -i ${LOCAL_SETTINGS} +sed "s/#ALLOWED_HOSTS = \['horizon.example.com', \]/ALLOWED_HOSTS = \['${SERVER_IP_ADDR}'\]/" -i ${LOCAL_SETTINGS} echo ----------------- -grep OPENSTACK_HOST $LOCAL_SETTINGS -grep OPENSTACK_KEYSTONE_URL LOCAL_SETTINGS +grep OPENSTACK_HOST ${LOCAL_SETTINGS} +grep ALLOWED_HOSTS ${LOCAL_SETTINGS} echo ----------------- +export NO_PROXY=127.0.0.1,10.0.2.15,10.96.0.0/12,192.168.0.0/16,10.192.118.95,10.192.118.96,keystone,manager,devstack + +echo "${KEYSTONE_HOST} devstack, keystone" | tee -a /etc/hosts -echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $CONSTANT_FILE" -cat $CONSTANT_FILE +echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ${CONSTANT_FILE}" +cat ${CONSTANT_FILE} echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" -tox -e runserver -- 0.0.0.0:8000 \ No newline at end of file +tox -e runserver -- 0.0.0.0:8000 diff --git a/moon_dashboard/setup.cfg b/moon_dashboard/setup.cfg index f68765dd..9cf3f779 100644 --- a/moon_dashboard/setup.cfg +++ b/moon_dashboard/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = moon -version=1.2.0 +version=1.5.0 summary = A dashboard plugin for Moon description-file = README.rst -- cgit 1.2.3-korg