Fix sonar issues
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / servlets / AbstractValidationsServlet.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  * Modifications copyright (c) 2019 Nokia
20  * ================================================================================
21  */
22
23 package org.openecomp.sdc.be.servlets;
24
25 import com.fasterxml.jackson.databind.ObjectMapper;
26 import com.google.gson.Gson;
27 import com.google.gson.JsonSyntaxException;
28 import fj.data.Either;
29 import java.io.File;
30 import java.io.FileInputStream;
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.lang.reflect.Type;
34 import java.nio.charset.StandardCharsets;
35 import java.util.Arrays;
36 import java.util.HashMap;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Optional;
40 import java.util.function.Supplier;
41 import javax.servlet.ServletContext;
42 import javax.servlet.http.HttpServletRequest;
43 import javax.ws.rs.core.Response;
44 import org.apache.commons.codec.binary.Base64;
45 import org.apache.commons.collections4.MapUtils;
46 import org.apache.commons.io.IOUtils;
47 import org.apache.commons.lang3.StringUtils;
48 import org.apache.commons.lang3.tuple.ImmutablePair;
49 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
50 import org.openecomp.sdc.be.components.impl.CsarValidationUtils;
51 import org.openecomp.sdc.be.components.impl.ImportUtils;
52 import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum;
53 import org.openecomp.sdc.be.components.impl.ImportUtils.ToscaElementTypeEnum;
54 import org.openecomp.sdc.be.components.impl.ResourceImportManager;
55 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
56 import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
57 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
58 import org.openecomp.sdc.be.config.BeEcompErrorManager;
59 import org.openecomp.sdc.be.config.ConfigurationManager;
60 import org.openecomp.sdc.be.dao.api.ActionStatus;
61 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
62 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
63 import org.openecomp.sdc.be.impl.ComponentsUtils;
64 import org.openecomp.sdc.be.impl.ServletUtils;
65 import org.openecomp.sdc.be.model.ArtifactDefinition;
66 import org.openecomp.sdc.be.model.Resource;
67 import org.openecomp.sdc.be.model.UploadResourceInfo;
68 import org.openecomp.sdc.be.model.User;
69 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
70 import org.openecomp.sdc.be.servlets.ResourceUploadServlet.ResourceAuthorityTypeEnum;
71 import org.openecomp.sdc.be.user.Role;
72 import org.openecomp.sdc.be.user.UserBusinessLogic;
73 import org.openecomp.sdc.be.utils.TypeUtils;
74 import org.openecomp.sdc.common.api.Constants;
75 import org.openecomp.sdc.common.api.UploadArtifactInfo;
76 import org.openecomp.sdc.common.datastructure.Wrapper;
77 import org.openecomp.sdc.common.log.wrappers.Logger;
78 import org.openecomp.sdc.common.util.GeneralUtility;
79 import org.openecomp.sdc.common.util.YamlToObjectConverter;
80 import org.openecomp.sdc.common.zip.ZipUtils;
81 import org.openecomp.sdc.common.zip.exception.ZipException;
82 import org.openecomp.sdc.exception.ResponseFormat;
83 import org.yaml.snakeyaml.Yaml;
84
85 public abstract class AbstractValidationsServlet extends BeGenericServlet {
86
87     private static final Logger log = Logger.getLogger(AbstractValidationsServlet.class);
88     private static final String TOSCA_SIMPLE_YAML_PREFIX = "tosca_simple_yaml_";
89     private static final List<String> TOSCA_DEFINITION_VERSIONS = Arrays.asList(
90         TOSCA_SIMPLE_YAML_PREFIX + "1_0_0",
91         TOSCA_SIMPLE_YAML_PREFIX + "1_1_0",
92         "tosca_simple_profile_for_nfv_1_0_0",
93         TOSCA_SIMPLE_YAML_PREFIX + "1_0",
94         TOSCA_SIMPLE_YAML_PREFIX + "1_1",
95         TOSCA_SIMPLE_YAML_PREFIX + "1_2");
96     private static final List<String> TOSCA_YML_CSAR_VALID_SUFFIX = Arrays.asList(".yml", ".yaml", ".csar");
97
98     protected ServletUtils servletUtils;
99     protected ResourceImportManager resourceImportManager;
100     protected final ComponentInstanceBusinessLogic componentInstanceBusinessLogic;
101
102
103     public AbstractValidationsServlet(UserBusinessLogic userBusinessLogic,
104         ComponentInstanceBusinessLogic componentInstanceBL, ComponentsUtils componentsUtils,
105         ServletUtils servletUtils, ResourceImportManager resourceImportManager) {
106         super(userBusinessLogic, componentsUtils);
107         this.servletUtils = servletUtils;
108         this.resourceImportManager = resourceImportManager;
109         this.componentInstanceBusinessLogic = componentInstanceBL;
110     }
111
112     protected void init() {
113     }
114
115     protected void validateResourceDoesNotExist(Wrapper<Response> responseWrapper, User user, String resourceName) {
116         if (resourceImportManager.isResourceExist(resourceName)) {
117             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESOURCE_ALREADY_EXISTS);
118             Response errorResponse = buildErrorResponse(responseFormat);
119             getComponentsUtils().auditResource(responseFormat, user, resourceName, AuditingActionEnum.IMPORT_RESOURCE);
120             responseWrapper.setInnerElement(errorResponse);
121         }
122     }
123
124     protected void validateUserExist(Wrapper<Response> responseWrapper, Wrapper<User> userWrapper, String userUserId) {
125         log.debug("get user {} from DB", userUserId);
126         // get user details
127         if (userUserId == null) {
128             log.info("user userId is null");
129             Response response = returnMissingInformation(new User());
130             responseWrapper.setInnerElement(response);
131         }
132
133         else {
134             UserBusinessLogic userAdmin = getServletUtils().getUserAdmin();
135             try {
136                 User user = userAdmin.getUser(userUserId);
137                 userWrapper.setInnerElement(user);
138             } catch (ComponentException ce) {
139                 log.info("user is not listed. userId={}", userUserId);
140                 User user = new User();
141                 user.setUserId(userUserId);
142                 Response response = returnMissingInformation(user);
143                 responseWrapper.setInnerElement(response);
144             }
145         }
146     }
147
148     protected Response returnMissingInformation(User user) {
149         ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_INFORMATION);
150         getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
151         return buildErrorResponse(responseFormat);
152     }
153
154     protected void validateDataNotNull(Wrapper<Response> responseWrapper, Object... dataParams) {
155         for (Object dataElement : dataParams) {
156             if (dataElement == null) {
157                 log.info("Invalid body was received.");
158                 Response response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
159                 responseWrapper.setInnerElement(response);
160                 break;
161             }
162         }
163
164     }
165
166     protected void validateUserRole(Wrapper<Response> errorResponseWrapper, User user) {
167         log.debug("validate user role");
168         if (!user.getRole().equals(Role.ADMIN.name()) && !user.getRole().equals(Role.DESIGNER.name())) {
169             log.info("user is not in appropriate role to perform action");
170             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
171             log.debug("audit before sending response");
172             getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
173
174             Response response = buildErrorResponse(responseFormat);
175             errorResponseWrapper.setInnerElement(response);
176         }
177
178     }
179
180     protected void validateZip(final Wrapper<Response> responseWrapper, final File zipFile, final String payloadName) {
181         if (StringUtils.isEmpty(payloadName)) {
182             log.info("Invalid JSON was received. Payload name is empty");
183             final Response errorResponse =
184                 buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
185             responseWrapper.setInnerElement(errorResponse);
186             return;
187         }
188         final Map<String, byte[]> unzippedFolder;
189         try {
190             unzippedFolder = ZipUtils.readZip(zipFile, false);
191         } catch (final ZipException e) {
192             log.error("Could not read ZIP file '{}' for validation", zipFile.getName(), e);
193             final Response errorResponse =
194                 buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
195             responseWrapper.setInnerElement(errorResponse);
196             return;
197         }
198         if (!unzippedFolder.containsKey(payloadName)) {
199             log.info("Could no find payload '{}' in ZIP file '{}'", payloadName, zipFile.getName());
200             final Response errorResponse =
201                 buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
202             responseWrapper.setInnerElement(errorResponse);
203         }
204
205
206     }
207
208     protected void validateCsar(final Wrapper<Response> responseWrapper, final File csarFile, final String payloadName) {
209         if (StringUtils.isEmpty(payloadName)) {
210             log.info("Invalid JSON was received. Payload name is empty");
211             Response errorResponse = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
212             responseWrapper.setInnerElement(errorResponse);
213             return;
214         }
215         final Map<String, byte[]> unzippedFolder;
216         try {
217             unzippedFolder = ZipUtils.readZip(csarFile, false);
218         } catch (final ZipException e) {
219             log.error("Could not read CSAR file '{}' for validation", csarFile.getName(), e);
220             final Response errorResponse =
221                 buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
222             responseWrapper.setInnerElement(errorResponse);
223             return;
224         }
225         if (unzippedFolder.isEmpty()) {
226             log.info("The CSAR file is empty");
227             Response errorResponse = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
228             responseWrapper.setInnerElement(errorResponse);
229         }
230
231     }
232
233     protected void fillZipContents(Wrapper<String> yamlStringWrapper, File file) throws ZipException {
234         extractZipContents(yamlStringWrapper, file);
235     }
236
237     public static void extractZipContents(Wrapper<String> yamlStringWrapper, File file) throws ZipException {
238         final Map<String, byte[]> unzippedFolder = ZipUtils.readZip(file, false);
239         String ymlName = unzippedFolder.keySet().iterator().next();
240         fillToscaTemplateFromZip(yamlStringWrapper, ymlName, file);
241     }
242
243     private static void fillToscaTemplateFromZip(final Wrapper<String> yamlStringWrapper, final String payloadName,
244                                                  final File file) throws ZipException {
245         final Map<String, byte[]> unzippedFolder = ZipUtils.readZip(file, false);
246         final byte[] yamlFileInBytes = unzippedFolder.get(payloadName);
247         final String yamlAsString = new String(yamlFileInBytes, StandardCharsets.UTF_8);
248         log.debug("received yaml: {}", yamlAsString);
249         yamlStringWrapper.setInnerElement(yamlAsString);
250     }
251
252     protected void fillPayloadDataFromFile(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfoWrapper, File file)  {
253         try(InputStream fileInputStream = new FileInputStream(file)){
254
255             byte [] data = new byte[(int)file.length()];
256             if( fileInputStream.read(data) == -1){
257                 log.info("Invalid json was received.");
258                 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
259
260                 Response errorResp = buildErrorResponse(responseFormat);
261                 responseWrapper.setInnerElement(errorResp);
262             }
263             String payloadData =  Base64.encodeBase64String(data);
264             uploadResourceInfoWrapper.setPayloadData(payloadData);
265
266
267
268         } catch (IOException e) {
269             log.info("Invalid json was received or Error while closing input Stream.");
270             log.debug("Invalid json was received or Error while closing input Stream. {}", e.getMessage(), e);
271             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
272
273             Response errorResp = buildErrorResponse(responseFormat);
274             responseWrapper.setInnerElement(errorResp);
275
276         }
277     }
278
279     protected void validateUserRole(Wrapper<Response> errorResponseWrapper, User user, ResourceAuthorityTypeEnum resourceAuthority) {
280         log.debug("validate user role");
281         if (resourceAuthority == ResourceAuthorityTypeEnum.NORMATIVE_TYPE_BE) {
282             if (!user.getRole().equals(Role.ADMIN.name())) {
283                 log.info("user is not in appropriate role to perform action");
284                 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
285                 log.debug("audit before sending response");
286                 getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
287
288                 Response response = buildErrorResponse(responseFormat);
289                 errorResponseWrapper.setInnerElement(response);
290             }
291         } else {
292             validateUserRole(errorResponseWrapper, user);
293         }
294
295     }
296
297     protected void validateAndFillResourceJson(Wrapper<Response> responseWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, User user, ResourceAuthorityTypeEnum resourceAuthorityEnum, String resourceInfo) {
298         boolean isValid;
299         try {
300             log.debug("The received json is {}", resourceInfo);
301             UploadResourceInfo resourceInfoObject = gson.fromJson(resourceInfo, UploadResourceInfo.class);
302             if (resourceInfoObject == null) {
303                 isValid = false;
304             } else {
305                 if (!resourceAuthorityEnum.isBackEndImport()) {
306                     isValid = resourceInfoObject.getPayloadName() != null && !resourceInfoObject.getPayloadName().isEmpty();
307                     //only resource name is checked
308                 } else {
309                     isValid = true;
310                 }
311                 uploadResourceInfoWrapper.setInnerElement(resourceInfoObject);
312             }
313
314         } catch (JsonSyntaxException e) {
315             log.debug("Invalid json was received. {}", e.getMessage(), e);
316             isValid = false;
317
318         }
319         if (!isValid) {
320             log.info("Invalid json was received.");
321             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
322             getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
323             Response errorResp = buildErrorResponse(responseFormat);
324             responseWrapper.setInnerElement(errorResp);
325         }
326     }
327
328     protected void validateAuthorityType(Wrapper<Response> responseWrapper, String authorityType) {
329         log.debug("The received authority type is {}", authorityType);
330         ResourceAuthorityTypeEnum authorityTypeEnum = ResourceAuthorityTypeEnum.findByUrlPath(authorityType);
331         if (authorityTypeEnum == null) {
332             log.info("Invalid authority type was received.");
333             Response errorResp = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
334             responseWrapper.setInnerElement(errorResp);
335         }
336     }
337
338     public ServletUtils getServletUtils() {
339         return servletUtils;
340     }
341
342     public Gson getGson() {
343         return getServletUtils().getGson();
344     }
345
346     public ComponentsUtils getComponentsUtils() {
347         return getServletUtils().getComponentsUtils();
348     }
349
350     protected void validatePayloadIsTosca(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user, String toscaPayload) {
351         log.debug("checking payload is valid tosca");
352         boolean isValid;
353         Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
354         Either<String, ResultStatusEnum> findFirstToscaStringElement = ImportUtils.findFirstToscaStringElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION);
355
356         if (findFirstToscaStringElement.isRight()) {
357             isValid = false;
358         } else {
359             String defenitionVersionFound = findFirstToscaStringElement.left().value();
360             if (defenitionVersionFound == null || defenitionVersionFound.isEmpty()) {
361                 isValid = false;
362             } else {
363                 isValid = TOSCA_DEFINITION_VERSIONS.contains(defenitionVersionFound);
364             }
365         }
366
367         if (!isValid) {
368             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_TEMPLATE);
369             Response errorResponse = buildErrorResponse(responseFormat);
370             getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
371             responseWrapper.setInnerElement(errorResponse);
372         }
373
374     }
375
376     protected void validatePayloadIsYml(Wrapper<Response> responseWrapper, User user, UploadResourceInfo uploadResourceInfo, String toscaTamplatePayload) {
377         log.debug("checking tosca template is valid yml");
378         YamlToObjectConverter yamlConvertor = new YamlToObjectConverter();
379         boolean isYamlValid = yamlConvertor.isValidYaml(toscaTamplatePayload.getBytes());
380         if (!isYamlValid) {
381             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_YAML_FILE);
382             Response errorResponse = buildErrorResponse(responseFormat);
383             getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
384             responseWrapper.setInnerElement(errorResponse);
385         }
386     }
387
388     /**
389      * Gets the Resource type from the given node type name.
390      *
391      * @param nodeTypeFullName - Node type Name
392      * @return Resource Type name
393      */
394     private String getResourceType(final String nodeTypeFullName) {
395
396         final Optional<String> nodeTypeNamePrefix = getNodeTypeNamePrefix(nodeTypeFullName);
397         if (nodeTypeNamePrefix.isPresent()) {
398             final String nameWithouNamespacePrefix = nodeTypeFullName.substring(nodeTypeNamePrefix.get().length());
399             final String[] findTypes = nameWithouNamespacePrefix.split("\\.");
400             if (findTypes.length > 0) {
401                 final ResourceTypeEnum resourceType = ResourceTypeEnum.getType(findTypes[0].toUpperCase());
402                 if (resourceType != null) {
403                     return resourceType.name();
404                 }
405             }
406         }
407         return ResourceTypeEnum.VFC.name();
408     }
409
410     /**
411      * Extracts the Node Type Name prefix from the given Node Type Name.
412      * @param nodeName - Node Type Name
413      * @return Node Type Name prefix
414      */
415     private Optional<String> getNodeTypeNamePrefix(final String nodeName) {
416         final List<String> definedNodeTypeNamespaceList = ConfigurationManager.getConfigurationManager()
417             .getConfiguration().getDefinedResourceNamespace();
418         for (final String validNamespace : definedNodeTypeNamespaceList) {
419             if (nodeName.startsWith(validNamespace)) {
420                 return Optional.of(validNamespace);
421             }
422         }
423         return Optional.empty();
424     }
425
426     protected void validatePayloadNameSpace(final Wrapper<Response> responseWrapper,
427                                             final UploadResourceInfo resourceInfo,
428                                             final User user, final String toscaPayload) {
429         boolean isValid;
430         String namespace = "";
431         final Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
432         final Either<Map<String, Object>, ResultStatusEnum> toscaElement = ImportUtils.findFirstToscaMapElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES);
433         if (toscaElement.isRight() || toscaElement.left().value().size() != 1) {
434             isValid = false;
435         } else {
436             namespace = toscaElement.left().value().keySet().iterator().next();
437             isValid = getNodeTypeNamePrefix(namespace).isPresent();
438         }
439         if (!isValid) {
440             final ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_NAMESPACE);
441             final Response errorResponse = buildErrorResponse(responseFormat);
442             getComponentsUtils().auditResource(responseFormat, user, resourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
443             responseWrapper.setInnerElement(errorResponse);
444         } else {
445             resourceInfo.setResourceType(getResourceType(namespace));
446         }
447     }
448
449     private void validatePayloadIsSingleResource(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user, String toscaPayload) {
450         log.debug("checking payload contains single resource");
451         boolean isValid;
452         Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
453         Either<Map<String, Object>, ResultStatusEnum> toscaElement = ImportUtils.findFirstToscaMapElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES);
454         if (toscaElement.isRight()) {
455             isValid = false;
456         } else {
457             isValid = toscaElement.left().value().size() == 1;
458         }
459
460         if (!isValid) {
461             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.NOT_SINGLE_RESOURCE);
462             Response errorResponse = buildErrorResponse(responseFormat);
463             getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
464             responseWrapper.setInnerElement(errorResponse);
465         }
466
467     }
468
469     private void validatePayloadIsNotService(Wrapper<Response> responseWrapper, User user, UploadResourceInfo uploadResourceInfo, String toscaPayload) {
470         log.debug("checking payload is not a tosca service");
471         Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
472         Either<Object, ResultStatusEnum> toscaElement = ImportUtils.findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOPOLOGY_TEMPLATE, ToscaElementTypeEnum.ALL);
473
474         if (toscaElement.isLeft()) {
475             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.NOT_RESOURCE_TOSCA_TEMPLATE);
476             Response errorResponse = buildErrorResponse(responseFormat);
477             getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
478             responseWrapper.setInnerElement(errorResponse);
479         }
480
481     }
482
483     private void validateToscaTemplatePayloadName(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user) {
484         String toscaTemplatePayloadName = uploadResourceInfo.getPayloadName();
485         boolean isValidSuffix = false;
486         if (toscaTemplatePayloadName != null && !toscaTemplatePayloadName.isEmpty()) {
487             for (String validSuffix : TOSCA_YML_CSAR_VALID_SUFFIX) {
488                 isValidSuffix = isValidSuffix || toscaTemplatePayloadName.toLowerCase().endsWith(validSuffix);
489             }
490         }
491         if (!isValidSuffix) {
492             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_FILE_EXTENSION);
493             Response errorResponse = buildErrorResponse(responseFormat);
494             getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
495             responseWrapper.setInnerElement(errorResponse);
496         }
497
498     }
499
500     private void validateMD5(Wrapper<Response> responseWrapper, User user, UploadResourceInfo resourceInfo, HttpServletRequest request, String resourceInfoJsonString) {
501         boolean isValid;
502         String recievedMD5 = request.getHeader(Constants.MD5_HEADER);
503         if (recievedMD5 == null) {
504             isValid = false;
505         } else {
506             String calculateMD5 = GeneralUtility.calculateMD5Base64EncodedByString(resourceInfoJsonString);
507             isValid = calculateMD5.equals(recievedMD5);
508         }
509         if (!isValid) {
510             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_CHECKSUM);
511             Response errorResponse = buildErrorResponse(responseFormat);
512             getComponentsUtils().auditResource(responseFormat, user, resourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
513             responseWrapper.setInnerElement(errorResponse);
514         }
515     }
516
517     ComponentTypeEnum validateComponentType(String componentType) {
518         if (componentType == null) {
519             throw new ByActionStatusComponentException(ActionStatus.UNSUPPORTED_ERROR);
520         }
521         if (ComponentTypeEnum.RESOURCE_PARAM_NAME.equalsIgnoreCase(componentType)) {
522             return ComponentTypeEnum.RESOURCE;
523         }
524         if (ComponentTypeEnum.SERVICE_PARAM_NAME.equalsIgnoreCase(componentType)) {
525             return ComponentTypeEnum.SERVICE;
526         }
527         log.debug("Invalid componentType:{}", componentType);
528         throw new ByActionStatusComponentException(ActionStatus.UNSUPPORTED_ERROR, componentType);
529     }
530
531
532     ComponentTypeEnum convertToComponentType(String componentType) {
533         return validateComponentType(componentType);
534     }
535
536     private void fillToscaTemplateFromJson(Wrapper<Response> responseWrapper, Wrapper<String> yamlStringWrapper, User user, UploadResourceInfo resourceInfo) {
537         if (resourceInfo.getPayloadData() == null || resourceInfo.getPayloadData().isEmpty()) {
538             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_PAYLOAD);
539             Response errorResponse = buildErrorResponse(responseFormat);
540             getComponentsUtils().auditResource(responseFormat, user, resourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
541             responseWrapper.setInnerElement(errorResponse);
542         } else {
543             String toscaPayload = resourceInfo.getPayloadData();
544             String decodedPayload = new String(Base64.decodeBase64(toscaPayload));
545             yamlStringWrapper.setInnerElement(decodedPayload);
546         }
547
548     }
549
550     void fillPayload(Wrapper<Response> responseWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, Wrapper<String> yamlStringWrapper, User user, String resourceInfoJsonString, ResourceAuthorityTypeEnum resourceAuthorityEnum,
551             File file) throws ZipException {
552
553         if (responseWrapper.isEmpty()) {
554             if (resourceAuthorityEnum.isBackEndImport()) {
555                 // PrePayload Validations
556                 if (responseWrapper.isEmpty()) {
557                     validateDataNotNull(responseWrapper, file, resourceInfoJsonString);
558                 }
559                 if(!resourceAuthorityEnum.equals(ResourceAuthorityTypeEnum.CSAR_TYPE_BE)){
560                     if (responseWrapper.isEmpty()) {
561                         validateZip(responseWrapper, file, uploadResourceInfoWrapper.getInnerElement().getPayloadName());
562                     }
563
564                     // Fill PayLoad From File
565                     if (responseWrapper.isEmpty()) {
566                         fillToscaTemplateFromZip(yamlStringWrapper, uploadResourceInfoWrapper.getInnerElement().getPayloadName(), file);
567                     }
568                 }else{
569
570                     if (responseWrapper.isEmpty()) {
571                         validateCsar(responseWrapper, file, uploadResourceInfoWrapper.getInnerElement().getPayloadName());
572                     }
573
574                     // Fill PayLoad From File
575                     if (responseWrapper.isEmpty()) {
576                         fillPayloadDataFromFile(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), file);
577                     }
578
579                 }
580
581             } else {
582                 // Fill PayLoad From JSON
583                 if (responseWrapper.isEmpty()) {
584                     fillToscaTemplateFromJson(responseWrapper, yamlStringWrapper, user, uploadResourceInfoWrapper.getInnerElement());
585                 }
586             }
587
588         }
589
590     }
591
592     protected void specificResourceAuthorityValidations(final Wrapper<Response> responseWrapper,
593                                                         final Wrapper<UploadResourceInfo> uploadResourceInfoWrapper,
594                                                         final Wrapper<String> yamlStringWrapper, final User user,
595                                                         final HttpServletRequest request, final String resourceInfoJsonString,
596                                                         final ResourceAuthorityTypeEnum resourceAuthorityEnum) {
597
598         if (responseWrapper.isEmpty()) {
599             // UI Only Validation
600             if (!resourceAuthorityEnum.isBackEndImport()) {
601                 importUIValidations(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), user, request, resourceInfoJsonString);
602             }
603
604             // User Defined Type Resources
605             if (resourceAuthorityEnum.isUserTypeResource()
606                     && !CsarValidationUtils.isCsarPayloadName(uploadResourceInfoWrapper.getInnerElement().getPayloadName())
607                     && responseWrapper.isEmpty()) {
608                             validatePayloadNameSpace(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), user, yamlStringWrapper.getInnerElement());
609             }
610         }
611     }
612
613     void commonGeneralValidations(Wrapper<Response> responseWrapper, Wrapper<User> userWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, ResourceAuthorityTypeEnum resourceAuthorityEnum, String userId,
614                                   String resourceInfoJsonString) {
615
616         if (responseWrapper.isEmpty()) {
617             validateUserExist(responseWrapper, userWrapper, userId);
618         }
619
620         if (responseWrapper.isEmpty()) {
621             validateUserRole(responseWrapper, userWrapper.getInnerElement(), resourceAuthorityEnum);
622         }
623
624         if (responseWrapper.isEmpty()) {
625             validateAndFillResourceJson(responseWrapper, uploadResourceInfoWrapper, userWrapper.getInnerElement(), resourceAuthorityEnum, resourceInfoJsonString);
626         }
627
628         if (responseWrapper.isEmpty()) {
629             validateToscaTemplatePayloadName(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), userWrapper.getInnerElement());
630         }
631         if (responseWrapper.isEmpty()) {
632             validateResourceType(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), userWrapper.getInnerElement());
633         }
634
635     }
636
637     private void validateResourceType(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user) {
638         String resourceType = uploadResourceInfo.getResourceType();
639         if (resourceType == null || !ResourceTypeEnum.containsName(resourceType)) {
640             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
641             Response errorResponse = buildErrorResponse(responseFormat);
642             getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
643             responseWrapper.setInnerElement(errorResponse);
644         }
645     }
646
647     private void importUIValidations(Wrapper<Response> responseWrapper, UploadResourceInfo resourceInfo, User user, HttpServletRequest request, String resourceInfoJsonString) {
648         if (responseWrapper.isEmpty()) {
649             validateMD5(responseWrapper, user, resourceInfo, request, resourceInfoJsonString);
650         }
651         if (responseWrapper.isEmpty() && request != null && request.getMethod() != null && request.getMethod().equals("POST")) {
652             validateResourceDoesNotExist(responseWrapper, user, resourceInfo.getName());
653         }
654     }
655
656     void commonPayloadValidations(Wrapper<Response> responseWrapper, Wrapper<String> yamlStringWrapper, User user, UploadResourceInfo uploadResourceInfo) {
657
658         if (responseWrapper.isEmpty()) {
659             validatePayloadIsYml(responseWrapper, user, uploadResourceInfo, yamlStringWrapper.getInnerElement());
660         }
661         if (responseWrapper.isEmpty()) {
662             validatePayloadIsTosca(responseWrapper, uploadResourceInfo, user, yamlStringWrapper.getInnerElement());
663         }
664         if (responseWrapper.isEmpty()) {
665             validatePayloadIsNotService(responseWrapper, user, uploadResourceInfo, yamlStringWrapper.getInnerElement());
666         }
667         if (responseWrapper.isEmpty()) {
668             validatePayloadIsSingleResource(responseWrapper, uploadResourceInfo, user, yamlStringWrapper.getInnerElement());
669         }
670     }
671
672
673     void handleImport(Wrapper<Response> responseWrapper, User user, UploadResourceInfo resourceInfoObject, String yamlAsString, ResourceAuthorityTypeEnum authority, boolean createNewVersion, String resourceUniqueId) {
674         ImmutablePair<Resource, ActionStatus> createOrUpdateResponse = null;
675         Response response = null;
676         Object representation = null;
677         ImmutablePair<Resource, ActionStatus> importedResourceStatus = null;
678         if (CsarValidationUtils.isCsarPayloadName(resourceInfoObject.getPayloadName())) {
679             log.debug("import resource from csar");
680             importedResourceStatus = importResourceFromUICsar(resourceInfoObject, user, resourceUniqueId);
681         } else if (!authority.isUserTypeResource()) {
682             log.debug("import normative type resource");
683             createOrUpdateResponse = resourceImportManager.importNormativeResource(yamlAsString, resourceInfoObject, user, createNewVersion, true);
684         } else {
685             log.debug("import user resource (not normative type)");
686             createOrUpdateResponse = resourceImportManager.importUserDefinedResource(yamlAsString, resourceInfoObject, user,  false);
687         }
688         if (createOrUpdateResponse!= null){
689             importedResourceStatus = createOrUpdateResponse;
690         }
691         if(importedResourceStatus != null){
692             try {
693                 representation = RepresentationUtils.toRepresentation(importedResourceStatus.left);
694             } catch (IOException e) {
695                 log.debug("Error while building resource representation : {}", e.getMessage(), e);
696             }
697             response = buildOkResponse(getComponentsUtils().getResponseFormat(importedResourceStatus.right), representation);
698         }
699         responseWrapper.setInnerElement(response);
700     }
701
702     private ImmutablePair<Resource, ActionStatus> importResourceFromUICsar(UploadResourceInfo resourceInfoObject, User user, String resourceUniqueId) {
703
704         Resource newResource;
705         ActionStatus actionStatus;
706         Resource resource = new Resource();
707         String payloadName = resourceInfoObject.getPayloadName();
708         fillResourceFromResourceInfoObject(resource, resourceInfoObject);
709
710         Map<String, byte[]> csarUIPayload = getCsarFromPayload(resourceInfoObject);
711         getAndValidateCsarYaml(csarUIPayload, resource, user, payloadName);
712
713         if (resourceUniqueId == null || resourceUniqueId.isEmpty()) {
714             newResource = resourceImportManager.getResourceBusinessLogic().createResource(resource, AuditingActionEnum.CREATE_RESOURCE, user, csarUIPayload, payloadName);
715             actionStatus = ActionStatus.CREATED;
716         } else {
717             newResource = resourceImportManager.getResourceBusinessLogic().validateAndUpdateResourceFromCsar(resource, user, csarUIPayload, payloadName, resourceUniqueId);
718             actionStatus = ActionStatus.OK;
719         }
720         return new ImmutablePair<>(newResource, actionStatus);
721     }
722
723     private Resource throwComponentException(ResponseFormat responseFormat) {
724         throw new ByResponseFormatComponentException(responseFormat);
725     }
726
727     private void getAndValidateCsarYaml(Map<String, byte[]> csarUIPayload, Resource resource, User user, String csarUUID) {
728
729         Either<ImmutablePair<String, String>, ResponseFormat> getToscaYamlRes = CsarValidationUtils.getToscaYaml(csarUIPayload, csarUUID, getComponentsUtils());
730
731         if (getToscaYamlRes.isRight()) {
732             ResponseFormat responseFormat = getToscaYamlRes.right().value();
733             log.debug("Error when try to get csar toscayamlFile with csar ID {}, error: {}", csarUUID, responseFormat);
734             BeEcompErrorManager.getInstance().logBeDaoSystemError("Creating resource from CSAR: fetching CSAR with id " + csarUUID + " failed");
735             getComponentsUtils().auditResource(responseFormat, user, resource, AuditingActionEnum.CREATE_RESOURCE);
736             throwComponentException(responseFormat);
737         }
738         String toscaYaml = getToscaYamlRes.left().value().getValue();
739
740         log.debug("checking tosca template is valid yml");
741         YamlToObjectConverter yamlConvertor = new YamlToObjectConverter();
742         boolean isValid = yamlConvertor.isValidYaml(toscaYaml.getBytes());
743         if (!isValid) {
744             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_YAML_FILE);
745             getComponentsUtils().auditResource(responseFormat, user, resource, AuditingActionEnum.IMPORT_RESOURCE);
746             throwComponentException(responseFormat);
747         }
748
749         log.debug("checking payload is valid tosca");
750         Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaYaml);
751         Either<String, ResultStatusEnum> findFirstToscaStringElement = ImportUtils.findFirstToscaStringElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION);
752
753         if (findFirstToscaStringElement.isRight()) {
754             isValid = false;
755         } else {
756             String defenitionVersionFound = findFirstToscaStringElement.left().value();
757             if (defenitionVersionFound == null || defenitionVersionFound.isEmpty()) {
758                 isValid = false;
759             } else {
760                 isValid = TOSCA_DEFINITION_VERSIONS.contains(defenitionVersionFound);
761             }
762         }
763
764         if (!isValid) {
765             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_TEMPLATE);
766             getComponentsUtils().auditResource(responseFormat, user, resource, AuditingActionEnum.IMPORT_RESOURCE);
767             throwComponentException(responseFormat);
768         }
769     }
770
771     private void fillResourceFromResourceInfoObject(Resource resource, UploadResourceInfo resourceInfoObject) {
772         resourceImportManager.populateResourceMetadata(resourceInfoObject, resource);
773         fillArtifacts(resource, resourceInfoObject);
774
775     }
776
777     private void fillArtifacts(Resource resource, UploadResourceInfo resourceInfoObject) {
778         if (resource != null && resourceInfoObject != null) {
779             List<UploadArtifactInfo> artifactList = resourceInfoObject.getArtifactList();
780             if (artifactList != null) {
781                 Map<String, ArtifactDefinition> artifactsHM = new HashMap<>();
782                 for (UploadArtifactInfo artifact : artifactList) {
783                     ArtifactDefinition artifactDef = new ArtifactDefinition();
784                     artifactDef.setArtifactName(artifact.getArtifactName());
785                     artifactDef.setArtifactType(artifact.getArtifactType().getType());
786                     artifactDef.setDescription(artifact.getArtifactDescription());
787                     artifactDef.setPayloadData(artifact.getArtifactData());
788                     artifactDef.setArtifactRef(artifact.getArtifactPath());
789                     artifactsHM.put(artifactDef.getArtifactName(), artifactDef);
790                 }
791                 resource.setArtifacts(artifactsHM);
792             }
793         }
794     }
795
796     private Map<String, byte[]> getCsarFromPayload(UploadResourceInfo innerElement) {
797         String csarUUID = innerElement.getPayloadName();
798         String payloadData = innerElement.getPayloadData();
799         if (payloadData == null) {
800             log.info("Failed to decode received csar {}", csarUUID);
801             throw new ByActionStatusComponentException(ActionStatus.CSAR_NOT_FOUND, csarUUID);
802         }
803
804         byte[] decodedPayload = Base64.decodeBase64(payloadData.getBytes(StandardCharsets.UTF_8));
805         if (decodedPayload == null) {
806             log.info("Failed to decode received csar {}", csarUUID);
807             throw new ByActionStatusComponentException(ActionStatus.CSAR_NOT_FOUND, csarUUID);
808         }
809
810         Map<String, byte[]> csar = null;
811         try {
812             csar = ZipUtils.readZip(decodedPayload, false);
813         } catch (final ZipException e) {
814             log.info("Failed to unzip received csar {}", csarUUID, e);
815         }
816         return csar;
817     }
818
819     void validateInputStream(final HttpServletRequest request, Wrapper<String> dataWrapper, Wrapper<ResponseFormat> errorWrapper) throws IOException {
820         InputStream inputStream = request.getInputStream();
821         byte[] bytes = IOUtils.toByteArray(inputStream);
822         if (bytes == null || bytes.length == 0) {
823             log.info("Empty body was sent.");
824             errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
825         } else {
826             dataWrapper.setInnerElement(new String(bytes, StandardCharsets.UTF_8));
827         }
828
829     }
830
831     <T> void validateClassParse(String data, Wrapper<T> parsedClassWrapper, Supplier<Class<T>> classGen, Wrapper<ResponseFormat> errorWrapper) {
832         try {
833             T parsedClass = gson.fromJson(data, classGen.get());
834             if (parsedClass == null) {
835                 errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
836             } else {
837                 parsedClassWrapper.setInnerElement(parsedClass);
838             }
839         } catch (JsonSyntaxException e) {
840             log.debug("Failed to decode received {} {} to object.", classGen.get().getName(), data, e);
841             errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
842         }
843     }
844
845     void validateComponentInstanceBusinessLogic(HttpServletRequest request, String containerComponentType, Wrapper<ComponentInstanceBusinessLogic> blWrapper, Wrapper<ResponseFormat> errorWrapper) {
846         ServletContext context = request.getSession().getServletContext();
847         ComponentInstanceBusinessLogic componentInstanceLogic = getComponentInstanceBL(context);
848         if (componentInstanceLogic == null) {
849             log.debug("Unsupported component type {}", containerComponentType);
850             errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
851         } else {
852             blWrapper.setInnerElement(componentInstanceLogic);
853         }
854     }
855
856     <T> Response buildResponseFromElement(Wrapper<ResponseFormat> errorWrapper, Wrapper<T> attributeWrapper) throws IOException {
857         Response response;
858         if (errorWrapper.isEmpty()) {
859             ObjectMapper mapper = new ObjectMapper();
860             String result = mapper.writeValueAsString(attributeWrapper.getInnerElement());
861             response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), result);
862         } else {
863             response = buildErrorResponse(errorWrapper.getInnerElement());
864         }
865         return response;
866     }
867
868     protected void validateXECOMPInstanceIDHeader(String instanceIdHeader, Wrapper<ResponseFormat> responseWrapper) {
869         ResponseFormat responseFormat;
870         if(StringUtils.isEmpty(instanceIdHeader) ){
871             log.debug("Missing X-ECOMP-InstanceID header");
872             responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_X_ECOMP_INSTANCE_ID);
873             responseWrapper.setInnerElement(responseFormat);
874         }
875     }
876
877     protected void validateHttpCspUserIdHeader(String header, Wrapper<ResponseFormat> responseWrapper) {
878         ResponseFormat responseFormat;
879         if( StringUtils.isEmpty(header)){
880             log.debug("MissingUSER_ID");
881             responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_USER_ID);
882             responseWrapper.setInnerElement(responseFormat);
883         }
884     }
885
886     <T> Either<T, ResponseFormat> parseToObject(String json, Supplier<Class<T>> classSupplier) {
887
888         try {
889             T object = RepresentationUtils.fromRepresentation(json, classSupplier.get());
890             return Either.left(object);
891         } catch (Exception e) {
892             log.debug("Failed to parse json to {} object", classSupplier.get().getName(), e);
893             ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
894             return Either.right(responseFormat);
895         }
896     }
897
898     public <T> Either<List<T>, ResponseFormat> parseListOfObjects(String json, Type type) {
899         try {
900             List<T> listOfObjects = gson.fromJson(json, type);
901             return Either.left(listOfObjects);
902         } catch (Exception e) {
903             log.debug("Failed to parse json to {} object", type.getClass().getName(), e);
904             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
905             return Either.right(responseFormat);
906         }
907     }
908     protected void validateNotEmptyBody(String data) {
909         if (StringUtils.isEmpty(data)) {
910             throw new ByActionStatusComponentException(ActionStatus.MISSING_BODY);
911         }
912     }
913 }