#726 : Resolving cannot log into devicemgt app when tenant is not loaded in API Manager

4.x.x
Rasika Perera 8 years ago
parent d3b322ed4e
commit 2831bfaf2c

@ -26,6 +26,12 @@ import org.wso2.carbon.apimgt.application.extension.exception.APIManagerExceptio
*/ */
public interface APIManagementProviderService { 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 * Generate and retreive application keys. if the application does exist then
* create it and subscribe to apis that are grouped with the tags. * create it and subscribe to apis that are grouped with the tags.

@ -45,8 +45,22 @@ public class APIManagementProviderServiceImpl implements APIManagementProviderSe
private static final String CONTENT_TYPE = "application/json"; private static final String CONTENT_TYPE = "application/json";
private static final int MAX_API_PER_TAG = 200; private static final int MAX_API_PER_TAG = 200;
private static final String APP_TIER_TYPE = "application"; private static final String APP_TIER_TYPE = "application";
private static final Map<String, String> 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 @Override
public void removeAPIApplication(String applicationName, String username) throws APIManagerException { public void removeAPIApplication(String applicationName, String username) throws APIManagerException {
@ -72,31 +86,8 @@ public class APIManagementProviderServiceImpl implements APIManagementProviderSe
throws APIManagerException { throws APIManagerException {
StoreClient storeClient = APIApplicationManagerExtensionDataHolder.getInstance().getIntegrationClientService() StoreClient storeClient = APIApplicationManagerExtensionDataHolder.getInstance().getIntegrationClientService()
.getStoreClient(); .getStoreClient();
//This is a fix to avoid race condition and trying to load tenant related tiers before invocation.
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext() String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext()
.getTenantDomain(); .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() ApplicationList applicationList = storeClient.getApplications()
.applicationsGet("", applicationName, 1, 0, CONTENT_TYPE, null); .applicationsGet("", applicationName, 1, 0, CONTENT_TYPE, null);

@ -19,7 +19,9 @@ package org.wso2.carbon.apimgt.integration.client.store;
import feign.Feign; import feign.Feign;
import feign.Logger; import feign.Logger;
import feign.Request;
import feign.RequestInterceptor; import feign.RequestInterceptor;
import feign.Retryer;
import feign.gson.GsonDecoder; import feign.gson.GsonDecoder;
import feign.gson.GsonEncoder; import feign.gson.GsonEncoder;
import feign.slf4j.Slf4jLogger; 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.apimgt.integration.generated.client.store.api.*;
import org.wso2.carbon.core.util.Utils; import org.wso2.carbon.core.util.Utils;
import java.util.concurrent.TimeUnit;
/** /**
* API Store client, created using swagger gen. * API Store client, created using swagger gen.
*/ */
@ -62,8 +66,10 @@ public class StoreClient {
individualSubscription = builder.target(SubscriptionIndividualApi.class, basePath); individualSubscription = builder.target(SubscriptionIndividualApi.class, basePath);
subscriptionMultitpleApi = builder.target(SubscriptionMultitpleApi.class, basePath); subscriptionMultitpleApi = builder.target(SubscriptionMultitpleApi.class, basePath);
tags = builder.target(TagCollectionApi.class, basePath); tags = builder.target(TagCollectionApi.class, basePath);
tiers = builder.target(ThrottlingTierCollectionApi.class, basePath);
individualTier = builder.target(ThrottlingTierIndividualApi.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);
} }

@ -176,6 +176,27 @@ if (uriMatcher.match("/{context}/api/user/authenticate")) {
} }
} else if (uriMatcher.match("/{context}/api/user/all")) { } else if (uriMatcher.match("/{context}/api/user/all")) {
result = userModule.getUsers(); 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. // returning the result.

@ -11,7 +11,7 @@
"login": { "login": {
"onSuccess": { "onSuccess": {
"script": "/app/modules/login.js", "script": "/app/modules/login.js",
"page": "cdmf.page.dashboard" "page": "cdmf.page.processing"
}, },
"onFail": { "onFail": {
"script": "/app/modules/login.js", "script": "/app/modules/login.js",

@ -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. --}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{{defineZone "favicon"}}
<title>
{{defineZone "title"}}
</title>
{{defineZone "topLibCss"}}
{{defineZone "topCss"}}
{{defineZone "topJs"}}
</head>
<body>
<!--modal-->
<div class="modal fade" tabindex="-1" role="dialog" aria-labelledby="modalDemo">
<div class="modal-dialog" role="document">
<div class="modal-content clearfix">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><i class="fw fw-cancel"></i></button>
</div>
<div class="modal-body add-margin-top-2x add-margin-bottom-2x">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<!--modal-->
{{defineZone "content"}}
{{defineZone "bottomModalContent"}}
{{defineZone "bottomLibJs"}}
{{defineZone "bottomJs"}}
</body>
</html>

@ -81,3 +81,6 @@ var CACHED_CREDENTIALS = "tenantBasedCredentials";
var CACHED_CREDENTIALS_FOR_WEBSOCKET_APP = "tenantBasedWebSocketClientCredentials"; var CACHED_CREDENTIALS_FOR_WEBSOCKET_APP = "tenantBasedWebSocketClientCredentials";
var ALLOWED_SCOPES = "scopes"; var ALLOWED_SCOPES = "scopes";
var SAML_TOKEN_KEY = "samlToken";
var SKIP_WELCOME_SCREEN ="skipWelcomeScreen";

@ -25,6 +25,19 @@ var onFail;
onSuccess = function (context) { onSuccess = function (context) {
var utility = require("/app/modules/utility.js").utility; var utility = require("/app/modules/utility.js").utility;
var apiWrapperUtil = require("/app/modules/oauth/token-handlers.js")["handlers"]; 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) { if (context.input.samlToken) {
//apiWrapperUtil.setupTokenPairBySamlGrantType(context.user.username + '@' + context.user.domain, context.input.samlToken); //apiWrapperUtil.setupTokenPairBySamlGrantType(context.user.username + '@' + context.user.domain, context.input.samlToken);
/** /**

@ -53,6 +53,10 @@ utility = function () {
return getOsgiService('org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService'); 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 () { publicMethods.getUserManagementService = function () {
return getOsgiService("org.wso2.carbon.device.mgt.user.core.UserManager"); return getOsgiService("org.wso2.carbon.device.mgt.user.core.UserManager");
}; };

@ -16,7 +16,7 @@
* under the License. * under the License.
*/ */
function onRequest() { function onRequest(context) {
var constants = require("/app/modules/constants.js"); var constants = require("/app/modules/constants.js");
var userModule = require("/app/modules/business-controllers/user.js")["userModule"]; var userModule = require("/app/modules/business-controllers/user.js")["userModule"];
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"]; 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 groupModule = require("/app/modules/business-controllers/group.js")["groupModule"];
var policyModule = require("/app/modules/business-controllers/policy.js")["policyModule"]; 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 user = session.get(constants["USER_SESSION_KEY"]);
var permissions = userModule.getUIPermissions(); var permissions = userModule.getUIPermissions();

@ -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"}}
<li>
<a href="{{@app.context}}/">
<i class="icon fw fw-home"></i>
</a>
</li>
{{/zone}}
{{#zone "content"}}
<div class="row">
<div class="col-md-12">
Loading...Please Wait
</div>
</div>
{{/zone}}
{{#zone "bottomJs"}}
<script type="text/javascript">
$('body').attr("data-toggle", "loading")
.attr("data-loading-style", "overlay")
.attr("data-loading-text", "SETTING UP YOUR ENVIRONMENT . . .");
$('[data-toggle="loading"]').loading('show');
</script>
{{js "/js/script.js"}}
{{/zone}}
{{#zone "topCss"}}
<style>
.loading[data-loading-style=overlay] .loading-bg{
background: #11375B;
opacity: 1;
filter: alpha(opacity=100);
}
.loading .loading-animation{
width : 200px;
}
</style>
{{/zone}}

@ -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 {};
}

@ -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(
'<i class="fw fw-error fw-inverse fw-2x" style="float: left;"></i>');
$(".loading-animation p").css("width", "150%")
.html("Ops... it seems something went wrong.<br/> Refresh the page to retry!");
}
}, 5000),
timeout: 5000
});
}
$(document).ready(function () {
poll();
});
Loading…
Cancel
Save