337c641b3355a4084dde3d3174b3f0f1ceae60c8
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / servlets / ModelServlet.java
1 /*
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2021 Nordix Foundation
4  *  ================================================================================
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
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  *  SPDX-License-Identifier: Apache-2.0
17  *  ============LICENSE_END=========================================================
18  */
19 package org.openecomp.sdc.be.servlets;
20
21 import com.googlecode.jmapper.JMapper;
22 import com.jcabi.aspects.Loggable;
23 import io.swagger.v3.oas.annotations.Operation;
24 import io.swagger.v3.oas.annotations.Parameter;
25 import io.swagger.v3.oas.annotations.media.ArraySchema;
26 import io.swagger.v3.oas.annotations.media.Content;
27 import io.swagger.v3.oas.annotations.media.Schema;
28 import io.swagger.v3.oas.annotations.responses.ApiResponse;
29 import io.swagger.v3.oas.annotations.servers.Server;
30 import io.swagger.v3.oas.annotations.tags.Tag;
31 import java.io.InputStream;
32 import java.util.Arrays;
33 import java.util.List;
34 import javax.inject.Inject;
35 import javax.validation.Valid;
36 import javax.validation.constraints.NotNull;
37 import javax.ws.rs.Consumes;
38 import javax.ws.rs.GET;
39 import javax.ws.rs.HeaderParam;
40 import javax.ws.rs.POST;
41 import javax.ws.rs.PUT;
42 import javax.ws.rs.Path;
43 import javax.ws.rs.Produces;
44 import javax.ws.rs.core.MediaType;
45 import javax.ws.rs.core.Response;
46 import javax.ws.rs.core.Response.Status;
47 import org.glassfish.jersey.media.multipart.FormDataParam;
48 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
49 import org.openecomp.sdc.be.components.impl.ModelBusinessLogic;
50 import org.openecomp.sdc.be.components.impl.ResourceImportManager;
51 import org.openecomp.sdc.be.components.impl.aaf.AafPermission;
52 import org.openecomp.sdc.be.components.impl.aaf.PermissionAllowed;
53 import org.openecomp.sdc.be.components.validation.UserValidations;
54 import org.openecomp.sdc.be.config.BeEcompErrorManager;
55 import org.openecomp.sdc.be.dao.api.ActionStatus;
56 import org.openecomp.sdc.be.exception.BusinessException;
57 import org.openecomp.sdc.be.impl.ComponentsUtils;
58 import org.openecomp.sdc.be.impl.ServletUtils;
59 import org.openecomp.sdc.be.model.Model;
60 import org.openecomp.sdc.be.ui.model.ModelCreateRequest;
61 import org.openecomp.sdc.be.user.Role;
62 import org.openecomp.sdc.be.user.UserBusinessLogic;
63 import org.openecomp.sdc.common.api.Constants;
64 import org.openecomp.sdc.common.util.ValidationUtils;
65 import org.slf4j.Logger;
66 import org.slf4j.LoggerFactory;
67 import org.springframework.stereotype.Controller;
68
69 /**
70  * Root resource (exposed at "/" path)
71  */
72 @Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
73 @Path("/v1/catalog")
74 @Tag(name = "SDCE-2 APIs")
75 @Server(url = "/sdc2/rest")
76 @Controller
77 public class ModelServlet extends AbstractValidationsServlet {
78
79     private static final Logger log = LoggerFactory.getLogger(ModelServlet.class);
80     private final ModelBusinessLogic modelBusinessLogic;
81     private final UserValidations userValidations;
82
83     @Inject
84     public ModelServlet(final UserBusinessLogic userBusinessLogic, final ComponentInstanceBusinessLogic componentInstanceBL,
85                         final ComponentsUtils componentsUtils, final ServletUtils servletUtils, final ResourceImportManager resourceImportManager,
86                         final ModelBusinessLogic modelBusinessLogic, final UserValidations userValidations) {
87         super(userBusinessLogic, componentInstanceBL, componentsUtils, servletUtils, resourceImportManager);
88         this.modelBusinessLogic = modelBusinessLogic;
89         this.userValidations = userValidations;
90     }
91
92     @POST
93     @Path("/model")
94     @Consumes(MediaType.MULTIPART_FORM_DATA)
95     @Produces(MediaType.APPLICATION_JSON)
96     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
97     @Operation(description = "Create a TOSCA model, along with its imports files", method = "POST", summary = "Create a TOSCA model", responses = {
98         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
99         @ApiResponse(responseCode = "201", description = "Model created"),
100         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
101         @ApiResponse(responseCode = "403", description = "Restricted operation"),
102         @ApiResponse(responseCode = "409", description = "Model already exists")})
103     public Response createModel(@Parameter(description = "model to be created", required = true)
104                                     @NotNull @Valid @FormDataParam("model") final ModelCreateRequest modelCreateRequest,
105                                 @Parameter(description = "the model TOSCA imports zipped", required = true)
106                                     @NotNull @FormDataParam("modelImportsZip") final InputStream modelImportsZip,
107                                 @HeaderParam(value = Constants.USER_ID_HEADER) final String userId) {
108         validateUser(ValidationUtils.sanitizeInputString(userId));
109         final var modelName = ValidationUtils.sanitizeInputString(modelCreateRequest.getName().trim());
110         try {
111             final Model createdModel = modelBusinessLogic
112                 .createModel(new JMapper<>(Model.class, ModelCreateRequest.class).getDestination(modelCreateRequest));
113             modelBusinessLogic.createModelImports(modelName, modelImportsZip);
114             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED),
115                 RepresentationUtils.toRepresentation(createdModel));
116         } catch (final BusinessException e) {
117             throw e;
118         } catch (final Exception e) {
119             var errorMsg = String.format("Unexpected error while creating model '%s' imports", modelName);
120             BeEcompErrorManager.getInstance().logBeRestApiGeneralError(errorMsg);
121             log.error(errorMsg, e);
122             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
123         }
124     }
125
126     @GET
127     @Path("/model")
128     @Produces(MediaType.APPLICATION_JSON)
129     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
130     @Operation(method = "GET", summary = "List TOSCA models", description = "List all the existing TOSCA models",
131         responses = {
132             @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Model.class)))),
133             @ApiResponse(responseCode = "200", description = "Listing successful"),
134             @ApiResponse(responseCode = "403", description = "Restricted operation")
135         }
136     )
137     public Response listModels(@HeaderParam(value = Constants.USER_ID_HEADER) final String userId) {
138         validateUser(ValidationUtils.sanitizeInputString(userId));
139         try {
140             final List<Model> modelList = modelBusinessLogic.listModels();
141             return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), RepresentationUtils.toRepresentation(modelList));
142         } catch (final BusinessException e) {
143             throw e;
144         } catch (final Exception e) {
145             var errorMsg = "Unexpected error while listing the models";
146             BeEcompErrorManager.getInstance().logBeRestApiGeneralError(errorMsg);
147             log.error(errorMsg, e);
148             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
149         }
150     }
151
152     @PUT
153     @Path("/model/imports")
154     @Consumes(MediaType.MULTIPART_FORM_DATA)
155     @Produces(MediaType.APPLICATION_JSON)
156     @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
157     @Operation(description = "Update a model TOSCA imports", method = "PUT", summary = "Update a model TOSCA imports", responses = {
158         @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
159         @ApiResponse(responseCode = "204", description = "Model imports updated"),
160         @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
161         @ApiResponse(responseCode = "403", description = "Restricted operation"),
162         @ApiResponse(responseCode = "404", description = "Model not found")})
163     public Response updateModelImports(@Parameter(description = "model to be created", required = true)
164                                            @NotNull @FormDataParam("modelName") String modelName,
165                                        @Parameter(description = "the model TOSCA imports zipped", required = true)
166                                            @NotNull @FormDataParam("modelImportsZip") final InputStream modelImportsZip,
167                                        @HeaderParam(value = Constants.USER_ID_HEADER) final String userId) {
168         validateUser(ValidationUtils.sanitizeInputString(userId));
169         modelName = ValidationUtils.sanitizeInputString(modelName);
170         try {
171             modelBusinessLogic.createModelImports(modelName, modelImportsZip);
172         } catch (final BusinessException e) {
173             throw e;
174         } catch (final Exception e) {
175             var errorMsg = String.format("Unexpected error while creating model '%s' imports", modelName);
176             BeEcompErrorManager.getInstance().logBeRestApiGeneralError(errorMsg);
177             log.error(errorMsg, e);
178             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
179         }
180         return Response.status(Status.NO_CONTENT).build();
181     }
182
183     private void validateUser(final String userId) {
184         userValidations.validateUserRole(userValidations.validateUserExists(userId), Arrays.asList(Role.DESIGNER, Role.ADMIN));
185     }
186
187 }