From 2831bfaf2c1dbe53aa5f40fdb2c9b9bc721b7acd Mon Sep 17 00:00:00 2001 From: Rasika Perera Date: Wed, 3 May 2017 19:59:17 +0530 Subject: [PATCH] #726 : Resolving cannot log into devicemgt app when tenant is not loaded in API Manager --- .../APIManagementProviderService.java | 6 ++ .../APIManagementProviderServiceImpl.java | 41 ++++++------- .../integration/client/store/StoreClient.java | 8 ++- .../jaggeryapps/devicemgt/api/user-api.jag | 21 +++++++ .../devicemgt/app/conf/app-conf.json | 2 +- .../app/layouts/cdmf.layout.loading.hbs | 57 +++++++++++++++++++ .../devicemgt/app/modules/constants.js | 3 + .../devicemgt/app/modules/login.js | 13 +++++ .../devicemgt/app/modules/utility.js | 4 ++ .../pages/cdmf.page.dashboard/dashboard.js | 7 ++- .../pages/cdmf.page.processing/processing.hbs | 57 +++++++++++++++++++ .../pages/cdmf.page.processing/processing.js | 27 +++++++++ .../cdmf.page.processing/processing.json | 5 ++ .../cdmf.page.processing/public/js/script.js | 30 ++++++++++ 14 files changed, 253 insertions(+), 28 deletions(-) create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/layouts/cdmf.layout.loading.hbs create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.processing/processing.hbs create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.processing/processing.js create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.processing/processing.json create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.processing/public/js/script.js diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/APIManagementProviderService.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/APIManagementProviderService.java index 8cad8b016f..611679e512 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/APIManagementProviderService.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/APIManagementProviderService.java @@ -26,6 +26,12 @@ import org.wso2.carbon.apimgt.application.extension.exception.APIManagerExceptio */ public interface APIManagementProviderService { + /** + * Check whether the tier is loaded for the tenant. + * @return + */ + boolean isTierLoaded(); + /** * Generate and retreive application keys. if the application does exist then * create it and subscribe to apis that are grouped with the tags. diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/APIManagementProviderServiceImpl.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/APIManagementProviderServiceImpl.java index b97146a02d..bc92961f64 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/APIManagementProviderServiceImpl.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/APIManagementProviderServiceImpl.java @@ -45,8 +45,22 @@ public class APIManagementProviderServiceImpl implements APIManagementProviderSe private static final String CONTENT_TYPE = "application/json"; private static final int MAX_API_PER_TAG = 200; private static final String APP_TIER_TYPE = "application"; - private static final Map tiersMap = new HashMap<>(); - private static final int MAX_ATTEMPTS = 20; + + public boolean isTierLoaded() { + StoreClient storeClient = APIApplicationManagerExtensionDataHolder.getInstance().getIntegrationClientService() + .getStoreClient(); + String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext() + .getTenantDomain(); + try { + + storeClient.getIndividualTier().tiersTierLevelTierNameGet(ApiApplicationConstants.DEFAULT_TIER, + APP_TIER_TYPE, + tenantDomain, CONTENT_TYPE, null, null); + return true; + } catch (FeignException e) { + return false; + } + } @Override public void removeAPIApplication(String applicationName, String username) throws APIManagerException { @@ -72,31 +86,8 @@ public class APIManagementProviderServiceImpl implements APIManagementProviderSe throws APIManagerException { StoreClient storeClient = APIApplicationManagerExtensionDataHolder.getInstance().getIntegrationClientService() .getStoreClient(); - //This is a fix to avoid race condition and trying to load tenant related tiers before invocation. String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext() .getTenantDomain(); - String tiersLoadedForTenant = tiersMap.get(tenantDomain); - - if (tiersLoadedForTenant == null) { - boolean tierLoaded = false; - int attempts = 0; - do { - try { - storeClient.getIndividualTier() - .tiersTierLevelTierNameGet(ApiApplicationConstants.DEFAULT_TIER, APP_TIER_TYPE, - tenantDomain, CONTENT_TYPE, null, null); - tiersMap.put(tenantDomain, "exist"); - tierLoaded = true; - } catch (FeignException e) { - attempts++; - try { - Thread.sleep(500); - } catch (InterruptedException ex) { - log.warn("Interrupted the waiting for tier availability."); - } - } - } while ((!tierLoaded) && attempts < MAX_ATTEMPTS); - } ApplicationList applicationList = storeClient.getApplications() .applicationsGet("", applicationName, 1, 0, CONTENT_TYPE, null); diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/store/StoreClient.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/store/StoreClient.java index 9c12b0cdaa..19633fa009 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/store/StoreClient.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/store/StoreClient.java @@ -19,7 +19,9 @@ package org.wso2.carbon.apimgt.integration.client.store; import feign.Feign; import feign.Logger; +import feign.Request; import feign.RequestInterceptor; +import feign.Retryer; import feign.gson.GsonDecoder; import feign.gson.GsonEncoder; import feign.slf4j.Slf4jLogger; @@ -28,6 +30,8 @@ import org.wso2.carbon.apimgt.integration.client.configs.APIMConfigReader; import org.wso2.carbon.apimgt.integration.generated.client.store.api.*; import org.wso2.carbon.core.util.Utils; +import java.util.concurrent.TimeUnit; + /** * API Store client, created using swagger gen. */ @@ -62,8 +66,10 @@ public class StoreClient { individualSubscription = builder.target(SubscriptionIndividualApi.class, basePath); subscriptionMultitpleApi = builder.target(SubscriptionMultitpleApi.class, basePath); tags = builder.target(TagCollectionApi.class, basePath); - tiers = builder.target(ThrottlingTierCollectionApi.class, basePath); individualTier = builder.target(ThrottlingTierIndividualApi.class, basePath); + tiers = builder.retryer(new Retryer.Default(100L, TimeUnit.SECONDS.toMillis(1L), 1)) + .options(new Request.Options(10000, 5000)) + .target(ThrottlingTierCollectionApi.class, basePath); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/api/user-api.jag b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/api/user-api.jag index 9d12aa9360..34e4ee14e7 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/api/user-api.jag +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/api/user-api.jag @@ -176,6 +176,27 @@ if (uriMatcher.match("/{context}/api/user/authenticate")) { } } else if (uriMatcher.match("/{context}/api/user/all")) { result = userModule.getUsers(); +} else if (uriMatcher.match("/{context}/api/user/environment-loaded")) { + try { + var carbonUser = session.get(constants.USER_SESSION_KEY); + if (!carbonUser) { + response.sendRedirect("/devicemgt/login?#login-required"); + exit(); + } + utility.startTenantFlow(carbonUser); + var APIManagementProviderService = utility.getAPIManagementProviderService(); + var isLoaded = APIManagementProviderService.isTierLoaded(); + result = {"isLoaded": isLoaded}; + if (isLoaded) { + var samlToken = session.get(constants.SAML_TOKEN_KEY); + if (samlToken) { + apiWrapperUtil.setupTokenPairByJWTGrantType(carbonUser.username + '@' + carbonUser.domain, samlToken); + } + } + response.contentType = 'application/json'; + } finally { + utility.endTenantFlow(); + } } // returning the result. diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/app-conf.json b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/app-conf.json index d2beaa71a7..58a741db8c 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/app-conf.json +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/app-conf.json @@ -11,7 +11,7 @@ "login": { "onSuccess": { "script": "/app/modules/login.js", - "page": "cdmf.page.dashboard" + "page": "cdmf.page.processing" }, "onFail": { "script": "/app/modules/login.js", diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/layouts/cdmf.layout.loading.hbs b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/layouts/cdmf.layout.loading.hbs new file mode 100644 index 0000000000..ab70bdc1cf --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/layouts/cdmf.layout.loading.hbs @@ -0,0 +1,57 @@ +{{!-- Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + +WSO2 Inc. licenses this file to you under the Apache License, +Version 2.0 (the "License"); you may not use this file 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. --}} + + + + + + + + {{defineZone "favicon"}} + + {{defineZone "title"}} + + {{defineZone "topLibCss"}} + {{defineZone "topCss"}} + {{defineZone "topJs"}} + + + + + + + + {{defineZone "content"}} + + {{defineZone "bottomModalContent"}} + {{defineZone "bottomLibJs"}} + {{defineZone "bottomJs"}} + + \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/constants.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/constants.js index a71495851f..56d03a6ce9 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/constants.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/constants.js @@ -81,3 +81,6 @@ var CACHED_CREDENTIALS = "tenantBasedCredentials"; var CACHED_CREDENTIALS_FOR_WEBSOCKET_APP = "tenantBasedWebSocketClientCredentials"; var ALLOWED_SCOPES = "scopes"; + +var SAML_TOKEN_KEY = "samlToken"; +var SKIP_WELCOME_SCREEN ="skipWelcomeScreen"; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/login.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/login.js index 166859f89b..461e4e4fbc 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/login.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/login.js @@ -25,6 +25,19 @@ var onFail; onSuccess = function (context) { var utility = require("/app/modules/utility.js").utility; var apiWrapperUtil = require("/app/modules/oauth/token-handlers.js")["handlers"]; + try { + utility.startTenantFlow(context.user); + var APIManagementProviderService = utility.getAPIManagementProviderService(); + var isLoaded = APIManagementProviderService.isTierLoaded(); + if(!isLoaded && context.input.samlToken) { + session.put(constants.SKIP_WELCOME_SCREEN, false); + session.put(constants.SAML_TOKEN_KEY, context.input.samlToken); + return; + } + } finally { + utility.endTenantFlow(); + } + session.put(constants.SKIP_WELCOME_SCREEN, true); if (context.input.samlToken) { //apiWrapperUtil.setupTokenPairBySamlGrantType(context.user.username + '@' + context.user.domain, context.input.samlToken); /** diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/utility.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/utility.js index 7b6add5fa8..5505219181 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/utility.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/utility.js @@ -53,6 +53,10 @@ utility = function () { return getOsgiService('org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService'); }; + publicMethods.getAPIManagementProviderService = function () { + return getOsgiService('org.wso2.carbon.apimgt.application.extension.APIManagementProviderService'); + }; + publicMethods.getUserManagementService = function () { return getOsgiService("org.wso2.carbon.device.mgt.user.core.UserManager"); }; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.dashboard/dashboard.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.dashboard/dashboard.js index 1d2d7c8607..4e0c9aafa1 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.dashboard/dashboard.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.dashboard/dashboard.js @@ -16,7 +16,7 @@ * under the License. */ -function onRequest() { +function onRequest(context) { var constants = require("/app/modules/constants.js"); var userModule = require("/app/modules/business-controllers/user.js")["userModule"]; var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"]; @@ -24,6 +24,11 @@ function onRequest() { var groupModule = require("/app/modules/business-controllers/group.js")["groupModule"]; var policyModule = require("/app/modules/business-controllers/policy.js")["policyModule"]; + if(!session.get(constants["TOKEN_PAIR"])){ + response.sendRedirect(context.app.context + "/welcome"); + return; + } + var user = session.get(constants["USER_SESSION_KEY"]); var permissions = userModule.getUIPermissions(); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.processing/processing.hbs b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.processing/processing.hbs new file mode 100644 index 0000000000..48a23ed87e --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.processing/processing.hbs @@ -0,0 +1,57 @@ +{{! + Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + + WSO2 Inc. licenses this file to you under the Apache License, + Version 2.0 (the "License"); you may not use this file 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. +}} +{{unit "cdmf.unit.ui.title" pageTitle="Home"}} + +{{#zone "breadcrumbs"}} +
  • + + + +
  • +{{/zone}} + +{{#zone "content"}} +
    +
    + Loading...Please Wait +
    +
    +{{/zone}} + +{{#zone "bottomJs"}} + + {{js "/js/script.js"}} +{{/zone}} + +{{#zone "topCss"}} + +{{/zone}} \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.processing/processing.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.processing/processing.js new file mode 100644 index 0000000000..f0df8f166e --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.processing/processing.js @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file 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. + */ + +function onRequest(context) { + var constants = require("/app/modules/constants.js"); + var skipWelcomeScreen = session.get(constants.SKIP_WELCOME_SCREEN); + if (skipWelcomeScreen) { + response.sendRedirect(context.app.context + "/"); + exit(); + } + return {}; +} \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.processing/processing.json b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.processing/processing.json new file mode 100644 index 0000000000..add6d0c2de --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.processing/processing.json @@ -0,0 +1,5 @@ +{ + "version": "1.0.0", + "uri": "/welcome", + "layout": "cdmf.layout.loading" +} \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.processing/public/js/script.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.processing/public/js/script.js new file mode 100644 index 0000000000..b45759dfba --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.processing/public/js/script.js @@ -0,0 +1,30 @@ +var pollingCount = 24; +function poll() { + $.ajax({ + url: context + "/api/user/environment-loaded", + type: "GET", + success: function (data) { + if (data.isLoaded) { + window.location = context + "/"; + } + }, + dataType: "json", + complete: setTimeout(function () { + pollingCount = pollingCount - 1; + if (pollingCount > 0) { + poll(); + } else { + $(".loading-animation .logo").hide(); + $(".loading-animation").prepend( + ''); + $(".loading-animation p").css("width", "150%") + .html("Ops... it seems something went wrong.
    Refresh the page to retry!"); + } + }, 5000), + timeout: 5000 + }); +} + +$(document).ready(function () { + poll(); +}); \ No newline at end of file