Publish swagger files for SDC APIs
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / distribution / servlet / DistributionCatalogServlet.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  * Modifications copyright (c) 2019 Nokia
20  * ================================================================================
21  */
22
23 package org.openecomp.sdc.be.distribution.servlet;
24
25 import com.jcabi.aspects.Loggable;
26 import io.swagger.v3.oas.annotations.Operation;
27 import io.swagger.v3.oas.annotations.Parameter;
28 import io.swagger.v3.oas.annotations.media.ArraySchema;
29 import io.swagger.v3.oas.annotations.media.Content;
30 import io.swagger.v3.oas.annotations.media.Schema;
31 import io.swagger.v3.oas.annotations.responses.ApiResponse;
32 import io.swagger.v3.oas.annotations.servers.Server;
33 import io.swagger.v3.oas.annotations.servers.Servers;
34 import io.swagger.v3.oas.annotations.tags.Tag;
35 import io.swagger.v3.oas.annotations.tags.Tags;
36 import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic;
37 import org.openecomp.sdc.be.components.impl.aaf.AafPermission;
38 import org.openecomp.sdc.be.components.impl.aaf.PermissionAllowed;
39 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
40 import org.openecomp.sdc.be.config.BeEcompErrorManager;
41 import org.openecomp.sdc.be.dao.api.ActionStatus;
42 import org.openecomp.sdc.be.impl.ComponentsUtils;
43 import org.openecomp.sdc.be.resources.data.auditing.model.DistributionData;
44 import org.openecomp.sdc.be.servlets.BeGenericServlet;
45 import org.openecomp.sdc.be.user.UserBusinessLogic;
46 import org.openecomp.sdc.common.api.Constants;
47 import org.openecomp.sdc.common.datastructure.Wrapper;
48 import org.openecomp.sdc.common.log.wrappers.Logger;
49 import org.openecomp.sdc.exception.ResponseFormat;
50
51 import javax.inject.Inject;
52 import javax.inject.Singleton;
53 import javax.servlet.http.HttpServletRequest;
54 import javax.ws.rs.Consumes;
55 import javax.ws.rs.GET;
56 import javax.ws.rs.HeaderParam;
57 import javax.ws.rs.Path;
58 import javax.ws.rs.PathParam;
59 import javax.ws.rs.Produces;
60 import javax.ws.rs.core.Context;
61 import javax.ws.rs.core.MediaType;
62 import javax.ws.rs.core.Response;
63 import java.io.ByteArrayInputStream;
64 import java.io.InputStream;
65 import java.util.HashMap;
66 import java.util.Map;
67
68 /**
69  * This Servlet serves external users to download artifacts.
70  * 
71  * @author tgitelman
72  *
73  */
74
75 @Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
76 @Path("/v1/catalog")
77 @Tags({@Tag(name = "SDCE-7 APIs")})
78 @Servers({@Server(url = "/sdc")})
79 @Singleton
80 public class DistributionCatalogServlet extends BeGenericServlet {
81
82     private static final String DOWNLOAD_ARTIFACT_FAILED_WITH_EXCEPTION = "download artifact failed with exception";
83         private static final String MISSING_X_ECOMP_INSTANCE_ID_HEADER = "Missing X-ECOMP-InstanceID header";
84         private static final Logger log = Logger.getLogger(DistributionCatalogServlet.class);
85         private final ArtifactsBusinessLogic artifactsBusinessLogic;
86
87         @Inject
88     public DistributionCatalogServlet(UserBusinessLogic userBusinessLogic,
89         ComponentsUtils componentsUtils,
90         ArtifactsBusinessLogic artifactsBusinessLogic) {
91         super(userBusinessLogic, componentsUtils);
92         this.artifactsBusinessLogic = artifactsBusinessLogic;
93     }
94
95     @Context
96     private HttpServletRequest request;
97
98     // *******************************************************
99     // Download (GET) artifacts
100     // **********************************************************/
101     /**
102      *
103      * @param requestId
104      * @param instanceIdHeader
105      * @param accept
106      * @param authorization
107      * @param serviceName
108      * @param serviceVersion
109      * @param artifactName
110      * @return
111      */
112     @GET
113     @Path("/services/{serviceName}/{serviceVersion}/artifacts/{artifactName}")
114     @Consumes(MediaType.APPLICATION_JSON)
115     @Produces(MediaType.APPLICATION_OCTET_STREAM)
116     @Operation(description = "Download service artifact", method = "GET", summary = "Returns downloaded artifact",
117             responses = {@ApiResponse(
118                     content = @Content(array = @ArraySchema(schema = @Schema(implementation = String.class)))),
119                     @ApiResponse(responseCode = "200", description = "The artifact is found and streamed.",
120                             content = @Content(array = @ArraySchema(schema = @Schema(implementation = String.class)))),
121                     @ApiResponse(responseCode = "400",
122                             description = "Missing  'X-ECOMP-InstanceID'  HTTP header - POL5001"),
123                     @ApiResponse(responseCode = "401",
124                             description = "ECOMP component  should authenticate itself  and  to  re-send  again  HTTP  request  with its Basic  Authentication credentials - POL5002"),
125                     @ApiResponse(responseCode = "403", description = "ECOMP component is not authorized - POL5003"),
126                     @ApiResponse(responseCode = "404", description = "Specified Service is not found - SVC4503"),
127                     @ApiResponse(responseCode = "404",
128                             description = "Specified Service Version is  not  found - SVC4504"),
129                     @ApiResponse(responseCode = "404", description = "Specified artifact is  not found - SVC4505"),
130                     @ApiResponse(responseCode = "405",
131                             description = "Method  Not Allowed: Invalid HTTP method type used (PUT,DELETE,POST will be rejected) - POL4050"),
132                     @ApiResponse(responseCode = "500",
133                             description = "The GET request failed either due to internal SDC problem or Cambria Service failure. ECOMP Component should continue the attempts to get the needed information - POL5000")})
134     @PermissionAllowed({AafPermission.PermNames.READ_VALUE})
135     public Response downloadServiceArtifact(
136             @Parameter(description = "X-ECOMP-RequestID header", required = false)@HeaderParam(value = Constants.X_ECOMP_REQUEST_ID_HEADER) String requestId,
137             @Parameter(description = "X-ECOMP-InstanceID header", required = true)@HeaderParam(value = Constants.X_ECOMP_INSTANCE_ID_HEADER) final String instanceIdHeader,
138             @Parameter(description = "Determines the format of the body of the response", required = false)@HeaderParam(value = Constants.ACCEPT_HEADER) String accept,
139             @Parameter(description = "The username and password", required = true)@HeaderParam(value = Constants.AUTHORIZATION_HEADER) String authorization,
140             @PathParam("serviceName") final String serviceName,
141             @PathParam("serviceVersion") final String serviceVersion,
142             @PathParam("artifactName") final String artifactName) {
143
144         String requestURI = request.getRequestURI();
145         Wrapper<Response> responseWrapper = validateInstanceIdHeader(new Wrapper<>(), instanceIdHeader, requestURI);
146         if(!responseWrapper.isEmpty()) {
147             return responseWrapper.getInnerElement();
148         }
149
150         try {
151             byte[] downloadRsrcArtifactEither = artifactsBusinessLogic.downloadServiceArtifactByNames(serviceName, serviceVersion, artifactName);
152             byte[] value = downloadRsrcArtifactEither;
153             InputStream is = new ByteArrayInputStream(value);
154
155             Map<String, String> headers = new HashMap<>();
156             headers.put(Constants.CONTENT_DISPOSITION_HEADER, getContentDispositionValue(artifactName));
157             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.OK);
158             getComponentsUtils().auditDistributionDownload(responseFormat, new DistributionData(instanceIdHeader, requestURI));
159             return buildOkResponse(responseFormat, is, headers);
160
161         } catch (ComponentException e) {
162             getComponentsUtils().auditDistributionDownload(e.getResponseFormat(), new DistributionData(instanceIdHeader, requestURI));
163             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("download Murano package artifact for service - external API");
164             log.debug(DOWNLOAD_ARTIFACT_FAILED_WITH_EXCEPTION, e);
165             return buildErrorResponse(e.getResponseFormat());
166         }
167     }
168
169     private Wrapper<Response> validateInstanceIdHeader(Wrapper<Response> responseWrapper, String instanceIdHeader, String requestURI) {
170         if (instanceIdHeader == null || instanceIdHeader.isEmpty()) {
171             log.debug(MISSING_X_ECOMP_INSTANCE_ID_HEADER);
172             ResponseFormat errorResponseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_X_ECOMP_INSTANCE_ID);
173             getComponentsUtils().auditDistributionDownload(errorResponseFormat, new DistributionData(instanceIdHeader, requestURI));
174             responseWrapper.setInnerElement(buildErrorResponse(errorResponseFormat));
175         }
176         return responseWrapper;
177     }
178
179     /**
180      *
181      * @param requestId
182      * @param instanceIdHeader
183      * @param accept
184      * @param authorization
185      * @param serviceName
186      * @param serviceVersion
187      * @param resourceName
188      * @param resourceVersion
189      * @param artifactName
190      * @return
191      */
192     @GET
193     @Path("/services/{serviceName}/{serviceVersion}/resources/{resourceName}/{resourceVersion}/artifacts/{artifactName}")
194     @Consumes(MediaType.APPLICATION_JSON)
195     @Produces(MediaType.APPLICATION_OCTET_STREAM)
196     @Operation(description = "Download resource artifact", method = "GET", summary = "Returns downloaded artifact",
197             responses = {@ApiResponse(
198                     content = @Content(array = @ArraySchema(schema = @Schema(implementation = String.class)))),
199                     @ApiResponse(responseCode = "200", description = "The artifact is found and streamed.",
200                             content = @Content(array = @ArraySchema(schema = @Schema(implementation = String.class)))),
201                     @ApiResponse(responseCode = "400",
202                             description = "Missing  'X-ECOMP-InstanceID'  HTTP header - POL5001"),
203                     @ApiResponse(responseCode = "401",
204                             description = "ECOMP component  should authenticate itself  and  to  re-send  again  HTTP  request  with its Basic  Authentication credentials - POL5002"),
205                     @ApiResponse(responseCode = "403", description = "ECOMP component is not authorized - POL5003"),
206                     @ApiResponse(responseCode = "404", description = "Specified Service is not found - SVC4503"),
207                     @ApiResponse(responseCode = "404",
208                             description = "Specified Resource Instance  is not found - SVC4526"),
209                     @ApiResponse(responseCode = "404",
210                             description = "Specified Service Version is  not  found - SVC4504"),
211                     @ApiResponse(responseCode = "404", description = "Specified artifact is  not found - SVC4505"),
212                     @ApiResponse(responseCode = "405",
213                             description = "Method  Not Allowed: Invalid HTTP method type used (PUT,DELETE,POST will be rejected) - POL4050"),
214                     @ApiResponse(responseCode = "500",
215                             description = "The GET request failed either due to internal SDC problem or Cambria Service failure. ECOMP Component should continue the attempts to get the needed information - POL5000")})
216     @PermissionAllowed({AafPermission.PermNames.READ_VALUE})
217     public Response downloadResourceArtifact(
218             @Parameter(description = "X-ECOMP-RequestID header", required = false)@HeaderParam(value = Constants.X_ECOMP_REQUEST_ID_HEADER) String requestId,
219             @Parameter(description = "X-ECOMP-InstanceID header", required = true)@HeaderParam(value = Constants.X_ECOMP_INSTANCE_ID_HEADER) final String instanceIdHeader,
220             @Parameter(description = "Determines the format of the body of the response", required = false)@HeaderParam(value = Constants.ACCEPT_HEADER) String accept,
221             @Parameter(description = "The username and password", required = true)@HeaderParam(value = Constants.AUTHORIZATION_HEADER) String authorization,
222             @PathParam("serviceName") final String serviceName,
223             @PathParam("serviceVersion") final String serviceVersion,
224             @PathParam("resourceName") final String resourceName,
225             @PathParam("resourceVersion") final String resourceVersion,
226             @PathParam("artifactName") final String artifactName) {
227
228         String requestURI = request.getRequestURI();
229         Wrapper<Response> responseWrapper = validateInstanceIdHeader(new Wrapper<>(), instanceIdHeader, requestURI);
230
231         if(!responseWrapper.isEmpty()) {
232             return responseWrapper.getInnerElement();
233         }
234
235         try {
236             ArtifactsBusinessLogic artifactsLogic = getArtifactBL(request.getSession().getServletContext());
237             byte[] downloadRsrcArtifactEither = artifactsLogic.downloadRsrcArtifactByNames(serviceName, serviceVersion, resourceName, resourceVersion, artifactName);
238             byte[] value = downloadRsrcArtifactEither;
239             // Returning 64-encoded as it was received during upload
240             InputStream is = new ByteArrayInputStream(value);
241             Map<String, String> headers = new HashMap<>();
242             headers.put(Constants.CONTENT_DISPOSITION_HEADER, getContentDispositionValue(artifactName));
243             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.OK);
244             getComponentsUtils().auditDistributionDownload(responseFormat, new DistributionData(instanceIdHeader, requestURI));
245             return buildOkResponse(responseFormat, is, headers);
246
247         } catch (ComponentException e) {
248             getComponentsUtils().auditDistributionDownload(e.getResponseFormat(), new DistributionData(instanceIdHeader, requestURI));
249             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("download interface artifact for resource - external API");
250             log.debug(DOWNLOAD_ARTIFACT_FAILED_WITH_EXCEPTION, e);
251             return buildErrorResponse(e.getResponseFormat());
252         }
253     }
254
255     /**
256      *
257      * @param requestId
258      * @param instanceIdHeader
259      * @param accept
260      * @param authorization
261      * @param serviceName
262      * @param serviceVersion
263      * @param resourceInstanceName
264      * @param artifactName
265      * @return
266      */
267     @GET
268     @Path("/services/{serviceName}/{serviceVersion}/resourceInstances/{resourceInstanceName}/artifacts/{artifactName}")
269     @Consumes(MediaType.APPLICATION_JSON)
270     @Produces(MediaType.APPLICATION_OCTET_STREAM)
271     @Operation(description = "Download resource instance artifact", method = "GET",
272             summary = "Returns downloaded artifact", responses = {
273             @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = String.class)))),
274             @ApiResponse(responseCode = "200", description = "The artifact is found and streamed.",
275                     content = @Content(array = @ArraySchema(schema = @Schema(implementation = String.class)))),
276             @ApiResponse(responseCode = "400", description = "Missing  'X-ECOMP-InstanceID'  HTTP header - POL5001"),
277             @ApiResponse(responseCode = "401",
278                     description = "ECOMP component  should authenticate itself  and  to  re-send  again  HTTP  request  with its Basic  Authentication credentials - POL5002"),
279             @ApiResponse(responseCode = "403", description = "ECOMP component is not authorized - POL5003"),
280             @ApiResponse(responseCode = "404", description = "Specified Service is not found - SVC4503"),
281             @ApiResponse(responseCode = "404", description = "Specified Resource Instance  is not found - SVC4526"),
282             @ApiResponse(responseCode = "404", description = "Specified Service Version is  not  found - SVC4504"),
283             @ApiResponse(responseCode = "404", description = "Specified artifact is  not found - SVC4505"),
284             @ApiResponse(responseCode = "405",
285                     description = "Method  Not Allowed: Invalid HTTP method type used (PUT,DELETE,POST will be rejected) - POL4050"),
286             @ApiResponse(responseCode = "500",
287                     description = "The GET request failed either due to internal SDC problem or Cambria Service failure. ECOMP Component should continue the attempts to get the needed information - POL5000")})
288     @PermissionAllowed({AafPermission.PermNames.READ_VALUE})
289     public Response downloadResourceInstanceArtifactByName(
290             @Parameter(description = "X-ECOMP-RequestID header", required = false)@HeaderParam(value = Constants.X_ECOMP_REQUEST_ID_HEADER) String requestId,
291             @Parameter(description = "X-ECOMP-InstanceID header", required = true)@HeaderParam(value = Constants.X_ECOMP_INSTANCE_ID_HEADER) final String instanceIdHeader,
292             @Parameter(description = "Determines the format of the body of the response", required = false)@HeaderParam(value = Constants.ACCEPT_HEADER) String accept,
293             @Parameter(description = "The username and password", required = true)@HeaderParam(value = Constants.AUTHORIZATION_HEADER) String authorization,
294             @PathParam("serviceName") final String serviceName,
295             @PathParam("serviceVersion") final String serviceVersion,
296             @PathParam("resourceInstanceName") final String resourceInstanceName,
297             @PathParam("artifactName") final String artifactName) {
298
299         String requestURI = request.getRequestURI();
300         Wrapper<Response> responseWrapper = validateInstanceIdHeader(new Wrapper<>(), instanceIdHeader, requestURI);
301
302         if(!responseWrapper.isEmpty()) {
303             return responseWrapper.getInnerElement();
304         }
305
306         try {
307             byte[] downloadRsrcArtifactEither = artifactsBusinessLogic.downloadRsrcInstArtifactByNames(serviceName, serviceVersion, resourceInstanceName, artifactName);
308             byte[] value = downloadRsrcArtifactEither;
309             // Returning 64-encoded as it was received during upload
310             InputStream is = new ByteArrayInputStream(value);
311             Map<String, String> headers = new HashMap<>();
312             headers.put(Constants.CONTENT_DISPOSITION_HEADER, getContentDispositionValue(artifactName));
313             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.OK);
314             getComponentsUtils().auditDistributionDownload(responseFormat, new DistributionData(instanceIdHeader, requestURI));
315             return buildOkResponse(responseFormat, is, headers);
316
317         } catch (ComponentException e) {
318             getComponentsUtils().auditDistributionDownload(e.getResponseFormat(), new DistributionData(instanceIdHeader, requestURI));
319             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("download interface artifact for resource - external API");
320             log.debug(DOWNLOAD_ARTIFACT_FAILED_WITH_EXCEPTION, e);
321             return buildErrorResponse(e.getResponseFormat());
322         }
323     }
324 }