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