JUnits for coverage
[portal.git] / ecomp-portal-BE-common / src / main / java / org / onap / portalapp / portal / utils / EcompPortalUtils.java
1 /*-
2  * ============LICENSE_START==========================================
3  * ONAP Portal
4  * ===================================================================
5  * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * ===================================================================
7  *
8  * Unless otherwise specified, all software contained herein is licensed
9  * under the Apache License, Version 2.0 (the "License");
10  * you may not use this software except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *             http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  * Unless otherwise specified, all documentation contained herein is licensed
22  * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
23  * you may not use this documentation except in compliance with the License.
24  * You may obtain a copy of the License at
25  *
26  *             https://creativecommons.org/licenses/by/4.0/
27  *
28  * Unless required by applicable law or agreed to in writing, documentation
29  * distributed under the License is distributed on an "AS IS" BASIS,
30  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
31  * See the License for the specific language governing permissions and
32  * limitations under the License.
33  *
34  * ============LICENSE_END============================================
35  *
36  * 
37  */
38 package org.onap.portalapp.portal.utils;
39
40 import java.io.IOException;
41 import java.net.InetAddress;
42 import java.net.UnknownHostException;
43 import java.nio.charset.Charset;
44 import java.text.SimpleDateFormat;
45 import java.util.ArrayList;
46 import java.util.Base64;
47 import java.util.Date;
48 import java.util.List;
49
50 import javax.servlet.http.HttpServletResponse;
51 import javax.xml.bind.DatatypeConverter;
52
53 import org.apache.commons.lang.StringUtils;
54 import org.hibernate.Session;
55 import org.hibernate.Transaction;
56 import org.onap.portalapp.portal.domain.EPUser;
57 import org.onap.portalapp.portal.logging.format.EPAppMessagesEnum;
58 import org.onap.portalapp.portal.logging.logic.EPLogUtil;
59 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
60 import org.onap.portalsdk.core.onboarding.util.CipherUtil;
61 import org.onap.portalsdk.core.onboarding.util.PortalApiConstants;
62 import org.onap.portalsdk.core.util.SystemProperties;
63 import org.slf4j.MDC;
64 import org.springframework.http.HttpHeaders;
65 import org.springframework.http.MediaType;
66
67 import com.fasterxml.jackson.core.JsonProcessingException;
68 import com.fasterxml.jackson.databind.ObjectMapper;
69
70 public class EcompPortalUtils {
71
72         private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(EcompPortalUtils.class);
73         
74         private static final String FUNCTION_PIPE = "|";
75         
76         // TODO: GLOBAL_LOGIN_URL is the same as in SessionTimeoutInterceptor.
77         // It should be defined in SystemProperties.
78         private static final String GLOBAL_LOGIN_URL = "global-login-url";
79         
80         // It is a regular expression used for while creating a External Central Auth Role 
81         public static final String EXTERNAL_CENTRAL_AUTH_ROLE_HANDLE_SPECIAL_CHARACTERS = "([^A-Z^a-z^0-9^\\.^%^(^)^=^:])";
82         
83         /**
84          * @param orgUserId
85          *            User ID to validate
86          * @return true if orgUserId is not empty and contains only alphanumeric, false
87          *         otherwise
88          */
89         public static boolean legitimateUserId(String orgUserId) {
90                 return orgUserId.matches("^[a-zA-Z0-9]+$");
91         }
92
93         /**
94          * Splits the string into a list of tokens using the specified regular
95          * expression
96          * 
97          * @param source
98          *            String to split
99          * @param regex
100          *            tokens
101          * @return List of tokens split from the source
102          */
103         public static List<String> parsingByRegularExpression(String source, String regex) {
104                 List<String> tokens = new ArrayList<String>();
105                 if (source != null && source.length() > 0) {
106                         String[] parsed = source.split(regex);
107                         for (String token : parsed) {
108                                 if (token.length() > 0) {
109                                         tokens.add(token);
110                                 }
111                         }
112                 }
113                 return tokens;
114         }
115
116         /**
117          * Builds a JSON object with error code and message information.
118          * 
119          * @param errorCode
120          *            error code
121          * @param errorMessage
122          *            message
123          * @return JSON object as a String
124          */
125         public static String jsonErrorMessageResponse(int errorCode, String errorMessage) {
126                 return "{\"error\":{\"code\":" + errorCode + "," + "\"message\":\"" + errorMessage + "\"}}";
127         }
128
129         /**
130          * Builds a JSON object with the specified message
131          * 
132          * @param message
133          *            Message to embed
134          * @return JSON object as a String
135          */
136         public static String jsonMessageResponse(String message) {
137                 return String.format("{\"message\":\"%s\"}", message);
138         }
139
140         /**
141          * Serializes the specified object as JSON and writes the result to the debug
142          * log. If serialization fails, logs a message to the error logger.
143          * 
144          * @param logger
145          *            Logger for the class where the object was built; the logger
146          *            carries the class name.
147          * @param source
148          *            First portion of the log message
149          * @param msg
150          *            Second portion of the log message
151          * @param obj
152          *            Object to serialize as JSON
153          */
154         public static void logAndSerializeObject(EELFLoggerDelegate logger, String source, String msg, Object obj) {
155                 try {
156                         String objectAsJson = new ObjectMapper().writeValueAsString(obj);
157                         logger.debug(EELFLoggerDelegate.debugLogger,
158                                         String.format("source= [%s]; %s [%s];", source, msg, objectAsJson));
159                 } catch (JsonProcessingException e) {
160                         logger.warn(EELFLoggerDelegate.errorLogger, "logAndSerializedObject failed to serialize", e);
161                         EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);
162                 } catch (Exception e) {
163                         logger.error(EELFLoggerDelegate.errorLogger, "logAndSerializedObject failed", e);
164                         EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);
165                 }
166         }
167
168         /**
169          * Serializes the specified object as JSON and writes the result to the debug
170          * log. If serialization fails, logs a message to the error logger.
171          * 
172          * @param source
173          *            First portion of the log message
174          * @param msg
175          *            Second portion of the log message
176          * @param obj
177          *            Object to serialize as JSON
178          */
179         public static void logAndSerializeObject(String source, String msg, Object obj) {
180                 logAndSerializeObject(logger, source, msg, obj);
181         }
182
183         public static void rollbackTransaction(Transaction transaction, String errorMessage) {
184                 logger.error(EELFLoggerDelegate.errorLogger, errorMessage);
185                 try {
186                         if (transaction != null) {
187                                 transaction.rollback();
188                         }
189                 } catch (Exception e) {
190                         EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeExecuteRollbackError, e);
191                         logger.error(EELFLoggerDelegate.errorLogger, "Exception occurred while performing a rollback transaction",
192                                         e);
193                 }
194         }
195
196         public static void closeLocalSession(Session localSession, String errorMessage) {
197                 logger.error(EELFLoggerDelegate.errorLogger, errorMessage);
198                 try {
199                         if (localSession != null) {
200                                 localSession.close();
201                         }
202                 } catch (Exception e) {
203                         EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeDaoCloseSessionError, e);
204                         logger.error(EELFLoggerDelegate.errorLogger, errorMessage + ", closeLocalSession exception", e);
205                 }
206         }
207
208         /**
209          * Set response status to Unauthorized if user == null and to Forbidden in all
210          * (!) other cases. Logging is not performed if invocator == null
211          * 
212          * @param user
213          *            User object
214          * @param response
215          *            HttpServletResponse
216          * @param invocator
217          *            may be null
218          */
219         public static void setBadPermissions(EPUser user, HttpServletResponse response, String invocator) {
220                 if (user == null) {
221                         String loginUrl = SystemProperties.getProperty(EPCommonSystemProperties.LOGIN_URL_NO_RET_VAL);
222                         response.setHeader(GLOBAL_LOGIN_URL, loginUrl);
223                         response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
224                         MDC.put(EPCommonSystemProperties.RESPONSE_CODE, Integer.toString(HttpServletResponse.SC_UNAUTHORIZED));
225                 } else {
226                         response.setStatus(HttpServletResponse.SC_FORBIDDEN);
227                         MDC.put(EPCommonSystemProperties.RESPONSE_CODE, Integer.toString(HttpServletResponse.SC_FORBIDDEN));
228                 }
229                 if (invocator != null) {
230                         logger.warn(EELFLoggerDelegate.errorLogger,
231                                         invocator + ", permissions problem, response status = " + response.getStatus());
232                 }
233         }
234
235         public static int getExternalAppResponseCode() {
236                 String responseCode = MDC.get(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE);
237                 int responseCodeInt = 0;
238                 try {
239                         if (responseCode != null && responseCode != "") {
240                                 responseCodeInt = Integer.valueOf(responseCode);
241                         }
242                 } catch (Exception e) {
243                         logger.error(EELFLoggerDelegate.errorLogger, "getExternalAppResponseCode failed", e);
244                 }
245                 return responseCodeInt;
246         }
247
248         // This method might be just for testing purposes.
249         public static void setExternalAppResponseCode(int responseCode) {
250                 try {
251                         String code = String.valueOf(responseCode);
252                         MDC.put(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE,code );
253                         code=StringUtils.EMPTY;
254                 } catch (Exception e) {
255                         logger.error(EELFLoggerDelegate.errorLogger, "setExternalAppResponseCode failed", e);
256                 }
257         }
258
259         public static String getHTTPStatusString(int httpStatusCode) {
260                 String httpStatusString = "unknown_error";
261                 try {
262                         httpStatusString = org.springframework.http.HttpStatus.valueOf(httpStatusCode).name();
263                         if (httpStatusString != null) {
264                                 httpStatusString = httpStatusString.toLowerCase();
265                         }
266                 } catch (Exception e) {
267                         logger.error(EELFLoggerDelegate.errorLogger, "getHTTPStatusString failed", e);
268                 }
269                 return httpStatusString;
270         }
271
272         public static String getFEErrorString(Boolean internal, int responseCode) {
273                 // Return a String like the following:
274                 // "Internal Onap Error: 500 internal_server_error" or
275                 // "External App Error: 404 not_found"
276                 // TODO: create our own Ecomp error codes, starting with 1000 and up.
277                 String internalExternalString = internal ? "Ecomp Error: " : "App Error: ";
278                 String httpStatusString = "unknown_error";
279                 try {
280                         if (responseCode < 1000) {
281                                 httpStatusString = getHTTPStatusString(responseCode);
282                         }
283                 } catch (Exception e) {
284                         logger.error(EELFLoggerDelegate.errorLogger, "getFEErrorString failed", e);
285                 }
286                 String responseString = internalExternalString + responseCode + " " + httpStatusString;
287                 return responseString;
288         }
289
290         public static boolean isProductionBuild() {
291                 boolean productionBuild = true;
292                 String epVersion = EcompVersion.buildNumber;
293                 if (epVersion != null) {
294                         int buildNum = epVersion.lastIndexOf('.');
295                         if (buildNum > 0) {
296                                 int buildNumber = Integer.parseInt(epVersion.substring(buildNum + 1));
297                                 if (buildNumber < 3000) // Production versions are 3000+, (ie
298                                                                                 // 1.0.3003)
299                                 {
300                                         productionBuild = false;
301                                 }
302                         }
303                 }
304                 return productionBuild;
305         }
306
307         public static String getMyIpAdddress() {
308                 InetAddress ip;
309                 String localIp;
310                 try {
311                         ip = InetAddress.getLocalHost();
312                         localIp = ip.getHostAddress();
313                 } catch (UnknownHostException e) {
314                         localIp = "unknown";
315                         logger.error(EELFLoggerDelegate.errorLogger, "getMyIpAdddress failed ", e);
316                 }
317                 return localIp;
318         }
319
320         public static String getMyHostName() {
321                 InetAddress ip;
322                 String hostName;
323                 try {
324                         ip = InetAddress.getLocalHost();
325                         hostName = ip.getHostName();
326                 } catch (UnknownHostException e) {
327                         hostName = "unknown";
328                         logger.error(EELFLoggerDelegate.errorLogger, "getMyHostName failed", e);
329                 }
330                 return hostName;
331         }
332
333         /**
334          * Returns a default property if the expected one is not available
335          * 
336          * @param property
337          *            Key
338          * @param defaultValue
339          *            default Value
340          * @return Default value if property is not defined or yields the empty string;
341          *         else the property value.
342          */
343         public static String getPropertyOrDefault(String property, String defaultValue) {
344                 if (!SystemProperties.containsProperty(property))
345                         return defaultValue;
346                 String value = SystemProperties.getProperty(property);
347                 if (value == null || "".equals(value))
348                         return defaultValue;
349                 return value;
350         }
351
352         /**
353          * Calculates the time duration of a function call for logging purpose. It
354          * stores the result by using "MDC.put(SystemProperties.MDC_TIMER,
355          * timeDifference);" It is important to call
356          * "MDC.remove(SystemProperties.MDC_TIMER);" after this method call to clean up
357          * the record in MDC
358          *
359          * @param beginDateTime
360          *            the given begin time for the call
361          * @param endDateTime
362          *            the given end time for the call
363          * 
364          */
365         public static void calculateDateTimeDifferenceForLog(String beginDateTime, String endDateTime) {
366                 if (beginDateTime != null && endDateTime != null) {
367                         try {
368                                 SimpleDateFormat ecompLogDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
369
370                                 Date beginDate = ecompLogDateFormat.parse(beginDateTime);
371                                 Date endDate = ecompLogDateFormat.parse(endDateTime);
372                                 String timeDifference = String.format("%d", endDate.getTime() - beginDate.getTime());
373                                 MDC.put(SystemProperties.MDC_TIMER, timeDifference);
374                         } catch (Exception e) {
375                                 logger.error(EELFLoggerDelegate.errorLogger, "calculateDateTimeDifferenceForLog failed", e);
376                         }
377                 }
378         }
379
380         /**
381          * Answers the protocol to use.
382          * 
383          * @return Protocol name from property file; defaults to https.
384          */
385         public static String widgetMsProtocol() {
386                 return getPropertyOrDefault(EPCommonSystemProperties.WIDGET_MS_PROTOCOL, "https");
387         }
388
389         /**
390          * Answers the host to use.
391          * 
392          * @return Host name from property file; defaults to localhost.
393          */
394         public static String localOrDockerHost() {
395                 return getPropertyOrDefault(EPCommonSystemProperties.WIDGET_MS_HOSTNAME, "localhost");
396         }
397
398         /**
399          * It returns headers where username and password of external central auth is
400          * encoded to base64
401          * 
402          * @return header which contains external central auth username and password
403          *         base64 encoded
404          * @throws Exception
405          *             if unable to decrypt the password
406          */
407         public static HttpHeaders base64encodeKeyForAAFBasicAuth() throws Exception {
408                 String userName = "";
409                 String decryptedPass = "";
410                 if (EPCommonSystemProperties.containsProperty(EPCommonSystemProperties.EXTERNAL_CENTRAL_AUTH_USER_NAME)
411                                 && EPCommonSystemProperties.containsProperty(EPCommonSystemProperties.EXTERNAL_CENTRAL_AUTH_PASSWORD)) {
412                         decryptedPass = SystemProperties.getProperty(EPCommonSystemProperties.EXTERNAL_CENTRAL_AUTH_PASSWORD);
413                         userName = SystemProperties.getProperty(EPCommonSystemProperties.EXTERNAL_CENTRAL_AUTH_USER_NAME);
414                 }
415                 String decPass = decrypted(decryptedPass);
416                 String usernamePass = userName + ":" + decPass;
417                 String encToBase64 = String.valueOf((DatatypeConverter.printBase64Binary(usernamePass.getBytes())));
418                 HttpHeaders headers = new HttpHeaders();
419                 headers.add("Authorization", "Basic " + encToBase64);
420                 headers.setContentType(MediaType.APPLICATION_JSON);
421                 return headers;
422         }
423
424         private static String decrypted(String encrypted) throws Exception {
425                 String result = "";
426                 if (encrypted != null && encrypted.length() > 0) {
427                         try {
428                                 result = CipherUtil.decryptPKC(encrypted, SystemProperties.getProperty(SystemProperties.Decryption_Key));
429                         } catch (Exception e) {
430                                 logger.error(EELFLoggerDelegate.errorLogger, "decryptedPassword failed", e);
431                                 throw e;
432                         }
433                 }
434                 return result;
435         }
436
437         public static String truncateString(String originString, int size){
438                 if(originString.length()>=size){
439                         StringBuilder stringBuilder = new StringBuilder();
440                         stringBuilder.append(originString);
441                         stringBuilder.setLength(size);
442                         stringBuilder.append("...");
443                         return stringBuilder.toString();
444                 }
445                 return originString;
446         }
447         
448         /**
449          * 
450          * If function code value has any pipes it does pipe filter and 
451          * returns value.
452          * 
453          * @param functionCode
454          * @return function instance without pipe
455          */
456         public static String getFunctionCode(String functionCode) {
457                 String finalFunctionCodeVal = "";
458                 if (functionCode.contains(FUNCTION_PIPE)) {
459                         int count = StringUtils.countMatches(functionCode, FUNCTION_PIPE);
460                         if (count == 2)
461                                 finalFunctionCodeVal = functionCode.substring(
462                                                 functionCode.indexOf(FUNCTION_PIPE) + 1,
463                                                 functionCode.lastIndexOf(FUNCTION_PIPE));
464                         else
465                                 finalFunctionCodeVal = functionCode
466                                                 .substring(functionCode.lastIndexOf(FUNCTION_PIPE) + 1);
467                 } else{
468                         finalFunctionCodeVal = functionCode;
469                 }
470                 return finalFunctionCodeVal;
471         }
472         
473         /**
474          * 
475          * If function code value has any pipes it does pipe filter and 
476          * returns value.
477          * 
478          * @param functionCode
479          * @return function Type without pipe
480          */
481         public static String getFunctionType(String functionCode) {
482                 String finalFunctionCodeVal = "";
483                 if (functionCode.contains(FUNCTION_PIPE)) {
484                         int count = StringUtils.countMatches(functionCode, FUNCTION_PIPE);
485                         if (count == 2){
486                                 String[] getTypeValue = functionCode.split("\\"+FUNCTION_PIPE);         
487                                 finalFunctionCodeVal = getTypeValue[0];
488                         }
489                 } else{
490                         finalFunctionCodeVal = functionCode;
491                 }
492                 return finalFunctionCodeVal;
493         }
494         
495         /**
496          * 
497          * If function code value has any pipes it does pipe filter and 
498          * returns value.
499          * 
500          * @param functionCode
501          * @return function Action without pipe
502          */
503         public static String getFunctionAction(String functionCode) {
504                 String finalFunctionCodeVal = "";
505                 if (functionCode.contains(FUNCTION_PIPE)) {
506                         int count = StringUtils.countMatches(functionCode, FUNCTION_PIPE);
507                         if (count == 2)
508                                 finalFunctionCodeVal = functionCode.substring(
509                                                 functionCode.lastIndexOf(FUNCTION_PIPE)+1);
510                 } else{
511                         finalFunctionCodeVal = functionCode;
512                 }
513                 return finalFunctionCodeVal;
514         }
515         
516         /**
517          * 
518          * It check whether the external auth namespace is matching with current namespace exists in local DB
519          * 
520          * @param permTypeVal
521          * @param appNamespaceVal
522          * @return true or false
523          */
524         public static boolean checkNameSpaceMatching(String permTypeVal, String appNamespaceVal) {
525                 String[] typeNamespace = permTypeVal.split("\\.");
526                 String[] appNamespace = appNamespaceVal.split("\\.");
527                 boolean isNamespaceMatching = true;
528                 if (appNamespace.length <= typeNamespace.length) {
529                         for (int k = 0; k < appNamespace.length; k++) {
530                                 if (!appNamespace[k].equals(typeNamespace[k]))
531                                         isNamespaceMatching = false;
532                         }
533                 } else {
534                         isNamespaceMatching = false;
535                 }
536                 return isNamespaceMatching;
537         }
538         
539         public static boolean checkIfRemoteCentralAccessAllowed() {
540                 boolean result = false;
541                 String rmtCentralAccess = SystemProperties.getProperty(EPCommonSystemProperties.REMOTE_CENTRALISED_SYSTEM_ACCESS);
542                 if(rmtCentralAccess == null) {
543                 logger.error(EELFLoggerDelegate.errorLogger, "Please check in system.properties whether the property exists or not!");
544                         return false;
545                 }else if(new Boolean(rmtCentralAccess)){
546                 logger.debug(EELFLoggerDelegate.debugLogger, "checkIfRemoteCentralAccessAllowed: {}",rmtCentralAccess);
547                         result = true;
548                 }
549                 return result;
550         }
551         
552         /**
553          * 
554          * It validates whether given string is JSON or not
555          * 
556          * @param jsonInString
557          * @return true or false
558          */
559           public static boolean isJSONValid(String jsonInString ) {
560                     try {
561                        final ObjectMapper mapper = new ObjectMapper();
562                        mapper.readTree(jsonInString);
563                        return true;
564                     } catch (IOException e) {
565                         logger.error(EELFLoggerDelegate.errorLogger, "Failed to parse Json!", e);
566                        return false;
567                     }
568                   }
569           /**
570            * 
571            *  It retrieves account information from input String
572            * 
573            * @param authValue
574            * @return Array of Account information
575            * 
576            */
577           public static String[] getUserNamePassword(String authValue) {
578                         String base64Credentials = authValue.substring("Basic".length()).trim();
579                         String credentials = new String(Base64.getDecoder().decode(base64Credentials), Charset.forName("UTF-8"));
580                         final String[] values = credentials.split(":", 2);
581                         return values;
582                 }
583 }