diff options
author | Thomas Duval <thomas.duval@orange.com> | 2018-06-19 16:13:31 +0200 |
---|---|---|
committer | Thomas Duval <thomas.duval@orange.com> | 2018-06-19 16:30:55 +0200 |
commit | 2dbe655587ca98b67c1a3e3798c63fd47229adc0 (patch) | |
tree | df374b5378225c9946ec0c97968bfa591fb9f9b6 /moon_dashboard/moon/static/moon/policy | |
parent | d28f8e68ac176a15dbbd7873f757f5a9f221d118 (diff) |
Update code to 4.5 official version
Change-Id: I5075da0e2a3247ae1564f21b358748f482b75aa4
Diffstat (limited to 'moon_dashboard/moon/static/moon/policy')
4 files changed, 1119 insertions, 0 deletions
diff --git a/moon_dashboard/moon/static/moon/policy/policy.controller.js b/moon_dashboard/moon/static/moon/policy/policy.controller.js new file mode 100644 index 00000000..6c6631cf --- /dev/null +++ b/moon_dashboard/moon/static/moon/policy/policy.controller.js @@ -0,0 +1,295 @@ +(function () { + 'use strict'; + + angular + .module('moon') + .controller('moon.policy.controller', + controller); + + controller.$inject = ['moon.util.service', 'moon.policy.service', 'moon.model.service', 'horizon.framework.widgets.form.ModalFormService']; + + function controller(util, policyService, modelService, ModalFormService) { + var self = this; + var genres = [{ value: 'admin', name: gettext('admin') }, { value: 'authz', name: gettext('authz') }]; + self.model = policyService; + self.selectedRule = null; + self.currentData = null; + policyService.initialize(); + + var dataTitleMaps = {}; + + var categoryMap = { + subject: { + perimeterId: 'subject_id' + }, + object: { + perimeterId: 'object_id' + }, + action: { + perimeterId: 'action_id' + }, + } + + function createAddDataButton(type, index, category, config, policy) { + config.form.push({ + "key": type + index + "Button", + "type": "button", + "title": "Add", + onClick: createDataFunction(type, category, policy) + }) + } + + function createDataFunction(type, category, policy) { + return function () { + var schema = { + type: "object", + properties: { + name: { type: "string", minLength: 2, title: gettext("Name") }, + description: { type: "string", minLength: 2, title: gettext("Description") }, + } + }; + var data = { name: '', description: '' }; + var config = { + title: gettext('Create Data of ' + category.name + ' category'), + schema: schema, + form: ['name', { key: 'description', type: 'textarea' }], + model: data + }; + ModalFormService.open(config).then(submit); + + function submit(form) { + policyService.createData(type, policy, category, form.model).then( + function (data) { + util.pushAll(dataTitleMaps[category.id], util.arrayToTitleMap(data)); + } + ); + } + } + } + + function getOrCreateDataTitleMap(category, data, policy) { + var result = dataTitleMaps[category.id]; + if (!result) { + result = util.arrayToTitleMap(data); + dataTitleMaps[category.id] = result; + } + return result; + } + + function createDataSelect(type, categories, data, config, policy) { + for (var i = 0; i < categories.length; i++) { + var category = categories[i]; + 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 }); + createAddDataButton(type, i, category, config, policy); + } + } + + function pushData(type, model, array) { + var i = 0; + while ((type + i) in model) { + array.push(model[type + i]); + i++; + } + } + + self.createPolicy = function createPolicy() { + var schema = { + type: "object", + properties: { + name: { type: "string", minLength: 2, title: gettext("Name") }, + description: { type: "string", minLength: 2, title: gettext("Description") }, + genre: { type: "string", title: gettext("genre") }, + model_id: { type: "string", title: gettext("Select a Model:") } + } + }; + var policy = { name: '', description: '', model_id: null, genre: '' }; + var titleMap = util.arrayToTitleMap(modelService.models) + var config = { + title: gettext('Create Policy'), + schema: schema, + form: ['name', { key: 'description', type: 'textarea' }, { key: 'genre', type: 'select', titleMap: genres }, { key: 'model_id', type: 'select', titleMap: titleMap }], + model: policy + }; + ModalFormService.open(config).then(submit); + + function submit(form) { + policyService.createPolicy(form.model); + } + } + + self.updatePolicy = function updatePolicy(policy) { + var schema = { + type: "object", + properties: { + name: { type: "string", minLength: 2, title: gettext("Name") }, + description: { type: "string", minLength: 2, title: gettext("Description") }, + genre: { type: "string", title: gettext("Genre") }, + } + }; + var config = { + title: gettext('Update Policy'), + schema: schema, + form: ['name', { key: 'description', type: 'textarea' }, { key: 'genre', type: 'select', titleMap: genres }], + model: { name: policy.name, description: policy.description, model_id: policy.model_id, id: policy.id, genre: policy.genre } + }; + ModalFormService.open(config).then(submit); + + function submit(form) { + policyService.updatePolicy(form.model); + } + } + + self.addRuleWithMetaRule = function addRuleWithMetaRule(policy, metaRule) { + var schema = { + type: "object", + properties: { + instructions: { type: "string", title: gettext("Instructions") } + } + }; + + var config = { + title: gettext('Add Rule'), + schema: schema, + form: [], + model: { + instructions: '[{"decision": "grant"}]' + } + }; + dataTitleMaps = {}; + createDataSelect('subject', metaRule.subject_categories, policy.subjectData, config, policy); + createDataSelect('object', metaRule.object_categories, policy.objectData, config, policy); + createDataSelect('action', metaRule.action_categories, policy.actionData, config, policy); + config.form.push({ key: 'instructions', type: 'textarea' }) + + ModalFormService.open(config).then(submit); + + function submit(form) { + var rule = { enabled: true }; + rule.instructions = JSON.parse(form.model.instructions); + rule.meta_rule_id = metaRule.id; + rule.policy_id = policy.id; + rule.rule = []; + pushData('subject', form.model, rule.rule); + pushData('object', form.model, rule.rule); + pushData('action', form.model, rule.rule); + policyService.addRuleToPolicy(policy, rule); + } + } + + self.addRule = function addRule(policy) { + var schema = { + type: "object", + properties: { + metaRuleId: { type: "string", title: gettext("Select a Metarule:") } + } + }; + var rule = { metaRuleId: null }; + var titleMap = util.arrayToTitleMap(policy.model.meta_rules); + var config = { + title: gettext('Add Rule'), + schema: schema, + form: [{ key: 'metaRuleId', type: 'select', titleMap: titleMap }], + model: rule + }; + ModalFormService.open(config).then(submit); + + function submit(form) { + self.addRuleWithMetaRule(policy, modelService.getMetaRule(form.model.metaRuleId)); + } + } + + self.removePolicy = function removePolicy(policy) { + if (confirm(gettext('Are you sure to delete this Policy?'))) + policyService.removePolicy(policy); + } + + self.populatePolicy = function populatePolicy(policy) { + policyService.populatePolicy(policy); + } + + self.removeRuleFromPolicy = function removeRuleFromPolicy(policy, rule) { + if (confirm(gettext('Are you sure to delete this Rule?'))) + policyService.removeRuleFromPolicy(policy, rule); + } + + self.showRule = function showRule(rule) { + self.selectedRule = rule; + } + + self.hideRule = function hideRule() { + self.selectedRule = null; + self.currentData = null; + } + + self.assignData = function assignData(type, policy, data) { + self.currentData = { + data: data, + type: type, + loading: true, + perimeters: [], + 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 assignment = values.assignments[index]; + if (assignment.assignments.indexOf(data.id) >= 0) { + var perimeter = values.perimetersMap[assignment[category.perimeterId]]; + self.currentData.assignments.push(perimeter); + self.currentData.perimeters.splice(self.currentData.perimeters.indexOf(perimeter), 1); + } + } + }) + } + + self.createPerimeter = function createPerimeter(type, policy) { + var schema = { + type: "object", + properties: { + name: { type: "string", minLength: 2, title: gettext("Name") }, + description: { type: "string", minLength: 2, title: gettext("Description") }, + } + }; + if (type == 'subject') { + schema.properties.email = { type: "email", "type": "string", "pattern": "^\\S+@\\S+$", title: gettext("Email") } + } + var perimeter = { name: '', description: '' }; + var config = { + title: gettext('Create Perimeter'), + schema: schema, + form: ['name', { key: 'description', type: 'textarea' }], + model: perimeter + }; + if (type == 'subject') { + config.form.push('email'); + } + + ModalFormService.open(config).then(submit); + + function submit(form) { + policyService.createPerimeter(type, policy, form.model).then(function (perimeters) { + util.pushAll(self.currentData.perimeters, perimeters); + }) + } + } + + self.assign = function assign(type, policy, perimeter, data) { + policyService.createAssignment(type, policy, perimeter, data).then(function () { + self.currentData.assignments.push(perimeter); + self.currentData.perimeters.splice(self.currentData.perimeters.indexOf(perimeter), 1); + }) + } + + self.unassign = function unassign(type, policy, perimeter, data) { + policyService.removeAssignment(type, policy, perimeter, data).then(function () { + self.currentData.perimeters.push(perimeter); + self.currentData.assignments.splice(self.currentData.assignments.indexOf(perimeter), 1); + }) + } + } +})();
\ 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 new file mode 100644 index 00000000..70789fbb --- /dev/null +++ b/moon_dashboard/moon/static/moon/policy/policy.html @@ -0,0 +1,158 @@ +<div ng-controller="moon.policy.controller as ctrl"> + <div class="clearfix list-group"> + <div class="pull-right"> + <input type="search" class="form-control filter" placeholder="Filter" ng-model="filterText"> + <button type="button" class="btn btn-default" ng-click="ctrl.createPolicy()"> + <span class="fa fa-plus"></span> + <translate>Create Policy</translate> + </button> + </div> + </div> + + <div class="list-group"> + <div ng-repeat="policy in ctrl.model.policies | orderBy:'name' | filter:filterText" class="list-group-item"> + <h3 class="list-group-item-heading inline">{$ policy.name $}</h3> + <div class="pull-right"> + <button type="button" class="fa fa-trash" title="{$ 'Remove Policy' | translate $}" ng-click="ctrl.removePolicy(policy)"></button> + <button type="button" class="fa fa-edit" title="{$ 'Edit Policy' | translate $}" ng-click="ctrl.updatePolicy(policy)"></button> + </div> + <p class="list-group-item-text">{$ policy.description $}</p> + <h4 class="list-group-item-text"> + <translate>Model: {$ policy.model ? policy.model.name : 'none' $}</translate> + </h4> + <h4 class="list-group-item-text"> + <translate>Genre:</translate> + <translate>{$ policy.genre ? policy.genre : 'none' $}</translate> + </h4> + <details class="list-group-item-text"> + <summary ng-click="ctrl.populatePolicy(policy)"> + <h4 class="inline" translate>Rules</h4> + <button type="button" class="fa fa-plus " ng-click="ctrl.addRule(policy)" title="{$ 'Add Rule' | translate $}"></button> + </summary> + <div class="list-group"> + <p ng-if="!policy.rules" class="list-group-item-text" translate>Loading rules...</p> + <div ng-if="policy.rules" ng-repeat="rule in policy.rules | orderBy:'name'" class="list-group-item"> + <div class="list-group-item-heading" ng-if="ctrl.selectedRule != rule"> + <div class="inline-block width-200"> + <b> + <translate>Metarule: </translate> + </b> {$ rule.metaRule.name $} + </div> + <b> + <translate>Rule: </translate> + </b> + <span ng-repeat="data in rule.subjectData"> + <span>{$ data.name $}{$ $last ? '' : ', ' $}</span> + </span> | + <span ng-repeat="data in rule.actionData"> + <span>{$ data.name $}{$ $last ? '' : ', ' $}</span> + </span> | + <span ng-repeat="data in rule.objectData"> + <span>{$ data.name $}{$ $last ? '' : ', ' $}</span> + </span> + <div class="pull-right"> + <button type="button" class="fa fa-trash pull-right" ng-click="ctrl.removeRuleFromPolicy(policy, rule)" title="{$ 'Remove Rule' | translate $}"></button> + <button type="button" class="fa fa-eye pull-right" ng-click="ctrl.showRule(rule)" title="{$ 'Show Rule' | translate $}"></button> + </div> + </div> + + <div ng-if="ctrl.selectedRule == rule"> + <h3 class="list-group-item-heading inline"> + <translate>Metarule: </translate> {$ rule.metaRule.name $}</h3> + <div class="pull-right"> + <button type="button" class="fa fa-trash pull-right" ng-click="ctrl.removeRuleFromPolicy(policy, rule)" title="{$ 'Remove Rule' | translate $}"></button> + <button type="button" class="fa fa-eye-slash pull-right" ng-click="ctrl.hideRule()" title="{$ 'Hide Rule' | translate $}"></button> + </div> + <p class="list-group-item-text"> + <table class="table"> + <thead> + <tr> + <th> + <span translate>Subjects</span> + </th> + <th> + <span translate>Objects</span> + </th> + <th> + <span translate>Actions</span> + </th> + <th> + <span translate>Instructions</span> + </th> + </tr> + </thead> + <tbody> + <tr> + <td> + <p ng-repeat="data in rule.subjectData"> + <span ng-class="{'text-primary': ctrl.currentData.data == data}">{$ data.name $}</span> + <button ng-if="ctrl.currentData.data != data" type="button" class="fa fa-exchange pull-right" ng-click="ctrl.assignData('subject', policy, data)" + title="{$ 'Assign to perimeters' | translate $}"></button> + <button ng-if="ctrl.currentData.data == data" type="button" class="fa fa-times pull-right" ng-click="ctrl.currentData = null" + title="{$ 'Close' | translate $}"></button> + </p> + </td> + <td> + <p ng-repeat="data in rule.objectData"> + <span ng-class="{'text-primary': ctrl.currentData.data == data}">{$ data.name $}</span> + <button ng-if="ctrl.currentData.data != data" type="button" class="fa fa-exchange pull-right" ng-click="ctrl.assignData('object', policy, data)" + title="{$ 'Assign to perimeters' | translate $}"></button> + <button ng-if="ctrl.currentData.data == data" type="button" class="fa fa-times pull-right" ng-click="ctrl.currentData = null" + title="{$ 'Close' | translate $}"></button> + </p> + </td> + <td> + <p ng-repeat="data in rule.actionData"> + <span ng-class="{'text-primary': ctrl.currentData.data == data}">{$ data.name $}</span> + <button ng-if="ctrl.currentData.data != data" type="button" class="fa fa-exchange pull-right" ng-click="ctrl.assignData('action', policy, data)" + title="{$ 'Assign to perimeters' | translate $}"></button> + <button ng-if="ctrl.currentData.data == data" type="button" class="fa fa-times pull-right" ng-click="ctrl.currentData = null" + title="{$ 'Close' | translate $}"></button> + </p> + </td> + <td> + <pre ng-bind="rule.instructions | json "></pre> + </td> + </tr> + </tbody> + </table> + <div ng-if="ctrl.currentData && ctrl.currentData.loading" class="row padding-10"> + <h4 translate>Loading...</h4> + </div> + <div ng-if="ctrl.currentData && !ctrl.currentData.loading" class="row"> + <div class="padding-10"> + <h3> + <translate>Assign perimeters to</translate> {$ ctrl.currentData.data.name $}</h3> + <input type="search" class="form-control filter" placeholder="Filter" ng-model="filterPerimeter"> + <button type="button" class="btn btn-default" ng-click="ctrl.createPerimeter(ctrl.currentData.type, policy)"> + <span class="fa fa-plus"></span> + <translate>Create Perimeter</translate> + </button> + </div> + <div> + <div class="col-lg-4"> + <h4 translate>Available perimeters</h4> + <div class="w-100 height-200 scroll list-group border"> + <button class="list-group-item" ng-repeat="perimeter in ctrl.currentData.perimeters | orderBy:'name' | filter:filterPerimeter" title="{$ perimeter.description $}" + ng-click="ctrl.assign(ctrl.currentData.type, policy, perimeter, ctrl.currentData.data)">{$ perimeter.name $}</button> + </div> + <p translate class="mt-5">Click to assign</p> + </div> + <div class="col-lg-4"> + <h4 translate>Assigned perimeters</h4> + <div class="w-100 list-group border height-200 scroll"> + <button class="list-group-item" ng-repeat="perimeter in ctrl.currentData.assignments | orderBy:'name' | filter:filterPerimeter" title="{$ perimeter.description $}" + ng-click="ctrl.unassign(ctrl.currentData.type, policy, perimeter, ctrl.currentData.data)">{$ perimeter.name $}</button> + </div> + <p translate class="mt-5">Click to unassign</p> + </div> + </div> + </div> + </p> + </div> + </div> + </div> + </details> + </div> + </div> +</div>
\ No newline at end of file diff --git a/moon_dashboard/moon/static/moon/policy/policy.service.js b/moon_dashboard/moon/static/moon/policy/policy.service.js new file mode 100755 index 00000000..87250b2e --- /dev/null +++ b/moon_dashboard/moon/static/moon/policy/policy.service.js @@ -0,0 +1,330 @@ +(function () { + + 'use strict'; + + angular + .module('moon') + .factory('moon.policy.service', policyService); + + policyService.$inject = ['moon.util.service', 'moon.model.service', '$resource', 'moon.URI', '$q', 'horizon.framework.widgets.toast.service']; + + function policyService(util, modelService, $resource, URI, $q, toast) { + var host = URI.API; + + var policyResource = $resource(host + '/policies/' + ':id', {}, { + get: { method: 'GET' }, + query: { method: 'GET' }, + create: { method: 'POST' }, + remove: { method: 'DELETE' }, + update: { method: 'PATCH' } + }); + + var policyRulesResource = $resource(host + '/policies/' + ':policy_id' + '/rules/' + ':rule_id', {}, { + get: { method: 'GET' }, + query: { method: 'GET' }, + create: { method: 'POST' }, + remove: { method: 'DELETE' } + }); + + var policySubjectDataResource = $resource(host + '/policies/' + ':policy_id' + '/subject_data/' + ':category_id', {}, { + query: {method: 'GET'}, + create: { method: 'POST' }, + }) + + var policyObjectDataResource = $resource(host + '/policies/' + ':policy_id' + '/object_data/' + ':category_id', {}, { + query: {method: 'GET'}, + create: { method: 'POST' }, + }) + + var policyActionDataResource = $resource(host + '/policies/' + ':policy_id' + '/action_data/' + ':category_id', {}, { + query: {method: 'GET'}, + create: { method: 'POST' }, + }) + + var policySubjectPerimetersResource = $resource(host + '/policies/' + ':policy_id' + '/subjects', {}, { + query: {method: 'GET'}, + create: { method: 'POST' }, + }) + + var policyObjectPerimetersResource = $resource(host + '/policies/' + ':policy_id' + '/objects', {}, { + query: {method: 'GET'}, + create: { method: 'POST' }, + }) + + var policyActionPerimetersResource = $resource(host + '/policies/' + ':policy_id' + '/actions', {}, { + query: {method: 'GET'}, + create: { method: 'POST' }, + }) + + var policySubjectAssignmentsResource = $resource(host + '/policies/' + ':policy_id' + '/subject_assignments/' + ':perimeter_id' + '/' + ':category_id' + '/' + ':data_id', {}, { + query: {method: 'GET'}, + create: { method: 'POST' }, + remove: { method: 'DELETE' } + }) + + var policyObjectAssignmentsResource = $resource(host + '/policies/' + ':policy_id' + '/object_assignments/' + ':perimeter_id' + '/' + ':category_id' + '/' + ':data_id', {}, { + query: {method: 'GET'}, + create: { method: 'POST' }, + remove: { method: 'DELETE' } + }) + + var policyActionAssignmentsResource = $resource(host + '/policies/' + ':policy_id' + '/action_assignments/' + ':perimeter_id' + '/' + ':category_id' + '/' + ':data_id', {}, { + query: {method: 'GET'}, + create: { method: 'POST' }, + remove: { method: 'DELETE' } + }) + + + var categoryMap = { + 'subject': { + resource: policySubjectDataResource, + arrayName: "subjectData", + mapName: "subjectDataMap", + responseName: "subject_data", + perimeterResource: policySubjectPerimetersResource, + assignmentResource: policySubjectAssignmentsResource, + perimeterResponseName: "subjects", + assignmentResponseName: "subject_assignments", + }, + 'object': { + resource: policyObjectDataResource, + arrayName: "objectData", + mapName: "objectDataMap", + responseName: "object_data", + perimeterResource: policyObjectPerimetersResource, + assignmentResource: policyObjectAssignmentsResource, + perimeterResponseName: "objects", + assignmentResponseName: "object_assignments", + }, + 'action': { + resource: policyActionDataResource, + arrayName: "actionData", + mapName: "actionDataMap", + responseName: "action_data", + perimeterResource: policyActionPerimetersResource, + assignmentResource: policyActionAssignmentsResource, + perimeterResponseName: "actions", + assignmentResponseName: "action_assignments", + } + } + + var policiesMap = {}; + var policies = []; + + function loadPolicies() { + var queries = { + policies: policyResource.query().$promise, + models: modelService.initialize(), + } + + $q.all(queries).then(function (result) { + createPolicies(result.policies); + console.log('moon', 'policies initialized') + }) + } + + function createPolicies(policiesData) { + policies.splice(0, policies.length); + util.cleanObject(policiesMap); + createPolicyInternal(policiesData.policies); + } + + function mapPolicy(policy) { + if (policy.model_id) { + policy.model = modelService.getModel(policy.model_id); + } + } + + function createPolicyInternal(data) { + return util.createInternal(data, policies, policiesMap, mapPolicy); + } + + function removePolicyInternal(id) { + return util.removeInternal(id, policies, policiesMap); + } + + function updatePolicyInternal(data) { + return util.updateInternal(data, policiesMap, mapPolicy); + } + + function removeRuleInternal(policy, rule) { + policy.rules.splice(policy.rules.indexOf(rule), 1); + } + + function loadPolicyRule(policy) { + if (!policy.rules) { + var queries = { + rules: policyRulesResource.query({ policy_id: policy.id }).$promise, + subjectData: policySubjectDataResource.query({ policy_id: policy.id }).$promise, + objectData: policyObjectDataResource.query({ policy_id: policy.id }).$promise, + actionData: policyActionDataResource.query({ policy_id: policy.id }).$promise, + } + + $q.all(queries).then(function (result) { + createRules(policy, result.rules, result.subjectData, result.objectData, result.actionData) + }, util.displayErrorFunction('Unable to load rules')) + } + } + + 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 : []; + policy.subjectData = util.mapToArray(policy.subjectDataMap); + policy.objectDataMap = objectsData.object_data.length > 0 ? objectsData.object_data[0].data : []; + policy.objectData = util.mapToArray(policy.objectDataMap); + policy.actionDataMap = actionsData.action_data.length > 0 ? actionsData.action_data[0].data : []; + policy.actionData = util.mapToArray(policy.actionDataMap); + for (var i = 0; i < policy.rules.length; i++) { + var rule = policy.rules[i]; + populateRule(policy, rule); + } + } + + function populateRule(policy, rule) { + if (rule.meta_rule_id) { + rule.metaRule = modelService.getMetaRule(rule.meta_rule_id); + } + if (rule.metaRule) { + var j = 0; + var k, id; + rule.subjectData = []; + rule.objectData = []; + rule.actionData = []; + for (k = 0; k < rule.metaRule.subject_categories.length; k++) { + id = rule.rule[j + k]; + rule.subjectData.push(policy.subjectDataMap[id]); + } + j += k; + for (k = 0; k < rule.metaRule.object_categories.length; k++) { + id = rule.rule[j + k]; + rule.objectData.push(policy.objectDataMap[id]); + } + j += k; + for (k = 0; k < rule.metaRule.action_categories.length; k++) { + id = rule.rule[j + k]; + rule.actionData.push(policy.actionDataMap[id]); + } + } + return rule; + } + + return { + initialize: loadPolicies, + createPolicies: createPolicies, + policies: policies, + getPolicy: function getPolicy(id) { + return policiesMap[id]; + }, + createPolicy: function createPolicy(policy) { + policyResource.create(null, policy, success, util.displayErrorFunction('Unable to create Policy')); + + function success(data) { + createPolicyInternal(data.policies); + util.displaySuccess('Policy created'); + } + }, + removePolicy: function removePolicy(policy) { + policyResource.remove({ id: policy.id }, null, success, util.displayErrorFunction('Unable to remove Policy')); + + function success(data) { + removePolicyInternal(policy.id); + util.displaySuccess('Policy removed'); + } + }, + updatePolicy: function updatePolicy(policy) { + policyResource.update({ id: policy.id }, policy, success, util.displayErrorFunction('Unable to update Policy')); + + function success(data) { + updatePolicyInternal(data.policies) + util.displaySuccess('Policy updated'); + } + }, + populatePolicy: loadPolicyRule, + createRules: createRules, + addRuleToPolicy: function addRuleToPolicy(policy, rule) { + policyRulesResource.create({ policy_id: policy.id }, rule, success, util.displayErrorFunction('Unable to create Rule')); + + function success(data) { + var rules = util.mapToArray(data.rules); + for (var i = 0; i < rules.length; i++) { + var rule = rules[i]; + policy.rules.push(populateRule(policy, rule)) + } + util.displaySuccess('Rule created'); + } + }, + removeRuleFromPolicy: function removeRuleFromPolicy(policy, rule) { + policyRulesResource.remove({ policy_id: policy.id, rule_id: rule.id }, null, success, util.displayErrorFunction('Unable to remove Rule')); + + function success(data) { + removeRuleInternal(policy, rule); + util.displaySuccess('Rule removed'); + } + }, + createData: function createData(type, policy, category, dataCategory) { + var categoryValue = categoryMap[type]; + return categoryValue.resource.create({ policy_id: policy.id, category_id: category.id }, dataCategory).$promise.then( + function (data) { + var result = util.createInternal(data[categoryValue.responseName].data, policy[categoryValue.arrayName], policy[categoryValue.mapName]); + util.displaySuccess('Data created'); + return result; + }, + util.displayErrorFunction('Unable to create Data') + ); + }, + createPerimeter: function createPerimeter(type, policy, perimeter) { + var categoryValue = categoryMap[type]; + return categoryValue.perimeterResource.create({ policy_id: policy.id }, perimeter).$promise.then( + function (data) { + util.displaySuccess('Perimeter created'); + return util.mapToArray(data[categoryValue.perimeterResponseName]); + }, + util.displayErrorFunction('Unable to create Perimeter') + ); + }, + loadPerimetersAndAssignments: function loadPerimetersAndAssignments(type, policy) { + var categoryValue = categoryMap[type]; + var queries = { + perimeters: categoryValue.perimeterResource.query({ policy_id: policy.id }).$promise, + assignments: categoryValue.assignmentResource.query({ policy_id: policy.id }).$promise, + } + + return $q.all(queries).then(function (data) { + var result = {}; + result.assignments = util.mapToArray(data.assignments[categoryValue.assignmentResponseName]); + result.perimetersMap = data.perimeters[categoryValue.perimeterResponseName]; + result.perimeters = util.mapToArray(result.perimetersMap); + return result; + }, util.displayErrorFunction('Unable to load Perimeters')) + + }, + createAssignment: function createAssignment(type, policy, perimeter, data) { + var categoryValue = categoryMap[type]; + var assignment = { + "id": perimeter.id, + "category_id": data.category_id, + "data_id": data.id, + "policy_id": policy.id + } + return categoryValue.assignmentResource.create({ policy_id: policy.id }, assignment).$promise.then( + function (data) { + util.displaySuccess('Assignment created'); + return util.mapToArray(data[categoryValue.assignmentResponseName]); + }, + util.displayErrorFunction('Unable to create Assignment') + ) + }, + removeAssignment: function removeAssignment(type, policy, perimeter, data) { + var categoryValue = categoryMap[type]; + + return categoryValue.assignmentResource.remove({ policy_id: policy.id, perimeter_id: perimeter.id, category_id: data.category_id, data_id: data.id }, null).$promise.then( + function (data) { + util.displaySuccess('Assignment removed'); + }, + util.displayErrorFunction('Unable to remove Assignment') + ) + }, + } + + } +})();
\ No newline at end of file diff --git a/moon_dashboard/moon/static/moon/policy/policy.service.spec.js b/moon_dashboard/moon/static/moon/policy/policy.service.spec.js new file mode 100755 index 00000000..045bf9b3 --- /dev/null +++ b/moon_dashboard/moon/static/moon/policy/policy.service.spec.js @@ -0,0 +1,336 @@ +(function () { + 'use strict'; + + describe('moon.policy.service', function () { + var service, modelService, $httpBackend, URI; + var policiesData; + var modelsData, metaRulesData, subjectCategoriesData, objectCategoriesData, actionCategoriesData; + var rulesData, subjectsData, objectsData, actionsData; + + + function initData() { + policiesData = { + policies: + { + 'policyId1': { name: 'policy1', description: 'pDescription1', genre: 'genre1', model_id: 'modelId1' }, + } + }; + + modelsData = { + models: + { 'modelId1': { name: 'model1', description: 'mDescription1', meta_rules: ['metaRuleId1'] } } + }; + + subjectCategoriesData = { + subject_categories: + { + 'subjectCategoryId1': { name: 'subjectCategory1', description: 'scDescription1' }, + 'subjectCategoryId2': { name: 'subjectCategory2', description: 'scDescription2' } + }, + }; + objectCategoriesData = { + object_categories: + { + 'objectCategoryId1': { name: 'objectCategory1', description: 'ocDescription1' }, + 'objectCategoryId2': { name: 'objectCategory2', description: 'ocDescription2' } + } + }; + actionCategoriesData = { + action_categories: + { + 'actionCategoryId1': { name: 'actionCategory1', description: 'acDescription1' }, + 'actionCategoryId2': { name: 'actionCategory2', description: 'acDescription2' } + } + }; + metaRulesData = { + meta_rules: + { + 'metaRuleId1': { name: 'metaRule1', description: 'mrDescription1', subject_categories: ['subjectCategoryId1'], object_categories: ['objectCategoryId1'], action_categories: ['actionCategoryId1'] }, + 'metaRuleId2': { name: 'metaRule2', description: 'mrDescription2', subject_categories: [], object_categories: [], action_categories: [] } + } + }; + } + + function initRuleData() { + rulesData = { + rules: { + rules: [ + { meta_rule_id: 'metaRuleId1', rule: ['subjectId1', 'objectId1', 'actionId1'], id: 'ruleId1', instructions: { test: 'test' } } + ] + } + }; + + subjectsData = { + subject_data: + [ + { + data: { + 'subjectId1': { name: 'subject1', description: 'sDescription1' }, + } + } + ] + }; + objectsData = { + object_data: + [ + { + data: { + 'objectId1': { name: 'object1', description: 'oDescription1' }, + } + } + ] + }; + actionsData = { + action_data: + [ + { + data: { + 'actionId1': { name: 'action1', description: 'aDescription1' }, + } + } + ] + }; + } + + beforeEach(module('horizon.app.core')); + beforeEach(module('horizon.framework')); + beforeEach(module('moon')); + + beforeEach(inject(function ($injector) { + service = $injector.get('moon.policy.service'); + modelService = $injector.get('moon.model.service'); + $httpBackend = $injector.get('$httpBackend'); + URI = $injector.get('moon.URI'); + })); + + afterEach(function () { + $httpBackend.verifyNoOutstandingExpectation(); + $httpBackend.verifyNoOutstandingRequest(); + }); + + it('should initialize', function () { + initData(); + $httpBackend.expectGET(URI.API + '/policies').respond(200, policiesData); + $httpBackend.expectGET(URI.API + '/subject_categories').respond(200, subjectCategoriesData); + $httpBackend.expectGET(URI.API + '/object_categories').respond(200, objectCategoriesData); + $httpBackend.expectGET(URI.API + '/action_categories').respond(200, actionCategoriesData); + $httpBackend.expectGET(URI.API + '/meta_rules').respond(200, metaRulesData); + $httpBackend.expectGET(URI.API + '/models').respond(200, modelsData); + + + service.initialize(); + $httpBackend.flush(); + + expect(service.policies.length).toBe(1); + var policy = service.policies[0]; + expect(policy.id).toBe('policyId1'); + expect(policy.name).toBe('policy1'); + expect(policy.description).toBe('pDescription1'); + expect(policy.genre).toBe('genre1'); + expect(policy.model.id).toBe('modelId1'); + + }); + + + + it('should create policy', function () { + initData(); + modelService.createModels(modelsData, metaRulesData, subjectCategoriesData, objectCategoriesData, actionCategoriesData); + + var policyCreatedData = { + policies: + { 'policyId1': { name: 'policy1', description: 'pDescription1', genre: 'genre1', model_id: 'modelId1' } } + }; + + $httpBackend.expectPOST(URI.API + '/policies').respond(200, policyCreatedData); + + service.createPolicy({ name: 'policy1', description: 'pDescription1', genre: 'genre1', model: modelService.getModel('modelId1') }); + $httpBackend.flush(); + + expect(service.policies.length).toBe(1); + var policy = service.policies[0]; + expect(policy.id).toBe('policyId1'); + expect(policy.name).toBe('policy1'); + expect(policy.description).toBe('pDescription1'); + expect(policy.genre).toBe('genre1'); + expect(policy.model.id).toBe('modelId1'); + }); + + it('should remove policy', function () { + initData(); + modelService.createModels(modelsData, metaRulesData, subjectCategoriesData, objectCategoriesData, actionCategoriesData); + service.createPolicies(policiesData); + + $httpBackend.expectDELETE(URI.API + '/policies/policyId1').respond(200); + + service.removePolicy({ id: 'policyId1' }); + $httpBackend.flush(); + + expect(service.policies.length).toBe(0); + }); + + it('should update policy', function () { + initData(); + var policyUpdatedData = { + policies: + { 'policyId1': { name: 'policy2', description: 'pDescription2', genre: 'genre2', model_id: 'modelId1' } } + }; + modelService.createModels(modelsData, metaRulesData, subjectCategoriesData, objectCategoriesData, actionCategoriesData); + service.createPolicies(policiesData); + + $httpBackend.expectPATCH(URI.API + '/policies/policyId1').respond(200, policyUpdatedData); + + service.updatePolicy({ id: 'policyId1', name: 'policy2', description: 'pDescription2', genre: 'genre2', model: modelService.getModel('modelId1') }); + $httpBackend.flush(); + + expect(service.policies.length).toBe(1); + var policy = service.policies[0]; + expect(policy.id).toBe('policyId1'); + expect(policy.name).toBe('policy2'); + expect(policy.description).toBe('pDescription2'); + expect(policy.genre).toBe('genre2'); + expect(policy.model.id).toBe('modelId1'); + + }); + + + it('should populate policy', function () { + initData(); + initRuleData(); + modelService.createModels(modelsData, metaRulesData, subjectCategoriesData, objectCategoriesData, actionCategoriesData); + service.createPolicies(policiesData); + + var policy = service.getPolicy('policyId1') + + $httpBackend.expectGET(URI.API + '/policies/policyId1/rules').respond(200, rulesData); + $httpBackend.expectGET(URI.API + '/policies/policyId1/subject_data').respond(200, subjectsData); + $httpBackend.expectGET(URI.API + '/policies/policyId1/object_data').respond(200, objectsData); + $httpBackend.expectGET(URI.API + '/policies/policyId1/action_data').respond(200, actionsData); + + service.populatePolicy(policy); + $httpBackend.flush(); + + expect(policy.rules.length).toBe(1); + var rule = policy.rules[0]; + expect(rule.id).toBe('ruleId1'); + expect(rule.metaRule.id).toBe('metaRuleId1'); + expect(rule.instructions.test).toBe('test'); + expect(rule.subjectData.length).toBe(1); + expect(rule.subjectData[0].id).toBe('subjectId1'); + expect(rule.objectData.length).toBe(1); + expect(rule.objectData[0].id).toBe('objectId1'); + expect(rule.actionData.length).toBe(1); + expect(rule.actionData[0].id).toBe('actionId1'); + + expect(policy.subjectData.length).toBe(1); + var subjectData = policy.subjectData[0]; + expect(subjectData.id).toBe('subjectId1'); + expect(subjectData.name).toBe('subject1'); + expect(subjectData.description).toBe('sDescription1'); + + expect(policy.objectData.length).toBe(1); + var objectData = policy.objectData[0]; + expect(objectData.id).toBe('objectId1'); + expect(objectData.name).toBe('object1'); + expect(objectData.description).toBe('oDescription1'); + + expect(policy.actionData.length).toBe(1); + var actionData = policy.actionData[0]; + expect(actionData.id).toBe('actionId1'); + expect(actionData.name).toBe('action1'); + expect(actionData.description).toBe('aDescription1'); + + }); + + + it('should add rule to policy', function () { + initData(); + initRuleData(); + modelService.createModels(modelsData, metaRulesData, subjectCategoriesData, objectCategoriesData, actionCategoriesData); + service.createPolicies(policiesData); + + + var ruleCreatedData = { + rules: { + 'ruleId1': { meta_rule_id: 'metaRuleId1', rule: ['subjectId1', 'objectId1', 'actionId1'], instructions: { test: 'test' } } + } + }; + + var policy = service.getPolicy('policyId1'); + + service.createRules(policy, null, subjectsData, objectsData, actionsData); + + $httpBackend.expectPOST(URI.API + '/policies/policyId1/rules').respond(200, ruleCreatedData); + + service.addRuleToPolicy(policy, { meta_rule_id: 'metaRuleId1', rule: ['subjectId1', 'objectId1', 'actionId1'], instructions: { test: 'test' } }); + $httpBackend.flush(); + + expect(policy.rules.length).toBe(1); + var rule = policy.rules[0]; + expect(rule.id).toBe('ruleId1'); + expect(rule.metaRule.id).toBe('metaRuleId1'); + expect(rule.subjectData.length).toBe(1); + expect(rule.subjectData[0].id).toBe('subjectId1'); + expect(rule.objectData.length).toBe(1); + expect(rule.objectData[0].id).toBe('objectId1'); + expect(rule.actionData.length).toBe(1); + expect(rule.actionData[0].id).toBe('actionId1'); + + }); + + it('should remove rule from policy', function () { + initData(); + initRuleData(); + modelService.createModels(modelsData, metaRulesData, subjectCategoriesData, objectCategoriesData, actionCategoriesData); + service.createPolicies(policiesData); + + var policy = service.getPolicy('policyId1'); + + service.createRules(policy, rulesData, subjectsData, objectsData, actionsData); + + $httpBackend.expectDELETE(URI.API + '/policies/policyId1/rules/ruleId1').respond(200); + + service.removeRuleFromPolicy(policy, { id: 'ruleId1' }); + $httpBackend.flush(); + + expect(policy.rules.length).toBe(0); + }); + + + it('should create data', function () { + initData(); + initRuleData(); + modelService.createModels(modelsData, metaRulesData, subjectCategoriesData, objectCategoriesData, actionCategoriesData); + service.createPolicies(policiesData); + + + var dataCreatedData = { + subject_data: { + data: { + 'subjectId1': { name: 'subject1', description: 'sDescription1' }, + } + } + }; + + var policy = service.getPolicy('policyId1'); + policy.subjectData = []; + policy.subjectDataMap = {}; + + $httpBackend.expectPOST(URI.API + '/policies/policyId1/subject_data/subjectCategoryId1').respond(200, dataCreatedData); + + service.createData('subject', policy, modelService.getCategory('subject', 'subjectCategoryId1'), { name: 'subject1', description: 'sDescription1' }); + $httpBackend.flush(); + + expect(policy.subjectData.length).toBe(1); + var subjectData = policy.subjectData[0]; + expect(subjectData.id).toBe('subjectId1'); + expect(subjectData.name).toBe('subject1'); + expect(subjectData.description).toBe('sDescription1'); + + }); + + + }); + + +})();
\ No newline at end of file |