From: Dominik Mizyn Date: Mon, 30 Sep 2019 08:42:17 +0000 (+0200) Subject: WidgetMSController and WebAnalyticsExtAppVersionController Up X-Git-Tag: 3.2.0~79^2~5 X-Git-Url: https://gerrit.onap.org/r/gitweb?p=portal.git;a=commitdiff_plain;h=1b2222568e5e8f32fa0f18fc854f9df79e8508f3 WidgetMSController and WebAnalyticsExtAppVersionController Up WidgetMSController, WebAnalyticsExtAppVersionController, WebAnalyticsExtAppController Up Issue-ID: PORTAL-710 Change-Id: Ie1d775e9122aa17d8ee709e793fb6a42d60c91ed Signed-off-by: Dominik Mizyn --- diff --git a/portal-BE/pom.xml b/portal-BE/pom.xml index 9aed3d54..f31b0a65 100644 --- a/portal-BE/pom.xml +++ b/portal-BE/pom.xml @@ -134,6 +134,23 @@ 4.0.1 compile + + io.swagger + swagger-annotations + 2.0.0-rc2 + compile + + + io.swagger + swagger-annotations + 2.0.0-rc2 + compile + + + io.swagger + swagger-annotations + 1.5.20 + portal diff --git a/portal-BE/src/main/java/org/onap/portal/annotation/ApiVersion.java b/portal-BE/src/main/java/org/onap/portal/annotation/ApiVersion.java new file mode 100644 index 00000000..1c4fafc3 --- /dev/null +++ b/portal-BE/src/main/java/org/onap/portal/annotation/ApiVersion.java @@ -0,0 +1,57 @@ +/* + * ============LICENSE_START========================================== + * ONAP Portal + * =================================================================== + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * =================================================================== + * Modifications Copyright (c) 2019 Samsung + * =================================================================== + * + * Unless otherwise specified, all software contained herein is licensed + * under the Apache License, Version 2.0 (the "License"); + * you may not use this software except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Unless otherwise specified, all documentation contained herein is licensed + * under the Creative Commons License, Attribution 4.0 Intl. (the "License"); + * you may not use this documentation except in compliance with the License. + * You may obtain a copy of the License at + * + * https://creativecommons.org/licenses/by/4.0/ + * + * Unless required by applicable law or agreed to in writing, documentation + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================ + * + * + */ + +package org.onap.portal.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ApiVersion { + + String service() default ""; + String max() default ""; + int min() default 0; + String method() default ""; + +} diff --git a/portal-BE/src/main/java/org/onap/portal/controller/WebAnalyticsExtAppController.java b/portal-BE/src/main/java/org/onap/portal/controller/WebAnalyticsExtAppController.java new file mode 100644 index 00000000..849b2620 --- /dev/null +++ b/portal-BE/src/main/java/org/onap/portal/controller/WebAnalyticsExtAppController.java @@ -0,0 +1,256 @@ +/* + * ============LICENSE_START========================================== + * ONAP Portal + * =================================================================== + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * =================================================================== + * Modifications Copyright (c) 2019 Samsung + * =================================================================== + * + * Unless otherwise specified, all software contained herein is licensed + * under the Apache License, Version 2.0 (the "License"); + * you may not use this software except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Unless otherwise specified, all documentation contained herein is licensed + * under the Creative Commons License, Attribution 4.0 Intl. (the "License"); + * you may not use this documentation except in compliance with the License. + * You may obtain a copy of the License at + * + * https://creativecommons.org/licenses/by/4.0/ + * + * Unless required by applicable law or agreed to in writing, documentation + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================ + * + * + */ + +package org.onap.portal.controller; + +import io.swagger.annotations.ApiOperation; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import javax.servlet.http.HttpServletRequest; +import lombok.NoArgsConstructor; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringUtils; +import org.onap.portal.domain.db.fn.FnApp; +import org.onap.portal.domain.dto.ecomp.EcompAuditLog; +import org.onap.portal.domain.dto.transport.Analytics; +import org.onap.portal.logging.aop.EPAuditLog; +import org.onap.portal.logging.aop.EPEELFLoggerAdvice; +import org.onap.portal.logging.logic.EPLogUtil; +import org.onap.portal.service.WidgetMService; +import org.onap.portal.service.fn.old.AppsCacheService; +import org.onap.portal.utils.EPCommonSystemProperties; +import org.onap.portal.utils.EcompPortalUtils; +import org.onap.portal.utils.PortalConstants; +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.portalsdk.core.onboarding.crossapi.PortalAPIResponse; +import org.onap.portalsdk.core.util.SystemProperties; +import org.slf4j.MDC; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.EnableAspectJAutoProxy; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.util.concurrent.FailureCallback; +import org.springframework.util.concurrent.ListenableFuture; +import org.springframework.util.concurrent.SuccessCallback; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.AsyncRestTemplate; + +@RestController +@RequestMapping(PortalConstants.REST_AUX_API) +@Configuration +@EnableAspectJAutoProxy +@EPAuditLog +@NoArgsConstructor +public class WebAnalyticsExtAppController { + + private static final String MACHINE_LEARNING_SERVICE_CTX = "/ml_api"; + private static final String REGISTER_ACTION = MACHINE_LEARNING_SERVICE_CTX + "/" + "registerAction"; + private static final String CONSUL_ML_SERVICE_ID = "machine-learning"; + private static final String APP_KEY = "uebkey"; + private final EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(WebAnalyticsExtAppController.class); + private final AsyncRestTemplate restTemplate = new AsyncRestTemplate(); + private final SuccessCallback> successCallback = arg -> logger.info(EELFLoggerDelegate.debugLogger, arg.getBody()); + private final FailureCallback failureCallback = arg -> logger.error(EELFLoggerDelegate.errorLogger, "storeAuxAnalytics failed", arg); + + private WidgetMService widgetMService; + private AppsCacheService appCacheService; + + @Autowired + public WebAnalyticsExtAppController(final WidgetMService widgetMService, + final AppsCacheService appCacheService) { + this.widgetMService = widgetMService; + this.appCacheService = appCacheService; + } + + /** + * Answers requests from partner applications for a file that is expected to + * contain javascript to support web analytics. + * + * @param request + * HttpServletRequest + * @return String + */ + @ApiOperation(value = "Gets javascript with functions that support gathering and reporting web analytics.", response = String.class) + @RequestMapping(value = { "/analytics" }, method = RequestMethod.GET, produces = "application/javascript") + public String getAnalyticsScript(HttpServletRequest request) { + String responseText = ""; + FnApp app = null; + String version = ""; + try { + app = getApp(request); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, + " Error retrieving Application to capture app name for analytics; Proceeding with empty app name"); + } + if (app != null) { + String restEndPoint = app.getAppRestEndpoint(); + if(restEndPoint.indexOf("/api")!=-1) { + version = restEndPoint.substring(restEndPoint.indexOf("api")); + } + } + String endPoint = "/storeAnalytics"; + if(StringUtils.isNotBlank(version)) { + endPoint = version + "/storeAnalytics"; + } + + final String fileName = "analytics.txt"; + try (InputStream analyticsFileStream = this.getClass().getClassLoader().getResourceAsStream(fileName)) { + responseText = IOUtils.toString(Objects.requireNonNull(analyticsFileStream), StandardCharsets.UTF_8.name()); + } catch (IOException e) { + logger.error(EELFLoggerDelegate.errorLogger, "Error reading contents of the file " + fileName, e); + } + + String feURLContext = SystemProperties.getProperty("frontend_url"); + String feURL = feURLContext.substring(0, feURLContext.lastIndexOf('/')); + responseText = responseText.replace("PORTAL_ENV_URL", feURL); + responseText = responseText.replace("$END_POINT", endPoint); + return responseText; + } + + /** + * Accepts data from partner applications with web analytics data. + * + * @param request + * HttpServletRequest + * @param analyticsMap + * Analytics + * @return PortalAPIResponse + */ + @RequestMapping(value = { "/storeAnalytics" }, method = RequestMethod.POST, produces = "application/json") + @ResponseBody + @ApiOperation(value = "Accepts data from partner applications with web analytics data.", response = PortalAPIResponse.class) + public PortalAPIResponse storeAnalyticsScript(HttpServletRequest request, @RequestBody Analytics analyticsMap) { + try { + MDC.put(EPCommonSystemProperties.AUDITLOG_BEGIN_TIMESTAMP, EPEELFLoggerAdvice.getCurrentDateTimeUTC()); + String appName = ""; + try { + appName = getAppName(request, appName); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, + " Error retrieving Application to capture app name for analytics; Proceeding with empty app name"); + } + + try { + storeAuxAnalytics(analyticsMap, appName); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, + " Error retrieving Application to capture app name for analytics; Proceeding with empty app name"); + } + + MDC.put(EPCommonSystemProperties.AUDITLOG_END_TIMESTAMP, EPEELFLoggerAdvice.getCurrentDateTimeUTC()); + + EcompPortalUtils.calculateDateTimeDifferenceForLog( + MDC.get(EPCommonSystemProperties.AUDITLOG_BEGIN_TIMESTAMP), + MDC.get(EPCommonSystemProperties.AUDITLOG_END_TIMESTAMP)); + logger.info(EELFLoggerDelegate.auditLogger, + EPLogUtil.formatStoreAnalyticsAuditLogMessage(analyticsMap.getUserid(), appName, + "WebAnalyticsExtAppController.postWebAnalyticsData", + EcompAuditLog.CD_ACTIVITY_STORE_ANALYTICS, analyticsMap.getAction(), analyticsMap.getPage(), + analyticsMap.getFunction(), analyticsMap.getType())); + + MDC.remove(EPCommonSystemProperties.AUDITLOG_BEGIN_TIMESTAMP); + MDC.remove(EPCommonSystemProperties.AUDITLOG_END_TIMESTAMP); + MDC.remove(SystemProperties.MDC_TIMER); + + return new PortalAPIResponse(true, "success"); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, "storeAnalytics failed", e); + return new PortalAPIResponse(true, "error"); + } + } + + private String getAppName(HttpServletRequest request, String appName) { + + FnApp appRecord = getApp(request); + if (appRecord != null) { + appName = appRecord.getAppName(); + } + return appName; + } + + private FnApp getApp(HttpServletRequest request) { + String appKeyValue = request.getHeader(APP_KEY); + FnApp appRecord = null; + if (appKeyValue == null || appKeyValue.equals("")) { + logger.error(EELFLoggerDelegate.errorLogger, " App Key unavailable; Proceeding with null app name"); + } else { + appRecord = appCacheService.getAppFromUeb(appKeyValue); + } + return appRecord; + } + + private void storeAuxAnalytics(Analytics analyticsMap, String appName) { + logger.info(EELFLoggerDelegate.debugLogger, + " Registering an action for recommendation: AppName/Function/UserId " + appName + "/" + + analyticsMap.getFunction() + "/" + analyticsMap.getUserid()); + + Map requestMapping = new HashMap<>(); + requestMapping.put("id", analyticsMap.getUserid()); + requestMapping.put("action", appName + "|" + analyticsMap.getFunction()); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + + // set your entity to send + HttpEntity> entity = new HttpEntity<>(requestMapping, headers); + + // send it! + ListenableFuture> out = restTemplate.exchange( + EcompPortalUtils.widgetMsProtocol() + "://" + + widgetMService.getServiceLocation(CONSUL_ML_SERVICE_ID, + SystemProperties.getProperty("microservices.m-learn.local.port")) + + REGISTER_ACTION, + HttpMethod.POST, entity, String.class); + out.addCallback(successCallback, failureCallback); + } + +} diff --git a/portal-BE/src/main/java/org/onap/portal/controller/WebAnalyticsExtAppVersionController.java b/portal-BE/src/main/java/org/onap/portal/controller/WebAnalyticsExtAppVersionController.java new file mode 100644 index 00000000..87be5439 --- /dev/null +++ b/portal-BE/src/main/java/org/onap/portal/controller/WebAnalyticsExtAppVersionController.java @@ -0,0 +1,77 @@ +/* + * ============LICENSE_START========================================== + * ONAP Portal + * =================================================================== + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * =================================================================== + * Modifications Copyright (c) 2019 Samsung + * =================================================================== + * + * Unless otherwise specified, all software contained herein is licensed + * under the Apache License, Version 2.0 (the "License"); + * you may not use this software except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Unless otherwise specified, all documentation contained herein is licensed + * under the Creative Commons License, Attribution 4.0 Intl. (the "License"); + * you may not use this documentation except in compliance with the License. + * You may obtain a copy of the License at + * + * https://creativecommons.org/licenses/by/4.0/ + * + * Unless required by applicable law or agreed to in writing, documentation + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================ + * + * + */ + +package org.onap.portal.controller; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.onap.portal.annotation.ApiVersion; +import org.onap.portal.domain.dto.transport.Analytics; +import org.onap.portal.logging.aop.EPAuditLog; +import org.onap.portalsdk.core.onboarding.crossapi.PortalAPIResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.EnableAspectJAutoProxy; + +@Configuration +@EnableAspectJAutoProxy +@EPAuditLog +@ApiVersion +public class WebAnalyticsExtAppVersionController { + + private final WebAnalyticsExtAppController webAnalyticsExtAppController; + + @Autowired + public WebAnalyticsExtAppVersionController(final + WebAnalyticsExtAppController webAnalyticsExtAppController) { + this.webAnalyticsExtAppController = webAnalyticsExtAppController; + } + + @ApiVersion(max = "v3", service = "/v3/analytics", min = 0,method = "GET") + public String getAnalyticsScript(HttpServletRequest request, HttpServletResponse response) throws Exception { + return webAnalyticsExtAppController.getAnalyticsScript(request); + } + + @ApiVersion(max = "v3", service = "/v3/storeAnalytics", min = 0,method = "POST") + public PortalAPIResponse storeAnalyticsScript(HttpServletRequest request, HttpServletResponse response, Analytics analyticsMap) throws Exception { + return webAnalyticsExtAppController.storeAnalyticsScript(request, analyticsMap); + } + +} diff --git a/portal-BE/src/main/java/org/onap/portal/controller/WidgetMSController.java b/portal-BE/src/main/java/org/onap/portal/controller/WidgetMSController.java new file mode 100644 index 00000000..b9434820 --- /dev/null +++ b/portal-BE/src/main/java/org/onap/portal/controller/WidgetMSController.java @@ -0,0 +1,84 @@ +/* + * ============LICENSE_START========================================== + * ONAP Portal + * =================================================================== + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * =================================================================== + * Modifications Copyright (c) 2019 Samsung + * =================================================================== + * + * Unless otherwise specified, all software contained herein is licensed + * under the Apache License, Version 2.0 (the "License"); + * you may not use this software except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Unless otherwise specified, all documentation contained herein is licensed + * under the Creative Commons License, Attribution 4.0 Intl. (the "License"); + * you may not use this documentation except in compliance with the License. + * You may obtain a copy of the License at + * + * https://creativecommons.org/licenses/by/4.0/ + * + * Unless required by applicable law or agreed to in writing, documentation + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================ + * + * + */ + +package org.onap.portal.controller; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.onap.portal.domain.dto.ecomp.PortalRestResponse; +import org.onap.portal.domain.dto.ecomp.PortalRestStatusEnum; +import org.onap.portal.service.WidgetMService; +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/portalApi/consul") +public class WidgetMSController { + private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(WidgetMSController.class); + + private final WidgetMService widgetMService; + + @Autowired + public WidgetMSController(final WidgetMService widgetMService) { + this.widgetMService = widgetMService; + } + + // Get location of a healthy node running our service + @RequestMapping(value = { "/service/{service}" }, method = RequestMethod.GET, produces = "application/json") + public PortalRestResponse getServiceLocation(HttpServletRequest request, HttpServletResponse response, + @PathVariable("service") String service) { + + try { + return new PortalRestResponse<>(PortalRestStatusEnum.OK, "Success!", + widgetMService.getServiceLocation(service, null)); + } + catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, "Couldn't get the service location"); + return new PortalRestResponse<>(PortalRestStatusEnum.ERROR, "Error!", + "Couldn't get the service location"); + + } + } + +}