Support deletion of archived VFs in SDC BE
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / servlets / ResourcesServlet.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  */
20 package org.openecomp.sdc.be.servlets;
21
22 import com.jcabi.aspects.Loggable;
23 import fj.data.Either;
24 import io.swagger.v3.oas.annotations.Operation;
25 import io.swagger.v3.oas.annotations.Parameter;
26 import io.swagger.v3.oas.annotations.media.ArraySchema;
27 import io.swagger.v3.oas.annotations.media.Content;
28 import io.swagger.v3.oas.annotations.media.Schema;
29 import io.swagger.v3.oas.annotations.responses.ApiResponse;
30 import io.swagger.v3.oas.annotations.servers.Server;
31 import io.swagger.v3.oas.annotations.servers.Servers;
32 import io.swagger.v3.oas.annotations.tags.Tag;
33 import io.swagger.v3.oas.annotations.tags.Tags;
34 import org.apache.http.HttpStatus;
35 import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
36 import org.glassfish.jersey.media.multipart.FormDataParam;
37 import org.json.JSONException;
38 import org.json.JSONObject;
39 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
40 import org.openecomp.sdc.be.components.impl.CsarValidationUtils;
41 import org.openecomp.sdc.be.components.impl.ImportUtils;
42 import org.openecomp.sdc.be.components.impl.ResourceBusinessLogic;
43 import org.openecomp.sdc.be.components.impl.ResourceImportManager;
44 import org.openecomp.sdc.be.components.impl.aaf.AafPermission;
45 import org.openecomp.sdc.be.components.impl.aaf.PermissionAllowed;
46 import org.openecomp.sdc.be.config.BeEcompErrorManager;
47 import org.openecomp.sdc.be.dao.api.ActionStatus;
48 import org.openecomp.sdc.be.datamodel.api.HighestFilterEnum;
49 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
50 import org.openecomp.sdc.be.datatypes.enums.DeleteActionEnum;
51 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
52 import org.openecomp.sdc.be.impl.ComponentsUtils;
53 import org.openecomp.sdc.be.impl.ServletUtils;
54 import org.openecomp.sdc.be.model.Resource;
55 import org.openecomp.sdc.be.model.UploadResourceInfo;
56 import org.openecomp.sdc.be.model.User;
57 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
58 import org.openecomp.sdc.be.resources.data.auditing.model.DistributionData;
59 import org.openecomp.sdc.be.resources.data.auditing.model.ResourceCommonInfo;
60 import org.openecomp.sdc.be.servlets.ResourceUploadServlet.ResourceAuthorityTypeEnum;
61 import org.openecomp.sdc.be.user.UserBusinessLogic;
62 import org.openecomp.sdc.common.api.Constants;
63 import org.openecomp.sdc.common.datastructure.Wrapper;
64 import org.openecomp.sdc.common.log.elements.LoggerSupportability;
65 import org.openecomp.sdc.common.log.enums.LoggerSupportabilityActions;
66 import org.openecomp.sdc.common.log.enums.StatusCode;
67 import org.openecomp.sdc.common.log.wrappers.Logger;
68 import org.openecomp.sdc.common.util.ValidationUtils;
69 import org.openecomp.sdc.common.zip.exception.ZipException;
70 import org.openecomp.sdc.exception.ResponseFormat;
71 import org.springframework.stereotype.Controller;
72
73 import javax.inject.Inject;
74 import javax.servlet.ServletContext;
75 import javax.servlet.http.HttpServletRequest;
76 import javax.ws.rs.Consumes;
77 import javax.ws.rs.DELETE;
78 import javax.ws.rs.GET;
79 import javax.ws.rs.HeaderParam;
80 import javax.ws.rs.POST;
81 import javax.ws.rs.PUT;
82 import javax.ws.rs.Path;
83 import javax.ws.rs.PathParam;
84 import javax.ws.rs.Produces;
85 import javax.ws.rs.QueryParam;
86 import javax.ws.rs.core.Context;
87 import javax.ws.rs.core.MediaType;
88 import javax.ws.rs.core.Response;
89 import java.io.File;
90 import java.io.IOException;
91 import java.util.List;
92 import java.util.Map;
93
94 @Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
95 @Path("/v1/catalog")
96 @Tags({@Tag(name = "SDCE-2 APIs")})
97 @Servers({@Server(url = "/sdc2/rest")})
98 @Controller
99 public class ResourcesServlet extends AbstractValidationsServlet {
100
101     private static final Logger log = Logger.getLogger(ResourcesServlet.class);
102     private static final LoggerSupportability loggerSupportability = LoggerSupportability.getLogger(ResourcesServlet.class.getName());
103     private static final String START_HANDLE_REQUEST_OF = "Start handle request of {}";
104     private static final String MODIFIER_ID_IS = "modifier id is {}";
105     private final ResourceBusinessLogic resourceBusinessLogic;
106
107     @Inject
108     public ResourcesServlet(UserBusinessLogic userBusinessLogic, ComponentInstanceBusinessLogic componentInstanceBL,
109                             ResourceBusinessLogic resourceBusinessLogic, ComponentsUtils componentsUtils, ServletUtils servletUtils,
110                             ResourceImportManager resourceImportManager) {
111         super(userBusinessLogic, componentInstanceBL, componentsUtils, servletUtils, resourceImportManager);
112         this.resourceBusinessLogic = resourceBusinessLogic;
113     }
114
115     @POST
116     @Path("/resources")
117     @Consumes(MediaType.APPLICATION_JSON)
118     @Produces(MediaType.APPLICATION_JSON)
119     @Operation(description = "Create Resource", method = "POST", summary = "Returns created resource", responses = {
120         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))),
121         @ApiResponse(responseCode = "201", description = "Resource created"),
122         @ApiResponse(responseCode = "403", description = "Restricted operation"),
123         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
124         @ApiResponse(responseCode = "409", description = "Resource already exist")})
125     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
126     public Response createResource(@Parameter(description = "Resource object to be created", required = true) String data,
127                                    @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId)
128         throws IOException, ZipException {
129         userId = (userId != null) ? userId : request.getHeader(Constants.USER_ID_HEADER);
130         init();
131         String url = request.getMethod() + " " + request.getRequestURI();
132         log.debug(START_HANDLE_REQUEST_OF, url);
133         // get modifier id
134         User modifier = new User();
135         modifier.setUserId(userId);
136         log.debug(MODIFIER_ID_IS, userId);
137         loggerSupportability.log(LoggerSupportabilityActions.CREATE_RESOURCE, StatusCode.STARTED, "Starting to create Resource by user {}", userId);
138         Response response;
139         try {
140             Wrapper<Response> responseWrapper = new Wrapper<>();
141             // UI Import
142             if (isUIImport(data)) {
143                 performUIImport(responseWrapper, data, request, userId, null);
144             }
145             // UI Create
146             else {
147                 Either<Resource, ResponseFormat> convertResponse = parseToResource(data, modifier);
148                 if (convertResponse.isRight()) {
149                     log.debug("failed to parse resource");
150                     response = buildErrorResponse(convertResponse.right().value());
151                     return response;
152                 }
153                 Resource resource = convertResponse.left().value();
154                 Resource createdResource = resourceBusinessLogic.createResource(resource, AuditingActionEnum.CREATE_RESOURCE, modifier, null, null);
155                 Object representation = RepresentationUtils.toRepresentation(createdResource);
156                 response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), representation);
157                 responseWrapper.setInnerElement(response);
158                 loggerSupportability
159                     .log(LoggerSupportabilityActions.CREATE_RESOURCE, resource.getComponentMetadataForSupportLog(), StatusCode.COMPLETE,
160                         "Resource successfully created user {}", userId);
161             }
162             return responseWrapper.getInnerElement();
163         } catch (final IOException | ZipException e) {
164             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Create Resource");
165             log.debug("create resource failed with exception", e);
166             throw e;
167         }
168     }
169
170     private boolean isUIImport(String data) {
171         boolean isUIImport;
172         try {
173             JSONObject json = new JSONObject(data);
174             String payloadName = json.getString(ImportUtils.Constants.UI_JSON_PAYLOAD_NAME);
175             isUIImport = payloadName != null && !payloadName.isEmpty();
176         } catch (JSONException e) {
177             log.debug("failed to parse json sent from client, json:{}", data, e);
178             isUIImport = false;
179         }
180         return isUIImport;
181     }
182
183     private void performUIImport(final Wrapper<Response> responseWrapper, final String data, final HttpServletRequest request, final String userId,
184                                  final String resourceUniqueId) throws ZipException {
185         Wrapper<User> userWrapper = new Wrapper<>();
186         Wrapper<UploadResourceInfo> uploadResourceInfoWrapper = new Wrapper<>();
187         Wrapper<String> yamlStringWrapper = new Wrapper<>();
188         ResourceAuthorityTypeEnum resourceAuthorityEnum = ResourceAuthorityTypeEnum.USER_TYPE_UI;
189         commonGeneralValidations(responseWrapper, userWrapper, uploadResourceInfoWrapper, resourceAuthorityEnum, userId, data);
190         if (!CsarValidationUtils.isCsarPayloadName(uploadResourceInfoWrapper.getInnerElement().getPayloadName())) {
191             fillPayload(responseWrapper, uploadResourceInfoWrapper, yamlStringWrapper, userWrapper.getInnerElement(), data, resourceAuthorityEnum,
192                 null);
193             // PayLoad Validations
194             commonPayloadValidations(responseWrapper, yamlStringWrapper, userWrapper.getInnerElement(), uploadResourceInfoWrapper.getInnerElement());
195         }
196         specificResourceAuthorityValidations(responseWrapper, uploadResourceInfoWrapper, yamlStringWrapper, userWrapper.getInnerElement(), request,
197             data, resourceAuthorityEnum);
198         if (responseWrapper.isEmpty()) {
199             handleImport(responseWrapper, userWrapper.getInnerElement(), uploadResourceInfoWrapper.getInnerElement(),
200                 yamlStringWrapper.getInnerElement(), resourceAuthorityEnum, true, resourceUniqueId);
201         }
202     }
203
204     private Either<Resource, ResponseFormat> parseToResource(String resourceJson, User user) {
205         return getComponentsUtils()
206             .convertJsonToObjectUsingObjectMapper(resourceJson, user, Resource.class, AuditingActionEnum.CREATE_RESOURCE, ComponentTypeEnum.RESOURCE);
207     }
208
209     private Either<Resource, ResponseFormat> parseToLightResource(String resourceJson, User user) {
210         Either<Resource, ResponseFormat> ret = getComponentsUtils()
211             .convertJsonToObjectUsingObjectMapper(resourceJson, user, Resource.class, AuditingActionEnum.UPDATE_RESOURCE_METADATA,
212                 ComponentTypeEnum.RESOURCE);
213         if (ret.isLeft()) {// drop unwanted data (sent from UI in update flow)
214             ret.left().value().setRequirements(null);
215             ret.left().value().setCapabilities(null);
216         }
217         return ret;
218     }
219
220     @DELETE
221     @Path("/resources/{resourceId}")
222     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
223     public Response deleteResource(@PathParam("resourceId") final String resourceId,
224                                    @Parameter(description = "Optional parameter to determine the delete action: " +
225                                            "DELETE, which will permanently delete the Resource from the system or " +
226                                            "MARK_AS_DELETE, which will logically mark the Resource as deleted. Default action is to MARK_AS_DELETE")
227                                    @QueryParam("deleteAction") final DeleteActionEnum deleteAction,
228                                    @Context final HttpServletRequest request) {
229         String url = request.getMethod() + " " + request.getRequestURI();
230         log.debug(START_HANDLE_REQUEST_OF, url);
231         // get modifier id
232         String userId = request.getHeader(Constants.USER_ID_HEADER);
233         User modifier = new User();
234         modifier.setUserId(userId);
235         log.debug(MODIFIER_ID_IS, userId);
236         loggerSupportability.log(LoggerSupportabilityActions.DELETE_RESOURCE, StatusCode.STARTED, "Starting to delete Resource by user {}", userId);
237         try {
238             String resourceIdLower = resourceId.toLowerCase();
239             ResponseFormat actionResponse;
240             if (DeleteActionEnum.DELETE.equals(deleteAction)) {
241                 resourceBusinessLogic.deleteResourceAllVersions(resourceId, modifier);
242                 actionResponse = componentsUtils.getResponseFormat(ActionStatus.NO_CONTENT);
243             } else {
244                 actionResponse = resourceBusinessLogic.deleteResource(resourceIdLower, modifier);
245             }
246             if (actionResponse.getStatus() != HttpStatus.SC_NO_CONTENT) {
247                 log.debug("failed to delete resource");
248                 return buildErrorResponse(actionResponse);
249             }
250
251             loggerSupportability.log(LoggerSupportabilityActions.DELETE_RESOURCE, StatusCode.COMPLETE, "Ended delete Resource by user {}", userId);
252             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.NO_CONTENT), null);
253         } catch (Exception e) {
254             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Delete Resource");
255             log.debug("delete resource failed with exception ", e);
256             throw e;
257         }
258     }
259
260     @DELETE
261     @Path("/resources/{resourceName}/{version}")
262     @Operation(description = "Delete Resource By Name And Version", method = "DELETE", summary = "Returns no content", responses = {
263         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))),
264         @ApiResponse(responseCode = "204", description = "Resource deleted"),
265         @ApiResponse(responseCode = "403", description = "Restricted operation"),
266         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
267         @ApiResponse(responseCode = "404", description = "Resource not found")})
268     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
269     public Response deleteResourceByNameAndVersion(@PathParam("resourceName") final String resourceName, @PathParam("version") final String version,
270                                                    @Context final HttpServletRequest request) {
271         ServletContext context = request.getSession().getServletContext();
272         String url = request.getMethod() + " " + request.getRequestURI();
273         log.debug(START_HANDLE_REQUEST_OF, url);
274         // get modifier id
275         String userId = request.getHeader(Constants.USER_ID_HEADER);
276         User modifier = new User();
277         modifier.setUserId(userId);
278         log.debug(MODIFIER_ID_IS, userId);
279         Response response;
280         ResourceBusinessLogic businessLogic = getResourceBL(context);
281         ResponseFormat actionResponse = businessLogic.deleteResourceByNameAndVersion(resourceName, version, modifier);
282         if (actionResponse.getStatus() != HttpStatus.SC_NO_CONTENT) {
283             log.debug("failed to delete resource");
284             response = buildErrorResponse(actionResponse);
285             return response;
286         }
287         response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.NO_CONTENT), null);
288         return response;
289     }
290
291     @GET
292     @Path("/resources/{resourceId}")
293     @Consumes(MediaType.APPLICATION_JSON)
294     @Produces(MediaType.APPLICATION_JSON)
295     @Operation(description = "Retrieve Resource", method = "GET", summary = "Returns resource according to resourceId", responses = {
296         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))),
297         @ApiResponse(responseCode = "200", description = "Resource found"), @ApiResponse(responseCode = "403", description = "Restricted operation"),
298         @ApiResponse(responseCode = "404", description = "Resource not found")})
299     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
300     public Response getResourceById(@PathParam("resourceId") final String resourceId, @Context final HttpServletRequest request,
301                                     @HeaderParam(value = Constants.USER_ID_HEADER) String userId) throws IOException {
302         ServletContext context = request.getSession().getServletContext();
303         String url = request.getMethod() + " " + request.getRequestURI();
304         log.debug(START_HANDLE_REQUEST_OF, url);
305         // get modifier id
306         User modifier = new User();
307         modifier.setUserId(userId);
308         log.debug(MODIFIER_ID_IS, userId);
309         Response response;
310         try {
311             String resourceIdLower = resourceId.toLowerCase();
312             log.trace("get resource with id {}", resourceId);
313             Either<Resource, ResponseFormat> actionResponse = resourceBusinessLogic.getResource(resourceIdLower, modifier);
314             if (actionResponse.isRight()) {
315                 log.debug("failed to get resource");
316                 response = buildErrorResponse(actionResponse.right().value());
317                 return response;
318             }
319             Object resource = RepresentationUtils.toRepresentation(actionResponse.left().value());
320             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), resource);
321         } catch (IOException e) {
322             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Resource");
323             log.debug("get resource failed with exception", e);
324             throw e;
325         }
326     }
327
328     @GET
329     @Path("/resources/resourceName/{resourceName}/resourceVersion/{resourceVersion}")
330     @Consumes(MediaType.APPLICATION_JSON)
331     @Produces(MediaType.APPLICATION_JSON)
332     @Operation(description = "Retrieve Resource by name and version", method = "GET", summary = "Returns resource according to resourceId", responses = {
333         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))),
334         @ApiResponse(responseCode = "200", description = "Resource found"), @ApiResponse(responseCode = "403", description = "Restricted operation"),
335         @ApiResponse(responseCode = "404", description = "Resource not found")})
336     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
337     public Response getResourceByNameAndVersion(@PathParam("resourceName") final String resourceName,
338                                                 @PathParam("resourceVersion") final String resourceVersion, @Context final HttpServletRequest request,
339                                                 @HeaderParam(value = Constants.USER_ID_HEADER) String userId) throws IOException {
340         // get modifier id
341         User modifier = new User();
342         modifier.setUserId(userId);
343         log.debug(MODIFIER_ID_IS, userId);
344         Response response;
345         try {
346             Either<Resource, ResponseFormat> actionResponse = resourceBusinessLogic
347                 .getResourceByNameAndVersion(resourceName, resourceVersion, userId);
348             if (actionResponse.isRight()) {
349                 response = buildErrorResponse(actionResponse.right().value());
350                 return response;
351             }
352             Object resource = RepresentationUtils.toRepresentation(actionResponse.left().value());
353             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), resource);
354         } catch (IOException e) {
355             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Resource by name and version");
356             log.debug("get resource failed with exception", e);
357             throw e;
358         }
359     }
360
361     @GET
362     @Path("/resources/validate-name/{resourceName}")
363     @Consumes(MediaType.APPLICATION_JSON)
364     @Produces(MediaType.APPLICATION_JSON)
365     @Operation(description = "validate resource name", method = "GET", summary = "checks if the chosen resource name is available ", responses = {
366         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))),
367         @ApiResponse(responseCode = "200", description = "Resource found"), @ApiResponse(responseCode = "403", description = "Restricted operation")})
368     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
369     public Response validateResourceName(@PathParam("resourceName") final String resourceName, @QueryParam("subtype") String resourceType,
370                                          @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
371         String url = request.getMethod() + " " + request.getRequestURI();
372         log.debug(START_HANDLE_REQUEST_OF, url);
373         // get modifier id
374         User modifier = new User();
375         modifier.setUserId(userId);
376         log.debug(MODIFIER_ID_IS, userId);
377         Response response;
378         if (resourceType != null && !ResourceTypeEnum.containsName(resourceType)) {
379             log.debug("invalid resource type received");
380             response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
381             return response;
382         }
383         ResourceTypeEnum typeEnum = null;
384         if (resourceType != null) {
385             typeEnum = ResourceTypeEnum.valueOf(resourceType);
386         }
387         Either<Map<String, Boolean>, ResponseFormat> actionResponse = resourceBusinessLogic
388             .validateResourceNameExists(resourceName, typeEnum, userId);
389         if (actionResponse.isRight()) {
390             log.debug("failed to validate resource name");
391             response = buildErrorResponse(actionResponse.right().value());
392             return response;
393         }
394         return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), actionResponse.left().value());
395     }
396
397     @GET
398     @Path("/resources/certified/abstract")
399     @Consumes(MediaType.APPLICATION_JSON)
400     @Produces(MediaType.APPLICATION_JSON)
401     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
402     public Response getCertifiedAbstractResources(@Context final HttpServletRequest request,
403                                                   @HeaderParam(value = Constants.USER_ID_HEADER) String userId) throws IOException {
404         String url = request.getMethod() + " " + request.getRequestURI();
405         log.debug("(get) Start handle request of {}", url);
406         try {
407             List<Resource> resources = resourceBusinessLogic.getAllCertifiedResources(true, HighestFilterEnum.HIGHEST_ONLY, userId);
408             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), RepresentationUtils.toRepresentation(resources));
409         } catch (IOException e) {
410             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Certified Abstract Resources");
411             log.debug("getCertifiedAbstractResources failed with exception", e);
412             throw e;
413         }
414     }
415
416     @GET
417     @Path("/resources/certified/notabstract")
418     @Consumes(MediaType.APPLICATION_JSON)
419     @Produces(MediaType.APPLICATION_JSON)
420     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
421     public Response getCertifiedNotAbstractResources(@Context final HttpServletRequest request,
422                                                      @HeaderParam(value = Constants.USER_ID_HEADER) String userId) throws IOException {
423         String url = request.getMethod() + " " + request.getRequestURI();
424         log.debug("(get) Start handle request of {}", url);
425         try {
426             List<Resource> resouces = resourceBusinessLogic.getAllCertifiedResources(false, HighestFilterEnum.ALL, userId);
427             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), RepresentationUtils.toRepresentation(resouces));
428         } catch (IOException e) {
429             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Certified Non Abstract Resources");
430             log.debug("getCertifiedNotAbstractResources failed with exception", e);
431             throw e;
432         }
433     }
434
435     @PUT
436     @Path("/resources/{resourceId}/metadata")
437     @Consumes(MediaType.APPLICATION_JSON)
438     @Produces(MediaType.APPLICATION_JSON)
439     @Operation(description = "Update Resource Metadata", method = "PUT", summary = "Returns updated resource metadata", responses = {
440         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))),
441         @ApiResponse(responseCode = "200", description = "Resource metadata updated"),
442         @ApiResponse(responseCode = "403", description = "Restricted operation"),
443         @ApiResponse(responseCode = "400", description = "Invalid content")})
444     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
445     public Response updateResourceMetadata(@PathParam("resourceId") final String resourceId,
446                                            @Parameter(description = "Resource metadata to be updated", required = true) String data,
447                                            @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId)
448         throws IOException {
449         String url = request.getMethod() + " " + request.getRequestURI();
450         log.debug(START_HANDLE_REQUEST_OF, url);
451         // get modifier id
452         User modifier = new User();
453         modifier.setUserId(userId);
454         log.debug(MODIFIER_ID_IS, userId);
455         Response response;
456         try {
457             String resourceIdLower = resourceId.toLowerCase();
458             Either<Resource, ResponseFormat> updateInfoResource = getComponentsUtils()
459                 .convertJsonToObjectUsingObjectMapper(data, modifier, Resource.class, AuditingActionEnum.UPDATE_RESOURCE_METADATA,
460                     ComponentTypeEnum.RESOURCE);
461             if (updateInfoResource.isRight()) {
462                 log.debug("failed to parse resource metadata");
463                 response = buildErrorResponse(updateInfoResource.right().value());
464                 return response;
465             }
466             Resource updatedResource = resourceBusinessLogic
467                 .updateResourceMetadata(resourceIdLower, updateInfoResource.left().value(), null, modifier, false);
468             Object resource = RepresentationUtils.toRepresentation(updatedResource);
469             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), resource);
470         } catch (IOException e) {
471             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Update Resource Metadata");
472             log.debug("Update Resource Metadata failed with exception", e);
473             throw e;
474         }
475     }
476
477     @PUT
478     @Path("/resources/{resourceId}")
479     @Consumes(MediaType.APPLICATION_JSON)
480     @Produces(MediaType.APPLICATION_JSON)
481     @Operation(description = "Update Resource", method = "PUT", summary = "Returns updated resource", responses = {
482         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))),
483         @ApiResponse(responseCode = "200", description = "Resource updated"),
484         @ApiResponse(responseCode = "403", description = "Restricted operation"),
485         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
486         @ApiResponse(responseCode = "409", description = "Resource already exist")})
487     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
488     public Response updateResource(@Parameter(description = "Resource object to be updated", required = true) String data,
489                                    @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId,
490                                    @PathParam(value = "resourceId") String resourceId) throws IOException, ZipException {
491         userId = (userId != null) ? userId : request.getHeader(Constants.USER_ID_HEADER);
492         init();
493         String url = request.getMethod() + " " + request.getRequestURI();
494         log.debug(START_HANDLE_REQUEST_OF, url);
495         // get modifier id
496         User modifier = new User();
497         modifier.setUserId(userId);
498         log.debug(MODIFIER_ID_IS, userId);
499         loggerSupportability.log(LoggerSupportabilityActions.UPDATE_RESOURCE, StatusCode.STARTED, "Starting to update a resource by user {}", userId);
500         Response response;
501         try {
502             Wrapper<Response> responseWrapper = new Wrapper<>();
503             // UI Import
504             if (isUIImport(data)) {
505                 performUIImport(responseWrapper, data, request, userId, resourceId);
506             } else {
507                 Either<Resource, ResponseFormat> convertResponse = parseToLightResource(data, modifier);
508                 if (convertResponse.isRight()) {
509                     log.debug("failed to parse resource");
510                     response = buildErrorResponse(convertResponse.right().value());
511                     return response;
512                 }
513                 Resource updatedResource = resourceBusinessLogic
514                     .validateAndUpdateResourceFromCsar(convertResponse.left().value(), modifier, null, null, resourceId);
515                 Object representation = RepresentationUtils.toRepresentation(updatedResource);
516                 response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), representation);
517                 responseWrapper.setInnerElement(response);
518                 loggerSupportability
519                     .log(LoggerSupportabilityActions.UPDATE_RESOURCE, updatedResource.getComponentMetadataForSupportLog(), StatusCode.COMPLETE,
520                         "Ended update a resource by user {}", userId);
521             }
522             return responseWrapper.getInnerElement();
523         } catch (final IOException | ZipException e) {
524             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Update Resource");
525             log.debug("update resource failed with exception", e);
526             throw e;
527         }
528     }
529
530     @GET
531     @Path("/resources/csar/{csaruuid}")
532     @Consumes(MediaType.APPLICATION_JSON)
533     @Produces(MediaType.APPLICATION_JSON)
534     @Operation(description = "Create Resource", method = "POST", summary = "Returns resource created from csar uuid", responses = {
535         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))),
536         @ApiResponse(responseCode = "201", description = "Resource retrieced"),
537         @ApiResponse(responseCode = "403", description = "Restricted operation"),
538         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
539     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
540     public Response getResourceFromCsar(@Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId,
541                                         @PathParam(value = "csaruuid") String csarUUID) throws IOException {
542         init();
543         String url = request.getMethod() + " " + request.getRequestURI();
544         log.debug(START_HANDLE_REQUEST_OF, url);
545         // retrieve user details
546         userId = (userId != null) ? userId : request.getHeader(Constants.USER_ID_HEADER);
547         User user = new User();
548         user.setUserId(userId);
549         log.debug("user id is {}", userId);
550         Response response;
551         try {
552             Either<Resource, ResponseFormat> eitherResource = resourceBusinessLogic
553                 .getLatestResourceFromCsarUuid(ValidationUtils.sanitizeInputString(csarUUID), user);
554             // validate response
555             if (eitherResource.isRight()) {
556                 log.debug("failed to get resource from csarUuid : {}", csarUUID);
557                 response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT), eitherResource.right().value());
558             } else {
559                 Object representation = RepresentationUtils.toRepresentation(eitherResource.left().value());
560                 response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), representation);
561             }
562             return response;
563         } catch (IOException e) {
564             log.debug("get resource by csar failed with exception", e);
565             throw e;
566         }
567     }
568
569     @POST
570     @Path("/resources/importReplaceResource")
571     @Produces(MediaType.APPLICATION_JSON)
572     @Operation(description = "Import Resource", method = "POST", summary = "Returns imported resource", responses = {
573         @ApiResponse(responseCode = "201", description = "Resource created"),
574         @ApiResponse(responseCode = "403", description = "Restricted operation"),
575         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
576         @ApiResponse(responseCode = "409", description = "Resource already exist")})
577     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
578     public Response importReplaceResource(
579         @Parameter(description = "The user id", required = true) @HeaderParam(value = Constants.USER_ID_HEADER) String userId,
580         @Parameter(description = "X-ECOMP-RequestID header", required = false) @HeaderParam(value = Constants.X_ECOMP_REQUEST_ID_HEADER) String requestId,
581         @Parameter(description = "X-ECOMP-InstanceID header", required = true) @HeaderParam(value = Constants.X_ECOMP_INSTANCE_ID_HEADER) final String instanceIdHeader,
582         @Parameter(description = "Determines the format of the body of the response", required = false) @HeaderParam(value = Constants.ACCEPT_HEADER) String accept,
583         @Parameter(description = "The username and password", required = true) @HeaderParam(value = Constants.AUTHORIZATION_HEADER) String authorization,
584         @Context final HttpServletRequest request, @Parameter(description = "FileInputStream") @FormDataParam("resourceZip") File file,
585         @Parameter(description = "ContentDisposition") @FormDataParam("resourceZip") FormDataContentDisposition contentDispositionHeader,
586         @Parameter(description = "resourceMetadata") @FormDataParam("resourceZipMetadata") String resourceInfoJsonString) {
587         init();
588         String requestURI = request.getRequestURI();
589         String url = request.getMethod() + " " + requestURI;
590         log.debug("importReplaceResource,Start handle request of {}", url);
591         // get modifier id
592         User modifier = new User();
593         modifier.setUserId(userId);
594         log.debug("importReplaceResource,modifier id is {}", userId);
595         log.debug("importReplaceResource,get file:{},fileName:{}", file, file.getName());
596         Response response;
597         ResponseFormat responseFormat = null;
598         AuditingActionEnum auditingActionEnum = AuditingActionEnum.Import_Replace_Resource;
599         String assetType = "resources";
600         ComponentTypeEnum componentType = ComponentTypeEnum.findByParamName(assetType);
601         ResourceCommonInfo resourceCommonInfo = new ResourceCommonInfo(componentType.getValue());
602         DistributionData distributionData = new DistributionData(instanceIdHeader, requestURI);
603         // Mandatory
604         if (instanceIdHeader == null || instanceIdHeader.isEmpty()) {
605             log.debug("importReplaceResource: Missing X-ECOMP-InstanceID header");
606             responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_X_ECOMP_INSTANCE_ID);
607             getComponentsUtils().auditExternalGetAsset(responseFormat, auditingActionEnum, distributionData, resourceCommonInfo, requestId, null);
608             return buildErrorResponse(responseFormat);
609         }
610         try {
611             Wrapper<Response> responseWrapper = new Wrapper<>();
612             // file import
613             Wrapper<User> userWrapper = new Wrapper<>();
614             Wrapper<UploadResourceInfo> uploadResourceInfoWrapper = new Wrapper<>();
615             Wrapper<String> yamlStringWrapper = new Wrapper<>();
616             ResourceAuthorityTypeEnum serviceAuthorityEnum = ResourceAuthorityTypeEnum.CSAR_TYPE_BE;
617             // PayLoad Validations
618             commonGeneralValidations(responseWrapper, userWrapper, uploadResourceInfoWrapper, serviceAuthorityEnum, userId, resourceInfoJsonString);
619             fillPayload(responseWrapper, uploadResourceInfoWrapper, yamlStringWrapper, modifier, resourceInfoJsonString, serviceAuthorityEnum, file);
620             specificResourceAuthorityValidations(responseWrapper, uploadResourceInfoWrapper, yamlStringWrapper, userWrapper.getInnerElement(),
621                 request, resourceInfoJsonString, serviceAuthorityEnum);
622             log.debug("importReplaceResource:get payload:{}", uploadResourceInfoWrapper.getInnerElement().getPayloadData());
623             log.debug("importReplaceResource:get ResourceType:{}", uploadResourceInfoWrapper.getInnerElement().getResourceType());
624             if (responseWrapper.isEmpty()) {
625                 log.debug("importReplaceService:start handleImport");
626                 handleImport(responseWrapper, userWrapper.getInnerElement(), uploadResourceInfoWrapper.getInnerElement(),
627                     yamlStringWrapper.getInnerElement(), serviceAuthorityEnum, true, null);
628             }
629             return responseWrapper.getInnerElement();
630         } catch (ZipException e) {
631             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Import Resource");
632             log.debug("import resource failed with exception", e);
633             response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
634             return response;
635         }
636     }
637 }