Merge "Push and unpush to support multiple policies"
[policy/engine.git] / POLICY-SDK-APP / src / main / java / org / onap / policy / controller / AutoPushController.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP Policy Engine
4  * ================================================================================
5  * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
6  * Modifications Copyright (C) 2019 Bell Canada
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  * 
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  * 
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.controller;
23
24 import java.io.BufferedWriter;
25 import java.io.File;
26 import java.io.FileWriter;
27 import java.io.IOException;
28 import java.io.PrintWriter;
29 import java.net.URI;
30 import java.util.ArrayList;
31 import java.util.Collection;
32 import java.util.Collections;
33 import java.util.HashMap;
34 import java.util.HashSet;
35 import java.util.Iterator;
36 import java.util.LinkedHashMap;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Set;
40
41 import java.util.stream.Collectors;
42 import java.util.stream.IntStream;
43 import java.util.stream.Stream;
44 import javax.script.SimpleBindings;
45 import javax.servlet.http.HttpServletRequest;
46 import javax.servlet.http.HttpServletResponse;
47
48 import org.json.JSONObject;
49 import org.onap.policy.common.logging.flexlogger.FlexLogger;
50 import org.onap.policy.common.logging.flexlogger.Logger;
51 import org.onap.policy.model.PDPGroupContainer;
52 import org.onap.policy.model.Roles;
53 import org.onap.policy.rest.adapter.AutoPushTabAdapter;
54 import org.onap.policy.rest.dao.CommonClassDao;
55 import org.onap.policy.rest.jpa.PolicyEntity;
56 import org.onap.policy.rest.jpa.PolicyVersion;
57 import org.onap.policy.rest.util.PDPPolicyContainer;
58 import org.onap.policy.utils.PolicyUtils;
59 import org.onap.policy.xacml.api.XACMLErrorConstants;
60 import org.onap.policy.xacml.api.pap.OnapPDPGroup;
61 import org.onap.policy.xacml.std.pap.StdPDPGroup;
62 import org.onap.policy.xacml.std.pap.StdPDPPolicy;
63 import org.onap.portalsdk.core.controller.RestrictedBaseController;
64 import org.onap.portalsdk.core.web.support.JsonMessage;
65 import org.onap.portalsdk.core.web.support.UserUtils;
66 import org.springframework.beans.factory.annotation.Autowired;
67 import org.springframework.http.MediaType;
68 import org.springframework.stereotype.Controller;
69 import org.springframework.web.bind.annotation.RequestMapping;
70 import org.springframework.web.bind.annotation.RequestMethod;
71 import org.springframework.web.servlet.ModelAndView;
72
73 import com.att.research.xacml.api.pap.PAPException;
74 import com.att.research.xacml.api.pap.PDPPolicy;
75 import com.fasterxml.jackson.databind.DeserializationFeature;
76 import com.fasterxml.jackson.databind.JsonNode;
77 import com.fasterxml.jackson.databind.ObjectMapper;
78
79 @Controller
80 @RequestMapping({ "/" })
81 public class AutoPushController extends RestrictedBaseController {
82
83     private static final Logger logger = FlexLogger.getLogger(AutoPushController.class);
84     private static final String UTF8 = "UTF-8";
85
86     @Autowired
87     CommonClassDao commonClassDao;
88
89     private PDPGroupContainer container;
90     private PDPPolicyContainer policyContainer;
91     private PolicyController policyController;
92     protected List<OnapPDPGroup> groups = Collections.synchronizedList(new ArrayList<>());
93
94     public PolicyController getPolicyController() {
95         return policyController;
96     }
97
98     public void setPolicyController(PolicyController policyController) {
99         this.policyController = policyController;
100     }
101
102     public synchronized void refreshGroups() {
103         synchronized (this.groups) {
104             this.groups.clear();
105             try {
106                 PolicyController controller = getPolicyControllerInstance();
107                 this.groups.addAll(controller.getPapEngine().getOnapPDPGroups());
108             } catch (PAPException e) {
109                 String message = "Unable to retrieve Groups from server: " + e;
110                 logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message);
111             }
112
113         }
114     }
115
116     private PolicyController getPolicyControllerInstance() {
117         return policyController != null ? getPolicyController() : new PolicyController();
118     }
119
120     @RequestMapping(value = {"/get_AutoPushPoliciesContainerData"}, method = {
121         RequestMethod.GET}, produces = MediaType.APPLICATION_JSON_VALUE)
122     public void getPolicyGroupContainerData(HttpServletRequest request, HttpServletResponse response) {
123         try {
124             Set<String> scopes = new HashSet<>();
125             List<String> roles = new ArrayList<>();
126             List<Object> data = new ArrayList<>();
127             Map<String, Object> model = new HashMap<>();
128
129             String userId = UserUtils.getUserSession(request).getOrgUserId();
130
131             PolicyController controller = policyController != null ? getPolicyController() : new PolicyController();
132             List<Object> userRoles = controller.getRoles(userId);
133             for (Object role : userRoles) {
134                 Roles userRole = (Roles) role;
135                 roles.add(userRole.getRole());
136                 scopes.addAll(Stream.of(userRole.getScope().split(","))
137                     .map(String::new)
138                     .collect(Collectors.toSet())
139                 );
140             }
141             if (roles.contains("super-admin") || roles.contains("super-editor") || roles.contains("super-guest")) {
142                 data = commonClassDao.getData(PolicyVersion.class);
143             } else {
144                 if (!scopes.isEmpty()) {
145                     for (String scope : scopes) {
146                         scope += "%";
147                         String query = "From PolicyVersion where policy_name like :scope and id > 0";
148                         SimpleBindings params = new SimpleBindings();
149                         params.put("scope", scope);
150                         List<Object> filterdatas = commonClassDao.getDataByQuery(query, params);
151                         if (filterdatas != null) {
152                             data.addAll(filterdatas);
153                         }
154                     }
155                 } else {
156                     PolicyVersion emptyPolicyName = new PolicyVersion();
157                     emptyPolicyName
158                         .setPolicyName("Please Contact Policy Super Admin, There are no scopes assigned to you");
159                     data.add(emptyPolicyName);
160                 }
161             }
162             ObjectMapper mapper = new ObjectMapper();
163             model.put("policydatas", mapper.writeValueAsString(data));
164             JsonMessage msg = new JsonMessage(mapper.writeValueAsString(model));
165             JSONObject j = new JSONObject(msg);
166             response.getWriter().write(j.toString());
167         } catch (Exception e) {
168             logger.error("Exception Occurred" + e);
169         }
170     }
171
172     @RequestMapping(value = { "/auto_Push/PushPolicyToPDP.htm" }, method = { RequestMethod.POST })
173     public ModelAndView pushPolicyToPDPGroup(HttpServletRequest request, HttpServletResponse response)
174             throws IOException {
175         try {
176             ArrayList<Object> selectedPDPS = new ArrayList<>();
177             ArrayList<String> selectedPoliciesInUI = new ArrayList<>();
178             PolicyController controller = getPolicyControllerInstance();
179             this.groups.addAll(controller.getPapEngine().getOnapPDPGroups());
180             ObjectMapper mapper = new ObjectMapper();
181             this.container = new PDPGroupContainer(controller.getPapEngine());
182             mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
183             JsonNode root = mapper.readTree(request.getReader());
184
185             String userId = UserUtils.getUserSession(request).getOrgUserId();
186             logger.info(
187                     "****************************************Logging UserID while Pushing  Policy to PDP Group*****************************************");
188             logger.info("UserId:  " + userId + "Push Policy Data:  " + root.get("pushTabData").toString());
189             logger.info(
190                     "***********************************************************************************************************************************");
191
192             AutoPushTabAdapter adapter = mapper.readValue(root.get("pushTabData").toString(), AutoPushTabAdapter.class);
193             for (Object pdpGroupId : adapter.getPdpDatas()) {
194                 LinkedHashMap<?, ?> selectedPDP = (LinkedHashMap<?, ?>) pdpGroupId;
195                 for (OnapPDPGroup pdpGroup : this.groups) {
196                     if (pdpGroup.getId().equals(selectedPDP.get("id"))) {
197                         selectedPDPS.add(pdpGroup);
198                     }
199                 }
200             }
201
202             for (Object policyId : adapter.getPolicyDatas()) {
203                 LinkedHashMap<?, ?> selected = (LinkedHashMap<?, ?>) policyId;
204                 String policyName = selected.get("policyName").toString() + "."
205                         + selected.get("activeVersion").toString() + ".xml";
206                 selectedPoliciesInUI.add(policyName);
207             }
208
209             for (Object pdpDestinationGroupId : selectedPDPS) {
210                 Set<PDPPolicy> currentPoliciesInGroup = new HashSet<>();
211                 Set<PDPPolicy> selectedPolicies = new HashSet<>();
212                 for (String policyId : selectedPoliciesInUI) {
213                     logger.debug("Handlepolicies..." + pdpDestinationGroupId + policyId);
214
215                     //
216                     // Get the current selection
217                     //
218                     assert policyId != null;
219                     // create the id of the target file
220                     // Our standard for file naming is:
221                     // <domain>.<filename>.<version>.xml
222                     // since the file name usually has a ".xml", we need to strip
223                     // that
224                     // before adding the other parts
225                     String name = policyId.replace(File.separator, ".");
226                     String id = name;
227                     if (id.endsWith(".xml")) {
228                         id = id.replace(".xml", "");
229                         id = id.substring(0, id.lastIndexOf('.'));
230                     }
231
232                     // Default policy to be Root policy; user can change to deferred
233                     // later
234
235                     StdPDPPolicy selectedPolicy = null;
236                     String dbCheckName = name;
237                     if (dbCheckName.contains("Config_")) {
238                         dbCheckName = dbCheckName.replace(".Config_", ":Config_");
239                     } else if (dbCheckName.contains("Action_")) {
240                         dbCheckName = dbCheckName.replace(".Action_", ":Action_");
241                     } else if (dbCheckName.contains("Decision_")) {
242                         dbCheckName = dbCheckName.replace(".Decision_", ":Decision_");
243                     }
244                     String[] split = dbCheckName.split(":");
245                     String query = "FROM PolicyEntity where policyName = :split_1 and scope = :split_0";
246                     SimpleBindings policyParams = new SimpleBindings();
247                     policyParams.put("split_1", split[1]);
248                     policyParams.put("split_0", split[0]);
249                     List<Object> queryData = controller.getDataByQuery(query, policyParams);
250                     PolicyEntity policyEntity = (PolicyEntity) queryData.get(0);
251                     File temp = new File(name);
252                     BufferedWriter bw = new BufferedWriter(new FileWriter(temp));
253                     bw.write(policyEntity.getPolicyData());
254                     bw.close();
255                     URI selectedURI = temp.toURI();
256                     try {
257                         // Create the policy
258                         selectedPolicy = new StdPDPPolicy(name, true, id, selectedURI);
259                     } catch (IOException e) {
260                         logger.error("Unable to create policy '" + name + "': " + e.getMessage(), e);
261                     }
262                     StdPDPGroup selectedGroup = (StdPDPGroup) pdpDestinationGroupId;
263                     if (selectedPolicy != null) {
264                         // Add Current policies from container
265                         for (OnapPDPGroup group : container.getGroups()) {
266                             if (group.getId().equals(selectedGroup.getId())) {
267                                 currentPoliciesInGroup.addAll(group.getPolicies());
268                             }
269                         }
270                         // copy policy to PAP
271                         try {
272                             controller.getPapEngine().copyPolicy(selectedPolicy, (StdPDPGroup) pdpDestinationGroupId);
273                         } catch (PAPException e) {
274                             logger.error("Exception Occured" + e);
275                             return null;
276                         }
277                         selectedPolicies.add(selectedPolicy);
278                     }
279                     temp.delete();
280                 }
281                 StdPDPGroup pdpGroup = (StdPDPGroup) pdpDestinationGroupId;
282                 StdPDPGroup updatedGroupObject = new StdPDPGroup(pdpGroup.getId(), pdpGroup.isDefaultGroup(),
283                         pdpGroup.getName(), pdpGroup.getDescription(), pdpGroup.getDirectory());
284                 updatedGroupObject.setOnapPdps(pdpGroup.getOnapPdps());
285                 updatedGroupObject.setPipConfigs(pdpGroup.getPipConfigs());
286                 updatedGroupObject.setStatus(pdpGroup.getStatus());
287                 updatedGroupObject.setOperation("push");
288
289                 // replace the original set of Policies with the set from the
290                 // container (possibly modified by the user)
291                 // do not allow multiple copies of same policy
292                 Iterator<PDPPolicy> policyIterator = currentPoliciesInGroup.iterator();
293                 logger.debug("policyIterator....." + selectedPolicies);
294                 while (policyIterator.hasNext()) {
295                     PDPPolicy existingPolicy = policyIterator.next();
296                     for (PDPPolicy selPolicy : selectedPolicies) {
297                         if (selPolicy.getName().equals(existingPolicy.getName())) {
298                             if (selPolicy.getVersion().equals(existingPolicy.getVersion())) {
299                                 if (selPolicy.getId().equals(existingPolicy.getId())) {
300                                     policyIterator.remove();
301                                     logger.debug("Removing policy: " + selPolicy);
302                                     break;
303                                 }
304                             } else {
305                                 policyIterator.remove();
306                                 logger.debug("Removing Old Policy version: " + selPolicy);
307                                 break;
308                             }
309                         }
310                     }
311                 }
312
313                 currentPoliciesInGroup.addAll(selectedPolicies);
314                 updatedGroupObject.setPolicies(currentPoliciesInGroup);
315                 this.container.updateGroup(updatedGroupObject);
316
317                 response.setCharacterEncoding(UTF8);
318                 response.setContentType("application / json");
319                 request.setCharacterEncoding(UTF8);
320
321                 PrintWriter out = response.getWriter();
322                 refreshGroups();
323                 JsonMessage msg = new JsonMessage(mapper.writeValueAsString(groups));
324                 JSONObject j = new JSONObject(msg);
325                 out.write(j.toString());
326                 //
327                 // Why is this here? This defeats the purpose of the loop??
328                 // Sonar says to remove it or make it conditional
329                 //
330                 return null;
331             }
332         } catch (Exception e) {
333             response.setCharacterEncoding(UTF8);
334             request.setCharacterEncoding(UTF8);
335             PrintWriter out = response.getWriter();
336             logger.error(e);
337             out.write(PolicyUtils.CATCH_EXCEPTION);
338         }
339         return null;
340     }
341
342     @SuppressWarnings("unchecked")
343     @RequestMapping(value = { "/auto_Push/remove_GroupPolicies.htm" }, method = { RequestMethod.POST })
344     public ModelAndView removePDPGroup(HttpServletRequest request, HttpServletResponse response) throws IOException {
345         try {
346             PolicyController controller = getPolicyControllerInstance();
347             this.container = new PDPGroupContainer(controller.getPapEngine());
348             ObjectMapper mapper = new ObjectMapper();
349             mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
350             JsonNode root = mapper.readTree(request.getReader());
351             StdPDPGroup group = mapper.readValue(root.get("activePdpGroup").toString(), StdPDPGroup.class);
352             JsonNode removePolicyData = root.get("data");
353
354             String userId = UserUtils.getUserSession(request).getOrgUserId();
355             logger.info(
356                     "****************************************Logging UserID while Removing Policy from PDP Group*****************************************");
357             logger.info("UserId:  " + userId + "PDP Group Data:  " + root.get("activePdpGroup").toString()
358                     + "Remove Policy Data: " + root.get("data"));
359             logger.info(
360                     "***********************************************************************************************************************************");
361
362             policyContainer = new PDPPolicyContainer(group);
363             if (removePolicyData.size() > 0) {
364                 IntStream.range(0, removePolicyData.size()).mapToObj(i -> removePolicyData.get(i).toString())
365                     .forEach(polData -> this.policyContainer.removeItem(polData));
366                 Set<PDPPolicy> changedPolicies = new HashSet<>(
367                     (Collection<PDPPolicy>) this.policyContainer.getItemIds());
368                 StdPDPGroup updatedGroupObject = new StdPDPGroup(group.getId(), group.isDefaultGroup(), group.getName(),
369                         group.getDescription(), null);
370                 updatedGroupObject.setPolicies(changedPolicies);
371                 updatedGroupObject.setOnapPdps(group.getOnapPdps());
372                 updatedGroupObject.setPipConfigs(group.getPipConfigs());
373                 updatedGroupObject.setStatus(group.getStatus());
374                 updatedGroupObject.setOperation("delete");
375                 this.container.updateGroup(updatedGroupObject);
376             }
377
378             response.setCharacterEncoding(UTF8);
379             response.setContentType("application / json");
380             request.setCharacterEncoding(UTF8);
381
382             PrintWriter out = response.getWriter();
383             refreshGroups();
384             JsonMessage msg = new JsonMessage(mapper.writeValueAsString(groups));
385             JSONObject j = new JSONObject(msg);
386
387             out.write(j.toString());
388
389             return null;
390         } catch (Exception e) {
391             response.setCharacterEncoding(UTF8);
392             request.setCharacterEncoding(UTF8);
393             PrintWriter out = response.getWriter();
394             logger.error(e);
395             out.write(PolicyUtils.CATCH_EXCEPTION);
396         }
397         return null;
398     }
399 }