Merge branch 'master' into 'master'

Fixes related to publishing ws api and routing requests

See merge request entgra/carbon-device-mgt!913
license
Pahansith Gunathilake 2 years ago
commit 08e42dcc53

@ -185,7 +185,9 @@
org.wso2.carbon.user.core.service;version="4.6", org.wso2.carbon.user.core.service;version="4.6",
org.wso2.carbon.user.core.tenant;version="4.6", org.wso2.carbon.user.core.tenant;version="4.6",
org.wso2.carbon.utils;version="4.6", org.wso2.carbon.utils;version="4.6",
org.wso2.carbon.utils.multitenancy;version="4.6" org.wso2.carbon.utils.multitenancy;version="4.6",
org.wso2.carbon.apimgt.impl.definitions,
org.apache.commons.lang
</Import-Package> </Import-Package>
<Embed-Dependency> <Embed-Dependency>
jsr311-api;scope=compile|runtime;inline=false jsr311-api;scope=compile|runtime;inline=false

@ -58,6 +58,10 @@ public class APIConfig {
private String[] tags; private String[] tags;
private Set<ApiScope> scopes; private Set<ApiScope> scopes;
private boolean isDefault = true; private boolean isDefault = true;
private String endpointType;
private String inSequenceName;
private String inSequenceConfig;
private String asyncApiDefinition;
@XmlElement(name = "Policy", required = true) @XmlElement(name = "Policy", required = true)
public String getPolicy() { public String getPolicy() {
@ -194,4 +198,40 @@ public class APIConfig {
public void setDefault(boolean aDefault) { public void setDefault(boolean aDefault) {
isDefault = aDefault; isDefault = aDefault;
} }
@XmlElement(name = "endpointType")
public String getEndpointType() {
return endpointType;
}
public void setEndpointType(String endpointType) {
this.endpointType = endpointType;
}
@XmlElement(name = "inSequenceName")
public String getInSequenceName() {
return inSequenceName;
}
public void setInSequenceName(String inSequenceName) {
this.inSequenceName = inSequenceName;
}
@XmlElement(name = "inSequenceConfig")
public String getInSequenceConfig() {
return inSequenceConfig;
}
public void setInSequenceConfig(String inSequenceConfig) {
this.inSequenceConfig = inSequenceConfig;
}
@XmlElement(name = "asyncApiDefinition")
public String getAsyncApiDefinition() {
return asyncApiDefinition;
}
public void setAsyncApiDefinition(String asyncApiDefinition) {
this.asyncApiDefinition = asyncApiDefinition;
}
} }

@ -35,4 +35,5 @@ public interface APIPublisherService {
*/ */
void publishAPI(APIConfig api) throws APIManagerPublisherException; void publishAPI(APIConfig api) throws APIManagerPublisherException;
void updateScopeRoleMapping() throws APIManagerPublisherException;
} }

@ -18,11 +18,9 @@
*/ */
package org.wso2.carbon.apimgt.webapp.publisher; package org.wso2.carbon.apimgt.webapp.publisher;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.apimgt.impl.utils.APIUtil;
import org.wso2.carbon.apimgt.webapp.publisher.dto.ApiScope;
import org.wso2.carbon.apimgt.webapp.publisher.dto.ApiUriTemplate;
import org.wso2.carbon.apimgt.api.APIManagementException; import org.wso2.carbon.apimgt.api.APIManagementException;
import org.wso2.carbon.apimgt.api.APIProvider; import org.wso2.carbon.apimgt.api.APIProvider;
import org.wso2.carbon.apimgt.api.FaultGatewaysException; import org.wso2.carbon.apimgt.api.FaultGatewaysException;
@ -31,26 +29,42 @@ import org.wso2.carbon.apimgt.api.model.APIIdentifier;
import org.wso2.carbon.apimgt.api.model.APIRevision; import org.wso2.carbon.apimgt.api.model.APIRevision;
import org.wso2.carbon.apimgt.api.model.APIRevisionDeployment; import org.wso2.carbon.apimgt.api.model.APIRevisionDeployment;
import org.wso2.carbon.apimgt.api.model.CORSConfiguration; import org.wso2.carbon.apimgt.api.model.CORSConfiguration;
import org.wso2.carbon.apimgt.api.model.Mediation;
import org.wso2.carbon.apimgt.api.model.Scope; import org.wso2.carbon.apimgt.api.model.Scope;
import org.wso2.carbon.apimgt.api.model.Tier; import org.wso2.carbon.apimgt.api.model.Tier;
import org.wso2.carbon.apimgt.api.model.URITemplate; import org.wso2.carbon.apimgt.api.model.URITemplate;
import org.wso2.carbon.apimgt.impl.APIConstants; import org.wso2.carbon.apimgt.impl.APIConstants;
import org.wso2.carbon.apimgt.impl.APIManagerFactory; import org.wso2.carbon.apimgt.impl.APIManagerFactory;
import org.wso2.carbon.apimgt.impl.definitions.AsyncApiParser;
import org.wso2.carbon.apimgt.impl.utils.APIUtil;
import org.wso2.carbon.apimgt.webapp.publisher.config.WebappPublisherConfig; import org.wso2.carbon.apimgt.webapp.publisher.config.WebappPublisherConfig;
import org.wso2.carbon.apimgt.webapp.publisher.dto.ApiScope;
import org.wso2.carbon.apimgt.webapp.publisher.dto.ApiUriTemplate;
import org.wso2.carbon.apimgt.webapp.publisher.exception.APIManagerPublisherException; import org.wso2.carbon.apimgt.webapp.publisher.exception.APIManagerPublisherException;
import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.core.service.RealmService; import org.wso2.carbon.user.core.service.RealmService;
import org.wso2.carbon.user.core.tenant.Tenant; import org.wso2.carbon.user.core.tenant.Tenant;
import org.wso2.carbon.user.core.tenant.TenantSearchResult; import org.wso2.carbon.user.core.tenant.TenantSearchResult;
import org.wso2.carbon.utils.CarbonUtils;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants; import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.DirectoryIteratorException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
/** /**
@ -59,6 +73,7 @@ import java.util.Set;
*/ */
public class APIPublisherServiceImpl implements APIPublisherService { public class APIPublisherServiceImpl implements APIPublisherService {
private static final String UNLIMITED_TIER = "Unlimited"; private static final String UNLIMITED_TIER = "Unlimited";
private static final String WS_UNLIMITED_TIER = "AsyncUnlimited";
private static final String API_PUBLISH_ENVIRONMENT = "Default"; private static final String API_PUBLISH_ENVIRONMENT = "Default";
private static final String CREATED_STATUS = "CREATED"; private static final String CREATED_STATUS = "CREATED";
private static final String PUBLISH_ACTION = "Publish"; private static final String PUBLISH_ACTION = "Publish";
@ -129,7 +144,20 @@ public class APIPublisherServiceImpl implements APIPublisherService {
API api = getAPI(apiConfig, true); API api = getAPI(apiConfig, true);
api.setId(apiIdentifier); api.setId(apiIdentifier);
API createdAPI = apiProvider.addAPI(api); API createdAPI = apiProvider.addAPI(api);
if (apiConfig.getEndpointType() != null && "WS".equals(apiConfig.getEndpointType())) {
apiProvider.saveAsyncApiDefinition(api, apiConfig.getAsyncApiDefinition());
}
if (CREATED_STATUS.equals(createdAPI.getStatus())) { if (CREATED_STATUS.equals(createdAPI.getStatus())) {
// if endpoint type "dynamic" and then add in sequence
if ("dynamic".equals(apiConfig.getEndpointType())) {
Mediation mediation = new Mediation();
mediation.setName(apiConfig.getInSequenceName());
mediation.setConfig(apiConfig.getInSequenceConfig());
mediation.setType("in");
mediation.setGlobal(false);
apiProvider.addApiSpecificMediationPolicy(createdAPI.getUuid(), mediation,
tenantDomain);
}
apiProvider.changeLifeCycleStatus(tenantDomain, createdAPI.getUuid(), PUBLISH_ACTION, null); apiProvider.changeLifeCycleStatus(tenantDomain, createdAPI.getUuid(), PUBLISH_ACTION, null);
APIRevision apiRevision = new APIRevision(); APIRevision apiRevision = new APIRevision();
apiRevision.setApiUUID(createdAPI.getUuid()); apiRevision.setApiUUID(createdAPI.getUuid());
@ -207,6 +235,37 @@ public class APIPublisherServiceImpl implements APIPublisherService {
api.setStatus(existingAPI.getStatus()); api.setStatus(existingAPI.getStatus());
apiProvider.updateAPI(api); apiProvider.updateAPI(api);
if (apiConfig.getEndpointType() != null && "WS".equals(apiConfig.getEndpointType())) {
apiProvider.saveAsyncApiDefinition(api, apiConfig.getAsyncApiDefinition());
}
// if endpoint type "dynamic" and then add /update in sequence
if ("dynamic".equals(apiConfig.getEndpointType())) {
Mediation mediation = new Mediation();
mediation.setName(apiConfig.getInSequenceName());
mediation.setConfig(apiConfig.getInSequenceConfig());
mediation.setType("in");
mediation.setGlobal(false);
List<Mediation> mediationList = apiProvider
.getAllApiSpecificMediationPolicies(apiIdentifier);
boolean isMediationPolicyFound = false;
for (Mediation m : mediationList) {
if (apiConfig.getInSequenceName().equals(m.getName())) {
m.setConfig(apiConfig.getInSequenceConfig());
apiProvider
.updateApiSpecificMediationPolicyContent(existingAPI.getUuid(), m,
tenantDomain);
isMediationPolicyFound = true;
break;
}
}
if (!isMediationPolicyFound) {
apiProvider.addApiSpecificMediationPolicy(existingAPI.getUuid(), mediation,
tenantDomain);
}
}
// Assumption: Assume the latest revision is the published one // Assumption: Assume the latest revision is the published one
String latestRevisionUUID = apiProvider.getLatestRevisionUUID(existingAPI.getUuid()); String latestRevisionUUID = apiProvider.getLatestRevisionUUID(existingAPI.getUuid());
List<APIRevisionDeployment> latestRevisionDeploymentList = List<APIRevisionDeployment> latestRevisionDeploymentList =
@ -250,6 +309,93 @@ public class APIPublisherServiceImpl implements APIPublisherService {
} }
} }
@Override
public void updateScopeRoleMapping()
throws APIManagerPublisherException {
// todo: This logic has written assuming all the scopes are now work as shared scopes
WebappPublisherConfig config = WebappPublisherConfig.getInstance();
List<String> tenants = new ArrayList<>(Collections.singletonList(APIConstants.SUPER_TENANT_DOMAIN));
tenants.addAll(config.getTenants().getTenant());
try {
for (String tenantDomain : tenants) {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true);
APIProvider apiProvider = API_MANAGER_FACTORY.getAPIProvider(MultitenantUtils.getTenantAwareUsername(
PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm().getRealmConfiguration()
.getAdminUserName()));
try {
String fileName =
CarbonUtils.getCarbonConfigDirPath() + File.separator + "etc"
+ File.separator + tenantDomain + ".csv";
if (Files.exists(Paths.get(fileName))) {
BufferedReader br = new BufferedReader(new FileReader(fileName));
int lineNumber = 0;
Map<Integer, String> roles = new HashMap<>();
String line = "";
String splitBy = ",";
while ((line = br.readLine()) != null) //returns a Boolean value
{
lineNumber++;
String[] scopeMapping = line.split(splitBy); // use comma as separator
if (lineNumber == 1) { // skip titles
for (int i = 0; i < scopeMapping.length; i++) {
if (i > 3) {
roles.put(i, scopeMapping[i]); // add roles to the map
}
}
continue;
}
Scope scope = new Scope();
scope.setName(
scopeMapping[0] != null ? StringUtils.trim(scopeMapping[0]) : StringUtils.EMPTY);
scope.setDescription(
scopeMapping[1] != null ? StringUtils.trim(scopeMapping[1]) : StringUtils.EMPTY);
scope.setKey(
scopeMapping[2] != null ? StringUtils.trim(scopeMapping[2]) : StringUtils.EMPTY);
// scope.setPermissions(
// scopeMapping[3] != null ? StringUtils.trim(scopeMapping[3]) : StringUtils.EMPTY);
String roleString = "";
for (int i = 4; i < scopeMapping.length; i++) {
if (scopeMapping[i] != null && StringUtils.trim(scopeMapping[i]).equals("Yes")) {
roleString = roleString + "," + roles.get(i);
}
}
if (roleString.length() > 1) {
roleString = roleString.substring(1); // remove first , (comma)
}
scope.setRoles(roleString);
if (apiProvider.isSharedScopeNameExists(scope.getKey(), tenantDomain)) {
apiProvider.updateSharedScope(scope, tenantDomain);
} else {
// todo: come to this level means, that scope is removed from API, but haven't removed from the scope-role-permission-mappings list
if (log.isDebugEnabled()) {
log.debug(scope.getKey() + " not available as shared scope");
}
}
}
}
} catch (IOException | DirectoryIteratorException ex) {
log.error("failed to read scopes from file.", ex);
}
}
} catch (UserStoreException e) {
String msg = "Error occurred while reading tenant admin username";
log.error(msg, e);
throw new APIManagerPublisherException(e);
} catch (APIManagementException e) {
String msg = "Error occurred while loading api provider";
log.error(msg, e);
throw new APIManagerPublisherException(e);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
private API getAPI(APIConfig config, boolean includeScopes) { private API getAPI(APIConfig config, boolean includeScopes) {
APIIdentifier apiIdentifier = new APIIdentifier(config.getOwner(), config.getName(), config.getVersion()); APIIdentifier apiIdentifier = new APIIdentifier(config.getOwner(), config.getName(), config.getVersion());
@ -262,44 +408,58 @@ public class APIPublisherServiceImpl implements APIPublisherService {
api.setWsdlUrl(null); api.setWsdlUrl(null);
api.setResponseCache("Disabled"); api.setResponseCache("Disabled");
api.setContextTemplate(context + "/{version}"); api.setContextTemplate(context + "/{version}");
api.setSwaggerDefinition(APIPublisherUtil.getSwaggerDefinition(config)); if (config.getEndpointType() != null && "WS".equals(config.getEndpointType())) {
api.setType("HTTP"); api.setAsyncApiDefinition(config.getAsyncApiDefinition());
AsyncApiParser asyncApiParser = new AsyncApiParser();
try {
api.setUriTemplates(asyncApiParser.getURITemplates(config.getAsyncApiDefinition(), true));
} catch (APIManagementException e) {
}
api.setWsUriMapping(asyncApiParser.buildWSUriMapping(config.getAsyncApiDefinition()));
} else {
api.setSwaggerDefinition(APIPublisherUtil.getSwaggerDefinition(config));
Set<URITemplate> uriTemplates = new HashSet<>();
Iterator<ApiUriTemplate> iterator;
for (iterator = config.getUriTemplates().iterator(); iterator.hasNext(); ) {
ApiUriTemplate apiUriTemplate = iterator.next();
URITemplate uriTemplate = new URITemplate();
uriTemplate.setAuthType(apiUriTemplate.getAuthType());
uriTemplate.setHTTPVerb(apiUriTemplate.getHttpVerb());
uriTemplate.setResourceURI(apiUriTemplate.getResourceURI());
uriTemplate.setUriTemplate(apiUriTemplate.getUriTemplate());
if (includeScopes) {
Scope scope = new Scope();
if (apiUriTemplate.getScope() != null) {
scope.setName(apiUriTemplate.getScope().getName());
scope.setDescription(apiUriTemplate.getScope().getDescription());
scope.setKey(apiUriTemplate.getScope().getKey());
scope.setRoles(apiUriTemplate.getScope().getRoles());
uriTemplate.setScopes(scope);
}
Set<URITemplate> uriTemplates = new HashSet<>();
Iterator<ApiUriTemplate> iterator;
for (iterator = config.getUriTemplates().iterator(); iterator.hasNext(); ) {
ApiUriTemplate apiUriTemplate = iterator.next();
URITemplate uriTemplate = new URITemplate();
uriTemplate.setAuthType(apiUriTemplate.getAuthType());
uriTemplate.setHTTPVerb(apiUriTemplate.getHttpVerb());
uriTemplate.setResourceURI(apiUriTemplate.getResourceURI());
uriTemplate.setUriTemplate(apiUriTemplate.getUriTemplate());
if (includeScopes) {
Scope scope = new Scope();
if (apiUriTemplate.getScope() != null) {
scope.setName(apiUriTemplate.getScope().getName());
scope.setDescription(apiUriTemplate.getScope().getDescription());
scope.setKey(apiUriTemplate.getScope().getKey());
scope.setRoles(apiUriTemplate.getScope().getRoles());
uriTemplate.setScopes(scope);
} }
uriTemplates.add(uriTemplate);
} }
uriTemplates.add(uriTemplate); api.setUriTemplates(uriTemplates);
} }
api.setUriTemplates(uriTemplates);
api.setApiOwner(config.getOwner()); api.setApiOwner(config.getOwner());
api.setDefaultVersion(config.isDefault()); api.setDefaultVersion(config.isDefault());
api.setTransports("https,http");
Set<String> tags = new HashSet<>(); Set<String> tags = new HashSet<>();
tags.addAll(Arrays.asList(config.getTags())); tags.addAll(Arrays.asList(config.getTags()));
api.setTags(tags); api.setTags(tags);
Set<Tier> availableTiers = new HashSet<>(); Set<Tier> availableTiers = new HashSet<>();
availableTiers.add(new Tier(UNLIMITED_TIER)); if (config.getEndpointType() != null && "WS".equals(config.getEndpointType())) {
availableTiers.add(new Tier(WS_UNLIMITED_TIER));
} else {
availableTiers.add(new Tier(UNLIMITED_TIER));
}
api.setAvailableTiers(availableTiers); api.setAvailableTiers(availableTiers);
Set<String> environments = new HashSet<>(); Set<String> environments = new HashSet<>();
@ -315,7 +475,23 @@ public class APIPublisherServiceImpl implements APIPublisherService {
} }
String endpointConfig = "{ \"endpoint_type\": \"http\", \"sandbox_endpoints\": { \"url\": \" " + String endpointConfig = "{ \"endpoint_type\": \"http\", \"sandbox_endpoints\": { \"url\": \" " +
config.getEndpoint() + "\" }, \"production_endpoints\": { \"url\": \" " + config.getEndpoint() + "\" } }"; config.getEndpoint() + "\" }, \"production_endpoints\": { \"url\": \" " + config.getEndpoint() + "\" } }";
api.setTransports(config.getTransports());
api.setType("HTTP");
// if dynamic endpoint
if (config.getEndpointType() != null && "dynamic".equals(config.getEndpointType())) {
endpointConfig = "{ \"endpoint_type\":\"default\", \"sandbox_endpoints\":{ \"url\":\"default\" }, \"production_endpoints\":{ \"url\":\"default\" } }";
api.setInSequence(config.getInSequenceName());
}
// if ws endpoint
if (config.getEndpointType() != null && "WS".equals(config.getEndpointType())) {
endpointConfig = "{ \"endpoint_type\": \"ws\", \"sandbox_endpoints\": { \"url\": \" " +
config.getEndpoint() + "\" }, \"production_endpoints\": { \"url\": \" " + config.getEndpoint()
+ "\" } }";
api.setTransports("wss,ws");
api.setType("WS");
}
api.setEndpointConfig(endpointConfig); api.setEndpointConfig(endpointConfig);
List<String> accessControlAllowOrigins = new ArrayList<>(); List<String> accessControlAllowOrigins = new ArrayList<>();
accessControlAllowOrigins.add("*"); accessControlAllowOrigins.add("*");
@ -343,7 +519,8 @@ public class APIPublisherServiceImpl implements APIPublisherService {
keyManagers.add("all"); keyManagers.add("all");
api.setKeyManagers(keyManagers); api.setKeyManagers(keyManagers);
api.setEnableStore(true); api.setEnableStore(true);
api.setEnableSchemaValidation(false);
api.setMonetizationEnabled(false);
return api; return api;
} }
} }

@ -85,6 +85,11 @@ public class APIPublisherStartupHandler implements ServerStartupObserver {
} }
} }
try {
publisher.updateScopeRoleMapping();
} catch (APIManagerPublisherException e) {
log.error("failed to update scope role mapping.", e);
}
} }
}); });
t.start(); t.start();

@ -47,6 +47,7 @@ public class APIPublisherUtil {
private static final String DEFAULT_API_VERSION = "1.0.0"; private static final String DEFAULT_API_VERSION = "1.0.0";
private static final String API_CONFIG_DEFAULT_VERSION = "1.0.0"; private static final String API_CONFIG_DEFAULT_VERSION = "1.0.0";
private static final String PARAM_MANAGED_API_ENDPOINT = "managed-api-endpoint"; private static final String PARAM_MANAGED_API_ENDPOINT = "managed-api-endpoint";
private static final String PARAM_MANAGED_API_ENDPOINT_TYPE = "managed-api-endpoint-type";
private static final String PARAM_MANAGED_API_TRANSPORTS = "managed-api-transports"; private static final String PARAM_MANAGED_API_TRANSPORTS = "managed-api-transports";
private static final String PARAM_MANAGED_API_POLICY = "managed-api-policy"; private static final String PARAM_MANAGED_API_POLICY = "managed-api-policy";
private static final String PARAM_MANAGED_API_IS_SECURED = "managed-api-isSecured"; private static final String PARAM_MANAGED_API_IS_SECURED = "managed-api-isSecured";
@ -62,10 +63,18 @@ public class APIPublisherUtil {
return Utils.replaceSystemProperty(webappPublisherConfig.getHost()); return Utils.replaceSystemProperty(webappPublisherConfig.getHost());
} }
public static String getWsServerBaseUrl() {
return getServerBaseUrl().replace("https","wss");
}
public static String getApiEndpointUrl(String context) { public static String getApiEndpointUrl(String context) {
return getServerBaseUrl() + context; return getServerBaseUrl() + context;
} }
public static String getWsApiEndpointUrl(String context) {
return getWsServerBaseUrl() + context;
}
/** /**
* Build the API Configuration to be passed to APIM, from a given list of URL templates * Build the API Configuration to be passed to APIM, from a given list of URL templates
* *
@ -105,6 +114,14 @@ public class APIPublisherUtil {
} }
apiConfig.setContext(context); apiConfig.setContext(context);
apiConfig.setEndpointType(apiDef.getEndpointType());
apiConfig.setInSequenceName(apiDef.getInSequenceName());
apiConfig.setInSequenceConfig(apiDef.getInSequenceConfig());
apiConfig.setAsyncApiDefinition(apiDef.getAsyncApiDefinition());
String[] tags = apiDef.getTags(); String[] tags = apiDef.getTags();
if (tags == null || tags.length == 0) { if (tags == null || tags.length == 0) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
@ -127,6 +144,10 @@ public class APIPublisherUtil {
} }
String endpointContext = apiDef.getContext(); String endpointContext = apiDef.getContext();
endpoint = APIPublisherUtil.getApiEndpointUrl(endpointContext); endpoint = APIPublisherUtil.getApiEndpointUrl(endpointContext);
if ("WS".equals(apiDef.getEndpointType())) {
endpoint = APIPublisherUtil.getWsApiEndpointUrl(endpointContext);
}
} }
apiConfig.setEndpoint(endpoint); apiConfig.setEndpoint(endpoint);
@ -158,6 +179,9 @@ public class APIPublisherUtil {
"which is 'https'"); "which is 'https'");
} }
transports = "https,http"; transports = "https,http";
if ("WS".equals(apiDef.getEndpointType())) {
transports = "wss,ws";
}
} }
apiConfig.setTransports(transports); apiConfig.setTransports(transports);
@ -176,6 +200,7 @@ public class APIPublisherUtil {
template.setResourceURI(apiResource.getUri()); template.setResourceURI(apiResource.getUri());
template.setUriTemplate(apiResource.getUriTemplate()); template.setUriTemplate(apiResource.getUriTemplate());
template.setScope(apiResource.getScope()); template.setScope(apiResource.getScope());
template.setUriMapping(apiResource.getUriMapping());
uriTemplates.add(template); uriTemplates.add(template);
} }
apiConfig.setUriTemplates(uriTemplates); apiConfig.setUriTemplates(uriTemplates);

@ -29,6 +29,7 @@ public class APIResource {
private String consumes; private String consumes;
private String produces; private String produces;
private ApiScope scope; private ApiScope scope;
private String uriMapping;
public String getAuthType() { public String getAuthType() {
return AuthType; return AuthType;
@ -85,4 +86,12 @@ public class APIResource {
public void setScope(ApiScope scope) { public void setScope(ApiScope scope) {
this.scope = scope; this.scope = scope;
} }
public String getUriMapping() {
return uriMapping;
}
public void setUriMapping(String uriMapping) {
this.uriMapping = uriMapping;
}
} }

@ -30,8 +30,12 @@ public class APIResourceConfiguration {
private String version; private String version;
private List<APIResource> resources; private List<APIResource> resources;
private String[] tags; private String[] tags;
private String endpointType;
private String inSequenceName;
private String inSequenceConfig;
private String asyncApiDefinition;
public List<APIResource> getResources() { public List<APIResource> getResources() {
return resources; return resources;
} }
@ -76,4 +80,38 @@ public class APIResourceConfiguration {
this.tags = tags; this.tags = tags;
} }
public String getEndpointType() {
return endpointType;
}
@XmlElement(name = "EndpointType")
public void setEndpointType(String endpointType) {
this.endpointType = endpointType;
}
public String getInSequenceName() {
return inSequenceName;
}
@XmlElement(name = "inSequenceName")
public void setInSequenceName(String inSequenceName) {
this.inSequenceName = inSequenceName;
}
public String getInSequenceConfig() {
return inSequenceConfig;
}
@XmlElement(name = "inSequenceConfig")
public void setInSequenceConfig(String inSequenceConfig) {
this.inSequenceConfig = inSequenceConfig;
}
public String getAsyncApiDefinition() {
return asyncApiDefinition;
}
@XmlElement(name = "asyncApiDefinition")
public void setAsyncApiDefinition(String asyncApiDefinition) {
this.asyncApiDefinition = asyncApiDefinition;
}
} }

@ -28,6 +28,7 @@ public class ApiUriTemplate {
private String resourceURI; private String resourceURI;
private String uriTemplate; private String uriTemplate;
private ApiScope scope; private ApiScope scope;
private String uriMapping;
public ApiUriTemplate() {} public ApiUriTemplate() {}
@ -70,4 +71,12 @@ public class ApiUriTemplate {
public void setScope(ApiScope scope) { public void setScope(ApiScope scope) {
this.scope = scope; this.scope = scope;
} }
public String getUriMapping() {
return uriMapping;
}
public void setUriMapping(String uriMapping) {
this.uriMapping = uriMapping;
}
} }

@ -73,6 +73,10 @@ public class AnnotationProcessor {
private static final String SWAGGER_ANNOTATIONS_PROPERTIES_ROLES = "roles"; private static final String SWAGGER_ANNOTATIONS_PROPERTIES_ROLES = "roles";
private static final String SWAGGER_ANNOTATIONS_PROPERTIES_VERSION = "version"; private static final String SWAGGER_ANNOTATIONS_PROPERTIES_VERSION = "version";
private static final String SWAGGER_ANNOTATIONS_PROPERTIES_CONTEXT = "context"; private static final String SWAGGER_ANNOTATIONS_PROPERTIES_CONTEXT = "context";
private static final String SWAGGER_ANNOTATIONS_PROPERTIES_ENDPOINT_TYPE = "endpointType";
private static final String SWAGGER_ANNOTATIONS_PROPERTIES_IN_SEQUENCE_NAME = "inSequenceName";
private static final String SWAGGER_ANNOTATIONS_PROPERTIES_IN_SEQUENCE_CONFIG = "inSequenceConfig";
private static final String SWAGGER_ANNOTATIONS_PROPERTIES_ASYNC_API_DEFINITION = "asyncApiDefinition";
private static final String SWAGGER_ANNOTATIONS_PROPERTIES_VALUE = "value"; private static final String SWAGGER_ANNOTATIONS_PROPERTIES_VALUE = "value";
private static final String ANNOTATIONS_SCOPES = "scopes"; private static final String ANNOTATIONS_SCOPES = "scopes";
private static final String ANNOTATIONS_SCOPE = "scope"; private static final String ANNOTATIONS_SCOPE = "scope";
@ -290,20 +294,23 @@ public class AnnotationProcessor {
resource.setProduces(invokeMethod(producesClassMethods[0], producesAnno, STRING_ARR)); resource.setProduces(invokeMethod(producesClassMethods[0], producesAnno, STRING_ARR));
} }
if (annotations[i].annotationType().getName().equals(ApiOperation.class.getName())) { if (annotations[i].annotationType().getName().equals(ApiOperation.class.getName())) {
ApiScope scope = this.getScope(annotations[i]); resource = getAPiOperationExtensions(annotations[i], resource);
if (scope != null) { // ApiScope scope = this.getScope(annotations[i]);
resource.setScope(scope); // if (scope != null) {
} else { // resource.setScope(scope);
log.warn("Scope is not defined for '" + makeContextURLReady(resourceRootContext) + // } else {
makeContextURLReady(subCtx) + "' endpoint, hence assigning the default scope"); // log.warn("Scope is not defined for '" + makeContextURLReady(resourceRootContext) +
scope = new ApiScope(); // makeContextURLReady(subCtx) + "' endpoint, hence assigning the default scope");
scope.setName(DEFAULT_SCOPE_NAME); // scope = new ApiScope();
scope.setDescription(DEFAULT_SCOPE_NAME); // scope.setName(DEFAULT_SCOPE_NAME);
scope.setKey(DEFAULT_SCOPE_KEY); // scope.setDescription(DEFAULT_SCOPE_NAME);
scope.setRoles(DEFAULT_SCOPE_ROLE); // scope.setKey(DEFAULT_SCOPE_KEY);
scope.setPermissions(DEFAULT_SCOPE_PERMISSION); // scope.setRoles(DEFAULT_SCOPE_ROLE);
resource.setScope(scope); // scope.setPermissions(DEFAULT_SCOPE_PERMISSION);
} // resource.setScope(scope);
// }
//
// String uriMapping =
} }
} }
resourceList.add(resource); resourceList.add(resource);
@ -404,6 +411,26 @@ public class AnnotationProcessor {
if ("".equals(value)) return null; if ("".equals(value)) return null;
apiResourceConfig.setContext(value); apiResourceConfig.setContext(value);
break; break;
case SWAGGER_ANNOTATIONS_PROPERTIES_ENDPOINT_TYPE:
if ("".equals(value))
return null;
apiResourceConfig.setEndpointType(value);
break;
case SWAGGER_ANNOTATIONS_PROPERTIES_IN_SEQUENCE_NAME:
if ("".equals(value))
return null;
apiResourceConfig.setInSequenceName(value);
break;
case SWAGGER_ANNOTATIONS_PROPERTIES_IN_SEQUENCE_CONFIG:
if ("".equals(value))
return null;
apiResourceConfig.setInSequenceConfig(value);
break;
case SWAGGER_ANNOTATIONS_PROPERTIES_ASYNC_API_DEFINITION:
if ("".equals(value))
return null;
apiResourceConfig.setAsyncApiDefinition(value);
break;
default: default:
break; break;
} }
@ -475,6 +502,56 @@ public class AnnotationProcessor {
} }
} }
private APIResource getAPiOperationExtensions(Annotation currentMethod, APIResource apiResource) throws Throwable {
InvocationHandler methodHandler = Proxy.getInvocationHandler(currentMethod);
Annotation[] extensions = (Annotation[]) methodHandler.invoke(currentMethod,
apiOperation.getMethod(SWAGGER_ANNOTATIONS_EXTENSIONS, null), null);
if (extensions != null) {
methodHandler = Proxy.getInvocationHandler(extensions[0]);
Annotation[] properties = (Annotation[]) methodHandler.invoke(extensions[0], extensionClass
.getMethod(SWAGGER_ANNOTATIONS_PROPERTIES, null), null);
String scopeKey;
String propertyName;
String urlMapping;
for (Annotation property : properties) {
methodHandler = Proxy.getInvocationHandler(property);
propertyName = (String) methodHandler.invoke(property, extensionPropertyClass
.getMethod(SWAGGER_ANNOTATIONS_PROPERTIES_NAME, null), null);
if (ANNOTATIONS_SCOPE.equals(propertyName)) {
scopeKey = (String) methodHandler.invoke(property, extensionPropertyClass
.getMethod(SWAGGER_ANNOTATIONS_PROPERTIES_VALUE, null), null);
if (scopeKey.isEmpty()) {
return null;
}
ApiScope scope = apiScopes.get(scopeKey);
if (scope != null) {
apiResource.setScope(scope);
} else {
// log.warn("Scope is not defined for '" + makeContextURLReady(resourceRootContext) +
// makeContextURLReady(subCtx) + "' endpoint, hence assigning the default scope");
scope = new ApiScope();
scope.setName(DEFAULT_SCOPE_NAME);
scope.setDescription(DEFAULT_SCOPE_NAME);
scope.setKey(DEFAULT_SCOPE_KEY);
scope.setRoles(DEFAULT_SCOPE_ROLE);
scope.setPermissions(DEFAULT_SCOPE_PERMISSION);
apiResource.setScope(scope);
}
}
if ("urlMapping".equals(propertyName)) {
urlMapping = (String) methodHandler.invoke(property, extensionPropertyClass
.getMethod(SWAGGER_ANNOTATIONS_PROPERTIES_VALUE, null), null);
apiResource.setUriMapping(urlMapping);
}
}
}
return apiResource;
}
private ApiScope getScope(Annotation currentMethod) throws Throwable { private ApiScope getScope(Annotation currentMethod) throws Throwable {
InvocationHandler methodHandler = Proxy.getInvocationHandler(currentMethod); InvocationHandler methodHandler = Proxy.getInvocationHandler(currentMethod);
Annotation[] extensions = (Annotation[]) methodHandler.invoke(currentMethod, Annotation[] extensions = (Annotation[]) methodHandler.invoke(currentMethod,

@ -2870,6 +2870,7 @@ public interface DeviceManagementService {
value = "Client Secret", value = "Client Secret",
required = true) required = true)
@PathParam("clientSecret") @PathParam("clientSecret")
String clientSecret String clientSecret,
@QueryParam("scopes") String scopes
); );
} }

@ -1752,7 +1752,8 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
@Override @Override
public Response getDefaultToken( public Response getDefaultToken(
@PathParam("clientId") String clientId, @PathParam("clientId") String clientId,
@PathParam("clientSecret") String clientSecret) { @PathParam("clientSecret") String clientSecret,
@QueryParam("scopes") String scopes) {
JWTClientManagerService jwtClientManagerService = DeviceMgtAPIUtils.getJWTClientManagerService(); JWTClientManagerService jwtClientManagerService = DeviceMgtAPIUtils.getJWTClientManagerService();
try { try {
JWTClient jwtClient = jwtClientManagerService.getJWTClient(); JWTClient jwtClient = jwtClientManagerService.getJWTClient();
@ -1761,7 +1762,11 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
if (!"carbon.super".equals(tenantDomain)) { if (!"carbon.super".equals(tenantDomain)) {
username += "@" + tenantDomain; username += "@" + tenantDomain;
} }
AccessTokenInfo accessTokenInfo = jwtClient.getAccessToken(clientId, clientSecret, username, "default"); String scopeString = "default";
if (!StringUtils.isBlank(scopes)) {
scopeString = scopes;
}
AccessTokenInfo accessTokenInfo = jwtClient.getAccessToken(clientId, clientSecret, username, scopeString);
return Response.status(Response.Status.OK).entity(accessTokenInfo).build(); return Response.status(Response.Status.OK).entity(accessTokenInfo).build();
} catch (JWTClientException e) { } catch (JWTClientException e) {
String msg = "Error occurred while getting default access token by using given client Id and client secret."; String msg = "Error occurred while getting default access token by using given client Id and client secret.";

@ -24,6 +24,8 @@ import io.entgra.server.bootup.heartbeat.beacon.exception.HeartBeatManagementExc
import io.entgra.server.bootup.heartbeat.beacon.service.HeartBeatManagementService; import io.entgra.server.bootup.heartbeat.beacon.service.HeartBeatManagementService;
import org.wso2.carbon.device.mgt.common.ServerCtxInfo; import org.wso2.carbon.device.mgt.common.ServerCtxInfo;
import java.util.Map;
public class TestHeartBeatManagementService implements HeartBeatManagementService { public class TestHeartBeatManagementService implements HeartBeatManagementService {
@Override @Override
public boolean isTaskPartitioningEnabled() throws HeartBeatManagementException { public boolean isTaskPartitioningEnabled() throws HeartBeatManagementException {
@ -60,4 +62,8 @@ public class TestHeartBeatManagementService implements HeartBeatManagementServic
public boolean isQualifiedToExecuteTask() throws HeartBeatManagementException { public boolean isQualifiedToExecuteTask() throws HeartBeatManagementException {
return false; return false;
} }
@Override public Map<Integer, ServerContext> getActiveServers() throws HeartBeatManagementException {
return null;
}
} }

@ -23,6 +23,8 @@ import io.entgra.server.bootup.heartbeat.beacon.dto.ServerContext;
import io.entgra.server.bootup.heartbeat.beacon.exception.HeartBeatManagementException; import io.entgra.server.bootup.heartbeat.beacon.exception.HeartBeatManagementException;
import org.wso2.carbon.device.mgt.common.ServerCtxInfo; import org.wso2.carbon.device.mgt.common.ServerCtxInfo;
import java.util.Map;
public interface HeartBeatManagementService { public interface HeartBeatManagementService {
boolean isTaskPartitioningEnabled() throws HeartBeatManagementException; boolean isTaskPartitioningEnabled() throws HeartBeatManagementException;
@ -39,4 +41,5 @@ public interface HeartBeatManagementService {
boolean isQualifiedToExecuteTask() throws HeartBeatManagementException; boolean isQualifiedToExecuteTask() throws HeartBeatManagementException;
Map<Integer, ServerContext> getActiveServers() throws HeartBeatManagementException;
} }

@ -35,6 +35,7 @@ import org.wso2.carbon.device.mgt.common.exceptions.TransactionManagementExcepti
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
@ -302,4 +303,37 @@ public class HeartBeatManagementServiceImpl implements HeartBeatManagementServic
return operationSuccess; return operationSuccess;
} }
@Override
public Map<Integer, ServerContext> getActiveServers() throws HeartBeatManagementException {
Map<Integer, ServerContext> activeServers = new HashMap<>();
if (HeartBeatBeaconConfig.getInstance().isEnabled()) {
try {
HeartBeatBeaconDAOFactory.openConnection();
int timeOutIntervalInSeconds = HeartBeatBeaconConfig.getInstance().getServerTimeOutIntervalInSeconds();
int timeSkew = HeartBeatBeaconConfig.getInstance().getTimeSkew();
int cumilativeTimeOut = timeOutIntervalInSeconds + timeSkew;
Map<String, ServerContext> serverCtxMap = heartBeatDAO.getActiveServerDetails(cumilativeTimeOut);
for (String uuid : serverCtxMap.keySet()) {
ServerContext serverContext = serverCtxMap.get(uuid);
activeServers.put(serverContext.getIndex(), serverContext);
}
} catch (SQLException e) {
String msg = "Error occurred while opening a connection to the underlying data source";
log.error(msg, e);
throw new HeartBeatManagementException(msg, e);
} catch (HeartBeatDAOException e) {
String msg = "Error occurred while retrieving active server details.";
log.error(msg, e);
throw new HeartBeatManagementException(msg, e);
} finally {
HeartBeatBeaconDAOFactory.closeConnection();
}
} else {
String msg = "Heart Beat Configuration Disabled. Server Context Information Not available.";
log.error(msg);
throw new HeartBeatManagementException(msg);
}
return activeServers;
}
} }

@ -24,6 +24,8 @@ import io.entgra.server.bootup.heartbeat.beacon.exception.HeartBeatManagementExc
import io.entgra.server.bootup.heartbeat.beacon.service.HeartBeatManagementService; import io.entgra.server.bootup.heartbeat.beacon.service.HeartBeatManagementService;
import org.wso2.carbon.device.mgt.common.ServerCtxInfo; import org.wso2.carbon.device.mgt.common.ServerCtxInfo;
import java.util.Map;
public class TestHeartBeatManagementService implements HeartBeatManagementService { public class TestHeartBeatManagementService implements HeartBeatManagementService {
@Override @Override
public boolean isTaskPartitioningEnabled() throws HeartBeatManagementException { public boolean isTaskPartitioningEnabled() throws HeartBeatManagementException {
@ -60,4 +62,8 @@ public class TestHeartBeatManagementService implements HeartBeatManagementServic
public boolean isQualifiedToExecuteTask() throws HeartBeatManagementException { public boolean isQualifiedToExecuteTask() throws HeartBeatManagementException {
return false; return false;
} }
@Override public Map<Integer, ServerContext> getActiveServers() throws HeartBeatManagementException {
return null;
}
} }

@ -24,6 +24,7 @@ import com.google.gson.JsonParser;
import io.entgra.ui.request.interceptor.beans.AuthData; import io.entgra.ui.request.interceptor.beans.AuthData;
import io.entgra.ui.request.interceptor.util.HandlerConstants; import io.entgra.ui.request.interceptor.util.HandlerConstants;
import io.entgra.ui.request.interceptor.util.HandlerUtil; import io.entgra.ui.request.interceptor.util.HandlerUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpHeaders; import org.apache.http.HttpHeaders;
@ -69,11 +70,20 @@ public class DefaultTokenHandler extends HttpServlet {
String clientId = authData.getClientId(); String clientId = authData.getClientId();
String clientSecret = authData.getClientSecret(); String clientSecret = authData.getClientSecret();
String queryString = req.getQueryString();
String scopeString = "";
if (StringUtils.isNotEmpty(queryString)) {
scopeString = req.getParameter("scopes");
if (scopeString != null) {
scopeString = "?scopes=" + scopeString;
}
}
String iotsCoreUrl = req.getScheme() + HandlerConstants.SCHEME_SEPARATOR String iotsCoreUrl = req.getScheme() + HandlerConstants.SCHEME_SEPARATOR
+ System.getProperty(HandlerConstants.IOT_GW_HOST_ENV_VAR) + System.getProperty(HandlerConstants.IOT_GW_HOST_ENV_VAR)
+ HandlerConstants.COLON + HandlerUtil.getGatewayPort(req.getScheme()); + HandlerConstants.COLON + HandlerUtil.getGatewayPort(req.getScheme());
String tokenUrl = iotsCoreUrl + "/api/device-mgt/v1.0/devices/" + clientId String tokenUrl = iotsCoreUrl + "/api/device-mgt/v1.0/devices/" + clientId
+ "/" + clientSecret + "/default-token"; + "/" + clientSecret + "/default-token" + scopeString;
HttpGet defaultTokenRequest = new HttpGet(tokenUrl); HttpGet defaultTokenRequest = new HttpGet(tokenUrl);
defaultTokenRequest defaultTokenRequest
@ -131,9 +141,21 @@ public class DefaultTokenHandler extends HttpServlet {
ub.setPort(Integer.parseInt(System.getProperty(HandlerConstants.IOT_REMOTE_SESSION_HTTPS_PORT_ENV_VAR))); ub.setPort(Integer.parseInt(System.getProperty(HandlerConstants.IOT_REMOTE_SESSION_HTTPS_PORT_ENV_VAR)));
ub.setPath(HandlerConstants.REMOTE_SESSION_CONTEXT); ub.setPath(HandlerConstants.REMOTE_SESSION_CONTEXT);
URIBuilder ub2 = new URIBuilder();
ub2.setScheme(HandlerConstants.WSS_PROTOCOL);
ub2.setHost(System.getProperty(HandlerConstants.IOT_GW_HOST_ENV_VAR));
ub2.setPort(Integer.parseInt(System.getProperty(HandlerConstants.IOT_GATEWAY_WEBSOCKET_WSS_PORT_ENV_VAR)));
URIBuilder ub3 = new URIBuilder();
ub3.setScheme(HandlerConstants.WS_PROTOCOL);
ub3.setHost(System.getProperty(HandlerConstants.IOT_GW_HOST_ENV_VAR));
ub3.setPort(Integer.parseInt(System.getProperty(HandlerConstants.IOT_GATEWAY_WEBSOCKET_WS_PORT_ENV_VAR)));
JsonObject responseJsonObj = new JsonObject(); JsonObject responseJsonObj = new JsonObject();
responseJsonObj.addProperty("default-access-token", defaultAccessToken); responseJsonObj.addProperty("default-access-token", defaultAccessToken);
responseJsonObj.addProperty("remote-session-base-url", ub.toString()); responseJsonObj.addProperty("remote-session-base-url", ub.toString());
responseJsonObj.addProperty("secured-websocket-gateway-url", ub2.toString());
responseJsonObj.addProperty("unsecured-websocket-gateway-url", ub3.toString());
Gson gson = new Gson(); Gson gson = new Gson();
String payload = gson.toJson(responseJsonObj); String payload = gson.toJson(responseJsonObj);

@ -99,6 +99,8 @@ public class HandlerConstants {
public static final String IOT_GW_HTTP_PORT_ENV_VAR = "iot.gateway.http.port"; public static final String IOT_GW_HTTP_PORT_ENV_VAR = "iot.gateway.http.port";
public static final String IOT_REMOTE_SESSION_HOST_ENV_VAR = "iot.remotesession.server.host"; public static final String IOT_REMOTE_SESSION_HOST_ENV_VAR = "iot.remotesession.server.host";
public static final String IOT_REMOTE_SESSION_HTTPS_PORT_ENV_VAR = "iot.remotesession.server.https.port"; public static final String IOT_REMOTE_SESSION_HTTPS_PORT_ENV_VAR = "iot.remotesession.server.https.port";
public static final String IOT_GATEWAY_WEBSOCKET_WSS_PORT_ENV_VAR = "iot.gateway.websocket.wss.port";
public static final String IOT_GATEWAY_WEBSOCKET_WS_PORT_ENV_VAR = "iot.gateway.websocket.ws.port";
public static final String IOT_GW_HTTPS_PORT_ENV_VAR = "iot.gateway.https.port"; public static final String IOT_GW_HTTPS_PORT_ENV_VAR = "iot.gateway.https.port";
public static final String IOT_REPORTING_WEBAPP_HOST_ENV_VAR = "iot.reporting.webapp.host"; public static final String IOT_REPORTING_WEBAPP_HOST_ENV_VAR = "iot.reporting.webapp.host";
public static final String USER_SCOPES = "userScopes"; public static final String USER_SCOPES = "userScopes";

Loading…
Cancel
Save