UserRolesController methods up
[portal.git] / portal-BE / src / main / java / org / onap / portal / service / ApplicationsRestClientService.java
1 /*
2  * ============LICENSE_START==========================================
3  * ONAP Portal
4  * ===================================================================
5  * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
6  * ===================================================================
7  * Modifications Copyright (c) 2019 Samsung
8  * ===================================================================
9  *
10  * Unless otherwise specified, all software contained herein is licensed
11  * under the Apache License, Version 2.0 (the "License");
12  * you may not use this software except in compliance with the License.
13  * You may obtain a copy of the License at
14  *
15  *             http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  *
23  * Unless otherwise specified, all documentation contained herein is licensed
24  * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
25  * you may not use this documentation except in compliance with the License.
26  * You may obtain a copy of the License at
27  *
28  *             https://creativecommons.org/licenses/by/4.0/
29  *
30  * Unless required by applicable law or agreed to in writing, documentation
31  * distributed under the License is distributed on an "AS IS" BASIS,
32  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
33  * See the License for the specific language governing permissions and
34  * limitations under the License.
35  *
36  * ============LICENSE_END============================================
37  *
38  *
39  */
40
41 package org.onap.portal.service;
42
43 import static com.att.eelf.configuration.Configuration.MDC_KEY_REQUEST_ID;
44
45 import com.fasterxml.jackson.databind.ObjectMapper;
46 import com.google.gson.Gson;
47 import java.net.MalformedURLException;
48 import java.net.URL;
49 import java.util.Base64;
50 import javax.servlet.http.HttpServletResponse;
51 import javax.ws.rs.core.MediaType;
52 import javax.ws.rs.core.Response;
53 import org.apache.commons.lang.StringUtils;
54 import org.apache.cxf.jaxrs.client.WebClient;
55 import org.apache.cxf.transport.http.HTTPException;
56 import org.onap.portal.domain.db.fn.FnApp;
57 import org.onap.portal.logging.aop.EPMetricsLog;
58 import org.onap.portal.logging.format.EPAppMessagesEnum;
59 import org.onap.portal.logging.logic.EPLogUtil;
60 import org.onap.portal.utils.EPCommonSystemProperties;
61 import org.onap.portal.utils.EcompPortalUtils;
62 import org.onap.portal.utils.SystemType;
63 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
64 import org.onap.portalsdk.core.onboarding.exception.CipherUtilException;
65 import org.onap.portalsdk.core.onboarding.util.CipherUtil;
66 import org.onap.portalsdk.core.util.SystemProperties;
67 import org.slf4j.MDC;
68 import org.springframework.beans.factory.annotation.Autowired;
69 import org.springframework.stereotype.Service;
70
71 @Service
72 public class ApplicationsRestClientService {
73
74   private static final String PASSWORD_HEADER = "password";
75   private static final String APP_USERNAME_HEADER = "username";
76   private static final String BASIC_AUTHENTICATION_HEADER = "Authorization";
77
78   private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ApplicationsRestClientService.class);
79
80   private Gson gson = null;
81
82   private final ObjectMapper mapper = new ObjectMapper();
83
84   private final AppsCacheService appsCacheService;
85
86   @Autowired
87   public ApplicationsRestClientService(AppsCacheService appsCacheService) {
88     this.appsCacheService = appsCacheService;
89   }
90
91   private static boolean isHttpSuccess(int status) {
92     return status / 100 == 2;
93   }
94
95   @EPMetricsLog
96   private void verifyResponse(Response response, String restPath) throws HTTPException {
97     int status = response.getStatus();
98     logger.debug(EELFLoggerDelegate.debugLogger, "http response status=" + status);
99     MDC.put(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE, Integer.toString(status));
100     if (!isHttpSuccess(status)) {
101       String errMsg =
102           "Failed. Status=" + status + restPath + "; [" + response.getStatusInfo()
103               .getReasonPhrase()
104               + "]";
105       URL url = null;
106       try {
107         // must not be null to avoid NPE in HTTPException constructor
108         url = new URL("http://null");
109         if (response.getLocation() != null) {
110           url = response.getLocation().toURL();
111         }
112       } catch (MalformedURLException e) {
113         // never mind. it is only for the debug message.
114         logger.warn(EELFLoggerDelegate.errorLogger, "Failed to build URL", e);
115       }
116       logger.error(EELFLoggerDelegate.errorLogger,
117           "http response failed. " + restPath + errMsg + "; url=" + url);
118       EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeIncorrectHttpStatusError);
119       throw new HTTPException(status, errMsg, url);
120     }
121   }
122
123   private WebClient createClientForApp(long appId, String restPath) {
124     return createClientFor(appId, restPath, SystemType.APPLICATION);
125   }
126
127   private static WebClient createClientForPath(String baseUri, String path) {
128     logger.info(EELFLoggerDelegate.debugLogger, "Creating web client for " + baseUri + "   +   " + path);
129     WebClient client = WebClient.create(baseUri);
130     client.type(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON);
131     client.path(path);
132     return client;
133   }
134
135   //TODO Need to implement the mylogins once the endpoint is confirmed
136   @EPMetricsLog
137   private WebClient createClientFor(long appSystemId, String restPath, SystemType type) {
138     logger.debug(EELFLoggerDelegate.debugLogger,
139         "creating client for appId=" + appSystemId + "; restPath=" + restPath);
140     FnApp externalApp = null;
141
142     if (type == SystemType.APPLICATION) {
143       externalApp = appsCacheService.getApp(appSystemId);
144     }
145
146     if (externalApp != null) {
147       String appBaseUri = (type == SystemType.APPLICATION) ? externalApp.getAppRestEndpoint() : "";
148       String username = (type == SystemType.APPLICATION) ? externalApp.getAppUsername() : "";
149       String encriptedPwd = (type == SystemType.APPLICATION) ? externalApp.getAppPassword() : "";
150
151       String appName = (type == SystemType.APPLICATION) ? externalApp.getAppName() : "";
152       String decreptedAppPwd = StringUtils.EMPTY;
153
154       // Set local context
155       MDC.put(EPCommonSystemProperties.PROTOCOL, EPCommonSystemProperties.HTTP);
156       if (appBaseUri != null && appBaseUri.contains("https")) {
157         MDC.put(EPCommonSystemProperties.PROTOCOL, EPCommonSystemProperties.HTTPS);
158       }
159       MDC.put(EPCommonSystemProperties.FULL_URL, appBaseUri + restPath);
160       MDC.put(EPCommonSystemProperties.TARGET_ENTITY, appName);
161       MDC.put(EPCommonSystemProperties.TARGET_SERVICE_NAME, restPath);
162
163       try {
164         decreptedAppPwd = CipherUtil.decryptPKC(encriptedPwd,
165             SystemProperties.getProperty(SystemProperties.Decryption_Key));
166       } catch (Exception e) {
167         logger.error(EELFLoggerDelegate.errorLogger, "createClientFor failed to decrypt", e);
168       }
169       WebClient client = createClientForPath(appBaseUri, restPath);
170
171       if (externalApp.getAppPassword().isEmpty() || externalApp.getAppPassword() == null) {
172         logger.debug(EELFLoggerDelegate.debugLogger,
173             "Entering in the externalApp get app password contains null : {}");
174
175         externalApp = appsCacheService.getApp(1L);
176         logger.debug(EELFLoggerDelegate.debugLogger, "external App Information : {}", externalApp);
177
178         String mechidUsername = externalApp.getAppUsername();
179         logger.debug(EELFLoggerDelegate.debugLogger, "external App mechidUsername Information : {}",
180             mechidUsername);
181
182         String password = externalApp.getAppPassword();
183         String decreptedexternalAppPwd = StringUtils.EMPTY;
184         try {
185           decreptedexternalAppPwd = CipherUtil.decryptPKC(password,
186               SystemProperties.getProperty(SystemProperties.Decryption_Key));
187         } catch (CipherUtilException e) {
188           logger.error(EELFLoggerDelegate.errorLogger,
189               "failed to decreptedexternalAppPwd when external app pwd is null", e);
190         }
191
192         username = mechidUsername;
193         decreptedAppPwd = decreptedexternalAppPwd;
194
195       } else {
196         logger.debug(EELFLoggerDelegate.debugLogger,
197             "Entering in the externalApp get app password  is not null : {}");
198
199         // support basic authentication for some partners
200         String encoding = Base64.getEncoder()
201             .encodeToString((username + ":" + decreptedAppPwd).getBytes());
202         String encodingStr = "Basic " + encoding;
203         client.header(BASIC_AUTHENTICATION_HEADER, encodingStr);
204       }
205
206       // But still keep code downward compatible for non compliant apps
207       client.header(APP_USERNAME_HEADER, username);
208       client.header(PASSWORD_HEADER, decreptedAppPwd);
209
210       String encoding = Base64.getEncoder()
211           .encodeToString((username + ":" + decreptedAppPwd).getBytes());
212       String encodingStr = "Basic " + encoding;
213       client.header(BASIC_AUTHENTICATION_HEADER, encodingStr);
214       client.header(SystemProperties.ECOMP_REQUEST_ID, MDC.get(MDC_KEY_REQUEST_ID));
215       client.header(SystemProperties.USERAGENT_NAME, EPCommonSystemProperties.ECOMP_PORTAL_BE);
216       logger.debug(EELFLoggerDelegate.debugLogger,
217           String.format(
218               "check the partner application URL App %d found, baseUri=[%s], Headers: [%s=%s]",
219               appSystemId, appBaseUri,
220               APP_USERNAME_HEADER, username));
221       return client;
222     }
223     return null;
224   }
225
226   public <T> T post(Class<T> clazz, long appId, Object payload, String restPath, SystemType type)
227       throws HTTPException {
228     WebClient client;
229     Response response = null;
230     T t = null;
231
232     client = createClientFor(appId, restPath, type);
233     EcompPortalUtils.logAndSerializeObject(logger, restPath, "POST request =", payload);
234
235     try {
236       if (client != null) {
237         response = client.post(payload);
238       } else {
239         logger.error(EELFLoggerDelegate.errorLogger,
240             "Unable to create the Webclient to make the '" + restPath + "' API call.");
241       }
242     } catch (Exception e) {
243       MDC.put(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE,
244           Integer.toString(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
245       EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeRestApiGeneralError, e);
246       logger.error(EELFLoggerDelegate.errorLogger,
247           "Exception occurred while making the POST REST API call", e);
248     }
249
250     if (response != null) {
251       verifyResponse(response, restPath);
252       if (clazz != null) {
253         String str = response.readEntity(String.class);
254         EcompPortalUtils.logAndSerializeObject(logger, restPath, "POST result =", str);
255         try {
256           t = gson.fromJson(str, clazz);
257         } catch (Exception e) {
258           EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);
259         }
260       }
261     }
262     return t;
263   }
264
265   public <T> T post(Class<T> clazz, long appId, Object payload, String restPath) throws HTTPException {
266     return post(clazz, appId, payload, restPath, SystemType.APPLICATION);
267   }
268
269   public <T> T put(Class<T> clazz, long appId, Object payload, String restPath) throws HTTPException {
270     WebClient client;
271     Response response = null;
272     T t = null;
273
274     logger.debug(EELFLoggerDelegate.debugLogger,
275         "Entering to createClientForApp method for payload: {} and restPath: {} and appId: {}",
276         payload.toString(), restPath, appId);
277
278     client = createClientForApp(appId, restPath);
279     EcompPortalUtils.logAndSerializeObject(logger, restPath, "PUT request =", payload);
280
281     logger.debug(EELFLoggerDelegate.debugLogger,
282         "Finished createClientForApp method for payload: {} and restPath: {} and appId: {}",
283         payload.toString(), restPath, appId);
284
285     try {
286       if (client != null) {
287         logger.debug(EELFLoggerDelegate.debugLogger,
288             "Entering to PUT for payload: {} and restPath: {} and appId: {}",
289             payload.toString(), restPath, appId);
290
291         response = client.put(payload);
292
293         logger.debug(EELFLoggerDelegate.debugLogger,
294             "Finished to PUT for payload: {} and restPath: {} and appId: {}",
295             payload.toString(), restPath, appId);
296
297       } else {
298         logger.error(EELFLoggerDelegate.errorLogger,
299             "Unable to create the Webclient to make the '" + restPath + "' API call.");
300       }
301     } catch (Exception e) {
302       MDC.put(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE,
303           Integer.toString(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
304       EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeRestApiGeneralError, e);
305       logger.error(EELFLoggerDelegate.errorLogger,
306           "Exception occurred while making the PUT REST API call", e);
307     }
308
309     if (response != null) {
310       verifyResponse(response, restPath);
311       String str = response.readEntity(String.class);
312       EcompPortalUtils.logAndSerializeObject(logger, restPath, "PUT result =", str);
313       try {
314         t = gson.fromJson(str, clazz);
315       } catch (Exception e) {
316         EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);
317       }
318     }
319     return t;
320   }
321
322   private Response getResponse(long appId, String restPath) {
323     WebClient webClient;
324     Response response = null;
325
326     webClient = createClientForApp(appId, restPath);
327     EcompPortalUtils.logAndSerializeObject(logger, restPath, "GET request =", "no-payload");
328
329     try {
330       if (webClient != null) {
331         response = webClient.get();
332       } else {
333         logger.error(EELFLoggerDelegate.errorLogger,
334             "Unable to create the Webclient to make the '" + restPath + "' API call.");
335       }
336     } catch (Exception e) {
337       MDC.put(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE,
338           Integer.toString(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
339       EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeRestApiGeneralError, e);
340       logger.error(EELFLoggerDelegate.errorLogger,
341           "Exception occurred while making the GET REST API call", e);
342     }
343     return response;
344   }
345
346   public <T> T get(Class<T> clazz, long appId, String restPath) throws HTTPException {
347     T t = null;
348     Response response = getResponse(appId, restPath);
349
350     if (response != null) {
351       //verifyResponse(response);
352       verifyResponse(response, restPath);
353                         /* It is not recommendable to use the implementation class org.apache.cxf.jaxrs.impl.ResponseImpl in the code,
354                         but had to force this in-order to prevent conflict with the ResponseImpl class of Jersey Client which
355                         doesn't work as expected. Created Portal-253 for tracking */
356       String str = response.readEntity(String.class);
357
358       EcompPortalUtils.logAndSerializeObject(logger, restPath, "GET result =", str);
359       try {
360         t = gson.fromJson(str, clazz);
361       } catch (Exception e) {
362         EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);
363       }
364     }
365
366     return t;
367   }
368
369   public String getIncomingJsonString(final Long appId, final String restPath) throws HTTPException {
370     Response response = getResponse(appId, restPath);
371
372     if (response != null) {
373       //verifyResponse(response);
374       verifyResponse(response, restPath);
375                         /* It is not recommendable to use the implementation class org.apache.cxf.jaxrs.impl.ResponseImpl in the code,
376                         but had to force this in-order to prevent conflict with the ResponseImpl class of Jersey Client which
377                         doesn't work as expected. Created Portal-253 for tracking  */
378       return (response).readEntity(String.class);
379     }
380
381     return "";
382   }
383
384   public <T> T get(Class<T> clazz, Long appId, String restPath, boolean useJacksonMapper) throws HTTPException {
385
386     if (!useJacksonMapper) {
387       return get(clazz, appId, restPath);
388     }
389
390     T t = null;
391     Response response = getResponse(appId, restPath);
392
393     if (response != null) {
394       //verifyResponse(response);
395       verifyResponse(response, restPath);
396       String str = (response).readEntity(String.class);
397       EcompPortalUtils.logAndSerializeObject(logger, restPath, "GET result =", str);
398
399       try {
400         t = mapper.readValue(str, clazz);
401       } catch (Exception e) {
402         e.printStackTrace();
403         EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);
404       }
405     }
406
407     return t;
408   }
409
410 }