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