Remove legacy certificate handling
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / servlets / ArtifactServlet.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.util.Map;
35 import javax.inject.Inject;
36 import javax.servlet.http.HttpServletRequest;
37 import javax.ws.rs.Consumes;
38 import javax.ws.rs.DELETE;
39 import javax.ws.rs.GET;
40 import javax.ws.rs.HeaderParam;
41 import javax.ws.rs.POST;
42 import javax.ws.rs.Path;
43 import javax.ws.rs.PathParam;
44 import javax.ws.rs.Produces;
45 import javax.ws.rs.core.Context;
46 import javax.ws.rs.core.MediaType;
47 import javax.ws.rs.core.Response;
48 import org.apache.commons.codec.binary.Base64;
49 import org.apache.commons.lang3.tuple.ImmutablePair;
50 import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic;
51 import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic.ArtifactOperationEnum;
52 import org.openecomp.sdc.be.components.impl.artifact.ArtifactOperationInfo;
53 import org.openecomp.sdc.be.config.BeEcompErrorManager;
54 import org.openecomp.sdc.be.dao.api.ActionStatus;
55 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
56 import org.openecomp.sdc.be.impl.ComponentsUtils;
57 import org.openecomp.sdc.be.model.ArtifactDefinition;
58 import org.openecomp.sdc.be.model.ArtifactUiDownloadData;
59 import org.openecomp.sdc.be.resources.data.auditing.model.ResourceCommonInfo;
60 import org.openecomp.sdc.common.api.Constants;
61 import org.openecomp.sdc.common.log.elements.LoggerSupportability;
62 import org.openecomp.sdc.common.log.enums.LoggerSupportabilityActions;
63 import org.openecomp.sdc.common.log.enums.StatusCode;
64 import org.openecomp.sdc.common.log.wrappers.Logger;
65 import org.openecomp.sdc.exception.ResponseFormat;
66 import org.springframework.stereotype.Controller;
67
68 /**
69  * Root resource (exposed at "/" path)
70  */
71 @Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
72 @Path("/v1/catalog")
73 @Tags({@Tag(name = "SDCE-2 APIs")})
74 @Servers({@Server(url = "/sdc2/rest")})
75 @Controller
76 public class ArtifactServlet extends BeGenericServlet {
77
78     private static final Logger log = Logger.getLogger(ArtifactServlet.class);
79     private static final LoggerSupportability loggerSupportability = LoggerSupportability.getLogger(ArtifactServlet.class.getName());
80     private static final String START_HANDLE_REQUEST_OF = "Start handle request of {}";
81     private static final String DOWNLOAD_RESOURCE_INSTANCE_ARTIFACT_BASE64 = "downloadResourceInstanceArtifactBase64";
82     private static final String DOWNLOAD_RESOURCE_INSTANCE_ARTIFACT_BASE64_EXCEPTION = "downloadResourceInstanceArtifactBase64 unexpected exception";
83     private final ArtifactsBusinessLogic artifactsBusinessLogic;
84
85     @Inject
86     public ArtifactServlet(ComponentsUtils componentsUtils, ArtifactsBusinessLogic artifactsBusinessLogic) {
87         super(componentsUtils);
88         this.artifactsBusinessLogic = artifactsBusinessLogic;
89     }
90
91     // *************** Resources
92     @POST
93     @Path("/resources/{resourceId}/artifacts")
94     @Consumes(MediaType.APPLICATION_JSON)
95     @Produces(MediaType.APPLICATION_JSON)
96     @Operation(description = "Create Artifact", method = "POST", summary = "Returns created ArtifactDefinition", responses = {
97         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
98         @ApiResponse(responseCode = "201", description = "Resource created"),
99         @ApiResponse(responseCode = "403", description = "Restricted operation"),
100         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
101         @ApiResponse(responseCode = "409", description = "Artifact already exist")})
102     public Response loadArtifact(@PathParam("resourceId") final String resourceId,
103                                  @Parameter(description = "json describe the artifact", required = true) String data,
104                                  @Context final HttpServletRequest request) {
105         String url = request.getMethod() + " " + request.getRequestURI();
106         log.debug(START_HANDLE_REQUEST_OF, url);
107         return handleUploadRequest(data, request, resourceId, ComponentTypeEnum.RESOURCE);
108     }
109
110     @POST
111     @Path("/resources/{resourceId}/artifacts/{artifactId}")
112     @Consumes(MediaType.APPLICATION_JSON)
113     @Produces(MediaType.APPLICATION_JSON)
114     @Operation(description = "Update Artifact", method = "POST", summary = "Returns updated artifact", responses = {
115         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
116         @ApiResponse(responseCode = "201", description = "Resource created"),
117         @ApiResponse(responseCode = "403", description = "Restricted operation"),
118         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
119     public Response updateArtifact(@PathParam("resourceId") final String resourceId, @PathParam("artifactId") final String artifactId,
120                                    @Parameter(description = "json describe the artifact", required = true) String data,
121                                    @Context final HttpServletRequest request) {
122         String url = request.getMethod() + " " + request.getRequestURI();
123         log.debug(START_HANDLE_REQUEST_OF, url);
124         try {
125             return handleUpdateRequest(data, request, resourceId, artifactId, ComponentTypeEnum.RESOURCE);
126         } catch (Exception e) {
127             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("updateArtifact");
128             log.debug("updateArtifact unexpected exception", e);
129             throw e;
130         }
131     }
132
133     @DELETE
134     @Path("/resources/{resourceId}/artifacts/{artifactId}")
135     @Consumes(MediaType.APPLICATION_JSON)
136     @Produces(MediaType.APPLICATION_JSON)
137     @Operation(description = "Delete Artifact", method = "DELETE", summary = "Returns delete artifact", responses = {
138         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
139         @ApiResponse(responseCode = "201", description = "Resource created"),
140         @ApiResponse(responseCode = "403", description = "Restricted operation"),
141         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
142     public Response deleteArtifact(@PathParam("resourceId") final String resourceId, @PathParam("artifactId") final String artifactId,
143                                    @Context final HttpServletRequest request) {
144         String url = request.getMethod() + " " + request.getRequestURI();
145         log.debug(START_HANDLE_REQUEST_OF, url);
146         try {
147             return handleDeleteRequest(request, resourceId, artifactId, ComponentTypeEnum.RESOURCE, null, null);
148         } catch (Exception e) {
149             log.debug("deleteArtifact unexpected exception", e);
150             throw e;
151         }
152     }
153
154     // *************** Services
155     @POST
156     @Path("/services/{serviceId}/artifacts")
157     @Consumes(MediaType.APPLICATION_JSON)
158     @Produces(MediaType.APPLICATION_JSON)
159     @Operation(description = "Create Artifact", method = "POST", summary = "Returns created ArtifactDefinition", responses = {
160         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
161         @ApiResponse(responseCode = "201", description = "Resource created"),
162         @ApiResponse(responseCode = "403", description = "Restricted operation"),
163         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
164         @ApiResponse(responseCode = "409", description = "Artifact already exist")})
165     public Response loadInformationArtifact(@PathParam("serviceId") final String serviceId,
166                                             @Parameter(description = "json describe the artifact", required = true) String data,
167                                             @Context final HttpServletRequest request) {
168         String url = request.getMethod() + " " + request.getRequestURI();
169         log.debug(START_HANDLE_REQUEST_OF, url);
170         try {
171             return handleUploadRequest(data, request, serviceId, ComponentTypeEnum.SERVICE);
172         } catch (Exception e) {
173             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("loadInformationArtifact");
174             log.debug("loadInformationArtifact unexpected exception", e);
175             throw e;
176         }
177     }
178
179     @POST
180     @Path("/services/{serviceId}/artifacts/{artifactId}")
181     @Consumes(MediaType.APPLICATION_JSON)
182     @Produces(MediaType.APPLICATION_JSON)
183     @Operation(description = "Update Artifact", method = "POST", summary = "Returns updated artifact", responses = {
184         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
185         @ApiResponse(responseCode = "201", description = "Service artifact created"),
186         @ApiResponse(responseCode = "403", description = "Restricted operation"),
187         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
188     public Response updateInformationArtifact(@PathParam("serviceId") final String serviceId, @PathParam("artifactId") final String artifactId,
189                                               @Parameter(description = "json describe the artifact", required = true) String data,
190                                               @Context final HttpServletRequest request) {
191         String url = request.getMethod() + " " + request.getRequestURI();
192         log.debug(START_HANDLE_REQUEST_OF, url);
193         try {
194             return handleUpdateRequest(data, request, serviceId, artifactId, ComponentTypeEnum.SERVICE);
195         } catch (Exception e) {
196             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("updateInformationArtifact");
197             log.debug("updateInformationArtifact unexpected exception", e);
198             throw e;
199         }
200     }
201
202     // *************** Services api artifacts
203     @POST
204     @Path("/services/{serviceId}/artifacts/api/{artifactId}")
205     @Consumes(MediaType.APPLICATION_JSON)
206     @Produces(MediaType.APPLICATION_JSON)
207     @Operation(description = "Update Api Artifact", method = "POST", summary = "Returns created ArtifactDefinition", responses = {
208         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
209         @ApiResponse(responseCode = "200", description = "Api Artifact Updated"),
210         @ApiResponse(responseCode = "403", description = "Restricted operation"),
211         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
212     public Response updateApiArtifact(@PathParam("serviceId") final String serviceId, @PathParam("artifactId") final String artifactId,
213                                       @Parameter(description = "json describe the artifact", required = true) String data,
214                                       @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId,
215                                       @HeaderParam(value = Constants.MD5_HEADER) String origMd5) {
216         String url = request.getMethod() + " " + request.getRequestURI();
217         log.debug(START_HANDLE_REQUEST_OF, url);
218         try {
219             return handleUpdateRequest(data, request, serviceId, artifactId, ComponentTypeEnum.SERVICE);
220         } catch (Exception e) {
221             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("updateApiArtifact");
222             log.debug("updateApiArtifact unexpected exception", e);
223             throw e;
224         }
225     }
226
227     @DELETE
228     @Path("/services/{serviceId}/artifacts/api/{artifactId}")
229     @Consumes(MediaType.APPLICATION_JSON)
230     @Produces(MediaType.APPLICATION_JSON)
231     @Operation(description = "Delete Api Artifact", method = "DELETE", summary = "Returns Deleted ArtifactDefinition", responses = {
232         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
233         @ApiResponse(responseCode = "204", description = "Api Artifact deleted"),
234         @ApiResponse(responseCode = "403", description = "Restricted operation")})
235     public Response deleteApiArtifact(@PathParam("serviceId") final String serviceId, @PathParam("artifactId") final String artifactId,
236                                       @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId,
237                                       @HeaderParam(value = Constants.MD5_HEADER) String origMd5) {
238         String url = request.getMethod() + " " + request.getRequestURI();
239         log.debug(START_HANDLE_REQUEST_OF, url);
240         try {
241             return handleDeleteRequest(request, serviceId, artifactId, ComponentTypeEnum.SERVICE, null, null);
242         } catch (Exception e) {
243             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("deleteApiArtifact");
244             log.debug("deleteApiArtifact unexpected exception", e);
245             throw e;
246         }
247     }
248
249     @DELETE
250     @Path("/services/{serviceId}/artifacts/{artifactId}")
251     @Consumes(MediaType.APPLICATION_JSON)
252     @Produces(MediaType.APPLICATION_JSON)
253     @Operation(description = "Delete Artifact", method = "DELETE", summary = "Returns delete artifact", responses = {
254         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
255         @ApiResponse(responseCode = "201", description = "Service artifact deleted"),
256         @ApiResponse(responseCode = "403", description = "Restricted operation"),
257         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
258     public Response deleteInformationalArtifact(@PathParam("serviceId") final String serviceId, @PathParam("artifactId") final String artifactId,
259                                                 @Context final HttpServletRequest request) {
260         String url = request.getMethod() + " " + request.getRequestURI();
261         log.debug(START_HANDLE_REQUEST_OF, url);
262         try {
263             return handleDeleteRequest(request, serviceId, artifactId, ComponentTypeEnum.SERVICE, null, null);
264         } catch (Exception e) {
265             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("deleteInformationalArtifact");
266             log.debug("deleteInformationalArtifact unexpected exception", e);
267             throw e;
268         }
269     }
270
271     /*
272      * DOWNLOAD Artifacts by json body in base 64 (because of userId problem with href)
273      */
274     @GET
275     @Path("/services/{serviceId}/artifacts/{artifactId}")
276     @Consumes(MediaType.APPLICATION_JSON)
277     @Produces(MediaType.APPLICATION_JSON)
278     @Operation(description = "Download service Artifact in Base64", method = "GET", summary = "Returns downloaded artifact", responses = {
279         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
280         @ApiResponse(responseCode = "200", description = "Service artifact downloaded"),
281         @ApiResponse(responseCode = "404", description = "Service/Artifact not found")})
282     public Response downloadServiceArtifactBase64(@PathParam("serviceId") final String serviceId, @PathParam("artifactId") final String artifactId,
283                                                   @Context final HttpServletRequest request) {
284         String url = request.getMethod() + " " + request.getRequestURI();
285         Response response;
286         log.debug(START_HANDLE_REQUEST_OF, url);
287         try {
288             response = handleDownloadRequest(request, serviceId, artifactId, null, ComponentTypeEnum.SERVICE, null);
289         } catch (Exception e) {
290             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("downloadServiceArtifactBase64");
291             log.debug("downloadServiceArtifactBase64 unexpected exception", e);
292             throw e;
293         } finally {
294             loggerSupportability.log(LoggerSupportabilityActions.DOWNLOAD_ARTIFACTS, StatusCode.COMPLETE, "Ended download Service Artifact ");
295         }
296         return response;
297     }
298
299     @GET
300     @Path("/resources/{resourceId}/artifacts/{artifactId}")
301     @Consumes(MediaType.APPLICATION_JSON)
302     @Produces(MediaType.APPLICATION_JSON)
303     @Operation(description = "Download resource Artifact in Base64", method = "GET", summary = "Returns downloaded artifact", responses = {
304         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
305         @ApiResponse(responseCode = "200", description = "Resource artifact downloaded"),
306         @ApiResponse(responseCode = "404", description = "Resource/Artifact not found")})
307     public Response downloadResourceArtifactBase64(@PathParam("resourceId") final String resourceId, @PathParam("artifactId") final String artifactId,
308                                                    @Context final HttpServletRequest request) {
309         String url = request.getMethod() + " " + request.getRequestURI();
310         log.debug(START_HANDLE_REQUEST_OF, url);
311         Response response;
312         try {
313             response = handleDownloadRequest(request, resourceId, artifactId, null, ComponentTypeEnum.RESOURCE, null);
314         } catch (Exception e) {
315             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("downloadResourceArtifactBase64");
316             log.debug("downloadResourceArtifactBase64 unexpected exception", e);
317             throw e;
318         } finally {
319             loggerSupportability
320                 .log(LoggerSupportabilityActions.DOWNLOAD_ARTIFACTS, null, StatusCode.COMPLETE, "Ended download artifact {}", artifactId);
321         }
322         return response;
323     }
324
325     @GET
326     @Path("/{containerComponentType}/{componentId}/resourceInstances/{componentInstanceId}/artifacts/{artifactId}")
327     @Consumes(MediaType.APPLICATION_JSON)
328     @Produces(MediaType.APPLICATION_JSON)
329     @Operation(description = "Download component Artifact in Base64", method = "GET", summary = "Returns downloaded artifact", responses = {
330         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
331         @ApiResponse(responseCode = "200", description = "ResourceInstance artifact downloaded"),
332         @ApiResponse(responseCode = "404", description = "ResourceInstance/Artifact not found")})
333     public Response downloadResourceInstanceArtifactBase64(
334         @Parameter(description = "valid values: resources / services", schema = @Schema(allowableValues = {ComponentTypeEnum.RESOURCE_PARAM_NAME,
335             ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("containerComponentType") final String containerComponentType,
336         @PathParam("componentId") final String componentId, @PathParam("componentInstanceId") final String componentInstanceId,
337         @PathParam("artifactId") final String artifactId, @Context final HttpServletRequest request) {
338         Response response;
339         String url = request.getMethod() + " " + request.getRequestURI();
340         log.debug(START_HANDLE_REQUEST_OF, url);
341         loggerSupportability.log(LoggerSupportabilityActions.DOWNLOAD_ARTIFACTS, StatusCode.STARTED,
342             " Starting to download Resource Instance Artifact for component {} ", componentId);
343         try {
344             response = handleDownloadRequest(request, componentInstanceId, artifactId, componentId, ComponentTypeEnum.RESOURCE_INSTANCE,
345                 containerComponentType);
346         } catch (Exception e) {
347             BeEcompErrorManager.getInstance().logBeRestApiGeneralError(DOWNLOAD_RESOURCE_INSTANCE_ARTIFACT_BASE64);
348             log.debug(DOWNLOAD_RESOURCE_INSTANCE_ARTIFACT_BASE64_EXCEPTION, e);
349             throw e;
350         } finally {
351             loggerSupportability.log(LoggerSupportabilityActions.DOWNLOAD_ARTIFACTS, StatusCode.COMPLETE,
352                 "Ended download Resource Instance Artifact for component {} ", componentId);
353         }
354         return response;
355     }
356
357     // *************** Resource lifecycle ( interfces )
358     @POST
359     @Path("/resources/{resourceId}/{interfaceType}/{operation}/artifacts")
360     @Consumes(MediaType.APPLICATION_JSON)
361     @Produces(MediaType.APPLICATION_JSON)
362     @Operation(description = "Create Artifact and Attach to interface", method = "POST", summary = "Returns created resource", responses = {
363         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
364         @ApiResponse(responseCode = "201", description = "Resource created"),
365         @ApiResponse(responseCode = "403", description = "Restricted operation"),
366         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
367         @ApiResponse(responseCode = "409", description = "Artifact already exist")})
368     public Response loadArtifactToInterface(@PathParam("resourceId") final String resourceId, @PathParam("interfaceType") final String interfaceType,
369                                             @PathParam("operation") final String operation,
370                                             @HeaderParam(value = Constants.USER_ID_HEADER) String userId,
371                                             @HeaderParam(value = Constants.MD5_HEADER) String origMd5,
372                                             @Parameter(description = "json describe the artifact", required = true) String data,
373                                             @Context final HttpServletRequest request) {
374         String url = request.getMethod() + " " + request.getRequestURI();
375         log.debug(START_HANDLE_REQUEST_OF, url);
376         try {
377             return handleArtifactRequest(data, request, resourceId, interfaceType, operation, null, ComponentTypeEnum.RESOURCE,
378                 ArtifactOperationEnum.CREATE, null, null, false);
379         } catch (Exception e) {
380             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("loadArtifactToInterface");
381             log.debug("loadArtifactToInterface unexpected exception", e);
382             throw e;
383         }
384     }
385
386     @DELETE
387     @Path("/resources/{resourceId}/{interfaceType}/{operation}/artifacts/{artifactId}")
388     @Consumes(MediaType.APPLICATION_JSON)
389     @Produces(MediaType.APPLICATION_JSON)
390     @Operation(description = "delete Artifact from interface", method = "delete", summary = "delete matching artifact from interface", responses = {
391         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
392         @ApiResponse(responseCode = "201", description = "delete artifact under interface deleted"),
393         @ApiResponse(responseCode = "403", description = "Restricted operation"),
394         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
395         @ApiResponse(responseCode = "409", description = "Artifact already exist")})
396     public Response deleteArtifactToInterface(@PathParam("resourceId") final String resourceId,
397                                               @PathParam("interfaceType") final String interfaceType, @PathParam("operation") final String operation,
398                                               @PathParam("artifactId") final String artifactId, @Context final HttpServletRequest request) {
399         String url = request.getMethod() + " " + request.getRequestURI();
400         log.debug(START_HANDLE_REQUEST_OF, url);
401         try {
402             return handleDeleteRequest(request, resourceId, artifactId, ComponentTypeEnum.RESOURCE, interfaceType, operation);
403         } catch (Exception e) {
404             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("deleteArtifactToInterface");
405             log.debug("deleteArtifactToInterface unexpected exception", e);
406             throw e;
407         }
408     }
409
410     @POST
411     @Path("/resources/{resourceId}/{interfaceType}/{operation}/artifacts/{artifactId}")
412     @Consumes(MediaType.APPLICATION_JSON)
413     @Produces(MediaType.APPLICATION_JSON)
414     @Operation(description = "update Artifact  Attach to interface", method = "post", summary = "updates artifact by interface", responses = {
415         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
416         @ApiResponse(responseCode = "201", description = "delete artifact under interface deleted"),
417         @ApiResponse(responseCode = "403", description = "Restricted operation"),
418         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
419         @ApiResponse(responseCode = "409", description = "Artifact already exist")})
420     public Response updateArtifactToInterface(@PathParam("resourceId") final String resourceId,
421                                               @PathParam("interfaceType") final String interfaceType, @PathParam("operation") final String operation,
422                                               @PathParam("artifactId") final String artifactId,
423                                               @HeaderParam(value = Constants.USER_ID_HEADER) String userId,
424                                               @HeaderParam(value = Constants.MD5_HEADER) String origMd5, @Context final HttpServletRequest request,
425                                               @Parameter(description = "json describe the artifact", required = true) String data) {
426         String url = request.getMethod() + " " + request.getRequestURI();
427         log.debug(START_HANDLE_REQUEST_OF, url);
428         try {
429             return handleArtifactRequest(data, request, resourceId, interfaceType, operation, artifactId, ComponentTypeEnum.RESOURCE,
430                 ArtifactOperationEnum.UPDATE, null, null, false);
431         } catch (Exception e) {
432             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("updateArtifactToInterface");
433             log.debug("updateArtifactToInterface unexpected exception", e);
434             throw e;
435         }
436     }
437
438     @POST
439     @Path("/{containerComponentType}/{componentId}/resourceInstance/{componentInstanceId}/artifacts/{artifactId}/heatParams")
440     @Consumes(MediaType.APPLICATION_JSON)
441     @Produces(MediaType.APPLICATION_JSON)
442     @Operation(description = "Update Resource Instance HEAT_ENV parameters", method = "POST", summary = "Returns updated artifact", responses = {
443         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
444         @ApiResponse(responseCode = "200", description = "Artifact updated"),
445         @ApiResponse(responseCode = "403", description = "Restricted operation"),
446         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
447     public Response updateRIArtifact(
448         @Parameter(description = "valid values: resources / services", schema = @Schema(allowableValues = {ComponentTypeEnum.RESOURCE_PARAM_NAME,
449             ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("containerComponentType") final String containerComponentType,
450         @PathParam("componentId") final String componentId, @PathParam("componentInstanceId") final String componentInstanceId,
451         @PathParam("artifactId") final String artifactId, @Parameter(description = "json describe the artifact", required = true) String data,
452         @Context final HttpServletRequest request) {
453         String url = request.getMethod() + " " + request.getRequestURI();
454         log.debug(START_HANDLE_REQUEST_OF, url);
455         loggerSupportability.log(LoggerSupportabilityActions.UPDATE_HEAT, StatusCode.STARTED, "Starting update RI Artifact {}", artifactId);
456         Response response;
457         try {
458             response = handleArtifactRequest(data, request, componentInstanceId, null, null, artifactId, ComponentTypeEnum.RESOURCE_INSTANCE,
459                 ArtifactOperationEnum.UPDATE, componentId, containerComponentType, false);
460         } catch (Exception e) {
461             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("updateRIArtifact");
462             log.debug("updateRIArtifact unexpected exception", e);
463             throw e;
464         } finally {
465             loggerSupportability.log(LoggerSupportabilityActions.UPDATE_HEAT, StatusCode.COMPLETE, "Ending update RI Artifact {}", artifactId);
466         }
467         return response;
468     }
469
470     @POST
471     @Path("/{containerComponentType}/{componentId}/resourceInstance/{componentInstanceId}/artifacts/{artifactId}")
472     @Consumes(MediaType.APPLICATION_JSON)
473     @Produces(MediaType.APPLICATION_JSON)
474     @Operation(description = "Update Resource Instance artifact payload", method = "POST", summary = "Returns updated artifact", responses = {
475         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
476         @ApiResponse(responseCode = "200", description = "Artifact updated"),
477         @ApiResponse(responseCode = "403", description = "Restricted operation"),
478         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
479     public Response updateComponentInstanceArtifact(@HeaderParam(value = Constants.USER_ID_HEADER) String userId,
480                                                     @HeaderParam(value = Constants.MD5_HEADER) String origMd5,
481                                                     @Parameter(description = "valid values: resources / services", schema = @Schema(allowableValues = {
482                                                         ComponentTypeEnum.RESOURCE_PARAM_NAME,
483                                                         ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("containerComponentType") final String containerComponentType,
484                                                     @PathParam("componentId") final String componentId,
485                                                     @PathParam("componentInstanceId") final String componentInstanceId,
486                                                     @PathParam("artifactId") final String artifactId,
487                                                     @Parameter(description = "json describe the artifact", required = true) String data,
488                                                     @Context final HttpServletRequest request) {
489         String url = request.getMethod() + " " + request.getRequestURI();
490         log.debug(START_HANDLE_REQUEST_OF, url);
491         try {
492             return handleArtifactRequest(data, request, componentInstanceId, null, null, artifactId, ComponentTypeEnum.RESOURCE_INSTANCE,
493                 ArtifactOperationEnum.UPDATE, componentId, containerComponentType, true);
494         } catch (Exception e) {
495             log.debug("loadResourceInstanceHeatEnvArtifact unexpected exception", e);
496             throw e;
497         }
498     }
499
500     @POST
501     @Path("/{containerComponentType}/{componentId}/resourceInstance/{componentInstanceId}/artifacts")
502     @Consumes(MediaType.APPLICATION_JSON)
503     @Produces(MediaType.APPLICATION_JSON)
504     @Operation(description = "Load Resource Instance artifact payload", method = "POST", summary = "Returns updated artifact", responses = {
505         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
506         @ApiResponse(responseCode = "200", description = "Artifact updated"),
507         @ApiResponse(responseCode = "403", description = "Restricted operation"),
508         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
509     public Response loadComponentInstanceArtifact(@HeaderParam(value = Constants.USER_ID_HEADER) String userId,
510                                                   @HeaderParam(value = Constants.MD5_HEADER) String origMd5,
511                                                   @Parameter(description = "valid values: resources / services", schema = @Schema(allowableValues = {
512                                                       ComponentTypeEnum.RESOURCE_PARAM_NAME,
513                                                       ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("containerComponentType") final String containerComponentType,
514                                                   @PathParam("componentId") final String componentId,
515                                                   @PathParam("componentInstanceId") final String componentInstanceId,
516                                                   @Parameter(description = "json describe the artifact", required = true) String data,
517                                                   @Context final HttpServletRequest request) {
518         String url = request.getMethod() + " " + request.getRequestURI();
519         log.debug(START_HANDLE_REQUEST_OF, url);
520         try {
521             return handleArtifactRequest(data, request, componentInstanceId, null, null, null, ComponentTypeEnum.RESOURCE_INSTANCE,
522                 ArtifactOperationEnum.CREATE, componentId, containerComponentType, false);
523         } catch (Exception e) {
524             log.debug("loadResourceInstanceHeatEnvArtifact unexpected exception", e);
525             throw e;
526         }
527     }
528
529     @DELETE
530     @Path("/{containerComponentType}/{componentId}/resourceInstance/{componentInstanceId}/artifacts/{artifactId}")
531     @Consumes(MediaType.APPLICATION_JSON)
532     @Produces(MediaType.APPLICATION_JSON)
533     @Operation(description = "Delete Resource Instance artifact", method = "POST", summary = "Returns deleted artifact", responses = {
534         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
535         @ApiResponse(responseCode = "200", description = "Artifact updated"),
536         @ApiResponse(responseCode = "403", description = "Restricted operation"),
537         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
538     public Response deleteComponentInstanceArtifact(@HeaderParam(value = Constants.USER_ID_HEADER) String userId,
539                                                     @HeaderParam(value = Constants.MD5_HEADER) String origMd5,
540                                                     @Parameter(description = "valid values: resources / services", schema = @Schema(allowableValues = {
541                                                         ComponentTypeEnum.RESOURCE_PARAM_NAME,
542                                                         ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("containerComponentType") final String containerComponentType,
543                                                     @PathParam("componentId") final String componentId,
544                                                     @PathParam("componentInstanceId") final String componentInstanceId,
545                                                     @PathParam("artifactId") final String artifactId,
546                                                     @Parameter(description = "json describe the artifact", required = true) String data,
547                                                     @Context final HttpServletRequest request) {
548         String url = request.getMethod() + " " + request.getRequestURI();
549         log.debug(START_HANDLE_REQUEST_OF, url);
550         loggerSupportability.log(LoggerSupportabilityActions.DELETE_COMPONENT_INSTANCE_ARTIFACT, null, StatusCode.STARTED,
551             "Starting delete component instance artifact {}", artifactId);
552         Response response;
553         try {
554             response = handleDeleteRequest(request, componentInstanceId, artifactId, ComponentTypeEnum.RESOURCE_INSTANCE, null, null, componentId);
555         } catch (Exception e) {
556             log.debug("deleteArtifact unexpected exception", e);
557             throw e;
558         } finally {
559             loggerSupportability.log(LoggerSupportabilityActions.DELETE_COMPONENT_INSTANCE_ARTIFACT, null, StatusCode.COMPLETE,
560                 "Ending delete component instance artifact {}", artifactId);
561         }
562         return response;
563     }
564
565     @GET
566     @Path("/{containerComponentType}/{componentId}/artifactsByType/{artifactGroupType}")
567     @Consumes(MediaType.APPLICATION_JSON)
568     @Produces(MediaType.APPLICATION_JSON)
569     @Operation(description = "Get component Artifacts", method = "GET", summary = "Returns artifacts", responses = {
570         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
571         @ApiResponse(responseCode = "200", description = "Component artifacts"),
572         @ApiResponse(responseCode = "404", description = "Resource/Artifact not found")})
573     public Response getComponentArtifacts(
574         @Parameter(description = "valid values: resources / services", schema = @Schema(allowableValues = {ComponentTypeEnum.RESOURCE_PARAM_NAME,
575             ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("containerComponentType") final String containerComponentType,
576         @PathParam("componentId") final String componentId, @PathParam("artifactGroupType") final String artifactGroupType,
577         @Context final HttpServletRequest request) {
578         String url = request.getMethod() + " " + request.getRequestURI();
579         log.debug(START_HANDLE_REQUEST_OF, url);
580         try {
581             return handleGetArtifactsRequest(request, componentId, null, artifactGroupType, containerComponentType);
582         } catch (Exception e) {
583             BeEcompErrorManager.getInstance().logBeRestApiGeneralError(DOWNLOAD_RESOURCE_INSTANCE_ARTIFACT_BASE64);
584             log.debug(DOWNLOAD_RESOURCE_INSTANCE_ARTIFACT_BASE64_EXCEPTION, e);
585             throw e;
586         }
587     }
588
589     @GET
590     @Path("/{containerComponentType}/{componentId}/resourceInstances/{componentInstanceId}/artifactsByType/{artifactGroupType}")
591     @Consumes(MediaType.APPLICATION_JSON)
592     @Produces(MediaType.APPLICATION_JSON)
593     @Operation(description = "Get component Artifacts", method = "GET", summary = "Returns artifacts", responses = {
594         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
595         @ApiResponse(responseCode = "200", description = "Component artifacts"),
596         @ApiResponse(responseCode = "404", description = "Resource/Artifact not found")})
597     public Response getComponentInstanceArtifacts(
598         @Parameter(description = "valid values: resources / services", schema = @Schema(allowableValues = {ComponentTypeEnum.RESOURCE_PARAM_NAME,
599             ComponentTypeEnum.SERVICE_PARAM_NAME})) @PathParam("containerComponentType") final String containerComponentType,
600         @PathParam("componentId") final String componentId, @PathParam("componentInstanceId") final String componentInstanceId,
601         @PathParam("artifactGroupType") final String artifactGroupType, @Context final HttpServletRequest request) {
602         String url = request.getMethod() + " " + request.getRequestURI();
603         log.debug(START_HANDLE_REQUEST_OF, url);
604         try {
605             return handleGetArtifactsRequest(request, componentInstanceId, componentId, artifactGroupType, containerComponentType);
606         } catch (Exception e) {
607             BeEcompErrorManager.getInstance().logBeRestApiGeneralError(DOWNLOAD_RESOURCE_INSTANCE_ARTIFACT_BASE64);
608             log.debug(DOWNLOAD_RESOURCE_INSTANCE_ARTIFACT_BASE64_EXCEPTION, e);
609             throw e;
610         }
611     }
612
613     @POST
614     @Path("/{assetType}/{uuid}/interfaces/{interfaceUUID}/operations/{operationUUID}/artifacts/{artifactUUID}")
615     @Consumes(MediaType.APPLICATION_JSON)
616     @Produces(MediaType.APPLICATION_JSON)
617     @Operation(description = "uploads of artifact to component operation workflow", method = "POST", summary = "uploads of artifact to component operation workflow", responses = {
618         @ApiResponse(responseCode = "200", description = "Artifact uploaded", content = @Content(array = @ArraySchema(schema = @Schema(implementation = ArtifactDefinition.class)))),
619         @ApiResponse(responseCode = "404", description = "Specified resource is not found - SVC4063"),
620         @ApiResponse(responseCode = "400", description = "Invalid artifactType was defined as input - SVC4122"),
621         @ApiResponse(responseCode = "400", description = "Artifact type (mandatory field) is missing in request - SVC4124"),
622         @ApiResponse(responseCode = "400", description = "Artifact name given in input already exists in the context of the asset - SVC4125"),
623         @ApiResponse(responseCode = "400", description = "Artifact name is missing in input - SVC4128"),
624         @ApiResponse(responseCode = "400", description = "Asset is being edited by different user. Only one user can checkout and edit an asset on given time. The asset will be available for checkout after the other user will checkin the asset - SVC4086"),
625         @ApiResponse(responseCode = "400", description = "Restricted Operation – the user provided does not have role of Designer or the asset is being used by another designer - SVC4301")})
626     public Response uploadInterfaceOperationArtifact(@Parameter(description = "Asset type") @PathParam("assetType") String assetType,
627                                                      @Parameter(description = "The uuid of the asset as published in the metadata", required = true) @PathParam("uuid") final String uuid,
628                                                      @Parameter(description = "The uuid of the interface", required = true) @PathParam("interfaceUUID") final String interfaceUUID,
629                                                      @Parameter(description = "The uuid of the operation", required = true) @PathParam("operationUUID") final String operationUUID,
630                                                      @Parameter(description = "The uuid of the artifact", required = true) @PathParam("artifactUUID") final String artifactUUID,
631                                                      @Parameter(hidden = true) String data,
632                                                      @HeaderParam(value = Constants.USER_ID_HEADER) String userId,
633                                                      @HeaderParam(value = Constants.MD5_HEADER) String origMd5,
634                                                      @Context final HttpServletRequest request) {
635         String url = request.getMethod() + " " + request.getRequestURI();
636         log.debug("Start handle request of {}", url);
637         try {
638             Either<ArtifactDefinition, ResponseFormat> uploadArtifactEither = artifactsBusinessLogic
639                 .updateArtifactOnInterfaceOperationByResourceUUID(data, request, ComponentTypeEnum.findByParamName(assetType), uuid, interfaceUUID,
640                     operationUUID, artifactUUID, new ResourceCommonInfo(assetType),
641                     new ArtifactOperationInfo(true, false, ArtifactOperationEnum.UPDATE));
642             if (uploadArtifactEither.isRight()) {
643                 log.debug("failed to update artifact");
644                 return buildErrorResponse(uploadArtifactEither.right().value());
645             }
646             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), uploadArtifactEither.left().value());
647         } catch (Exception e) {
648             final String message = "failed to update artifact on a resource or service";
649             BeEcompErrorManager.getInstance().logBeRestApiGeneralError(message);
650             log.debug(message, e);
651             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
652         }
653     }
654     // ////////// API END ///////////////////////////
655
656     // ************ private *********************
657     private Response handleUploadRequest(String data, HttpServletRequest request, String componentId, ComponentTypeEnum componentType) {
658         return handleArtifactRequest(data, componentId, null, componentType, ArtifactOperationEnum.CREATE);
659     }
660
661     private Response handleUpdateRequest(String data, HttpServletRequest request, String componentId, String artifactId,
662                                          ComponentTypeEnum componentType) {
663         return handleArtifactRequest(data, componentId, artifactId, componentType, ArtifactOperationEnum.UPDATE);
664     }
665
666     private Response handleDownloadRequest(HttpServletRequest request, String componentId, String artifactId, String parentId,
667                                            ComponentTypeEnum componentType, String containerComponentType) {
668         String userId = request.getHeader(Constants.USER_ID_HEADER);
669         ImmutablePair<String, byte[]> actionResult = artifactsBusinessLogic
670             .handleDownloadRequestById(componentId, artifactId, userId, componentType, parentId, containerComponentType);
671         Response response;
672         byte[] file = actionResult.getRight();
673         String base64Contents = new String(Base64.encodeBase64(file));
674         String artifactName = actionResult.getLeft();
675         ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.OK);
676         ArtifactUiDownloadData artifactUiDownloadData = new ArtifactUiDownloadData();
677         artifactUiDownloadData.setArtifactName(artifactName);
678         artifactUiDownloadData.setBase64Contents(base64Contents);
679         response = buildOkResponse(responseFormat, artifactUiDownloadData);
680         return response;
681     }
682
683     private Response handleGetArtifactsRequest(HttpServletRequest request, String componentId, String parentId, String artifactGroupType,
684                                                String containerComponentType) {
685         String userId = request.getHeader(Constants.USER_ID_HEADER);
686         ComponentTypeEnum componentTypeEnum =
687             parentId == null || parentId.isEmpty() ? ComponentTypeEnum.findByParamName(containerComponentType) : ComponentTypeEnum.RESOURCE_INSTANCE;
688         Map<String, ArtifactDefinition> actionResult = artifactsBusinessLogic
689             .handleGetArtifactsByType(containerComponentType, parentId, componentTypeEnum, componentId, artifactGroupType, userId);
690         return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), actionResult);
691     }
692
693     private Response handleDeleteRequest(HttpServletRequest request, String componentId, String artifactId, ComponentTypeEnum componentType,
694                                          String interfaceType, String operationName) {
695         return handleDeleteRequest(request, componentId, artifactId, componentType, interfaceType, operationName, null);
696     }
697
698     private Response handleDeleteRequest(HttpServletRequest request, String componentId, String artifactId, ComponentTypeEnum componentType,
699                                          String interfaceType, String operationName, String parentId) {
700         String userId = request.getHeader(Constants.USER_ID_HEADER);
701         Either<ArtifactDefinition, org.openecomp.sdc.be.model.Operation> actionResult = artifactsBusinessLogic
702             .handleArtifactRequest(componentId, userId, componentType, new ArtifactOperationInfo(false, false, ArtifactOperationEnum.DELETE),
703                 artifactId, null, null, null, interfaceType, operationName, parentId, null);
704         Response response;
705         Either<ArtifactDefinition, org.openecomp.sdc.be.model.Operation> result = actionResult;
706         if (result.isLeft()) {
707             response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), result.left().value());
708         } else {
709             response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), result.right().value());
710         }
711         return response;
712     }
713
714     private Response handleArtifactRequest(String data, HttpServletRequest request, String componentId, String interfaceName, String operationName,
715                                            String artifactId, ComponentTypeEnum componentType, ArtifactOperationEnum operationEnum, String parentId,
716                                            String containerComponentType, boolean validateTimeout) {
717         loggerSupportability.log(LoggerSupportabilityActions.UPDATE_ARTIFACT, StatusCode.STARTED, "Starting to update artifact {} ",
718             artifactId + " for component " + componentId);
719         ArtifactDefinition artifactInfo = RepresentationUtils.convertJsonToArtifactDefinition(data, ArtifactDefinition.class, validateTimeout);
720         String origMd5 = request.getHeader(Constants.MD5_HEADER);
721         String userId = request.getHeader(Constants.USER_ID_HEADER);
722         Either<ArtifactDefinition, org.openecomp.sdc.be.model.Operation> result = artifactsBusinessLogic
723             .handleArtifactRequest(componentId, userId, componentType, new ArtifactOperationInfo(false, false, operationEnum), artifactId,
724                 artifactInfo, origMd5, data, interfaceName, operationName, parentId, containerComponentType);
725         Response response;
726         if (result.isLeft()) {
727             response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), result.left().value());
728         } else {
729             response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), result.right().value());
730         }
731         loggerSupportability.log(LoggerSupportabilityActions.UPDATE_ARTIFACT, StatusCode.COMPLETE, "Ended update artifact {} ",
732             artifactId + " for component " + componentId);
733         return response;
734     }
735
736     private Response handleArtifactRequest(String data, String componentId, String artifactId, ComponentTypeEnum componentType,
737                                            ArtifactOperationEnum operation) {
738         return handleArtifactRequest(data, servletRequest, componentId, null, null, artifactId, componentType, operation, null, null, false);
739     }
740 }