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