Remove legacy certificate handling
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / servlets / ComponentPropertyServlet.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 package org.openecomp.sdc.be.servlets;
17
18 import com.jcabi.aspects.Loggable;
19 import fj.data.Either;
20 import io.swagger.v3.oas.annotations.Operation;
21 import io.swagger.v3.oas.annotations.Parameter;
22 import io.swagger.v3.oas.annotations.media.ArraySchema;
23 import io.swagger.v3.oas.annotations.media.Content;
24 import io.swagger.v3.oas.annotations.media.Schema;
25 import io.swagger.v3.oas.annotations.responses.ApiResponse;
26 import io.swagger.v3.oas.annotations.servers.Server;
27 import io.swagger.v3.oas.annotations.tags.Tag;
28 import java.util.List;
29 import java.util.Map;
30 import javax.inject.Inject;
31 import javax.inject.Singleton;
32 import javax.servlet.http.HttpServletRequest;
33 import javax.ws.rs.Consumes;
34 import javax.ws.rs.DELETE;
35 import javax.ws.rs.GET;
36 import javax.ws.rs.HeaderParam;
37 import javax.ws.rs.POST;
38 import javax.ws.rs.PUT;
39 import javax.ws.rs.Path;
40 import javax.ws.rs.PathParam;
41 import javax.ws.rs.Produces;
42 import javax.ws.rs.core.Context;
43 import javax.ws.rs.core.MediaType;
44 import javax.ws.rs.core.Response;
45 import org.openecomp.sdc.be.components.impl.PropertyBusinessLogic;
46 import org.openecomp.sdc.be.config.BeEcompErrorManager;
47 import org.openecomp.sdc.be.dao.api.ActionStatus;
48 import org.openecomp.sdc.be.datamodel.utils.PropertyValueConstraintValidationUtil;
49 import org.openecomp.sdc.be.impl.ComponentsUtils;
50 import org.openecomp.sdc.be.model.PropertyDefinition;
51 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
52 import org.openecomp.sdc.be.resources.data.EntryData;
53 import org.openecomp.sdc.common.api.Constants;
54 import org.openecomp.sdc.common.log.elements.LoggerSupportability;
55 import org.openecomp.sdc.common.log.enums.LoggerSupportabilityActions;
56 import org.openecomp.sdc.common.log.enums.StatusCode;
57 import org.openecomp.sdc.exception.ResponseFormat;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
60
61 @Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
62 @Path("/v1/catalog")
63 @Tag(name = "SDCE-2 APIs")
64 @Server(url = "/sdc2/rest")
65 @Singleton
66 public class ComponentPropertyServlet extends BeGenericServlet {
67
68     private static final Logger log = LoggerFactory.getLogger(ComponentPropertyServlet.class);
69     private static final String CREATE_PROPERTY = "Create Property";
70     private static final String DEBUG_MESSAGE = "Start handle request of {} modifier id is {}";
71     private static final LoggerSupportability loggerSupportability = LoggerSupportability.getLogger(ComponentPropertyServlet.class.getName());
72     private final PropertyBusinessLogic propertyBusinessLogic;
73     private final ApplicationDataTypeCache applicationDataTypeCache;
74
75     @Inject
76     public ComponentPropertyServlet(ComponentsUtils componentsUtils,
77                                     ApplicationDataTypeCache applicationDataTypeCache, PropertyBusinessLogic propertyBusinessLogic) {
78         super(componentsUtils);
79         this.applicationDataTypeCache = applicationDataTypeCache;
80         this.propertyBusinessLogic = propertyBusinessLogic;
81     }
82
83     @POST
84     @Path("services/{serviceId}/properties")
85     @Consumes(MediaType.APPLICATION_JSON)
86     @Produces(MediaType.APPLICATION_JSON)
87     @Operation(description = "Create Service Property", method = "POST", summary = "Returns created service property", responses = {
88         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
89         @ApiResponse(responseCode = "201", description = "Service property created"),
90         @ApiResponse(responseCode = "403", description = "Restricted operation"),
91         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
92         @ApiResponse(responseCode = "409", description = "Service property already exist")})
93     public Response createPropertyInService(
94         @Parameter(description = "service id to update with new property", required = true) @PathParam("serviceId") final String serviceId,
95         @Parameter(description = "Service property to be created", required = true) String data, @Context final HttpServletRequest request,
96         @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
97         return createProperty(serviceId, data, request, userId);
98     }
99
100     @POST
101     @Path("resources/{resourceId}/properties")
102     @Consumes(MediaType.APPLICATION_JSON)
103     @Produces(MediaType.APPLICATION_JSON)
104     @Operation(description = "Create Resource Property", method = "POST", summary = "Returns created service property", responses = {
105         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
106         @ApiResponse(responseCode = "201", description = "Resource property created"),
107         @ApiResponse(responseCode = "403", description = "Restricted operation"),
108         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
109         @ApiResponse(responseCode = "409", description = "Resource property already exist")})
110     public Response createPropertyInResource(
111         @Parameter(description = "Resource id to update with new property", required = true) @PathParam("resourceId") final String resourceId,
112         @Parameter(description = "Resource property to be created", required = true) String data, @Context final HttpServletRequest request,
113         @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
114         return createProperty(resourceId, data, request, userId);
115     }
116
117     @GET
118     @Path("services/{serviceId}/properties/{propertyId}")
119     @Consumes(MediaType.APPLICATION_JSON)
120     @Produces(MediaType.APPLICATION_JSON)
121     @Operation(description = "Get Service Property", method = "GET", summary = "Returns property of service", responses = {
122         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
123         @ApiResponse(responseCode = "200", description = "property"), @ApiResponse(responseCode = "403", description = "Restricted operation"),
124         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
125         @ApiResponse(responseCode = "404", description = "Service property not found")})
126     public Response getPropertyInService(
127         @Parameter(description = "service id of property", required = true) @PathParam("serviceId") final String serviceId,
128         @Parameter(description = "property id to get", required = true) @PathParam("propertyId") final String propertyId,
129         @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
130         return getProperty(serviceId, propertyId, request, userId);
131     }
132
133     @GET
134     @Path("resources/{resourceId}/properties/{propertyId}")
135     @Consumes(MediaType.APPLICATION_JSON)
136     @Produces(MediaType.APPLICATION_JSON)
137     @Operation(description = "Get Resource Property", method = "GET", summary = "Returns property of resource", responses = {
138         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
139         @ApiResponse(responseCode = "200", description = "property"), @ApiResponse(responseCode = "403", description = "Restricted operation"),
140         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
141         @ApiResponse(responseCode = "404", description = "Resource property not found")})
142     public Response getPropertyInResource(
143         @Parameter(description = "resource id of property", required = true) @PathParam("resourceId") final String resourceId,
144         @Parameter(description = "property id to get", required = true) @PathParam("propertyId") final String propertyId,
145         @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
146         return getProperty(resourceId, propertyId, request, userId);
147     }
148
149     @GET
150     @Path("services/{serviceId}/properties")
151     @Consumes(MediaType.APPLICATION_JSON)
152     @Produces(MediaType.APPLICATION_JSON)
153     @Operation(description = "Get Service Property", method = "GET", summary = "Returns property list of service", responses = {
154         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
155         @ApiResponse(responseCode = "200", description = "property"), @ApiResponse(responseCode = "403", description = "Restricted operation"),
156         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
157         @ApiResponse(responseCode = "404", description = "Service property not found")})
158     public Response getPropertyListInService(
159         @Parameter(description = "service id of property", required = true) @PathParam("serviceId") final String serviceId,
160         @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
161         return getPropertyList(serviceId, request, userId);
162     }
163
164     @GET
165     @Path("resources/{resourceId}/properties")
166     @Consumes(MediaType.APPLICATION_JSON)
167     @Produces(MediaType.APPLICATION_JSON)
168     @Operation(description = "Get Resource Property", method = "GET", summary = "Returns property list of resource", responses = {
169         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
170         @ApiResponse(responseCode = "200", description = "property"), @ApiResponse(responseCode = "403", description = "Restricted operation"),
171         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
172         @ApiResponse(responseCode = "404", description = "Resource property not found")})
173     public Response getPropertyListInResource(
174         @Parameter(description = "resource id of property", required = true) @PathParam("resourceId") final String resourceId,
175         @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
176         return getPropertyList(resourceId, request, userId);
177     }
178
179     @DELETE
180     @Path("services/{serviceId}/properties/{propertyId}")
181     @Consumes(MediaType.APPLICATION_JSON)
182     @Produces(MediaType.APPLICATION_JSON)
183     @Operation(description = "Delete Service Property", method = "DELETE", summary = "Returns deleted property", responses = {
184         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
185         @ApiResponse(responseCode = "204", description = "deleted property"),
186         @ApiResponse(responseCode = "403", description = "Restricted operation"),
187         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
188         @ApiResponse(responseCode = "404", description = "Service property not found")})
189     public Response deletePropertyInService(
190         @Parameter(description = "service id of property", required = true) @PathParam("serviceId") final String serviceId,
191         @Parameter(description = "Property id to delete", required = true) @PathParam("propertyId") final String propertyId,
192         @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
193         return deleteProperty(serviceId, propertyId, request, userId);
194     }
195
196     @DELETE
197     @Path("resources/{resourceId}/properties/{propertyId}")
198     @Consumes(MediaType.APPLICATION_JSON)
199     @Produces(MediaType.APPLICATION_JSON)
200     @Operation(description = "Delete Resource Property", method = "DELETE", summary = "Returns deleted property", responses = {
201         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
202         @ApiResponse(responseCode = "204", description = "deleted property"),
203         @ApiResponse(responseCode = "403", description = "Restricted operation"),
204         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
205         @ApiResponse(responseCode = "404", description = "Resource property not found")})
206     public Response deletePropertyInResource(
207         @Parameter(description = "resource id of property", required = true) @PathParam("resourceId") final String resourceId,
208         @Parameter(description = "Property id to delete", required = true) @PathParam("propertyId") final String propertyId,
209         @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
210         return deleteProperty(resourceId, propertyId, request, userId);
211     }
212
213     @PUT
214     @Path("services/{serviceId}/properties")
215     @Consumes(MediaType.APPLICATION_JSON)
216     @Produces(MediaType.APPLICATION_JSON)
217     @Operation(description = "Update Service Property", method = "PUT", summary = "Returns updated property", responses = {
218         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
219         @ApiResponse(responseCode = "200", description = "Service property updated"),
220         @ApiResponse(responseCode = "403", description = "Restricted operation"),
221         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
222     public Response updatePropertyInService(
223         @Parameter(description = "service id to update with new property", required = true) @PathParam("serviceId") final String serviceId,
224         @Parameter(description = "Service property to update", required = true) String data, @Context final HttpServletRequest request,
225         @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
226         return updateProperty(serviceId, data, request, userId);
227     }
228
229     @PUT
230     @Path("resources/{resourceId}/properties")
231     @Consumes(MediaType.APPLICATION_JSON)
232     @Produces(MediaType.APPLICATION_JSON)
233     @Operation(description = "Update Resource Property", method = "PUT", summary = "Returns updated property", responses = {
234         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
235         @ApiResponse(responseCode = "200", description = "Resource property updated"),
236         @ApiResponse(responseCode = "403", description = "Restricted operation"),
237         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
238     public Response updatePropertyInResource(
239         @Parameter(description = "resource id to update with new property", required = true) @PathParam("resourceId") final String resourceId,
240         @Parameter(description = "Resource property to update", required = true) String data, @Context final HttpServletRequest request,
241         @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
242         return updateProperty(resourceId, data, request, userId);
243     }
244
245     private Response createProperty(String componentId, String data, HttpServletRequest request, String userId) {
246         String url = request.getMethod() + " " + request.getRequestURI();
247         log.debug("Start handle request of {} modifier id is {} data is {}", url, userId, data);
248         loggerSupportability.log(LoggerSupportabilityActions.CREATE_PROPERTIES, StatusCode.STARTED, "CREATE_PROPERTIES by user {} ", userId);
249         try {
250             Either<Map<String, PropertyDefinition>, ActionStatus> propertyDefinition = getPropertyModel(componentId, data);
251             if (propertyDefinition.isRight()) {
252                 return buildErrorResponse(getComponentsUtils().getResponseFormat(propertyDefinition.right().value()));
253             }
254             Map<String, PropertyDefinition> properties = propertyDefinition.left().value();
255             if (properties == null || properties.size() != 1) {
256                 log.info("Property content is invalid - {}", data);
257                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
258             }
259
260             //Validate value and Constraint of property and Fetch all data types from cache
261             Either<Boolean, ResponseFormat> constraintValidatorResponse = new PropertyValueConstraintValidationUtil()
262                 .validatePropertyConstraints(properties.values(), applicationDataTypeCache,
263                     propertyBusinessLogic.getComponentModelByComponentId(componentId));
264             if (constraintValidatorResponse.isRight()) {
265                 log.error("Failed validation value and constraint of property: {}", constraintValidatorResponse.right().value());
266                 return buildErrorResponse(constraintValidatorResponse.right().value());
267             }
268
269             Map.Entry<String, PropertyDefinition> entry = properties.entrySet().iterator().next();
270             PropertyDefinition newPropertyDefinition = entry.getValue();
271             newPropertyDefinition.setParentUniqueId(componentId);
272             newPropertyDefinition.setUserCreated(true);
273             Either<EntryData<String, PropertyDefinition>, ResponseFormat> addPropertyEither =
274                 propertyBusinessLogic.addPropertyToComponent(componentId, newPropertyDefinition, userId);
275             if (addPropertyEither.isRight()) {
276                 return buildErrorResponse(addPropertyEither.right().value());
277             }
278             loggerSupportability.log(LoggerSupportabilityActions.CREATE_PROPERTIES, StatusCode.COMPLETE, "CREATE_PROPERTIES by user {} ", userId);
279             return buildOkResponse(newPropertyDefinition);
280         } catch (Exception e) {
281             BeEcompErrorManager.getInstance().logBeRestApiGeneralError(CREATE_PROPERTY);
282             log.debug("create property failed with exception", e);
283             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
284         }
285     }
286
287     private Response updateProperty(String componentId, String data, HttpServletRequest request, String userId) {
288         String url = request.getMethod() + " " + request.getRequestURI();
289         log.debug("Start handle request of {}", url);
290         loggerSupportability.log(LoggerSupportabilityActions.UPDATE_PROPERTIES, StatusCode.STARTED, "UPDATE_PROPERTIES by user {} ", userId);
291         log.debug("modifier id is {}", userId);
292
293         try {
294             // convert json to PropertyDefinition
295             Either<Map<String, PropertyDefinition>, ActionStatus> propertiesListEither = getPropertiesListForUpdate(data);
296             if (propertiesListEither.isRight()) {
297                 return buildErrorResponse(getComponentsUtils().getResponseFormat(propertiesListEither.right().value()));
298             }
299             Map<String, PropertyDefinition> properties = propertiesListEither.left().value();
300             if (properties == null) {
301                 log.info("Property content is invalid - {}", data);
302                 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
303             }
304             //Validate value and Constraint of property and Fetch all data types from cache
305             Either<Boolean, ResponseFormat> constraintValidatorResponse = new PropertyValueConstraintValidationUtil()
306                 .validatePropertyConstraints(properties.values(), applicationDataTypeCache,
307                     propertyBusinessLogic.getComponentModelByComponentId(componentId));
308             if (constraintValidatorResponse.isRight()) {
309                 log.error("Failed validation value and constraint of property: {}", constraintValidatorResponse.right().value());
310                 return buildErrorResponse(constraintValidatorResponse.right().value());
311             }
312             // update property
313             for (PropertyDefinition propertyDefinition : properties.values()) {
314                 Either<EntryData<String, PropertyDefinition>, ResponseFormat> status = propertyBusinessLogic
315                     .updateComponentProperty(componentId, propertyDefinition.getUniqueId(), propertyDefinition, userId);
316                 if (status.isRight()) {
317                     log.info("Failed to update Property. Reason - {}", status.right().value());
318                     return buildErrorResponse(status.right().value());
319                 }
320                 log.debug("Property id {} updated successfully ", status.left().value().getValue().getUniqueId());
321             }
322             loggerSupportability.log(LoggerSupportabilityActions.UPDATE_PROPERTIES, StatusCode.COMPLETE, "UPDATE_PROPERTIES by user {} ", userId);
323             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), properties);
324         } catch (Exception e) {
325             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Update Property");
326             log.debug("update property failed with exception", e);
327             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
328         }
329     }
330
331     private Response getProperty(String componentId, String propertyId, HttpServletRequest request, String userId) {
332         String url = request.getMethod() + " " + request.getRequestURI();
333         log.debug(DEBUG_MESSAGE, url, userId);
334         try {
335             Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> retrievedPropertyEither = propertyBusinessLogic
336                 .getComponentProperty(componentId, propertyId, userId);
337             if (retrievedPropertyEither.isRight()) {
338                 return buildErrorResponse(retrievedPropertyEither.right().value());
339             }
340             return buildOkResponse(retrievedPropertyEither.left().value());
341         } catch (Exception e) {
342             BeEcompErrorManager.getInstance().logBeRestApiGeneralError(CREATE_PROPERTY);
343             log.debug("get property failed with exception", e);
344             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
345         }
346     }
347
348     private Response getPropertyList(String componentId, HttpServletRequest request, String userId) {
349         String url = request.getMethod() + " " + request.getRequestURI();
350         log.debug(DEBUG_MESSAGE, url, userId);
351         try {
352             Either<List<PropertyDefinition>, ResponseFormat> propertiesListEither = propertyBusinessLogic.getPropertiesList(componentId, userId);
353             if (propertiesListEither.isRight()) {
354                 return buildErrorResponse(propertiesListEither.right().value());
355             }
356             return buildOkResponse(propertiesListEither.left().value());
357         } catch (Exception e) {
358             BeEcompErrorManager.getInstance().logBeRestApiGeneralError(CREATE_PROPERTY);
359             log.debug("get property failed with exception", e);
360             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
361         }
362     }
363
364     private Response deleteProperty(String componentId, String propertyId, HttpServletRequest request, String userId) {
365         String url = request.getMethod() + " " + request.getRequestURI();
366         log.debug(DEBUG_MESSAGE, url, userId);
367         try {
368             // delete the property
369             Either<Map.Entry<String, PropertyDefinition>, ResponseFormat> status = propertyBusinessLogic
370                 .deletePropertyFromComponent(componentId, propertyId, userId);
371             if (status.isRight()) {
372                 log.debug("Failed to delete Property. Reason - ", status.right().value());
373                 return buildErrorResponse(status.right().value());
374             }
375             Map.Entry<String, PropertyDefinition> property = status.left().value();
376             log.debug("Property {} deleted successfully with id {}", property.getKey(), property.getValue().getUniqueId());
377             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.NO_CONTENT), propertyToJson(property));
378         } catch (Exception e) {
379             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Delete Property");
380             log.debug("delete property failed with exception", e);
381             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
382         }
383     }
384 }