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