diff options
Diffstat (limited to 'dashboard/src/services/Policy.service.js')
-rw-r--r-- | dashboard/src/services/Policy.service.js | 470 |
1 files changed, 470 insertions, 0 deletions
diff --git a/dashboard/src/services/Policy.service.js b/dashboard/src/services/Policy.service.js new file mode 100644 index 00000000..433680e9 --- /dev/null +++ b/dashboard/src/services/Policy.service.js @@ -0,0 +1,470 @@ +import Vue from 'vue' +import util from './Util.service.js' +import ModelService from './Model.service.js' +import AttributeService from './Attribute.service' +import config from '../config.js' + +var host = config.host; + +var policyResource; +var policyRulesResource; + +var categoryMap = { + 'subject': { + arrayName: "subjectData", + mapName: "subjectDataMap", + responseName: "subject_data", + perimeterResponseName: "subjects", + assignmentResponseName: "subject_assignments", + unusedArrayName: "unusedSubjectData", + }, + 'object': { + arrayName: "objectData", + mapName: "objectDataMap", + responseName: "object_data", + perimeterResponseName: "objects", + assignmentResponseName: "object_assignments", + unusedArrayName: "unusedObjectData", + }, + 'action': { + arrayName: "actionData", + mapName: "actionDataMap", + responseName: "action_data", + perimeterResponseName: "actions", + assignmentResponseName: "action_assignments", + unusedArrayName: "unusedActionData", + } +} + +var policiesMap = {}; +var policies = []; + +function loadPolicies() { + policyResource = Vue.resource(host + '/policies{/id}', {}, {patch: {method: 'PATCH'}}); + categoryMap['subject'].policyPerimeterResource = Vue.resource(host + '/policies{/policy_id}/subjects{/perimeter_id}', {}); + categoryMap['object'].policyPerimeterResource = Vue.resource(host + '/policies{/policy_id}/objects{/perimeter_id}', {}, ); + categoryMap['action'].policyPerimeterResource = Vue.resource(host + '/policies{/policy_id}/actions{/perimeter_id}', {}, ); + categoryMap['subject'].perimeterResource = Vue.resource(host + '/subjects{/perimeter_id}', {}, {patch: {method: 'PATCH'}}); + categoryMap['object'].perimeterResource = Vue.resource(host + '/objects{/perimeter_id}', {}, {patch: {method: 'PATCH'}}); + categoryMap['action'].perimeterResource = Vue.resource(host + '/actions{/perimeter_id}', {}, {patch: {method: 'PATCH'}}); + categoryMap['subject'].assignmentResource = Vue.resource(host + '/policies{/policy_id}/subject_assignments{/perimeter_id}{/category_id}{/data_id}', {}, ); + categoryMap['object'].assignmentResource = Vue.resource(host + '/policies{/policy_id}/object_assignments{/perimeter_id}{/category_id}{/data_id}', {}, ); + categoryMap['action'].assignmentResource = Vue.resource(host + '/policies{/policy_id}/action_assignments{/perimeter_id}{/category_id}{/data_id}', {}, ); + var queries = [ + policyResource.query(), + ModelService.initialize(), + AttributeService.initialize() + ] + + Promise.all(queries).then(function (result) { + createPolicies(result[0].body); + }) +} + +function createPolicies(policiesData) { + policies.splice(0, policies.length); + util.cleanObject(policiesMap); + createPolicyInternal(policiesData.policies); +} + +function mapPolicy(policy) { + policy.rulesPopulated = false; + policy.rules = []; + policy.subjectData = []; + policy.objectData = []; + policy.actionData = []; + policy.unusedSubjectData = []; + policy.unusedObjectData = []; + policy.unusedActionData = []; + policy.attributes = []; + if (policy.model_id) { + policy.model = ModelService.getModel(policy.model_id); + policy.attributes = ModelService.getAttributesForModelId(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); + updateUnusedData(policy); +} + +function loadPolicyRule(policy) { + if (!policy.rulesPopulated) { + policyRulesResource = Vue.resource(host + '/policies{/policy_id}/rules{/rule_id}', {}, {patch: {method: 'PATCH'}}); + categoryMap['subject'].resource = Vue.resource(host + '/policies{/policy_id}/subject_data{/category_id}{/data_id}', {}); + categoryMap['object'].resource = Vue.resource(host + '/policies{/policy_id}/object_data{/category_id}{/data_id}', {}); + categoryMap['action'].resource = Vue.resource(host + '/policies{/policy_id}/action_data{/category_id}{/data_id}', {}); + var queries = [ + policyRulesResource.query({ policy_id: policy.id }), + categoryMap['subject'].resource.query({ policy_id: policy.id }), + categoryMap['object'].resource.query({ policy_id: policy.id }), + categoryMap['action'].resource.query({ policy_id: policy.id }) + ] + + Promise.all(queries).then(function (result) { + createRules(policy, result[0].body, result[1].body, result[2].body, result[3].body); + 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]; + if (data) { + var notOrphanIndex = util.indexOf(orphanList, "id", data.id); + if (notOrphanIndex >= 0) { + orphanList.splice(notOrphanIndex, 1); + } + } + } +} + +function transformData(list) { + var result = {}; + for (var index = 0; index < list.length; index++) { + var data = list[index].data; + for (var key in data) { + if (data.hasOwnProperty(key)) { + result[key] = data[key]; + } + } + } + return result; +} + +function createRules(policy, rulesData, subjectsData, objectsData, actionsData) { + policy.rules = rulesData ? rulesData.rules.rules : []; + policy.subjectDataMap = transformData(subjectsData.subject_data); + policy.subjectData = util.mapToArray(policy.subjectDataMap); + policy.objectDataMap = transformData(objectsData.object_data); + policy.objectData = util.mapToArray(policy.objectDataMap); + policy.actionDataMap = transformData(actionsData.action_data); + policy.actionData = util.mapToArray(policy.actionDataMap); + for (var i = 0; i < policy.rules.length; i++) { + var rule = policy.rules[i]; + populateRule(policy, rule); + } + policy.rulesPopulated = true; +} + +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 = []; + rule.attributeData = []; + + for (k = 0; k < rule.metaRule.subject_categories.length; k++) { + id = rule.rule[j + k]; + if (policy.subjectDataMap[id]) + rule.subjectData.push(policy.subjectDataMap[id]); + } + j += k; + for (k = 0; k < rule.metaRule.object_categories.length; k++) { + id = rule.rule[j + k]; + if (policy.objectDataMap[id]) + rule.objectData.push(policy.objectDataMap[id]); + } + j += k; + for (k = 0; k < rule.metaRule.action_categories.length; k++) { + id = rule.rule[j + k]; + if (policy.actionDataMap[id]) { + rule.actionData.push(policy.actionDataMap[id]); + } + } + + for (const value of rule.rule.values()){ + if (value.includes("attributes:")){ + let attrName = value.split(':')[1]; + let attrId = AttributeService.getAttributeId(attrName); + rule.attributeData.push({id: attrId, name: attrName}); + + } + } + } + return rule; +} + +function updateRule(policy, rule, decision){ + return new Promise(resolveUpdateRule => { + var body = { + "instructions":[ + {"decision": decision} + ] + }; + + policyRulesResource.patch({policy_id: policy.id, rule_id: rule.id}, body).then(success, util.displayErrorFunction('Unable to update Rule')); + + function success(data){ + resolveUpdateRule(data.body.rules[rule.id].instructions); + } + }); +} + +function filterRuleBySpecificItem(filteredRules, rule, items, filter){ + items.forEach(item => { + if (item){ + if (filter == null || item.name.indexOf(filter) >= 0){ + if (!(filteredRules.includes(rule))) + filteredRules.push(rule) + } + } + + }); +} + +function interArray(array1, array2){ + let inter = []; + + + for (let i = 0; i < array1.length; i++){ + for (let j = 0; j < array2.length; j++){ + if (array1[i] === array2[j]) + inter.push(array2[j]); + } + } + return inter; +} + + +function filterByRules(rules, filters){ + let filteredRules = []; + let filteredByWords = []; + + + if (filters === ""){ + filteredRules = rules; + } else { + filters = filters.split(' '); + filters.forEach( filter => { + if (filter !== "") { + let tmp = []; + rules.forEach((rule) => { + + filterRuleBySpecificItem(tmp, rule, rule.subjectData, filter); + filterRuleBySpecificItem(tmp, rule, rule.objectData, filter); + filterRuleBySpecificItem(tmp, rule, rule.actionData, filter); + filterRuleBySpecificItem(tmp, rule, rule.attributeData, filter); + + filteredByWords.push(tmp); + }); + + } + }); + + filteredRules = filteredByWords[0]; + for (let i = 1; i < filteredByWords.length; i++){ + filteredRules = interArray(filteredRules, filteredByWords[i]); + } + } + + return filteredRules; +} + +function policyRuleWithAttributes(policy){ + const meta_rules = policy.model.meta_rules; + + for (let i = 0; i < meta_rules.length; i++){ + const meta_rule = meta_rules[i]; + if (meta_rule.actionAttributes.length || meta_rule.subjectAttributes.length || meta_rule.objectAttributes.length) + return true; + } + return false; +} + +export default { + policyRuleWithAttributes: policyRuleWithAttributes, + filterByRules: filterByRules, + initialize: loadPolicies, + createPolicies: createPolicies, + policies: policies, + getPolicy: function getPolicy(id) { + return policiesMap[id]; + }, + createPolicy: function createPolicy(policy) { + policyResource.save(null, policy).then(success, util.displayErrorFunction('Unable to create Policy')); + + function success(data) { + createPolicyInternal(data.body.policies); + util.displaySuccess('Policy created'); + } + }, + removePolicy: function removePolicy(policy) { + policyResource.remove({ id: policy.id }, null).then(success, util.displayErrorFunction('Unable to remove Policy')); + + function success() { + removePolicyInternal(policy.id); + util.displaySuccess('Policy removed'); + } + }, + updatePolicy: function updatePolicy(policy) { + policyResource.patch({ id: policy.id }, policy).then(success, util.displayErrorFunction('Unable to update Policy')); + + function success(data) { + updatePolicyInternal(data.body.policies) + util.displaySuccess('Policy updated'); + } + }, + populatePolicy: loadPolicyRule, + createRules: createRules, + updateRule: updateRule, + addRuleToPolicy: function addRuleToPolicy(policy, rule) { + policyRulesResource.save({ policy_id: policy.id }, rule).then(success, util.displayErrorFunction('Unable to create Rule')); + + function success(data) { + var rules = util.mapToArray(data.body.rules); + for (var i = 0; i < rules.length; i++) { + var rule = rules[i]; + policy.rules.push(populateRule(policy, rule)) + } + util.displaySuccess('Rule created'); + updateUnusedData(policy); + } + }, + removeRuleFromPolicy: function removeRuleFromPolicy(policy, rule) { + policyRulesResource.remove({ policy_id: policy.id, rule_id: rule.id }, null).then(success, util.displayErrorFunction('Unable to remove Rule')); + + function success() { + removeRuleInternal(policy, rule); + util.displaySuccess('Rule removed'); + } + }, + createData: function createData(type, policy, categoryId, dataCategory) { + var categoryValue = categoryMap[type]; + return categoryValue.resource.save({ policy_id: policy.id, category_id: categoryId }, dataCategory).then( + function (data) { + var result = util.createInternal(data.body[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 }).then( + function () { + 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.policyPerimeterResource.save({ policy_id: policy.id }, perimeter).then( + function (data) { + util.displaySuccess('Perimeter created'); + return util.mapToArray(data.body[categoryValue.perimeterResponseName]); + }, + 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).then( + function () { + 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); + var perimeterClone = util.clone(perimeter); + delete perimeterClone.policy_list; + return categoryValue.policyPerimeterResource.save({ policy_id: policy.id }, perimeterClone).then( + function () { + util.displaySuccess('Perimeter added'); + }, + util.displayErrorFunction('Unable to add Perimeter') + ) + }, + loadPerimetersAndAssignments: function loadPerimetersAndAssignments(type, policy) { + var categoryValue = categoryMap[type]; + var queries = [ + categoryValue.perimeterResource.query(), + categoryValue.policyPerimeterResource.query({ policy_id: policy.id }), + categoryValue.assignmentResource.query({ policy_id: policy.id }), + ] + + return Promise.all(queries).then(function (data) { + var result = {}; + result.assignments = util.mapToArray(data[2].body[categoryValue.assignmentResponseName]); + result.perimetersMap = data[1].body[categoryValue.perimeterResponseName]; + result.perimeters = util.mapToArray(result.perimetersMap); + result.allPerimeters = util.mapToArray(data[0].body[categoryValue.perimeterResponseName]); + 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.save({ policy_id: policy.id }, assignment).then( + function (data) { + util.displaySuccess('Assignment created'); + return util.mapToArray(data.body[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).then( + function () { + util.displaySuccess('Assignment removed'); + }, + util.displayErrorFunction('Unable to remove Assignment') + ) + }, +} + |