Fix sonar issues
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / externalapi / servlet / ServiceActivationServlet.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2019 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
21 package org.openecomp.sdc.be.externalapi.servlet;
22
23 import com.fasterxml.jackson.databind.ObjectMapper;
24 import com.jcabi.aspects.Loggable;
25 import fj.data.Either;
26 import io.swagger.v3.oas.annotations.Operation;
27 import io.swagger.v3.oas.annotations.Parameter;
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.IOException;
32 import javax.inject.Inject;
33 import javax.servlet.http.HttpServletRequest;
34 import javax.ws.rs.Consumes;
35 import javax.ws.rs.HeaderParam;
36 import javax.ws.rs.POST;
37 import javax.ws.rs.Path;
38 import javax.ws.rs.PathParam;
39 import javax.ws.rs.Produces;
40 import javax.ws.rs.core.Context;
41 import javax.ws.rs.core.MediaType;
42 import javax.ws.rs.core.Response;
43 import org.apache.commons.lang3.StringUtils;
44 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
45 import org.openecomp.sdc.be.components.impl.ResourceImportManager;
46 import org.openecomp.sdc.be.components.impl.ServiceBusinessLogic;
47 import org.openecomp.sdc.be.components.impl.aaf.AafPermission;
48 import org.openecomp.sdc.be.components.impl.aaf.PermissionAllowed;
49 import org.openecomp.sdc.be.config.BeEcompErrorManager;
50 import org.openecomp.sdc.be.dao.api.ActionStatus;
51 import org.openecomp.sdc.be.externalapi.servlet.representation.ServiceDistributionReqInfo;
52 import org.openecomp.sdc.be.externalapi.servlet.representation.ServiceDistributionRespInfo;
53 import org.openecomp.sdc.be.impl.ComponentsUtils;
54 import org.openecomp.sdc.be.impl.ServletUtils;
55 import org.openecomp.sdc.be.model.User;
56 import org.openecomp.sdc.be.resources.data.auditing.model.DistributionData;
57 import org.openecomp.sdc.be.servlets.AbstractValidationsServlet;
58 import org.openecomp.sdc.be.servlets.RepresentationUtils;
59 import org.openecomp.sdc.be.user.UserBusinessLogic;
60 import org.openecomp.sdc.common.api.Constants;
61 import org.openecomp.sdc.common.datastructure.Wrapper;
62 import org.openecomp.sdc.common.log.wrappers.Logger;
63 import org.openecomp.sdc.exception.ResponseFormat;
64 import org.springframework.stereotype.Controller;
65
66 /**
67  * Created by chaya on 10/17/2017.
68  */
69 @SuppressWarnings("ALL")
70 @Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
71 @Path("/v1/catalog")
72 @Tag(name = "SDC External APIs")
73 @Server(url = "/sdc")
74 @Controller
75 public class ServiceActivationServlet extends AbstractValidationsServlet {
76
77     @Context
78     private HttpServletRequest request;
79
80     private static final Logger log = Logger.getLogger(ServiceActivationServlet.class);
81
82     private final ServiceBusinessLogic serviceBusinessLogic;
83
84     @Inject
85     public ServiceActivationServlet(UserBusinessLogic userBusinessLogic,
86         ComponentInstanceBusinessLogic componentInstanceBL,
87         ComponentsUtils componentsUtils, ServletUtils servletUtils,
88         ResourceImportManager resourceImportManager,
89         ServiceBusinessLogic serviceBusinessLogic) {
90         super(userBusinessLogic, componentInstanceBL, componentsUtils, servletUtils, resourceImportManager);
91         this.serviceBusinessLogic = serviceBusinessLogic;
92     }
93
94     /**
95      * Activates a service on a specific environment
96      */
97     @POST
98     @Path("/services/{serviceUUID}/distribution/{opEnvId}/activate")
99     @Consumes(MediaType.APPLICATION_JSON)
100     @Produces(MediaType.APPLICATION_JSON)
101     @Operation(description = "activate a service", method = "POST", summary = "Activates a service", responses = {
102             @ApiResponse(responseCode = "202",
103                     description = "ECOMP component is authenticated and required service may be distributed"),
104             @ApiResponse(responseCode = "400", description = "Missing  X-ECOMP-InstanceID  HTTP header - POL5001"),
105             @ApiResponse(responseCode = "401",
106                     description = "ECOMP component  should authenticate itself  and  to  re-send  again  HTTP  request  with its Basic Authentication credentials - POL5002"),
107             @ApiResponse(responseCode = "403", description = "ECOMP component is not authorized - POL5003"),
108             @ApiResponse(responseCode = "404",
109                     description = "Error: Requested '%1' (uuid) resource was not found - SVC4063"),
110             @ApiResponse(responseCode = "405",
111                     description = "Method  Not Allowed  :  Invalid HTTP method type used ( PUT,DELETE,POST will be rejected) - POL4050"),
112             @ApiResponse(responseCode = "500",
113                     description = "The request failed either due to internal SDC problem. ECOMP Component should continue the attempts to get the needed information - POL5000"),
114             @ApiResponse(responseCode = "400",
115                     description = "Invalid field format. One of the provided fields does not comply with the field rules - SVC4126"),
116             @ApiResponse(responseCode = "400",
117                     description = "Missing request body. The post request did not contain the expected body - SVC4500"),
118             @ApiResponse(responseCode = "400",
119                     description = "The resource name is missing in the request body - SVC4062"),
120             @ApiResponse(responseCode = "409", description = "Service state is invalid for this action"),
121             @ApiResponse(responseCode = "502",
122                     description = "The server was acting as a gateway or proxy and received an invalid response from the upstream server")})
123     @PermissionAllowed({AafPermission.PermNames.WRITE_VALUE})
124     public Response activateServiceExternal(
125             @Parameter(description = "Determines the format of the body of the request",
126                     required = true) @HeaderParam(value = Constants.CONTENT_TYPE_HEADER) String contentType,
127             @Parameter(description = "The user id",
128                     required = true) @HeaderParam(value = Constants.USER_ID_HEADER) final String userId,
129             @Parameter(description = "X-ECOMP-RequestID header",
130                     required = false) @HeaderParam(value = Constants.X_ECOMP_REQUEST_ID_HEADER) String requestId,
131             @Parameter(description = "X-ECOMP-InstanceID header", required = true) @HeaderParam(
132                     value = Constants.X_ECOMP_INSTANCE_ID_HEADER) final String instanceIdHeader,
133             @Parameter(description = "Determines the format of the body of the response",
134                     required = false) @HeaderParam(value = Constants.ACCEPT_HEADER) String accept,
135             @Parameter(description = "The username and password",
136                     required = true) @HeaderParam(value = Constants.AUTHORIZATION_HEADER) String authorization,
137             @Parameter(description = "The serviceUUid to activate",
138                     required = true) @PathParam("serviceUUID") final String serviceUUID,
139             @Parameter(description = "The operational environment on which to activate the service on",
140                     required = true) @PathParam("opEnvId") final String opEnvId,
141             String data) throws IOException {
142
143         init();
144
145         ResponseFormat responseFormat = null;
146         String requestURI = request.getRequestURI();
147         String url = request.getMethod() + " " + requestURI;
148         log.debug("Start handle request of {}", url);
149
150         User modifier = new User();
151
152         try {
153
154             Wrapper<ResponseFormat> responseWrapper = validateRequestHeaders(instanceIdHeader, userId);
155
156             if (responseWrapper.isEmpty()) {
157                 modifier.setUserId(userId);
158                 log.debug("modifier id is {}", userId);
159
160                 ServiceDistributionReqInfo reqMetadata = convertJsonToActivationMetadata(data);
161                 Either<String, ResponseFormat> distResponse = serviceBusinessLogic.activateServiceOnTenantEnvironment(serviceUUID, opEnvId, modifier, reqMetadata);
162
163                 if (distResponse.isRight()) {
164                     log.debug("failed to activate service distribution");
165                     responseFormat = distResponse.right().value();
166                     return buildErrorResponse(responseFormat);
167                 }
168                 String distributionId = distResponse.left().value();
169                 Object result = RepresentationUtils.toRepresentation(new ServiceDistributionRespInfo(distributionId));
170                 responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.ACCEPTED);
171                 return buildOkResponse(responseFormat, result);
172             } else {
173                 log.debug("request instanceId/userId header validation failed");
174                 responseFormat = responseWrapper.getInnerElement();
175                 return buildErrorResponse(responseFormat);
176             }
177         } catch (Exception e) {
178             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Activate Distribution");
179             log.debug("activate distribution failed with exception", e);
180             throw e;
181         } finally {
182             getComponentsUtils().auditExternalActivateService(responseFormat,
183                     new DistributionData(instanceIdHeader, requestURI), requestId, serviceUUID, modifier);
184         }
185     }
186
187     private Wrapper<ResponseFormat> validateRequestHeaders(String instanceIdHeader, String userId) {
188         Wrapper<ResponseFormat> responseWrapper = new Wrapper<>();
189         if (responseWrapper.isEmpty()) {
190             validateXECOMPInstanceIDHeader(instanceIdHeader, responseWrapper);
191         }
192         if (responseWrapper.isEmpty()) {
193             validateHttpCspUserIdHeader(userId, responseWrapper);
194         }
195         return responseWrapper;
196     }
197
198     private ServiceDistributionReqInfo convertJsonToActivationMetadata(String data) {
199         ObjectMapper mapper = new ObjectMapper();
200         try {
201             return mapper.readValue(data, ServiceDistributionReqInfo.class);
202         } catch (IOException e) {
203             log.error("#convertJsonToActivationMetadata - json deserialization failed with error: ", e);
204             return new ServiceDistributionReqInfo(null);
205         }
206     }
207
208     @Override
209     protected void validateHttpCspUserIdHeader(String header, Wrapper<ResponseFormat> responseWrapper) {
210         ResponseFormat responseFormat;
211         if( StringUtils.isEmpty(header)){
212             log.debug("MissingUSER_ID");
213             responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.AUTH_FAILED);
214             responseWrapper.setInnerElement(responseFormat);
215         }
216     }
217 }
218
219
220