Publish swagger files for SDC APIs
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / servlets / CapabilityServlet.java
1 /*
2  * Copyright © 2016-2018 European Support Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.openecomp.sdc.be.servlets;
18
19 import com.jcabi.aspects.Loggable;
20 import fj.data.Either;
21 import io.swagger.v3.oas.annotations.Operation;
22 import io.swagger.v3.oas.annotations.Parameter;
23 import io.swagger.v3.oas.annotations.media.ArraySchema;
24 import io.swagger.v3.oas.annotations.media.Content;
25 import io.swagger.v3.oas.annotations.media.Schema;
26 import io.swagger.v3.oas.annotations.responses.ApiResponse;
27 import io.swagger.v3.oas.annotations.servers.Server;
28 import io.swagger.v3.oas.annotations.servers.Servers;
29 import io.swagger.v3.oas.annotations.tags.Tag;
30 import io.swagger.v3.oas.annotations.tags.Tags;
31 import org.openecomp.sdc.be.components.impl.CapabilitiesBusinessLogic;
32 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
33 import org.openecomp.sdc.be.components.impl.ResourceImportManager;
34 import org.openecomp.sdc.be.components.impl.aaf.AafPermission;
35 import org.openecomp.sdc.be.components.impl.aaf.PermissionAllowed;
36 import org.openecomp.sdc.be.config.BeEcompErrorManager;
37 import org.openecomp.sdc.be.dao.api.ActionStatus;
38 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
39 import org.openecomp.sdc.be.impl.ComponentsUtils;
40 import org.openecomp.sdc.be.impl.ServletUtils;
41 import org.openecomp.sdc.be.model.CapabilityDefinition;
42 import org.openecomp.sdc.be.model.User;
43 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
44 import org.openecomp.sdc.be.ui.model.UiComponentDataTransfer;
45 import org.openecomp.sdc.be.user.UserBusinessLogic;
46 import org.openecomp.sdc.common.api.Constants;
47 import org.openecomp.sdc.common.log.wrappers.Logger;
48 import org.openecomp.sdc.exception.ResponseFormat;
49 import org.springframework.stereotype.Controller;
50
51 import javax.inject.Inject;
52 import javax.servlet.ServletContext;
53 import javax.servlet.http.HttpServletRequest;
54 import javax.ws.rs.Consumes;
55 import javax.ws.rs.DELETE;
56 import javax.ws.rs.GET;
57 import javax.ws.rs.HeaderParam;
58 import javax.ws.rs.POST;
59 import javax.ws.rs.PUT;
60 import javax.ws.rs.Path;
61 import javax.ws.rs.PathParam;
62 import javax.ws.rs.Produces;
63 import javax.ws.rs.core.Context;
64 import javax.ws.rs.core.MediaType;
65 import javax.ws.rs.core.Response;
66 import java.util.List;
67 import java.util.Optional;
68
69 @Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
70 @Path("/v1/catalog")
71 @Consumes(MediaType.APPLICATION_JSON)
72 @Produces(MediaType.APPLICATION_JSON)
73 @Tags({@Tag(name = "SDCE-2 APIs")})
74 @Servers({@Server(url = "/sdc2/rest")})
75 @Controller
76 public class CapabilityServlet extends AbstractValidationsServlet {
77     private static final Logger LOGGER = Logger.getLogger(CapabilityServlet.class);
78     private final CapabilitiesBusinessLogic capabilitiesBusinessLogic;
79
80     @Inject
81     public CapabilityServlet(UserBusinessLogic userBusinessLogic,
82         ComponentInstanceBusinessLogic componentInstanceBL,
83         ComponentsUtils componentsUtils, ServletUtils servletUtils,
84         ResourceImportManager resourceImportManager,
85         CapabilitiesBusinessLogic capabilitiesBusinessLogic) {
86         super(userBusinessLogic, componentInstanceBL, componentsUtils, servletUtils, resourceImportManager);
87         this.capabilitiesBusinessLogic = capabilitiesBusinessLogic;
88     }
89
90
91     @POST
92     @Consumes(MediaType.APPLICATION_JSON)
93     @Produces(MediaType.APPLICATION_JSON)
94     @Path("/resources/{resourceId}/capabilities")
95     @Operation(description = "Create Capabilities on resource", method = "POST",
96             summary = "Create Capabilities on resource", responses = {
97             @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
98             @ApiResponse(responseCode = "201", description = "Create Capabilities"),
99             @ApiResponse(responseCode = "403", description = "Restricted operation"),
100             @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
101             @ApiResponse(responseCode = "409", description = "Capability already exist")})
102     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
103     public Response createCapabilitiesOnResource(
104             @Parameter(description = "Capability to create", required = true) String data,
105             @Parameter(description = "Resource Id") @PathParam("resourceId") String resourceId,
106             @Context final HttpServletRequest request,
107             @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
108         return createOrUpdate(data, "resources" , resourceId,
109                 request, userId, false, "createCapabilities");
110     }
111
112     @PUT
113     @Consumes(MediaType.APPLICATION_JSON)
114     @Produces(MediaType.APPLICATION_JSON)
115     @Path("/resources/{resourceId}/capabilities")
116     @Operation(description = "Update Capabilities on resource", method = "PUT",
117             summary = "Update Capabilities on resource", responses = {@ApiResponse(
118             content = @Content(array = @ArraySchema(schema = @Schema(implementation = CapabilityDefinition.class)))),
119             @ApiResponse(responseCode = "201", description = "Update Capabilities"),
120             @ApiResponse(responseCode = "403", description = "Restricted operation"),
121             @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
122     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
123     public Response updateCapabilitiesOnResource(
124             @Parameter(description = "Capabilities to update", required = true) String data,
125             @Parameter(description = "Component Id") @PathParam("resourceId") String resourceId,
126             @Context final HttpServletRequest request,
127             @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
128         return createOrUpdate(data, "resources", resourceId,
129                 request, userId, true, "updateCapabilities");
130     }
131
132     @GET
133     @Consumes(MediaType.APPLICATION_JSON)
134     @Produces(MediaType.APPLICATION_JSON)
135     @Path("/resources/{resourceId}/capabilities/{capabilityId}")
136     @Operation(description = "Get Capability from resource", method = "GET", summary = "GET Capability from resource",
137             responses = {@ApiResponse(content = @Content(
138                     array = @ArraySchema(schema = @Schema(implementation = CapabilityDefinition.class)))),
139                     @ApiResponse(responseCode = "201", description = "GET Capability"),
140                     @ApiResponse(responseCode = "403", description = "Restricted operation"),
141                     @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
142     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
143     public Response getCapabilityOnResource(
144             @Parameter(description = "Resource Id") @PathParam("resourceId") String resourceId,
145             @Parameter(description = "Capability Id") @PathParam("capabilityId") String capabilityId,
146             @Context final HttpServletRequest request,
147             @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
148
149         return get(capabilityId, resourceId, request, userId);
150     }
151
152     @DELETE
153     @Consumes(MediaType.APPLICATION_JSON)
154     @Produces(MediaType.APPLICATION_JSON)
155     @Path("/resources/{resourceId}/capabilities/{capabilityId}")
156     @Operation(description = "Delete capability from resource", method = "DELETE",
157             summary = "Delete capability from resource", responses = {@ApiResponse(
158             content = @Content(array = @ArraySchema(schema = @Schema(implementation = CapabilityDefinition.class)))),
159             @ApiResponse(responseCode = "201", description = "Delete capability"),
160             @ApiResponse(responseCode = "403", description = "Restricted operation"),
161             @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
162     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
163     public Response deleteCapabilityOnResource(
164             @Parameter(description = "capability Id") @PathParam("capabilityId") String capabilityId,
165             @Parameter(description = "Resource Id") @PathParam("resourceId") String resourceId,
166             @Context final HttpServletRequest request,
167             @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
168         return delete(capabilityId, resourceId, request, userId);
169     }
170
171     @POST
172     @Consumes(MediaType.APPLICATION_JSON)
173     @Produces(MediaType.APPLICATION_JSON)
174     @Path("/services/{serviceId}/capabilities")
175     @Operation(description = "Create Capabilities on service", method = "POST",
176             summary = "Create Capabilities on service", responses = {
177             @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
178             @ApiResponse(responseCode = "201", description = "Create Capabilities"),
179             @ApiResponse(responseCode = "403", description = "Restricted operation"),
180             @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
181             @ApiResponse(responseCode = "409", description = "Capability already exist")})
182     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
183     public Response createCapabilitiesOnService(
184             @Parameter(description = "Capability to create", required = true) String data,
185             @Parameter(description = "Service Id") @PathParam("serviceId") String serviceId,
186             @Context final HttpServletRequest request,
187             @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
188         return createOrUpdate(data, "services" , serviceId,
189                 request, userId, false, "createCapabilities");
190     }
191
192     @PUT
193     @Consumes(MediaType.APPLICATION_JSON)
194     @Produces(MediaType.APPLICATION_JSON)
195     @Path("/services/{serviceId}/capabilities")
196     @Operation(description = "Update Capabilities on service", method = "PUT",
197             summary = "Update Capabilities on service", responses = {@ApiResponse(
198             content = @Content(array = @ArraySchema(schema = @Schema(implementation = CapabilityDefinition.class)))),
199             @ApiResponse(responseCode = "201", description = "Update Capabilities"),
200             @ApiResponse(responseCode = "403", description = "Restricted operation"),
201             @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
202     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
203     public Response updateCapabilitiesOnService(
204             @Parameter(description = "Capabilities to update", required = true) String data,
205             @Parameter(description = "Component Id") @PathParam("serviceId") String serviceId,
206             @Context final HttpServletRequest request,
207             @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
208         return createOrUpdate(data, "services", serviceId,
209                 request, userId, true, "updateCapabilities");
210     }
211
212     @GET
213     @Consumes(MediaType.APPLICATION_JSON)
214     @Produces(MediaType.APPLICATION_JSON)
215     @Path("/services/{serviceId}/capabilities/{capabilityId}")
216     @Operation(description = "Get Capability from service", method = "GET", summary = "GET Capability from service",
217             responses = {@ApiResponse(content = @Content(
218                     array = @ArraySchema(schema = @Schema(implementation = CapabilityDefinition.class)))),
219                     @ApiResponse(responseCode = "201", description = "GET Capability"),
220                     @ApiResponse(responseCode = "403", description = "Restricted operation"),
221                     @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
222     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
223     public Response getCapabilityOnService(
224             @Parameter(description = "Service Id") @PathParam("serviceId") String serviceId,
225             @Parameter(description = "Capability Id") @PathParam("capabilityId") String capabilityId,
226             @Context final HttpServletRequest request,
227             @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
228
229         return get(capabilityId, serviceId, request, userId);
230     }
231
232     @DELETE
233     @Consumes(MediaType.APPLICATION_JSON)
234     @Produces(MediaType.APPLICATION_JSON)
235     @Path("/services/{serviceId}/capabilities/{capabilityId}")
236     @Operation(description = "Delete capability from service", method = "DELETE",
237             summary = "Delete capability from service", responses = {@ApiResponse(
238             content = @Content(array = @ArraySchema(schema = @Schema(implementation = CapabilityDefinition.class)))),
239             @ApiResponse(responseCode = "201", description = "Delete capability"),
240             @ApiResponse(responseCode = "403", description = "Restricted operation"),
241             @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
242     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
243     public Response deleteCapabilityOnService(
244             @Parameter(description = "capability Id") @PathParam("capabilityId") String capabilityId,
245             @Parameter(description = "Service Id") @PathParam("serviceId") String serviceId,
246             @Context final HttpServletRequest request,
247             @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
248         return delete(capabilityId, serviceId, request, userId);
249     }
250
251     private Response createOrUpdate (String data, String componentType, String componentId,
252                                      HttpServletRequest request,
253                                      String userId,
254                                      boolean isUpdate,
255                                      String errorContext) {
256         ServletContext context = request.getSession().getServletContext();
257         String url = request.getMethod() + " " + request.getRequestURI();
258
259         User modifier = new User();
260         modifier.setUserId(userId);
261         LOGGER.debug("Start create or update request of {} with modifier id {}", url, userId);
262         try {
263             String componentIdLower = componentId.toLowerCase();
264
265             Either<List<CapabilityDefinition>, ResponseFormat> mappedCapabilitiesDataEither
266                     = getMappedCapabilitiesData(data, modifier, ComponentTypeEnum.findByParamName(componentType));
267             if(mappedCapabilitiesDataEither.isRight()) {
268                 LOGGER.error("Failed to create or update capabilities");
269                 return buildErrorResponse(mappedCapabilitiesDataEither.right().value());
270             }
271             List<CapabilityDefinition> mappedCapabilitiesData = mappedCapabilitiesDataEither.left().value();
272             Either<List<CapabilityDefinition>, ResponseFormat> actionResponse;
273             if(isUpdate) {
274                 actionResponse = capabilitiesBusinessLogic.updateCapabilities(componentIdLower,
275                         mappedCapabilitiesData, modifier, errorContext, true);
276             } else {
277                 actionResponse = capabilitiesBusinessLogic.createCapabilities(componentIdLower,
278                         mappedCapabilitiesData, modifier, errorContext, true);
279             }
280             if (actionResponse.isRight()) {
281                 LOGGER.error("Failed to create or update capabilities");
282                 return buildErrorResponse(actionResponse.right().value());
283             }
284             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK),
285                     actionResponse.left().value());
286         } catch (Exception e) {
287             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Capabilities create or update");
288             LOGGER.error("Failed to create or update capabilities with an error", e);
289             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
290         }
291     }
292
293     private Response get (String capabilityIdToGet,  String componentId,
294                           HttpServletRequest request, String userId){
295         ServletContext context = request.getSession().getServletContext();
296         String url = request.getMethod() + " " + request.getRequestURI();
297
298         User modifier = new User();
299         modifier.setUserId(userId);
300         LOGGER.debug("Start get request of {} with modifier id {}", url, userId);
301
302         try {
303             String componentIdLower = componentId.toLowerCase();
304
305             Either<CapabilityDefinition, ResponseFormat> actionResponse = capabilitiesBusinessLogic
306                     .getCapability(componentIdLower, capabilityIdToGet, modifier, true);
307             if (actionResponse.isRight()) {
308                 LOGGER.error("failed to get capability");
309                 return buildErrorResponse(actionResponse.right().value());
310             }
311             Object result = RepresentationUtils.toFilteredRepresentation(actionResponse.left().value());
312             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), result);
313         } catch (Exception e) {
314             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get capability");
315             LOGGER.error("get capabilities failed with exception", e);
316             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
317         }
318     }
319
320     private Response delete (String capabilityId, String componentId, HttpServletRequest
321             request, String userId){
322
323         ServletContext context = request.getSession().getServletContext();
324         String url = request.getMethod() + " " + request.getRequestURI();
325
326         User modifier = new User();
327         modifier.setUserId(userId);
328         LOGGER.debug("Start delete request of {} with modifier id {}", url, userId);
329
330         try {
331             String componentIdLower = componentId.toLowerCase();
332
333             Either<CapabilityDefinition, ResponseFormat> actionResponse = capabilitiesBusinessLogic
334                     .deleteCapability(componentIdLower, capabilityId, modifier, true);
335             if (actionResponse.isRight()) {
336                 LOGGER.error("failed to delete capability");
337                 return buildErrorResponse(actionResponse.right().value());
338             }
339             Object result = RepresentationUtils.toRepresentation(actionResponse.left().value());
340             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), result);
341         } catch (Exception e) {
342             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Delete capability");
343             LOGGER.error("Delete capability failed with an error", e);
344             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
345         }
346     }
347
348     private Either<List<CapabilityDefinition>, ResponseFormat> getMappedCapabilitiesData(String inputJson, User user,
349                                                                  ComponentTypeEnum componentTypeEnum){
350         Either<UiComponentDataTransfer, ResponseFormat> mappedData = getComponentsUtils()
351                 .convertJsonToObjectUsingObjectMapper(inputJson, user, UiComponentDataTransfer.class,
352                         AuditingActionEnum.CREATE_RESOURCE, componentTypeEnum);
353         if (mappedData.isRight()) {
354             return Either.right(getComponentsUtils()
355                 .getResponseFormat(ActionStatus.INVALID_CONTENT));
356         }
357         Optional<List<CapabilityDefinition>> capabilityDefinitionList =
358                 mappedData.left().value().getCapabilities().values().stream().findFirst();
359         return capabilityDefinitionList.<Either<List<CapabilityDefinition>, ResponseFormat>>
360                 map(Either::left).orElseGet(() -> Either.right(getComponentsUtils()
361                 .getResponseFormat(ActionStatus.GENERAL_ERROR)));
362     }
363 }