diff --git a/README.md b/README.md index 5ff98b8ff5..e07bdc3705 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # carbon-device-mgt + + WSO2 CONNECTED DEVICE MANAGEMENT COMPONENTS WSO2 Connected Device Manager (WSO2 CDM) is a comprehensive platform that helps solve mobile computing challenges enterprises face today when dealing with both corporate owned, personally enabled (COPE) devices and employee owned devices as part of a bring your own device (BYOD) program. diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.annotations/pom.xml b/components/apimgt-extensions/org.wso2.carbon.apimgt.annotations/pom.xml index 0f73119954..8111f47006 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.annotations/pom.xml +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.annotations/pom.xml @@ -22,13 +22,13 @@ apimgt-extensions org.wso2.carbon.devicemgt - 2.0.18-SNAPSHOT + 2.0.37-SNAPSHOT ../pom.xml 4.0.0 org.wso2.carbon.apimgt.annotations - 2.0.18-SNAPSHOT + 2.0.37-SNAPSHOT bundle WSO2 Carbon - API Management Annotations WSO2 Carbon - API Management Custom Annotation Module diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/pom.xml b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/pom.xml index c8f7bf0b5a..f67822c70e 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/pom.xml +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/pom.xml @@ -21,12 +21,12 @@ apimgt-extensions org.wso2.carbon.devicemgt - 2.0.18-SNAPSHOT + 2.0.37-SNAPSHOT ../pom.xml 4.0.0 - 2.0.18-SNAPSHOT + 2.0.37-SNAPSHOT org.wso2.carbon.apimgt.application.extension.api war WSO2 Carbon - API Application Management API diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/ApiApplicationRegistrationService.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/ApiApplicationRegistrationService.java index 5f122b593a..3515a2e893 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/ApiApplicationRegistrationService.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/ApiApplicationRegistrationService.java @@ -51,12 +51,4 @@ public interface ApiApplicationRegistrationService { @Path("register") Response register(RegistrationProfile registrationProfile); - /** - * This method is used to unregister an API application. - * @param applicationName name of the application that needs to be unregistered. - * @return the response status of request. - */ - @DELETE - @Path("unregister") - Response unregister(@QueryParam("applicationName") String applicationName); } diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/ApiApplicationRegistrationServiceImpl.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/ApiApplicationRegistrationServiceImpl.java index a69ae339f2..4656653988 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/ApiApplicationRegistrationServiceImpl.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/ApiApplicationRegistrationServiceImpl.java @@ -18,6 +18,7 @@ package org.wso2.carbon.apimgt.application.extension.api; +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.json.simple.JSONObject; @@ -60,11 +61,10 @@ public class ApiApplicationRegistrationServiceImpl implements ApiApplicationRegi } String username = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm() .getRealmConfiguration().getAdminUserName(); - username = username + "@" + APIUtil.getTenantDomainOftheUser(); PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(username); APIManagementProviderService apiManagementProviderService = APIUtil.getAPIManagementProviderService(); ApiApplicationKey apiApplicationKey = apiManagementProviderService.generateAndRetrieveApplicationKeys( - applicationName, APIUtil.getAllowedApisTags().toArray(new String[APIUtil.getAllowedApisTags().size()]), + applicationName, APIUtil.getDefaultTags(), ApiApplicationConstants.DEFAULT_TOKEN_TYPE, username, false, ApiApplicationConstants.DEFAULT_VALIDITY_PERIOD); return Response.status(Response.Status.CREATED).entity(apiApplicationKey.toString()).build(); @@ -96,7 +96,9 @@ public class ApiApplicationRegistrationServiceImpl implements ApiApplicationRegi return Response.status(Response.Status.NOT_ACCEPTABLE).entity("APIs(Tags) are not allowed to this user." ).build(); } - String username = APIUtil.getAuthenticatedUser() + "@" + APIUtil.getTenantDomainOftheUser(); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(PrivilegedCarbonContext. + getThreadLocalCarbonContext().getUserRealm().getRealmConfiguration().getAdminUserName()); + String username = APIUtil.getAuthenticatedUser(); APIManagementProviderService apiManagementProviderService = APIUtil.getAPIManagementProviderService(); String validityPeriod; if (registrationProfile.getValidityPeriod() == null) { @@ -104,51 +106,29 @@ public class ApiApplicationRegistrationServiceImpl implements ApiApplicationRegi } else { validityPeriod = registrationProfile.getValidityPeriod(); } - if (registrationProfile.isMappingAnExistingOAuthApp()) { - JSONObject jsonStringObject = new JSONObject(); - jsonStringObject.put(ApiApplicationConstants.JSONSTRING_USERNAME_TAG, username); - jsonStringObject.put(ApiApplicationConstants.JSONSTRING_KEY_TYPE_TAG, - ApiApplicationConstants.DEFAULT_TOKEN_TYPE); - jsonStringObject.put(ApiApplicationConstants.OAUTH_CLIENT_ID, registrationProfile.getConsumerKey()); - jsonStringObject.put(ApiApplicationConstants.OAUTH_CLIENT_SECRET, - registrationProfile.getConsumerSecret()); - jsonStringObject.put(ApiApplicationConstants.JSONSTRING_VALIDITY_PERIOD_TAG, validityPeriod); - apiManagementProviderService.registerExistingOAuthApplicationToAPIApplication( - jsonStringObject.toJSONString(), registrationProfile.getApplicationName(), - registrationProfile.getConsumerKey(), username, registrationProfile.isAllowedToAllDomains(), - ApiApplicationConstants.DEFAULT_TOKEN_TYPE, registrationProfile.getTags()); - return Response.status(Response.Status.ACCEPTED).entity("true").build(); - } else { + + String applicationName = registrationProfile.getApplicationName(); + synchronized (ApiApplicationRegistrationServiceImpl.class) { ApiApplicationKey apiApplicationKey = apiManagementProviderService.generateAndRetrieveApplicationKeys( - registrationProfile.getApplicationName(), registrationProfile.getTags(), + applicationName, registrationProfile.getTags(), ApiApplicationConstants.DEFAULT_TOKEN_TYPE, username, registrationProfile.isAllowedToAllDomains(), validityPeriod); return Response.status(Response.Status.CREATED).entity(apiApplicationKey.toString()).build(); } } catch (APIManagerException e) { - String msg = "Error occurred while registering an application '" - + registrationProfile.getApplicationName() + "'"; + String msg = "Error occurred while registering an application with apis '" + + StringUtils.join(registrationProfile.getTags(), ",") + "'"; log.error(msg, e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity("false").build(); } catch (DeviceManagementException e) { String msg = "Failed to retrieve the device service"; log.error(msg, e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); - } - } - - @Path("unregister") - @DELETE - public Response unregister(@QueryParam("applicationName") String applicationName) { - try { - String username = APIUtil.getAuthenticatedUser() + "@" + APIUtil.getTenantDomainOftheUser(); - APIManagementProviderService apiManagementProviderService = APIUtil.getAPIManagementProviderService(); - apiManagementProviderService.removeAPIApplication(applicationName, username); - return Response.status(Response.Status.ACCEPTED).build(); - } catch (APIManagerException e) { - String msg = "Error occurred while removing the application '" + applicationName; + } catch (UserStoreException e) { + String msg = "Failed to access user space."; log.error(msg, e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } } + } \ No newline at end of file diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/filter/ApiPermissionFilter.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/filter/ApiPermissionFilter.java index 5f05dfb337..1f043c7b86 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/filter/ApiPermissionFilter.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/filter/ApiPermissionFilter.java @@ -23,6 +23,7 @@ import org.wso2.carbon.apimgt.application.extension.api.util.APIUtil; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.user.api.UserRealm; import org.wso2.carbon.user.api.UserStoreException; +import org.wso2.carbon.utils.multitenancy.MultitenantUtils; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; @@ -120,7 +121,8 @@ public class ApiPermissionFilter implements Filter { try { UserRealm userRealm = APIUtil.getRealmService().getTenantUserRealm(PrivilegedCarbonContext .getThreadLocalCarbonContext().getTenantId()); - return userRealm.getAuthorizationManager().isUserAuthorized(username, permission, action); + String tenantAwareUsername = MultitenantUtils.getTenantAwareUsername(username); + return userRealm.getAuthorizationManager().isUserAuthorized(tenantAwareUsername, permission, action); } catch (UserStoreException e) { String errorMsg = String.format("Unable to authorize the user : %s", username); log.error(errorMsg, e); diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/util/APIUtil.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/util/APIUtil.java index cdce160c54..8b888a010d 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/util/APIUtil.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/util/APIUtil.java @@ -31,6 +31,7 @@ import org.wso2.carbon.registry.core.exceptions.RegistryException; import org.wso2.carbon.registry.core.service.RegistryService; import org.wso2.carbon.user.core.service.RealmService; +import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; @@ -95,8 +96,13 @@ public class APIUtil { return deviceManagementProviderService; } + public static String[] getDefaultTags() throws DeviceManagementException { + String[] allowedApisTags = new String[1]; + allowedApisTags[0] = DEFAULT_CDMF_API_TAG; + return allowedApisTags; + } + public static List getAllowedApisTags() throws DeviceManagementException { - //Todo get allowed cdmf service tags from config. List allowedApisTags = getDeviceManagementProviderService().getAvailableDeviceTypes(); allowedApisTags.add(DEFAULT_CDMF_API_TAG); allowedApisTags.add(DEFAULT_CERT_API_TAG); diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/util/RegistrationProfile.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/util/RegistrationProfile.java index b1634923f3..44cc5554fc 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/util/RegistrationProfile.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/util/RegistrationProfile.java @@ -30,17 +30,12 @@ import javax.xml.bind.annotation.XmlRootElement; @JsonIgnoreProperties(ignoreUnknown = true) public class RegistrationProfile { - @XmlElement(required = true) private String applicationName; @XmlElement(required = true) private String tags[]; @XmlElement(required = true) private boolean isAllowedToAllDomains; - @XmlElement(required = true) - private boolean isMappingAnExistingOAuthApp; - private String consumerKey; - private String consumerSecret; @XmlElement(required = false) private String validityPeriod; @@ -68,30 +63,6 @@ public class RegistrationProfile { this.isAllowedToAllDomains = isAllowedToAllDomains; } - public boolean isMappingAnExistingOAuthApp() { - return isMappingAnExistingOAuthApp; - } - - public void setIsMappingAnExistingOAuthApp(boolean isMappingAnExistingOAuthApp) { - this.isMappingAnExistingOAuthApp = isMappingAnExistingOAuthApp; - } - - public String getConsumerKey() { - return consumerKey; - } - - public void setConsumerKey(String consumerKey) { - this.consumerKey = consumerKey; - } - - public String getConsumerSecret() { - return consumerSecret; - } - - public void setConsumerSecret(String consumerSecret) { - this.consumerSecret = consumerSecret; - } - public String getValidityPeriod() { return validityPeriod; } diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/webapp/META-INF/permissions.xml b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/webapp/META-INF/permissions.xml index 591725fa12..2d907f170e 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/webapp/META-INF/permissions.xml +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/webapp/META-INF/permissions.xml @@ -37,16 +37,9 @@ Register application - /device-mgt/api/application + /device-mgt/device/api/subscribe /register POST application_user - - Delete application - /device-mgt/api/application - /unregister - DELETE - application_user - \ No newline at end of file diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/pom.xml b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/pom.xml index e963999238..f7355ae880 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/pom.xml +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/pom.xml @@ -22,12 +22,12 @@ apimgt-extensions org.wso2.carbon.devicemgt - 2.0.18-SNAPSHOT + 2.0.37-SNAPSHOT ../pom.xml 4.0.0 - 2.0.18-SNAPSHOT + 2.0.37-SNAPSHOT org.wso2.carbon.apimgt.application.extension bundle WSO2 Carbon - API Application Management @@ -51,14 +51,14 @@ org.wso2.carbon org.wso2.carbon.logging - - org.wso2.carbon.apimgt - org.wso2.carbon.apimgt.impl - - - org.wso2.carbon.apimgt - org.wso2.carbon.apimgt.api - + + org.wso2.carbon.devicemgt + org.wso2.carbon.apimgt.integration.client + + + org.wso2.carbon.devicemgt + org.wso2.carbon.apimgt.integration.generated.client + com.googlecode.json-simple.wso2 json-simple @@ -100,16 +100,17 @@ org.osgi.service.component, org.apache.commons.logging.*, org.wso2.carbon.user.core.*, - org.wso2.carbon.apimgt.api;version="${carbon.api.mgt.version.range}", - org.wso2.carbon.apimgt.api.model;version="${carbon.api.mgt.version.range}", - org.wso2.carbon.apimgt.impl;version="${carbon.api.mgt.version.range}", org.wso2.carbon.user.api, org.wso2.carbon.utils.multitenancy, org.json.simple, org.wso2.carbon.context, org.wso2.carbon.base, org.wso2.carbon.registry.core.*;resolution:=optional, - org.wso2.carbon.registry.indexing.*; version="${carbon.registry.imp.pkg.version.range}" + org.wso2.carbon.registry.indexing.*; version="${carbon.registry.imp.pkg.version.range}", + org.wso2.carbon.apimgt.integration.client.*, + org.wso2.carbon.apimgt.integration.generated.client.store.api, + org.wso2.carbon.apimgt.integration.generated.client.store.model, + feign !org.wso2.carbon.apimgt.application.extension.internal, 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 7e04924dc4..8cad8b016f 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 @@ -41,15 +41,7 @@ public interface APIManagementProviderService { */ ApiApplicationKey generateAndRetrieveApplicationKeys(String apiApplicationName, String tags[], String keyType, String username, boolean isAllowedAllDomains, - String validityTime) - throws APIManagerException; - - /** - * Register existing Oauth application as apim application. - */ - void registerExistingOAuthApplicationToAPIApplication(String jsonString, String applicationName, String clientId, - String username, boolean isAllowedAllDomains, String keyType, - String tags[]) throws APIManagerException; + String validityTime) throws APIManagerException; /** * Remove APIM Application. 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 087a6ee4a2..fa473a4133 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 @@ -18,23 +18,23 @@ package org.wso2.carbon.apimgt.application.extension; +import feign.FeignException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.json.simple.JSONObject; -import org.wso2.carbon.apimgt.api.APIConsumer; -import org.wso2.carbon.apimgt.api.APIManagementException; -import org.wso2.carbon.apimgt.api.model.*; import org.wso2.carbon.apimgt.application.extension.constants.ApiApplicationConstants; import org.wso2.carbon.apimgt.application.extension.dto.ApiApplicationKey; import org.wso2.carbon.apimgt.application.extension.exception.APIManagerException; +import org.wso2.carbon.apimgt.application.extension.internal.APIApplicationManagerExtensionDataHolder; import org.wso2.carbon.apimgt.application.extension.util.APIManagerUtil; -import org.wso2.carbon.apimgt.impl.APIConstants; -import org.wso2.carbon.apimgt.impl.APIManagerFactory; +import org.wso2.carbon.apimgt.integration.client.store.*; +import org.wso2.carbon.apimgt.integration.generated.client.store.model.*; +import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.utils.multitenancy.MultitenantConstants; -import org.wso2.carbon.utils.multitenancy.MultitenantUtils; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; import java.util.Map; -import java.util.Set; /** * This class represents an implementation of APIManagementProviderService. @@ -42,81 +42,23 @@ import java.util.Set; public class APIManagementProviderServiceImpl implements APIManagementProviderService { private static final Log log = LogFactory.getLog(APIManagementProviderServiceImpl.class); - - /** - * {@inheritDoc} - */ - @Override - public void registerExistingOAuthApplicationToAPIApplication(String jsonString, String applicationName, - String clientId, String username, - boolean isAllowedAllDomains, String keyType, - String tags[]) throws APIManagerException { - try { - APIManagerUtil.loadTenantRegistry(); - APIConsumer apiConsumer = APIManagerFactory.getInstance().getAPIConsumer(username); - if (apiConsumer != null) { - String groupId = getLoggedInUserGroupId(username, APIManagerUtil.getTenantDomain()); - int applicationId = createApplication(apiConsumer, applicationName, username, groupId); - Subscriber subscriber = apiConsumer.getSubscriber(username); - if (subscriber == null) { - String tenantDomain = MultitenantUtils.getTenantDomain(username); - addSubscriber(username, "", groupId, APIManagerUtil.getTenantId(tenantDomain)); - subscriber = apiConsumer.getSubscriber(username); - } - Application[] applications = apiConsumer.getApplications(subscriber, groupId); - Application application = null; - for (Application app : applications) { - if (app.getId() == applicationId) { - application = app; - } - } - if (application == null) { - throw new APIManagerException( - "Api application creation failed for " + applicationName + " to the user " + username); - } - - OAuthApplicationInfo oAuthApp = application.getOAuthApp(keyType); - if (oAuthApp != null) { - if (oAuthApp.getClientId().equals(clientId)) { - if (tags != null && tags.length > 0) { - createApplicationAndSubscribeToAPIs(applicationName, tags, username); - } - return; - } else { - throw new APIManagerException("Api application already mapped to another OAuth App"); - } - } - - apiConsumer.mapExistingOAuthClient(jsonString, username, clientId, applicationName, - ApiApplicationConstants.DEFAULT_TOKEN_TYPE); - if (tags != null && tags.length > 0) { - createApplicationAndSubscribeToAPIs(applicationName, tags, username); - } - } - } catch (APIManagementException e) { - throw new APIManagerException( - "Failed registering the OAuth app [ clientId " + clientId + " ] with api manager application", e); - } - } + 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 = 10; @Override public void removeAPIApplication(String applicationName, String username) throws APIManagerException { - try { - APIManagerUtil.loadTenantRegistry(); - APIConsumer apiConsumer = APIManagerFactory.getInstance().getAPIConsumer(username); - if (apiConsumer != null) { - String groupId = getLoggedInUserGroupId(username, APIManagerUtil.getTenantDomain()); - Application[] applications = apiConsumer.getApplications(new Subscriber(username), groupId); - for (Application application : applications) { - if (application.getName().equals(applicationName)) { - apiConsumer.removeApplication(application); - break; - } - } - } - } catch (APIManagementException e) { - throw new APIManagerException( - "Failed to remove the application [ application name " + applicationName + " ]", e); + + StoreClient storeClient = APIApplicationManagerExtensionDataHolder.getInstance().getIntegrationClientService() + .getStoreClient(); + ApplicationList applicationList = storeClient.getApplications() + .applicationsGet("", applicationName, 1, 0, CONTENT_TYPE, null); + if (applicationList.getList() != null && applicationList.getList().size() > 0) { + ApplicationInfo applicationInfo = applicationList.getList().get(0); + storeClient.getIndividualApplication().applicationsApplicationIdDelete(applicationInfo.getApplicationId(), + null, null); } } @@ -124,203 +66,134 @@ public class APIManagementProviderServiceImpl implements APIManagementProviderSe * {@inheritDoc} */ @Override - public synchronized ApiApplicationKey generateAndRetrieveApplicationKeys(String apiApplicationName, String tags[], + public synchronized ApiApplicationKey generateAndRetrieveApplicationKeys(String applicationName, String tags[], String keyType, String username, boolean isAllowedAllDomains, String validityTime) throws APIManagerException { - try { - APIManagerUtil.loadTenantRegistry(); - APIConsumer apiConsumer = APIManagerFactory.getInstance().getAPIConsumer(username); - String groupId = getLoggedInUserGroupId(username, APIManagerUtil.getTenantDomain()); - int applicationId = createApplicationAndSubscribeToAPIs(apiApplicationName, tags, username); - Application[] applications = apiConsumer.getApplications(apiConsumer.getSubscriber(username), groupId); - Application application = null; - for (Application app : applications) { - if (app.getId() == applicationId) { - application = app; - } - } - if (application == null) { - throw new APIManagerException( - "Api application creation failed for " + apiApplicationName + " to the user " + username); - } - - OAuthApplicationInfo oAuthApp = application.getOAuthApp(keyType); - if (oAuthApp != null) { - ApiApplicationKey apiApplicationKey = new ApiApplicationKey(); - apiApplicationKey.setConsumerKey(oAuthApp.getClientId()); - apiApplicationKey.setConsumerSecret(oAuthApp.getClientSecret()); - return apiApplicationKey; - } - String[] allowedDomains = new String[1]; - if (isAllowedAllDomains) { - allowedDomains[0] = ApiApplicationConstants.ALLOWED_DOMAINS; - } else { - allowedDomains[0] = APIManagerUtil.getTenantDomain(); - } - String ownerJsonString = "{\"username\":\"" + username + "\"}"; - Map keyDetails = apiConsumer.requestApprovalForApplicationRegistration(username, - apiApplicationName, - keyType, "", - allowedDomains, - validityTime, - "null", - groupId, - ownerJsonString); - ApiApplicationKey apiApplicationKey = new ApiApplicationKey(); - apiApplicationKey.setConsumerKey((String) keyDetails.get(APIConstants.FrontEndParameterNames - .CONSUMER_KEY)); - apiApplicationKey.setConsumerSecret((String) keyDetails.get( - APIConstants.FrontEndParameterNames.CONSUMER_SECRET)); - return apiApplicationKey; - } catch (APIManagementException e) { - throw new APIManagerException("Failed to register a api application : " + apiApplicationName, e); - } - } - - private int createApplication(APIConsumer apiConsumer, String applicationName, String username, String groupId) - throws APIManagerException { - try { - if (apiConsumer != null) { - if (apiConsumer.getSubscriber(username) == null) { - String tenantDomain = MultitenantUtils.getTenantDomain(username); - addSubscriber(username, "", groupId, APIManagerUtil.getTenantId(tenantDomain)); - } - Application application = apiConsumer.getApplicationsByName(username, applicationName, groupId); - if (application == null) { - Subscriber subscriber = apiConsumer.getSubscriber(username); - application = new Application(applicationName, subscriber); - application.setTier(ApiApplicationConstants.DEFAULT_TIER); - application.setGroupId(groupId); - return apiConsumer.addApplication(application, username); - } else { - if (log.isDebugEnabled()) { - log.debug("Application [" + applicationName + "] already exists for Subscriber [" + username + - "]"); + 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) { + int tierStatus = 0; + int attempts = 0; + do { + try { + storeClient.getIndividualTier() + .tiersTierLevelTierNameGet(ApiApplicationConstants.DEFAULT_TIER, APP_TIER_TYPE, + tenantDomain, CONTENT_TYPE, null, null); + tiersMap.put(tenantDomain, "exist"); + tierStatus = 200; + } catch (FeignException e) { + tierStatus = e.status(); + attempts++; + try { + Thread.sleep(500); + } catch (InterruptedException ex) { + log.warn("Interrupted the waiting for tier availability."); } - return application.getId(); } - } else { - throw new APIManagerException("Failed to retrieve the api consumer for username" + username); - } - } catch (APIManagementException e) { - throw new APIManagerException("Failed to create application [name:" + applicationName + " , username:" - + username + ", " + "groupId:" + groupId, e); + } while (tierStatus == 500 && attempts < MAX_ATTEMPTS); } - } - private void addSubscription(APIConsumer apiConsumer, APIIdentifier apiId, int applicationId, String username) - throws APIManagerException { - try { - if (apiConsumer != null) { - APIIdentifier apiIdentifier = new APIIdentifier(apiId.getProviderName(), apiId.getApiName(), - apiId.getVersion()); - apiIdentifier.setTier(ApiApplicationConstants.DEFAULT_TIER); - apiConsumer.addSubscription(apiIdentifier, username, applicationId); - if (log.isDebugEnabled()) { - log.debug("Successfully created subscription for API : " + apiId + " from application : " + - applicationId); - } - } else { - throw new APIManagerException("API provider configured for the given API configuration is null. " + - "Thus, the API is not published"); - } - } catch (APIManagementException e) { - throw new APIManagerException("Failed to create subscription for api name : " + apiId.getApiName(), e); + ApplicationList applicationList = storeClient.getApplications() + .applicationsGet("", applicationName, 1, 0, CONTENT_TYPE, null); + Application application; + if (applicationList == null || applicationList.getList() == null || applicationList.getList().size() == 0) { + //create application; + application = new Application(); + application.setName(applicationName); + application.setSubscriber(username); + application.setDescription(""); + application.setThrottlingTier(ApiApplicationConstants.DEFAULT_TIER); + application.setGroupId(""); + application = storeClient.getIndividualApplication().applicationsPost(application, CONTENT_TYPE); + } else { + ApplicationInfo applicationInfo = applicationList.getList().get(0); + application = storeClient.getIndividualApplication() + .applicationsApplicationIdGet(applicationInfo.getApplicationId(), CONTENT_TYPE, null, null); + } + if (application == null) { + throw new APIManagerException ( + "Api application creation failed for " + applicationName + " to the user " + username); } - } + SubscriptionList subscriptionList = storeClient.getSubscriptions().subscriptionsGet + (null, application.getApplicationId(), "", 0, 100, CONTENT_TYPE, null); + List needToSubscribe = new ArrayList<>(); + // subscribe to apis. + if (tags != null && tags.length > 0) { + for (String tag: tags) { + APIList apiList = storeClient.getApis().apisGet(MAX_API_PER_TAG, 0, tenantDomain, "tag:" + tag + , CONTENT_TYPE, null); + if (apiList.getList() == null || apiList.getList().size() == 0) { + apiList = storeClient.getApis().apisGet(MAX_API_PER_TAG, 0 + , MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, "tag:" + tag, CONTENT_TYPE, null); + } - private void addSubscriber(String subscriberName, String subscriberEmail, String groupId, int tenantId) - throws APIManagerException { - if (log.isDebugEnabled()) { - log.debug("Creating subscriber with name " + subscriberName); - } - try { - APIConsumer consumer = APIManagerFactory.getInstance().getAPIConsumer(subscriberName); - if (consumer != null) { - synchronized (consumer) { - if (consumer.getSubscriber(subscriberName) == null) { - consumer.addSubscriber(subscriberName, groupId); - if (log.isDebugEnabled()) { - log.debug("Successfully created subscriber with name : " + subscriberName + - " with groupID : " + groupId); + if (apiList.getList() != null && apiList.getList().size() > 0) { + for (APIInfo apiInfo : apiList.getList()) { + String id = apiInfo.getProvider().replace("@", "-AT-") + + "-" + apiInfo.getName()+ "-" + apiInfo.getVersion(); + boolean subscriptionExist = false; + if (subscriptionList.getList() != null && subscriptionList.getList().size() > 0) { + for (Subscription subs : subscriptionList.getList()) { + if (subs.getApiIdentifier().equals(id)) { + subscriptionExist = true; + break; + } + } + } + if (!subscriptionExist) { + Subscription subscription = new Subscription(); + //fix for APIMANAGER-5566 admin-AT-tenant1.com-Tenant1API1-1.0.0 + + subscription.setApiIdentifier(id); + subscription.setApplicationId(application.getApplicationId()); + subscription.tier(ApiApplicationConstants.DEFAULT_TIER); + needToSubscribe.add(subscription); } } } - } else { - throw new APIManagerException("API provider configured for the given API configuration is null. " + - "Thus, the API is not published"); } - } catch (APIManagementException e) { - throw new APIManagerException("API provider configured for the given API configuration is null. " + - "Thus, the API is not published", e); } - } - - /** - * This method registers an api application and then subscribe the application to the api. - * - * @param apiApplicationName name of the application. - * @param tags are used subscribe the apis with the tag. - * @param username subscription is created for the user. - * @throws APIManagerException - */ - private int createApplicationAndSubscribeToAPIs(String apiApplicationName, String tags[], String username) - throws APIManagerException { - try { - APIConsumer apiConsumer = APIManagerFactory.getInstance().getAPIConsumer(username); - String groupId = getLoggedInUserGroupId(username, APIManagerUtil.getTenantDomain()); - int applicationId = createApplication(apiConsumer, apiApplicationName, username, groupId); - Subscriber subscriber = apiConsumer.getSubscriber(username); - Set userVisibleAPIs = null; - for (String tag : tags) { - Set tagAPIs = apiConsumer.getAPIsWithTag(tag, APIManagerUtil.getTenantDomain()); - if (userVisibleAPIs == null) { - userVisibleAPIs = tagAPIs; - } else { - userVisibleAPIs.addAll(tagAPIs); - } - } - if (userVisibleAPIs != null) { - Set subscribedAPIs = apiConsumer.getSubscribedAPIs(subscriber, apiApplicationName, - groupId); - for (API userVisibleAPI : userVisibleAPIs) { - APIIdentifier apiIdentifier = userVisibleAPI.getId(); - boolean isSubscribed = false; - if (subscribedAPIs != null) { - for (SubscribedAPI subscribedAPI : subscribedAPIs) { - if (subscribedAPI.getApiId().equals(apiIdentifier)) { - isSubscribed = true; - } - } - } - if (!isSubscribed) { - addSubscription(apiConsumer, apiIdentifier, applicationId, username); - } + if (!needToSubscribe.isEmpty()) { + storeClient.getSubscriptionMultitpleApi().subscriptionsMultiplePost(needToSubscribe, CONTENT_TYPE); + } + //end of subscription + + List applicationKeys = application.getKeys(); + if (applicationKeys != null) { + for (ApplicationKey applicationKey : applicationKeys) { + if (keyType.equals(applicationKey.getKeyType().toString())) { + ApiApplicationKey apiApplicationKey = new ApiApplicationKey(); + apiApplicationKey.setConsumerKey(applicationKey.getConsumerKey()); + apiApplicationKey.setConsumerSecret(applicationKey.getConsumerSecret()); + return apiApplicationKey; } } - return applicationId; - } catch (APIManagementException e) { - throw new APIManagerException("Failed to fetch device apis information for the user " + username, e); } - } - private String getLoggedInUserGroupId(String username, String tenantDomain) throws APIManagerException { - JSONObject loginInfoJsonObj = new JSONObject(); - try { - APIConsumer apiConsumer = APIManagerFactory.getInstance().getAPIConsumer(username); - loginInfoJsonObj.put("user", username); - if (MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) { - loginInfoJsonObj.put("isSuperTenant", true); - } else { - loginInfoJsonObj.put("isSuperTenant", false); - } - String loginInfoString = loginInfoJsonObj.toString(); - return apiConsumer.getGroupIds(loginInfoString); - } catch (APIManagementException e) { - throw new APIManagerException("Unable to get groupIds of user " + username, e); + ApplicationKeyGenerateRequest applicationKeyGenerateRequest = new ApplicationKeyGenerateRequest(); + List allowedDomains = new ArrayList<>(); + if (isAllowedAllDomains) { + allowedDomains.add(ApiApplicationConstants.ALLOWED_DOMAINS); + } else { + allowedDomains.add(APIManagerUtil.getTenantDomain()); } + applicationKeyGenerateRequest.setAccessAllowDomains(allowedDomains); + applicationKeyGenerateRequest.setCallbackUrl(""); + applicationKeyGenerateRequest.setKeyType(ApplicationKeyGenerateRequest.KeyTypeEnum.PRODUCTION); + applicationKeyGenerateRequest.setValidityTime(validityTime); + + ApplicationKey applicationKey = storeClient.getIndividualApplication().applicationsGenerateKeysPost( + application.getApplicationId(), applicationKeyGenerateRequest, CONTENT_TYPE, null, null); + ApiApplicationKey apiApplicationKey = new ApiApplicationKey(); + apiApplicationKey.setConsumerKey(applicationKey.getConsumerKey()); + apiApplicationKey.setConsumerSecret(applicationKey.getConsumerSecret()); + return apiApplicationKey; } } diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/internal/APIApplicationManagerExtensionDataHolder.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/internal/APIApplicationManagerExtensionDataHolder.java index 6beb0bbb62..cf7cbadea4 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/internal/APIApplicationManagerExtensionDataHolder.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/internal/APIApplicationManagerExtensionDataHolder.java @@ -18,6 +18,7 @@ package org.wso2.carbon.apimgt.application.extension.internal; import org.wso2.carbon.apimgt.application.extension.APIManagementProviderService; +import org.wso2.carbon.apimgt.integration.client.service.IntegrationClientService; import org.wso2.carbon.registry.core.service.TenantRegistryLoader; import org.wso2.carbon.registry.indexing.service.TenantIndexingLoader; import org.wso2.carbon.user.core.service.RealmService; @@ -30,6 +31,7 @@ public class APIApplicationManagerExtensionDataHolder { private TenantManager tenantManager; private TenantRegistryLoader tenantRegistryLoader; private TenantIndexingLoader indexLoader; + private IntegrationClientService integrationClientService; private APIApplicationManagerExtensionDataHolder() { } @@ -86,4 +88,13 @@ public class APIApplicationManagerExtensionDataHolder { public TenantIndexingLoader getIndexLoaderService(){ return indexLoader; } + + public IntegrationClientService getIntegrationClientService() { + return integrationClientService; + } + + public void setIntegrationClientService( + IntegrationClientService integrationClientService) { + this.integrationClientService = integrationClientService; + } } diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/internal/APIApplicationManagerExtensionServiceComponent.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/internal/APIApplicationManagerExtensionServiceComponent.java index 27104c13bd..18bdec251a 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/internal/APIApplicationManagerExtensionServiceComponent.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/internal/APIApplicationManagerExtensionServiceComponent.java @@ -23,6 +23,7 @@ import org.osgi.framework.BundleContext; import org.osgi.service.component.ComponentContext;; import org.wso2.carbon.apimgt.application.extension.APIManagementProviderService; import org.wso2.carbon.apimgt.application.extension.APIManagementProviderServiceImpl; +import org.wso2.carbon.apimgt.integration.client.service.IntegrationClientService; import org.wso2.carbon.registry.core.service.TenantRegistryLoader; import org.wso2.carbon.registry.indexing.service.TenantIndexingLoader; import org.wso2.carbon.user.core.service.RealmService; @@ -48,6 +49,12 @@ import org.wso2.carbon.user.core.service.RealmService; * policy="dynamic" * bind="setRealmService" * unbind="unsetRealmService" + * @scr.reference name="integration.client.service" + * interface="org.wso2.carbon.apimgt.integration.client.service.IntegrationClientService" + * cardinality="1..1" + * policy="dynamic" + * bind="setIntegrationClientService" + * unbind="unsetIntegrationClientService" */ public class APIApplicationManagerExtensionServiceComponent { @@ -86,6 +93,17 @@ public class APIApplicationManagerExtensionServiceComponent { APIApplicationManagerExtensionDataHolder.getInstance().setIndexLoaderService(null); } + protected void setIntegrationClientService(IntegrationClientService integrationClientService) { + if (integrationClientService != null && log.isDebugEnabled()) { + log.debug("integrationClientService initialized"); + } + APIApplicationManagerExtensionDataHolder.getInstance().setIntegrationClientService(integrationClientService); + } + + protected void unsetIntegrationClientService(IntegrationClientService integrationClientService) { + APIApplicationManagerExtensionDataHolder.getInstance().setIntegrationClientService(null); + } + /** * Sets Realm Service. * diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/pom.xml b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/pom.xml index 6591e2e062..0bdc33ad44 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/pom.xml +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/pom.xml @@ -21,13 +21,13 @@ apimgt-extensions org.wso2.carbon.devicemgt - 2.0.18-SNAPSHOT + 2.0.37-SNAPSHOT ../pom.xml 4.0.0 org.wso2.carbon.apimgt.handlers - 2.0.18-SNAPSHOT + 2.0.37-SNAPSHOT bundle WSO2 Carbon - API Security Handler Component WSO2 Carbon - API Management Security Handler Module diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/pom.xml b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/pom.xml new file mode 100644 index 0000000000..f6ae9c8508 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/pom.xml @@ -0,0 +1,147 @@ + + + + + + apimgt-extensions + org.wso2.carbon.devicemgt + 2.0.37-SNAPSHOT + ../pom.xml + + + 4.0.0 + org.wso2.carbon.apimgt.integration.client + 2.0.37-SNAPSHOT + bundle + WSO2 Carbon - API Management Integration Client + WSO2 Carbon - API Management Integration Client + http://wso2.org + + + + + org.apache.felix + maven-scr-plugin + + + org.apache.felix + maven-bundle-plugin + 1.4.0 + true + + + ${project.artifactId} + ${project.artifactId} + ${project.version} + APIM Integration + org.wso2.carbon.apimgt.integration.client.internal + + org.wso2.carbon.apimgt.integration.client.*, + !org.wso2.carbon.apimgt.integration.client.internal + + + org.osgi.framework, + org.osgi.service.component, + feign, + feign.codec, + feign.auth, + feign.gson, + feign.slf4j, + org.wso2.carbon.apimgt.integration.generated.client.publisher.api, + org.wso2.carbon.apimgt.integration.generated.client.store.api, + javax.xml.bind, + javax.xml.bind.annotation, + javax.xml.parsers;resolution:=optional, + org.apache.commons.logging, + org.w3c.dom, + org.wso2.carbon.context, + org.wso2.carbon.identity.jwt.client.*, + org.wso2.carbon.user.api, + org.wso2.carbon.utils, + com.fasterxml.jackson.annotation, + io.swagger.annotations, + org.wso2.carbon.core.util, + javax.xml, + org.wso2.carbon.base, + javax.net.ssl, + + + jsr311-api, + feign-jaxrs + + + + + + + + + + org.wso2.carbon + org.wso2.carbon.logging + + + org.eclipse.osgi + org.eclipse.osgi + + + org.eclipse.osgi + org.eclipse.osgi.services + + + com.google.code.gson + gson + + + javax.ws.rs + jsr311-api + + + + io.swagger + swagger-annotations + + + junit + junit + + + io.github.openfeign + feign-core + + + io.github.openfeign + feign-jackson + + + io.github.openfeign + feign-jaxrs + + + io.github.openfeign + feign-gson + + + + org.testng + testng + + + org.wso2.carbon.devicemgt + org.wso2.carbon.identity.jwt.client.extension + + + org.wso2.carbon.devicemgt + org.wso2.carbon.apimgt.integration.generated.client + + + + diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/IntegrationClientServiceImpl.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/IntegrationClientServiceImpl.java new file mode 100644 index 0000000000..7878bcfffd --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/IntegrationClientServiceImpl.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017, 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. + */ + +package org.wso2.carbon.apimgt.integration.client; + +import feign.RequestInterceptor; +import org.wso2.carbon.apimgt.integration.client.publisher.PublisherClient; +import org.wso2.carbon.apimgt.integration.client.service.IntegrationClientService; +import org.wso2.carbon.apimgt.integration.client.store.StoreClient; + +public class IntegrationClientServiceImpl implements IntegrationClientService { + + private static StoreClient storeClient; + private static PublisherClient publisherClient; + + public IntegrationClientServiceImpl() { + RequestInterceptor oAuthRequestInterceptor = new OAuthRequestInterceptor(); + storeClient = new StoreClient(oAuthRequestInterceptor); + publisherClient = new PublisherClient(oAuthRequestInterceptor); + } + @Override + public StoreClient getStoreClient() { + return storeClient; + } + + @Override + public PublisherClient getPublisherClient() { + return publisherClient; + } +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/OAuthRequestInterceptor.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/OAuthRequestInterceptor.java new file mode 100755 index 0000000000..d9afb2aa55 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/OAuthRequestInterceptor.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * Licensed 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. + * + */ + +package org.wso2.carbon.apimgt.integration.client; + +import feign.Feign; +import feign.Logger; +import feign.RequestInterceptor; +import feign.RequestTemplate; +import feign.auth.BasicAuthRequestInterceptor; +import feign.gson.GsonDecoder; +import feign.gson.GsonEncoder; +import feign.jaxrs.JAXRSContract; +import feign.slf4j.Slf4jLogger; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.apimgt.integration.client.configs.APIMConfigReader; +import org.wso2.carbon.apimgt.integration.client.exception.APIMClientOAuthException; +import org.wso2.carbon.apimgt.integration.client.internal.APIIntegrationClientDataHolder; +import org.wso2.carbon.apimgt.integration.client.model.ClientProfile; +import org.wso2.carbon.apimgt.integration.client.model.DCRClient; +import org.wso2.carbon.apimgt.integration.client.model.OAuthApplication; +import org.wso2.carbon.apimgt.integration.client.util.Utils; +import org.wso2.carbon.base.MultitenantConstants; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.identity.jwt.client.extension.JWTClient; +import org.wso2.carbon.identity.jwt.client.extension.dto.AccessTokenInfo; +import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException; + +import java.util.HashMap; +import java.util.Map; + +/** + * This is a request interceptor to add oauth token header. + */ +public class OAuthRequestInterceptor implements RequestInterceptor { + + private static final String APPLICATION_NAME = "api_integration_client"; + private static final String GRANT_TYPES = "password refresh_token urn:ietf:params:oauth:grant-type:jwt-bearer"; + private static final String REQUIRED_SCOPE = + "apim:api_create apim:api_view apim:api_publish apim:subscribe apim:tier_view apim:tier_manage " + + "apim:subscription_view apim:subscription_block"; + private static final String APIM_SUBSCRIBE_SCOPE = "apim:subscribe"; + private static final long DEFAULT_REFRESH_TIME_OFFSET_IN_MILLIS = 100000; + private DCRClient dcrClient; + private static OAuthApplication oAuthApplication; + private static Map tenantUserTokenMap = new HashMap<>(); + private static final Log log = LogFactory.getLog(OAuthRequestInterceptor.class); + + /** + * Creates an interceptor that authenticates all requests. + */ + public OAuthRequestInterceptor() { + String username = APIMConfigReader.getInstance().getConfig().getUsername(); + String password = APIMConfigReader.getInstance().getConfig().getPassword(); + dcrClient = Feign.builder().client(Utils.getSSLClient()).logger(new Slf4jLogger()).logLevel( + Logger.Level.FULL).requestInterceptor(new BasicAuthRequestInterceptor(username, password)) + .contract(new JAXRSContract()).encoder(new GsonEncoder()).decoder(new GsonDecoder()) + .target(DCRClient.class, Utils.replaceProperties( + APIMConfigReader.getInstance().getConfig().getDcrEndpoint())); + } + + @Override + public void apply(RequestTemplate template) { + if (oAuthApplication == null) { + //had to do on demand initialization due to start up error. + ClientProfile clientProfile = new ClientProfile(); + clientProfile.setClientName(APPLICATION_NAME); + clientProfile.setCallbackUrl(""); + clientProfile.setGrantType(GRANT_TYPES); + clientProfile.setOwner(APIMConfigReader.getInstance().getConfig().getUsername()); + clientProfile.setSaasApp(true); + oAuthApplication = dcrClient.register(clientProfile); + } + try { + String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); + String username = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); + if (!tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) { + username = username + "@" + tenantDomain; + } + AccessTokenInfo tenantBasedAccessTokenInfo = tenantUserTokenMap.get(username); + if ((tenantBasedAccessTokenInfo == null || + ((System.currentTimeMillis() + DEFAULT_REFRESH_TIME_OFFSET_IN_MILLIS) > + tenantBasedAccessTokenInfo.getExpiresIn()))) { + + JWTClient jwtClient = APIIntegrationClientDataHolder.getInstance().getJwtClientManagerService() + .getJWTClient(); + tenantBasedAccessTokenInfo = jwtClient.getAccessToken(oAuthApplication.getClientId(), + oAuthApplication.getClientSecret(), username, + REQUIRED_SCOPE); + tenantBasedAccessTokenInfo.setExpiresIn( + System.currentTimeMillis() + (tenantBasedAccessTokenInfo.getExpiresIn() * 1000)); + if (tenantBasedAccessTokenInfo.getScopes().contains(APIM_SUBSCRIBE_SCOPE)) { + tenantUserTokenMap.put(username, tenantBasedAccessTokenInfo); + } + + } + if (tenantBasedAccessTokenInfo.getAccessToken() != null) { + String headerValue = "Bearer " + tenantBasedAccessTokenInfo.getAccessToken(); + template.header("Authorization", headerValue); + } + } catch (JWTClientException e) { + throw new APIMClientOAuthException("failed to retrieve oauth token using jwt", e); + } + } + +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/configs/APIMConfig.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/configs/APIMConfig.java new file mode 100644 index 0000000000..1e3d34c746 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/configs/APIMConfig.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2017, 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. + */ + +package org.wso2.carbon.apimgt.integration.client.configs; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * This holds the configuration api manager integration. + */ +@XmlRootElement(name = "APIMConfiguration") +public class APIMConfig { + + String dcrEndpoint; + String tokenEndpoint; + String publisherEndpoint; + String storeEndpoint; + String username; + String password; + + @XmlElement(name = "DCREndpoint", required = true) + public String getDcrEndpoint() { + return dcrEndpoint; + } + + public void setDcrEndpoint(String dcrEndpoint) { + this.dcrEndpoint = dcrEndpoint; + } + + @XmlElement(name = "TokenEndpoint", required = true) + public String getTokenEndpoint() { + return tokenEndpoint; + } + + public void setTokenEndpoint(String tokenEndpoint) { + this.tokenEndpoint = tokenEndpoint; + } + + @XmlElement(name = "PublisherEndpoint", required = true) + public String getPublisherEndpoint() { + return publisherEndpoint; + } + + public void setPublisherEndpoint(String publisherEndpoint) { + this.publisherEndpoint = publisherEndpoint; + } + + @XmlElement(name = "StoreEndpoint", required = true) + public String getStoreEndpoint() { + return storeEndpoint; + } + + public void setStoreEndpoint(String storeEndpoint) { + this.storeEndpoint = storeEndpoint; + } + + @XmlElement(name = "Username", required = true) + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + @XmlElement(name = "Password", required = true) + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/configs/APIMConfigReader.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/configs/APIMConfigReader.java new file mode 100644 index 0000000000..8655a4d6a2 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/configs/APIMConfigReader.java @@ -0,0 +1,94 @@ +/* + * 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. + */ + +package org.wso2.carbon.apimgt.integration.client.configs; + +import org.w3c.dom.Document; +import org.wso2.carbon.apimgt.integration.client.exception.APIMClientException; +import org.wso2.carbon.apimgt.integration.client.exception.InvalidConfigurationStateException; +import org.wso2.carbon.utils.CarbonUtils; + +import javax.xml.XMLConstants; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.File; + +/** + * This holds the configuration parser for api integration.xml + */ +public class APIMConfigReader { + + private static APIMConfig config; + private static APIMConfigReader configReader= new APIMConfigReader(); + private static boolean isInitialized = false; + private static final String API_INTEGRATION_CONFIG_PATH = + CarbonUtils.getCarbonConfigDirPath() + File.separator + "apim-integration.xml"; + + private APIMConfigReader() { + + } + + private static String apimIntegrationXmlFilePath = ""; + + //TOD file may be a part of another file + public static APIMConfigReader getInstance() { + if (!isInitialized) { + try { + init(); + } catch (APIMClientException e) { + throw new InvalidConfigurationStateException("Webapp Authenticator Configuration is not " + + "initialized properly"); + } + } + return configReader; + } + + public static void init() throws APIMClientException { + try { + File apimConfigFile = new File(API_INTEGRATION_CONFIG_PATH); + Document doc = convertToDocument(apimConfigFile); + + JAXBContext ctx = JAXBContext.newInstance(APIMConfig.class); + Unmarshaller unmarshaller = ctx.createUnmarshaller(); + config = (APIMConfig) unmarshaller.unmarshal(doc); + isInitialized = true; + } catch (JAXBException e) { + throw new APIMClientException("Error occurred while un-marshalling APIMConfig", e); + } + } + + private static Document convertToDocument(File file) throws APIMClientException { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + try { + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + DocumentBuilder docBuilder = factory.newDocumentBuilder(); + return docBuilder.parse(file); + } catch (Exception e) { + throw new APIMClientException("Error occurred while parsing file 'apim-integration.xml' to a org.w3c.dom.Document", e); + } + } + + public APIMConfig getConfig() { + return config; + } + +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/exception/APIMClientException.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/exception/APIMClientException.java new file mode 100644 index 0000000000..f893f6d276 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/exception/APIMClientException.java @@ -0,0 +1,58 @@ +/* + * 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. + */ + +package org.wso2.carbon.apimgt.integration.client.exception; + +/** + * This holds api client exception. + */ +public class APIMClientException extends Exception { + + private static final long serialVersionUID = -3976392476319079281L; + private String responseReason; + private int responseStatus; + private String methodKey; + + APIMClientException(String methodKey, String reason, int status) { + super("Exception occured while invoking " + methodKey + " status = " + status + " reason = " + reason); + this.methodKey = methodKey; + this.responseReason = reason; + this.responseStatus = status; + } + + APIMClientException(String message) { + super(message); + } + + public APIMClientException(String message, Exception e) { + super(message, e); + } + + public String getResponseReason() { + return responseReason; + } + + public int getResponseStatus() { + return responseStatus; + } + + public String getMethodKey() { + return methodKey; + } + +} \ No newline at end of file diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/exception/APIMClientOAuthException.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/exception/APIMClientOAuthException.java new file mode 100644 index 0000000000..48f92d5abd --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/exception/APIMClientOAuthException.java @@ -0,0 +1,58 @@ +/* + * 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. + */ + +package org.wso2.carbon.apimgt.integration.client.exception; + +/** + * This holds api client exception. + */ +public class APIMClientOAuthException extends RuntimeException { + + private static final long serialVersionUID = -3976392476319079281L; + private String responseReason; + private int responseStatus; + private String methodKey; + + APIMClientOAuthException(String methodKey, String reason, int status) { + super("Exception occured while invoking " + methodKey + " status = " + status + " reason = " + reason); + this.methodKey = methodKey; + this.responseReason = reason; + this.responseStatus = status; + } + + APIMClientOAuthException(String message) { + super(message); + } + + public APIMClientOAuthException(String message, Exception e) { + super(message, e); + } + + public String getResponseReason() { + return responseReason; + } + + public int getResponseStatus() { + return responseStatus; + } + + public String getMethodKey() { + return methodKey; + } + +} \ No newline at end of file diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/exception/InvalidConfigurationStateException.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/exception/InvalidConfigurationStateException.java new file mode 100644 index 0000000000..dedb63c4bd --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/exception/InvalidConfigurationStateException.java @@ -0,0 +1,78 @@ +/* + * 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. + * + */ + +package org.wso2.carbon.apimgt.integration.client.exception; + +/** + * This error is thrown when there is an issue with the client. + */ +public class InvalidConfigurationStateException extends RuntimeException { + + private static final long serialVersionUID = -3151279311329070397L; + + private String errorMessage; + private int errorCode; + + public InvalidConfigurationStateException(int errorCode, String message) { + super(message); + this.errorCode = errorCode; + } + + public InvalidConfigurationStateException(int errorCode, String message, Throwable cause) { + super(message, cause); + this.errorCode = errorCode; + } + + public int getErrorCode() { + return errorCode; + } + + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public InvalidConfigurationStateException(String msg, Exception nestedEx) { + super(msg, nestedEx); + setErrorMessage(msg); + } + + public InvalidConfigurationStateException(String message, Throwable cause) { + super(message, cause); + setErrorMessage(message); + } + + public InvalidConfigurationStateException(String msg) { + super(msg); + setErrorMessage(msg); + } + + public InvalidConfigurationStateException() { + super(); + } + + public InvalidConfigurationStateException(Throwable cause) { + super(cause); + } + +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/internal/APIIntegrationClientDataHolder.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/internal/APIIntegrationClientDataHolder.java new file mode 100644 index 0000000000..a53572cf25 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/internal/APIIntegrationClientDataHolder.java @@ -0,0 +1,45 @@ +/* + * 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. + * + */ +package org.wso2.carbon.apimgt.integration.client.internal; + + +import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService; + +/** + * This holds the required service for this component + */ +public class APIIntegrationClientDataHolder { + private static APIIntegrationClientDataHolder thisInstance = new APIIntegrationClientDataHolder(); + private JWTClientManagerService jwtClientManagerService; + private APIIntegrationClientDataHolder() { + } + + + public static APIIntegrationClientDataHolder getInstance() { + return thisInstance; + } + + public void setJwtClientManagerService(JWTClientManagerService jwtClientManagerService) { + this.jwtClientManagerService = jwtClientManagerService; + } + + public JWTClientManagerService getJwtClientManagerService() { + return jwtClientManagerService; + } +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/internal/APIIntegrationClientServiceComponent.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/internal/APIIntegrationClientServiceComponent.java new file mode 100644 index 0000000000..aaf178b718 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/internal/APIIntegrationClientServiceComponent.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017, 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. + * + */ +package org.wso2.carbon.apimgt.integration.client.internal; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.osgi.framework.BundleContext; +import org.osgi.service.component.ComponentContext; +import org.wso2.carbon.apimgt.integration.client.IntegrationClientServiceImpl; +import org.wso2.carbon.apimgt.integration.client.configs.APIMConfigReader; +import org.wso2.carbon.apimgt.integration.client.service.IntegrationClientService; +import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService; + +/** + * @scr.component name="org.wso2.carbon.api.integration.client" immediate="true" + * @scr.reference name="api.integration.client.service" + * interface="org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService" + * cardinality="1..1" + * policy="dynamic" + * bind="setJWTClientManagerService" + * unbind="unsetJWTClientManagerService" + */ +public class APIIntegrationClientServiceComponent { + + private static Log log = LogFactory.getLog(APIIntegrationClientServiceComponent.class); + + protected void activate(ComponentContext componentContext) { + try { + if (log.isDebugEnabled()) { + log.debug("Initializing apimgt client bundle"); + } + + /* Initializing webapp publisher configuration */ + APIMConfigReader.init(); + BundleContext bundleContext = componentContext.getBundleContext(); + bundleContext.registerService(IntegrationClientService.class.getName(), new IntegrationClientServiceImpl(), null); + + if (log.isDebugEnabled()) { + log.debug("apimgt client bundle has been successfully initialized"); + } + } catch (Throwable e) { + log.error("Error occurred while initializing apimgt client bundle", e); + } + } + + protected void deactivate(ComponentContext componentContext) { + //do nothing + } + + protected void setJWTClientManagerService(JWTClientManagerService jwtClientManagerService) { + if (jwtClientManagerService != null) { + log.debug("jwtClientManagerService service is initialized"); + } + APIIntegrationClientDataHolder.getInstance().setJwtClientManagerService(jwtClientManagerService); + } + + protected void unsetJWTClientManagerService(JWTClientManagerService jwtClientManagerService) { + APIIntegrationClientDataHolder.getInstance().setJwtClientManagerService(null); + } + +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/model/ClientProfile.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/model/ClientProfile.java new file mode 100644 index 0000000000..fe1821d3a4 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/model/ClientProfile.java @@ -0,0 +1,96 @@ +/* + * 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. + */ + +package org.wso2.carbon.apimgt.integration.client.model; + +/** + * DTO fo DCR request. + */ +public class ClientProfile { + + private String clientName; + private String callbackUrl; + private String tokenScope; + private String owner; + private String grantType; + private boolean saasApp; + + public String getClientName() { + return clientName; + } + + public void setClientName(String clientName) { + this.clientName = clientName; + } + + public String getCallbackUrl() { + return callbackUrl; + } + + public void setCallbackUrl(String callbackUrl) { + this.callbackUrl = callbackUrl; + } + + public String getTokenScope() { + return tokenScope; + } + + public void setTokenScope(String tokenScope) { + this.tokenScope = tokenScope; + } + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + this.owner = owner; + } + + public String getGrantType() { + return grantType; + } + + public void setGrantType(String grantTypem) { + this.grantType = grantTypem; + } + + public boolean isSaasApp() { + return saasApp; + } + + public void setSaasApp(boolean saasApp) { + this.saasApp = saasApp; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("{\n"); + + sb.append(" clientName: ").append(clientName).append("\n"); + sb.append(" callbackUrl: ").append("callbackUrl").append("\n"); + sb.append(" grantType: ").append(grantType).append("\n"); + sb.append(" tokenScope: ").append(tokenScope).append("\n"); + sb.append(" owner: ").append(owner).append("\n"); + sb.append(" saasApp: ").append(saasApp).append("\n"); + sb.append("}\n"); + return sb.toString(); + } + +} diff --git a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/handlers/grant/ExtendedPasswordGrantHandler.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/model/DCRClient.java similarity index 57% rename from components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/handlers/grant/ExtendedPasswordGrantHandler.java rename to components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/model/DCRClient.java index 8a5be8bc8d..2adcfa45ad 100644 --- a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/handlers/grant/ExtendedPasswordGrantHandler.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/model/DCRClient.java @@ -16,17 +16,21 @@ * under the License. */ -package org.wso2.carbon.device.mgt.oauth.extensions.handlers.grant; +package org.wso2.carbon.apimgt.integration.client.model; -import org.wso2.carbon.device.mgt.oauth.extensions.OAuthExtUtils; -import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext; +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; -@SuppressWarnings("unused") -public class ExtendedPasswordGrantHandler extends org.wso2.carbon.apimgt.keymgt.handlers.ExtendedPasswordGrantHandler { +/** + * DCR Rest resource. + */ +@Path("/") +public interface DCRClient { - @Override - public boolean validateScope(OAuthTokenReqMessageContext tokReqMsgCtx) { - return OAuthExtUtils.setScopes(tokReqMsgCtx); - } + // DCR APIs + @POST + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + OAuthApplication register(ClientProfile registrationProfile); } diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/model/OAuthApplication.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/model/OAuthApplication.java new file mode 100644 index 0000000000..7f3bf458f4 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/model/OAuthApplication.java @@ -0,0 +1,103 @@ +/* + * 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. + */ + +package org.wso2.carbon.apimgt.integration.client.model; + +public class OAuthApplication { + + private String jsonString; + private String appOwner; + private String clientName; + private String callBackURL; + private String isSaasApplication; + private String clientId; + private String clientSecret; + + public String getJsonString() { + return jsonString; + } + + public void setJsonString(String jsonString) { + this.jsonString = jsonString; + } + + public String getAppOwner() { + return appOwner; + } + + public void setAppOwner(String appOwner) { + this.appOwner = appOwner; + } + + public String getClientName() { + return clientName; + } + + public void setClientName(String clientName) { + this.clientName = clientName; + } + + public String getCallBackURL() { + return callBackURL; + } + + public void setCallBackURL(String callBackURL) { + this.callBackURL = callBackURL; + } + + public String getIsSaasApplication() { + return isSaasApplication; + } + + public void setIsSaasApplication(String isSaasApplication) { + this.isSaasApplication = isSaasApplication; + } + + public String getClientId() { + return clientId; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public String getClientSecret() { + return clientSecret; + } + + public void setClientSecret(String clientSecret) { + this.clientSecret = clientSecret; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class OAuthApplication {\n"); + + sb.append(" jsonString: ").append(jsonString).append("\n"); + sb.append(" appOwner: ").append(appOwner).append("\n"); + sb.append(" clientName: ").append(clientName).append("\n"); + sb.append(" callBackURL: ").append(callBackURL).append("\n"); + sb.append(" isSaasApplication: ").append(isSaasApplication).append("\n"); + sb.append(" clientId: ").append(isSaasApplication).append("\n"); + sb.append(" clientSecret: ").append(clientSecret).append("\n"); + sb.append("}\n"); + return sb.toString(); + } + +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/publisher/PublisherClient.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/publisher/PublisherClient.java new file mode 100644 index 0000000000..5ce49b7e83 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/publisher/PublisherClient.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2017, 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. + */ +package org.wso2.carbon.apimgt.integration.client.publisher; + +import feign.Feign; +import feign.Logger; +import feign.RequestInterceptor; +import feign.gson.GsonDecoder; +import feign.gson.GsonEncoder; +import feign.slf4j.Slf4jLogger; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.apimgt.integration.client.configs.APIMConfigReader; +import org.wso2.carbon.apimgt.integration.generated.client.publisher.api.*; +import org.wso2.carbon.core.util.Utils; + +/** + * Publisher client generated using swagger. + */ +public class PublisherClient { + + private static final Log log = LogFactory.getLog(PublisherClient.class); + private APIsApi api = null; + private APIDocumentApi document = null; + private ApplicationsApi application = null; + private EnvironmentsApi environments = null; + private SubscriptionsApi subscriptions = null; + private TiersApi tiers = null; + + + /** + * PublisherClient constructor - Initialize a PublisherClient instance + * + */ + public PublisherClient(RequestInterceptor requestInterceptor) { + Feign.Builder builder = Feign.builder().client( + org.wso2.carbon.apimgt.integration.client.util.Utils.getSSLClient()).logger(new Slf4jLogger()) + .logLevel(Logger.Level.FULL) + .requestInterceptor(requestInterceptor).encoder(new GsonEncoder()).decoder(new GsonDecoder()); + String basePath = Utils.replaceSystemProperty(APIMConfigReader.getInstance().getConfig().getPublisherEndpoint()); + + api = builder.target(APIsApi.class, basePath); + document = builder.target(APIDocumentApi.class, basePath); + application = builder.target(ApplicationsApi.class, basePath); + environments = builder.target(EnvironmentsApi.class, basePath); + subscriptions = builder.target(SubscriptionsApi.class, basePath); + tiers = builder.target(TiersApi.class, basePath); + } + + public APIsApi getApi() { + return api; + } + + public APIDocumentApi getDocument() { + return document; + } + + public ApplicationsApi getApplication() { + return application; + } + + public EnvironmentsApi getEnvironments() { + return environments; + } + + public SubscriptionsApi getSubscriptions() { + return subscriptions; + } + + public TiersApi getTiers() { + return tiers; + } +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/service/IntegrationClientService.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/service/IntegrationClientService.java new file mode 100644 index 0000000000..0ac7e4616f --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/service/IntegrationClientService.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2017, 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. + */ +package org.wso2.carbon.apimgt.integration.client.service; + + +import org.wso2.carbon.apimgt.integration.client.publisher.PublisherClient; +import org.wso2.carbon.apimgt.integration.client.store.StoreClient; + +/** + * This is a service that can be called upon to access store and publisher. + */ +public interface IntegrationClientService { + + /** + * + * @return API Store Client. + */ + StoreClient getStoreClient(); + + /** + * + * @return API Publisher Client. + */ + PublisherClient getPublisherClient(); + +} 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 new file mode 100644 index 0000000000..9c12b0cdaa --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/store/StoreClient.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2017, 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. + */ +package org.wso2.carbon.apimgt.integration.client.store; + +import feign.Feign; +import feign.Logger; +import feign.RequestInterceptor; +import feign.gson.GsonDecoder; +import feign.gson.GsonEncoder; +import feign.slf4j.Slf4jLogger; +import org.apache.commons.logging.LogFactory; +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; + +/** + * API Store client, created using swagger gen. + */ +public class StoreClient { + + private static final org.apache.commons.logging.Log log = LogFactory.getLog(StoreClient.class); + private APICollectionApi apis = null; + private APIIndividualApi individualApi = null; + private ApplicationCollectionApi applications = null; + private ApplicationIndividualApi individualApplication = null; + private SubscriptionCollectionApi subscriptions = null; + private SubscriptionIndividualApi individualSubscription = null; + private SubscriptionMultitpleApi subscriptionMultitpleApi = null; + private ThrottlingTierIndividualApi individualTier = null; + private TagCollectionApi tags = null; + private ThrottlingTierCollectionApi tiers = null; + + + public StoreClient(RequestInterceptor requestInterceptor) { + + Feign.Builder builder = Feign.builder().client( + org.wso2.carbon.apimgt.integration.client.util.Utils.getSSLClient()).logger(new Slf4jLogger()) + .logLevel(Logger.Level.FULL) + .requestInterceptor(requestInterceptor).encoder(new GsonEncoder()).decoder(new GsonDecoder()); + String basePath = Utils.replaceSystemProperty(APIMConfigReader.getInstance().getConfig().getStoreEndpoint()); + + apis = builder.target(APICollectionApi.class, basePath); + individualApi = builder.target(APIIndividualApi.class, basePath); + applications = builder.target(ApplicationCollectionApi.class, basePath); + individualApplication = builder.target(ApplicationIndividualApi.class, basePath); + subscriptions = builder.target(SubscriptionCollectionApi.class, basePath); + 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); + + } + + public APICollectionApi getApis() { + return apis; + } + + public APIIndividualApi getIndividualApi() { + return individualApi; + } + + public ApplicationCollectionApi getApplications() { + return applications; + } + + public ApplicationIndividualApi getIndividualApplication() { + return individualApplication; + } + + public SubscriptionCollectionApi getSubscriptions() { + return subscriptions; + } + + public SubscriptionIndividualApi getIndividualSubscription() { + return individualSubscription; + } + + public ThrottlingTierIndividualApi getIndividualTier() { + return individualTier; + } + + public TagCollectionApi getTags() { + return tags; + } + + public ThrottlingTierCollectionApi getTiers() { + return tiers; + } + + public SubscriptionMultitpleApi getSubscriptionMultitpleApi() { + return subscriptionMultitpleApi; + } +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/util/Utils.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/util/Utils.java new file mode 100644 index 0000000000..ed5a587986 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/util/Utils.java @@ -0,0 +1,89 @@ +/* +* 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. +*/ + +package org.wso2.carbon.apimgt.integration.client.util; + + +import feign.Client; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import java.io.IOException; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import feign.Logger; +import feign.Request; +import feign.Response; +import org.apache.commons.logging.Log; + +public class Utils { + + //This method is only used if the mb features are within DAS. + public static String replaceProperties(String text) { + String regex = "\\$\\{(.*?)\\}"; + Pattern pattern = Pattern.compile(regex); + Matcher matchPattern = pattern.matcher(text); + while (matchPattern.find()) { + String sysPropertyName = matchPattern.group(1); + String sysPropertyValue = System.getProperty(sysPropertyName); + if (sysPropertyValue != null && !sysPropertyName.isEmpty()) { + text = text.replaceAll("\\$\\{(" + sysPropertyName + ")\\}", sysPropertyValue); + } + } + return text; + } + + public static Client getSSLClient() { + return new Client.Default(getTrustedSSLSocketFactory(), new HostnameVerifier() { + @Override + public boolean verify(String s, SSLSession sslSession) { + return true; + } + }); + } + + private static SSLSocketFactory getTrustedSSLSocketFactory() { + try { + TrustManager[] trustAllCerts = new TrustManager[]{ + new X509TrustManager() { + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return null; + } + public void checkClientTrusted( + java.security.cert.X509Certificate[] certs, String authType) { + } + public void checkServerTrusted( + java.security.cert.X509Certificate[] certs, String authType) { + } + } + }; + SSLContext sc = SSLContext.getInstance("SSL"); + sc.init(null, trustAllCerts, new java.security.SecureRandom()); + return sc.getSocketFactory(); + } catch (KeyManagementException | NoSuchAlgorithmException e) { + return null; + } + + } +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.generated.client/pom.xml b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.generated.client/pom.xml new file mode 100644 index 0000000000..c9cb4af3fb --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.generated.client/pom.xml @@ -0,0 +1,206 @@ + + + + + + apimgt-extensions + org.wso2.carbon.devicemgt + 2.0.37-SNAPSHOT + ../pom.xml + + + 4.0.0 + org.wso2.carbon.apimgt.integration.generated.client + 2.0.37-SNAPSHOT + bundle + WSO2 Carbon - API Management Integration Generated Client + WSO2 Carbon - API Management Integration Client + http://wso2.org + + + + + + io.swagger + swagger-codegen-maven-plugin + 2.2.1 + + + process-resources + publisher + + generate + + + ${project.basedir}/src/main/resources/publisher-api.yaml + java + + ${project.artifactId}.publisher.api + ${project.artifactId}.publisher.model + + feign + + + + process-resources + store + + generate + + + ${project.basedir}/src/main/resources/store-api.yaml + java + + ${project.artifactId}.store.api + ${project.artifactId}.store.model + + feign + + + + + + com.google.code.maven-replacer-plugin + replacer + 1.5.2 + + + + process-resources + replace-for-swagger-genenerated-code-publisher + + replace + + + ${project.basedir}/target/generated-sources/swagger/src/main/java/org/wso2/carbon/apimgt/integration/generated/client/publisher/model/API.java + + + CURRENT_TENANT + current_tenant + + + ALL_TENANTS + all_tenants + + + SPECIFIC_TENANTS + specific_tenants + + + + + + + + org.apache.felix + maven-bundle-plugin + true + + + ${project.artifactId} + ${project.artifactId} + ${project.version} + APIM Integration + + org.wso2.carbon.apimgt.integration.generated.client.publisher.api.*, + org.wso2.carbon.apimgt.integration.generated.client.publisher.model.*, + org.wso2.carbon.apimgt.integration.generated.client.store.api.*, + org.wso2.carbon.apimgt.integration.generated.client.store.model.* + + + feign;version="${io.github.openfeign.version.range}", + feign.jackson;version="${io.github.openfeign.version.range}", + feign.codec;version="${io.github.openfeign.version.range}", + feign.auth;version="${io.github.openfeign.version.range}", + feign.gson;version="${io.github.openfeign.version.range}", + feign.slf4j;version="${io.github.openfeign.version.range}", + com.google.gson, + com.fasterxml.jackson.core;resolution:=optional, + com.fasterxml.jackson.annotation, + com.fasterxml.jackson.databind;resolution:=optional, + io.swagger.annotations, + javax.net.ssl, + com.fasterxml.jackson.datatype.joda;resolution:=optional, + org.apache.oltu.oauth2.client.*;resolution:=optional, + org.apache.oltu.oauth2.common.*;resolution:=optional, + org.junit;resolution:=optional, + + + jsr311-api, + feign-jaxrs + + + + + + + + + + + com.google.code.gson + gson + + + javax.ws.rs + jsr311-api + + + + io.swagger + swagger-annotations + + + junit + junit + + + io.github.openfeign + feign-core + + + io.github.openfeign + feign-jackson + + + io.github.openfeign + feign-jaxrs + + + io.github.openfeign + feign-gson + + + org.testng + testng + + + org.apache.oltu.oauth2 + org.apache.oltu.oauth2.client + + + io.github.openfeign + feign-slf4j + + + org.wso2.orbit.com.fasterxml.jackson.core + jackson-databind + ${jackson-databind.version} + + + com.fasterxml.jackson.datatype + jackson-datatype-joda + + + + true + + diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.generated.client/src/main/resources/publisher-api.yaml b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.generated.client/src/main/resources/publisher-api.yaml new file mode 100644 index 0000000000..f213bd6652 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.generated.client/src/main/resources/publisher-api.yaml @@ -0,0 +1,2747 @@ +swagger: '2.0' +###################################################### +# Prolog +###################################################### +info: + version: "0.10.0" + title: "WSO2 API Manager - Publisher API" + description: | + This document specifies a **RESTful API** for WSO2 **API Manager** - Publisher. + + It is written with [swagger 2](http://swagger.io/). + + contact: + name: "WSO2" + url: "http://wso2.com/products/api-manager/" + email: "architecture@wso2.com" + license: + name: "Apache 2.0" + url: "http://www.apache.org/licenses/LICENSE-2.0.html" + +###################################################### +# The fixed parts of the URLs of the API +###################################################### + +# The schemes supported by the API +schemes: + - https + +# The domain of the API. +# This is configured by the customer during deployment. +# The given host is just an example. +host: apis.wso2.com + +# The base path of the API. +# Will be prefixed to all paths. +basePath: /api/am/publisher/v0.10 + +# The following media types can be passed as input in message bodies of the API. +# The actual media type must be specified in the Content-Type header field of the request. +# The default is json, i.e. the Content-Type header is not needed to +# be set, but supporting it serves extensibility. +consumes: + - application/json + +# The following media types may be passed as output in message bodies of the API. +# The media type(s) consumable by the requestor is specified in the Accept header field +# of the corresponding request. +# The actual media type returned will be specfied in the Content-Type header field +# of the of the response. +# The default of the Accept header is json, i.e. there is not needed to +# set the value, but supporting it serves extensibility. +produces: + - application/json + + +x-wso2-security: + apim: + x-wso2-scopes: + - description: "" + roles: admin + name: apim:api_view + key: apim:api_view + - description: "" + roles: admin + name: apim:api_create + key: apim:api_create + - description: "" + roles: admin + name: apim:api_publish + key: apim:api_publish + - description: "" + roles: admin + name: apim:tier_view + key: apim:tier_view + - description: "" + roles: admin + name: apim:tier_manage + key: apim:tier_manage + - description: "" + roles: admin + name: apim:subscription_view + key: apim:subscription_view + - description: "" + roles: admin + name: apim:subscription_block + key: apim:subscription_block + +###################################################### +# The "API Collection" resource APIs +###################################################### +paths: + /apis: + +#----------------------------------------------------- +# Retrieving the list of all APIs qualifying under a given search condition +#----------------------------------------------------- + get: + x-scope: apim:api_view + x-wso2-curl: "curl -H \"Authorization: Bearer b0982cd2aacd463ff5f63cd5ebe58f4a\" http://127.0.0.1:9763/api/am/publisher/v0.10/apis" + x-wso2-response: "HTTP/1.1 200 OK\nContent-Type: application/json\n\n{\n \"previous\": \"\",\n \"list\": [\n {\n \"provider\": \"admin\",\n \"version\": \"1.0.0\",\n \"description\": \"This sample API provides Account Status Validation\",\n \"name\": \"AccountVal\",\n \"context\": \"/account\",\n \"id\": \"2e81f147-c8a8-4f68-b4f0-69e0e7510b01\",\n \"status\": \"PUBLISHED\"\n },\n {\n \"provider\": \"admin\",\n \"version\": \"1.0.0\",\n \"description\": null,\n \"name\": \"api1\",\n \"context\": \"/api1\",\n \"id\": \"3e22d2fb-277a-4e9e-8c7e-1c0f7f73960e\",\n \"status\": \"PUBLISHED\"\n }\n ],\n \"next\": \"\",\n \"count\": 2\n}" + summary: | + Get all APIs + description: | + Get a list of available APIs qualifying under a given search condition. + parameters: + - $ref : '#/parameters/limit' + - $ref : '#/parameters/offset' + - name : query + in: query + description: | + **Search condition**. + + You can search in attributes by using an **"attribute:"** modifier. + + Eg. "provider:wso2" will match an API if the provider of the API contains "wso2". + + Supported attribute modifiers are [**version, context, status, + description, subcontext, doc, provider**] + + If no advanced attribute modifier has been specified, search will match the + given query string against API Name. + type: string + - $ref : "#/parameters/Accept" + - $ref : "#/parameters/If-None-Match" + tags: + - APIs + responses: + 200: + description: | + OK. + List of qualifying APIs is returned. + schema: + $ref: '#/definitions/APIList' + headers: + Content-Type: + description: The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. Used by caches, or in conditional requests. + type: string + 304: + description: | + Not Modified. + Empty body because the client has already the latest version of the requested resource. + 406: + description: | + Not Acceptable. + The requested media type is not supported + schema: + $ref: '#/definitions/Error' + +#----------------------------------------------------- +# Create a new API +#----------------------------------------------------- + post: + x-scope: apim:api_create + x-wso2-curl: "curl -H \"Authorization: Bearer 40e486e50ce43407181fb4c570d2cac7\" -H \"Content-Type: application/json\" -X POST -d @data.json http://127.0.0.1:9763/api/am/publisher/v0.10/apis" + x-wso2-request: "{\n \"sequences\": [],\n \"tiers\": [\n \"Bronze\",\n \"Gold\"\n ],\n \"thumbnailUrl\": null,\n \"visibility\": \"PUBLIC\",\n \"visibleRoles\": [],\n \"visibleTenants\": [],\n \"cacheTimeout\": 300,\n \"endpointConfig\": \"{\\\"production_endpoints\\\":{\\\"url\\\":\\\" http://ws.cdyne.com/phoneverify/phoneverify.asmx\\\",\\\"config\\\":null},\\\"endpoint_type\\\":\\\"http\\\"}\",\n \"subscriptionAvailability\": null,\n \"subscriptionAvailableTenants\": [],\n \"destinationStatsEnabled\": \"Disabled\",\n \"apiDefinition\": \"{\\\"paths\\\":{\\\"\\/*\\\":{\\\"get\\\":{\\\"x-auth-type\\\":\\\"Application\\\",\\\"x-throttling-tier\\\":\\\"Unlimited\\\",\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"OK\\\"}}}}},\\\"x-wso2-security\\\":{\\\"apim\\\":{\\\"x-wso2-scopes\\\":[]}},\\\"swagger\\\":\\\"2.0\\\",\\\"info\\\":{\\\"title\\\":\\\"PhoneVerification\\\",\\\"description\\\":\\\"Verify a phone number\\\",\\\"contact\\\":{\\\"email\\\":\\\"xx@ee.com\\\",\\\"name\\\":\\\"xx\\\"},\\\"version\\\":\\\"1.0.0\\\"}}\",\n \"responseCaching\": \"Disabled\",\n \"isDefaultVersion\": true,\n \"gatewayEnvironments\": \"Production and Sandbox\",\n \"businessInformation\": {\n \"technicalOwner\": \"xx\",\n \"technicalOwnerEmail\": \"ggg@ww.com\",\n \"businessOwner\": \"xx\",\n \"businessOwnerEmail\": \"xx@ee.com\"\n },\n \"transport\": [\n \"http\",\n \"https\"\n ],\n \"tags\": [\n \"phone\",\n \"multimedia\",\n \"mobile\"\n ],\n \"provider\": \"admin\",\n \"version\": \"1.0.0\",\n \"description\": \"Verify a phone number\",\n \"name\": \"PhoneVerification\",\n \"context\": \"/phoneverify\"\n}" + x-wso2-response: "HTTP/1.1 201 Created\nLocation: http://localhost:9763/api/am/publisher/v0.10/apis/890a4f4d-09eb-4877-a323-57f6ce2ed79b\nContent-Type: application/json\n\n{\n \"sequences\": [],\n \"tiers\": [\n \"Bronze\",\n \"Gold\"\n ],\n \"thumbnailUrl\": null,\n \"visibility\": \"PUBLIC\",\n \"visibleRoles\": [],\n \"visibleTenants\": [],\n \"cacheTimeout\": 300,\n \"endpointConfig\": \"{\\\"production_endpoints\\\":{\\\"url\\\":\\\" http://ws.cdyne.com/phoneverify/phoneverify.asmx\\\",\\\"config\\\":null},\\\"endpoint_type\\\":\\\"http\\\"}\",\n \"subscriptionAvailability\": null,\n \"subscriptionAvailableTenants\": [],\n \"destinationStatsEnabled\": \"Disabled\",\n \"apiDefinition\": \"{\\\"paths\\\":{\\\"\\/*\\\":{\\\"get\\\":{\\\"x-auth-type\\\":\\\"Application\\\",\\\"x-throttling-tier\\\":\\\"Unlimited\\\",\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"OK\\\"}}}}},\\\"x-wso2-security\\\":{\\\"apim\\\":{\\\"x-wso2-scopes\\\":[]}},\\\"swagger\\\":\\\"2.0\\\",\\\"info\\\":{\\\"title\\\":\\\"PhoneVerification\\\",\\\"description\\\":\\\"Verify a phone number\\\",\\\"contact\\\":{\\\"email\\\":\\\"xx@ee.com\\\",\\\"name\\\":\\\"xx\\\"},\\\"version\\\":\\\"1.0.0\\\"}}\",\n \"responseCaching\": \"Disabled\",\n \"isDefaultVersion\": true,\n \"gatewayEnvironments\": \"Production and Sandbox\",\n \"businessInformation\": {\n \"technicalOwner\": \"xx\",\n \"technicalOwnerEmail\": \"ggg@ww.com\",\n \"businessOwner\": \"xx\",\n \"businessOwnerEmail\": \"xx@ee.com\"\n },\n \"transport\": [\n \"http\",\n \"https\"\n ],\n \"tags\": [\n \"phone\",\n \"multimedia\",\n \"mobile\"\n ],\n \"provider\": \"admin\",\n \"version\": \"1.0.0\",\n \"description\": \"Verify a phone number\",\n \"name\": \"PhoneVerification\",\n \"context\": \"/phoneverify\",\n \"id\": \"890a4f4d-09eb-4877-a323-57f6ce2ed79b\",\n \"status\": \"CREATED\"\n}" + summary: Create a new API + description: | + Create a new API + parameters: + - in: body + name: body + description: | + API object that needs to be added + required: true + schema: + $ref: '#/definitions/API' + - $ref: '#/parameters/Content-Type' + tags: + - APIs + responses: + 201: + description: | + Created. + Successful response with the newly created object as entity in the body. + Location header contains URL of newly created entity. + schema: + $ref: '#/definitions/API' + headers: + Location: + description: | + The URL of the newly created resource. + type: string + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. Used by caches, or in conditional request + type: string + 400: + description: | + Bad Request. + Invalid request or validation error. + schema: + $ref: '#/definitions/Error' + 415: + description: | + Unsupported Media Type. + The entity of the request was in a not supported format. + schema: + $ref: '#/definitions/Error' + +###################################################### +# The "Individual API" resource APIs +###################################################### + /apis/{apiId}: + +#----------------------------------------------------- +# Retrieve the details of an API definition +#----------------------------------------------------- + get: + x-scope: apim:api_view + x-wso2-curl: "curl -H \"Authorization: Bearer b0982cd2aacd463ff5f63cd5ebe58f4a\" http://127.0.0.1:9763/api/am/publisher/v0.10/apis/890a4f4d-09eb-4877-a323-57f6ce2ed79b" + x-wso2-response: "HTTP/1.1 200 OK\nDate: Mon, 22 Feb 2016 13:27:08 GMT\nContent-Type: application/json\nTransfer-Encoding: chunked\nServer: WSO2 Carbon Server\n\n{\n \"sequences\": [],\n \"tiers\": [\n \"Bronze\",\n \"Gold\"\n ],\n \"thumbnailUrl\": null,\n \"visibility\": \"PUBLIC\",\n \"visibleRoles\": [],\n \"visibleTenants\": [],\n \"cacheTimeout\": 300,\n \"endpointConfig\": \"{\\\"production_endpoints\\\":{\\\"url\\\":\\\" http://ws.cdyne.com/phoneverify/phoneverify.asmx\\\",\\\"config\\\":null},\\\"endpoint_type\\\":\\\"http\\\"}\",\n \"subscriptionAvailability\": null,\n \"subscriptionAvailableTenants\": [],\n \"destinationStatsEnabled\": \"Disabled\",\n \"apiDefinition\": \"{\\\"paths\\\":{\\\"\\/*\\\":{\\\"get\\\":{\\\"x-auth-type\\\":\\\"Application\\\",\\\"x-throttling-tier\\\":\\\"Unlimited\\\",\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"OK\\\"}}}}},\\\"x-wso2-security\\\":{\\\"apim\\\":{\\\"x-wso2-scopes\\\":[]}},\\\"swagger\\\":\\\"2.0\\\",\\\"info\\\":{\\\"title\\\":\\\"PhoneVerification\\\",\\\"description\\\":\\\"Verify a phone number\\\",\\\"contact\\\":{\\\"email\\\":\\\"xx@ee.com\\\",\\\"name\\\":\\\"xx\\\"},\\\"version\\\":\\\"1.0.0\\\"}}\",\n \"responseCaching\": \"Disabled\",\n \"isDefaultVersion\": false,\n \"gatewayEnvironments\": \"Production and Sandbox\",\n \"businessInformation\": {\n \"technicalOwner\": \"xx\",\n \"technicalOwnerEmail\": \"ggg@ww.com\",\n \"businessOwner\": \"xx\",\n \"businessOwnerEmail\": \"xx@ee.com\"\n },\n \"transport\": [\n \"http\",\n \"https\"\n ],\n \"tags\": [\n \"phone\",\n \"multimedia\",\n \"mobile\"\n ],\n \"provider\": \"admin\",\n \"version\": \"1.0.0\",\n \"description\": \"Verify a phone number\",\n \"name\": \"PhoneVerification\",\n \"context\": \"/phoneverify\",\n \"id\": \"890a4f4d-09eb-4877-a323-57f6ce2ed79b\",\n \"status\": \"PUBLISHED\"\n}" + summary: Get API details + description: | + Get details of an API + parameters: + - $ref: '#/parameters/apiId' + - $ref: '#/parameters/Accept' + - $ref: '#/parameters/If-None-Match' + - $ref: '#/parameters/If-Modified-Since' + tags: + - APIs + responses: + 200: + description: | + OK. + Requested API is returned + headers: + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. Used by caches, or in conditional requests. + type: string + Last-Modified: + description: | + Date and time the resource has been modifed the last time. + Used by caches, or in conditional requests. + type: string + schema: + $ref: '#/definitions/API' + 304: + description: | + Not Modified. + Empty body because the client has already the latest version of the requested resource. + 404: + description: | + Not Found. + Requested API does not exist. + schema: + $ref: '#/definitions/Error' + 406: + description: | + Not Acceptable. + The requested media type is not supported + schema: + $ref: '#/definitions/Error' + +#----------------------------------------------------- +# Update the definition of an API +#----------------------------------------------------- + put: + x-scope: apim:api_create + x-wso2-curl: "curl -H \"Authorization: Bearer b0982cd2aacd463ff5f63cd5ebe58f4a\" -H \"Content-Type: application/json\" -X PUT -d @data.json http://127.0.0.1:9763/api/am/publisher/v0.10/apis/6fb74674-4ab8-4b52-9886-f9a376985060" + x-wso2-request: "{\n \"sequences\": [],\n \"tiers\": [\n \"Bronze\",\n \"Gold\"\n ],\n \"thumbnailUrl\": null,\n \"visibility\": \"PUBLIC\",\n \"visibleRoles\": [],\n \"visibleTenants\": [],\n \"cacheTimeout\": 300,\n \"endpointConfig\": \"{\\\"production_endpoints\\\":{\\\"url\\\":\\\" http://ws.cdyne.com/phoneverify/phoneverify.asmx\\\",\\\"config\\\":null},\\\"endpoint_type\\\":\\\"http\\\"}\",\n \"subscriptionAvailability\": null,\n \"subscriptionAvailableTenants\": [],\n \"destinationStatsEnabled\": \"Disabled\",\n \"apiDefinition\": \"{\\\"paths\\\":{\\\"\\/*\\\":{\\\"get\\\":{\\\"x-auth-type\\\":\\\"Application\\\",\\\"x-throttling-tier\\\":\\\"Unlimited\\\",\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"OK\\\"}}}}},\\\"x-wso2-security\\\":{\\\"apim\\\":{\\\"x-wso2-scopes\\\":[]}},\\\"swagger\\\":\\\"2.0\\\",\\\"info\\\":{\\\"title\\\":\\\"PhoneVerification\\\",\\\"description\\\":\\\"Verify a phone number\\\",\\\"contact\\\":{\\\"email\\\":\\\"xx@ee.com\\\",\\\"name\\\":\\\"xx\\\"},\\\"version\\\":\\\"2.0.0\\\"}}\",\n \"responseCaching\": \"Disabled\",\n \"isDefaultVersion\": false,\n \"gatewayEnvironments\": \"Production and Sandbox\",\n \"businessInformation\": {\n \"technicalOwner\": \"xx\",\n \"technicalOwnerEmail\": \"ggg@ww.com\",\n \"businessOwner\": \"xx\",\n \"businessOwnerEmail\": \"xx@ee.com\"\n },\n \"transport\": [\n \"http\",\n \"https\"\n ],\n \"tags\": [\n \"phone\",\n \"multimedia\",\n \"verification\",\n \"mobile\"\n ],\n \"provider\": \"admin\",\n \"version\": \"2.0.0\",\n \"description\": \"Use this API to verify a phone number\",\n \"name\": \"PhoneVerification\",\n \"context\": \"/phoneverify\",\n \"id\": \"6fb74674-4ab8-4b52-9886-f9a376985060\",\n \"status\": \"CREATED\"\n}" + x-wso2-response: "HTTP/1.1 200 OK\nDate: Mon, 22 Feb 2016 13:31:35 GMT\nContent-Type: application/json\nTransfer-Encoding: chunked\nServer: WSO2 Carbon Server\n\n{\n \"sequences\": [],\n \"tiers\": [\n \"Bronze\",\n \"Gold\"\n ],\n \"thumbnailUrl\": null,\n \"visibility\": \"PUBLIC\",\n \"visibleRoles\": [],\n \"visibleTenants\": [],\n \"cacheTimeout\": 300,\n \"endpointConfig\": \"{\\\"production_endpoints\\\":{\\\"url\\\":\\\" http://ws.cdyne.com/phoneverify/phoneverify.asmx\\\",\\\"config\\\":null},\\\"endpoint_type\\\":\\\"http\\\"}\",\n \"subscriptionAvailability\": null,\n \"subscriptionAvailableTenants\": [],\n \"destinationStatsEnabled\": \"Disabled\",\n \"apiDefinition\": \"{\\\"paths\\\":{\\\"\\/*\\\":{\\\"get\\\":{\\\"x-auth-type\\\":\\\"Application\\\",\\\"x-throttling-tier\\\":\\\"Unlimited\\\",\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"OK\\\"}}}}},\\\"x-wso2-security\\\":{\\\"apim\\\":{\\\"x-wso2-scopes\\\":[]}},\\\"swagger\\\":\\\"2.0\\\",\\\"info\\\":{\\\"title\\\":\\\"PhoneVerification\\\",\\\"description\\\":\\\"Verify a phone number\\\",\\\"contact\\\":{\\\"email\\\":\\\"xx@ee.com\\\",\\\"name\\\":\\\"xx\\\"},\\\"version\\\":\\\"2.0.0\\\"}}\",\n \"responseCaching\": \"Disabled\",\n \"isDefaultVersion\": false,\n \"gatewayEnvironments\": \"Production and Sandbox\",\n \"businessInformation\": {\n \"technicalOwner\": \"xx\",\n \"technicalOwnerEmail\": \"ggg@ww.com\",\n \"businessOwner\": \"xx\",\n \"businessOwnerEmail\": \"xx@ee.com\"\n },\n \"transport\": [\n \"http\",\n \"https\"\n ],\n \"tags\": [\n \"phone\",\n \"multimedia\",\n \"verification\",\n \"mobile\"\n ],\n \"provider\": \"admin\",\n \"version\": \"2.0.0\",\n \"description\": \"Use this API to verify a phone number\",\n \"name\": \"PhoneVerification\",\n \"context\": \"/phoneverify\",\n \"id\": \"6fb74674-4ab8-4b52-9886-f9a376985060\",\n \"status\": \"CREATED\"\n}" + summary: Update an existing API + description: | + Update an existing API + parameters: + - $ref: '#/parameters/apiId' + - in: body + name: body + description: | + API object that needs to be added + required: true + schema: + $ref: '#/definitions/API' + - $ref: '#/parameters/Content-Type' + - $ref: '#/parameters/If-Match' + - $ref: '#/parameters/If-Unmodified-Since' + tags: + - APIs + responses: + 200: + description: | + OK. + Successful response with updated API object + schema: + $ref: '#/definitions/API' + headers: + Location: + description: | + The URL of the newly created resource. + type: string + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. Used by caches, or in conditional request. + type: string + Last-Modified: + description: | + Date and time the resource has been modifed the last time. + Used by caches, or in conditional requests. + type: string + 400: + description: | + Bad Request. + Invalid request or validation error + schema: + $ref: '#/definitions/Error' + 403: + description: | + Forbidden. + The request must be conditional but no condition has been specified. + schema: + $ref: '#/definitions/Error' + 404: + description: | + Not Found. + The resource to be updated does not exist. + schema: + $ref: '#/definitions/Error' + 412: + description: | + Precondition Failed. + The request has not been performed because one of the preconditions is not met. + schema: + $ref: '#/definitions/Error' + +#----------------------------------------------------- +# Delete the definition of an API +#----------------------------------------------------- + delete: + x-scope: apim:api_create + x-wso2-curl: "curl -H \"Authorization: Bearer b0982cd2aacd463ff5f63cd5ebe58f4a\" -X DELETE http://127.0.0.1:9763/api/am/publisher/v0.10/apis/6fb74674-4ab8-4b52-9886-f9a376985060" + x-wso2-response: "HTTP/1.1 200 OK" + summary: Delete API + description: | + Delete an existing API + parameters: + - $ref: '#/parameters/apiId' + - $ref: '#/parameters/If-Match' + - $ref: '#/parameters/If-Unmodified-Since' + tags: + - APIs + responses: + 200: + description: | + OK. + Resource successfully deleted. + 403: + description: | + Forbidden. + The request must be conditional but no condition has been specified. + schema: + $ref: '#/definitions/Error' + 404: + description: | + Not Found. + Resource to be deleted does not exist. + schema: + $ref: '#/definitions/Error' + 412: + description: | + Precondition Failed. + The request has not been performed because one of the preconditions is not met. + schema: + $ref: '#/definitions/Error' + +################################################################ +# The swagger resource of "Individual API" resource APIs +################################################################ + + /apis/{apiId}/swagger: +#----------------------------------------------------- +# Retrieve the API swagger definition +#----------------------------------------------------- + get: + x-scope: apim:api_view + x-wso2-curl: "curl -H \"Authorization: Bearer b0982cd2aacd463ff5f63cd5ebe58f4a\" http://127.0.0.1:9763/api/am/publisher/v0.10/apis/890a4f4d-09eb-4877-a323-57f6ce2ed79b/swagger" + x-wso2-response: "HTTP/1.1 200 OK\nContent-Type: application/json\nContent-Length: 329\n\n{\n \"paths\": {\"/*\": {\"get\": {\n \"x-auth-type\": \"Application\",\n \"x-throttling-tier\": \"Unlimited\",\n \"responses\": {\"200\": {\"description\": \"OK\"}}\n }}},\n \"x-wso2-security\": {\"apim\": {\"x-wso2-scopes\": []}},\n \"swagger\": \"2.0\",\n \"info\": {\n \"title\": \"PhoneVerification\",\n \"description\": \"Verify a phone number\",\n \"contact\": {\n \"email\": \"xx@ee.com\",\n \"name\": \"xx\"\n },\n \"version\": \"1.0.0\"\n }\n}" + summary: Get API Definition + description: | + Get the swagger of an API + parameters: + - $ref: '#/parameters/apiId' + - $ref: '#/parameters/Accept' + - $ref: '#/parameters/If-None-Match' + - $ref: '#/parameters/If-Modified-Since' + tags: + - APIs + responses: + 200: + description: | + OK. + Requested swagger document of the API is returned + headers: + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. Used by caches, or in conditional requests. + type: string + Last-Modified: + description: | + Date and time the resource has been modifed the last time. + Used by caches, or in conditional requests. + type: string + 304: + description: | + Not Modified. + Empty body because the client has already the latest version of the requested resource. + 404: + description: | + Not Found. + Requested API does not exist. + schema: + $ref: '#/definitions/Error' + 406: + description: | + Not Acceptable. + The requested media type is not supported + schema: + $ref: '#/definitions/Error' + +#----------------------------------------------------- +# Update the API swagger definition +#----------------------------------------------------- + put: + consumes: + - multipart/form-data + x-scope: apim:api_create + x-wso2-curl: "curl -k -H \"Authorization:Bearer b0982cd2aacd463ff5f63cd5ebe58f4a\" -F apiDefinition=\"{\\\"paths\\\":{\\\"\\/*\\\":{\\\"get\\\":{\\\"x-auth-type\\\":\\\"Application\\\",\\\"x-throttling-tier\\\":\\\"Unlimited\\\",\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"OK\\\"}}}}},\\\"x-wso2-security\\\":{\\\"apim\\\":{\\\"x-wso2-scopes\\\":[]}},\\\"swagger\\\":\\\"2.0\\\",\\\"info\\\":{\\\"title\\\":\\\"PhoneVerification\\\",\\\"description\\\":\\\"Verify a phone number\\\",\\\"contact\\\":{\\\"email\\\":\\\"xx@ee.com\\\",\\\"name\\\":\\\"xx\\\"},\\\"version\\\":\\\"1.0.0\\\"}}\" -X PUT \"http://127.0.0.1:9763/api/am/publisher/v0.10/apis/890a4f4d-09eb-4877-a323-57f6ce2ed79b/swagger\"" + x-wso2-request: "{\n \"paths\": {\n \"\\/*\": {\n \"get\": {\n \"x-auth-type\": \"Application\",\n \"x-throttling-tier\": \"Unlimited\",\n \"responses\": {\n \"200\": {\n \"description\": \"OK\"\n }\n }\n }\n }\n },\n \"x-wso2-security\": {\n \"apim\": {\n \"x-wso2-scopes\": []\n }\n },\n \"swagger\": \"2.0\",\n \"info\": {\n \"title\": \"PhoneVerification\",\n \"description\": \"Verify a phone number\",\n \"contact\": {\n \"email\": \"xx@ee.com\",\n \"name\": \"xx\"\n },\n \"version\": \"1.0.0\"\n }\n}" + x-wso2-response: "HTTP/1.1 200 OK\nContent-Type: application/json\n\n{\n \"paths\": {\"/*\": {\"get\": {\n \"x-auth-type\": \"Application\",\n \"x-throttling-tier\": \"Unlimited\",\n \"responses\": {\"200\": {\"description\": \"OK\"}}\n }}},\n \"x-wso2-security\": {\"apim\": {\"x-wso2-scopes\": []}},\n \"swagger\": \"2.0\",\n \"info\": {\n \"title\": \"PhoneVerification\",\n \"description\": \"Verify a phone number\",\n \"contact\": {\n \"email\": \"xx@ee.com\",\n \"name\": \"xx\"\n },\n \"version\": \"1.0.0\"\n }\n}" + summary: Update API Definition + description: | + Update an existing swagger definition of an API + parameters: + - $ref: '#/parameters/apiId' + - in: formData + name: apiDefinition + description: Swagger definition of the API + type: string + required: true + - $ref: '#/parameters/Content-Type' + - $ref: '#/parameters/If-Match' + - $ref: '#/parameters/If-Unmodified-Since' + tags: + - APIs + responses: + 200: + description: | + OK. + Successful response with updated Swagger definition + headers: + Location: + description: | + The URL of the newly created resource. + type: string + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. Used by caches, or in conditional request. + type: string + Last-Modified: + description: | + Date and time the resource has been modifed the last time. + Used by caches, or in conditional requests. + type: string + 400: + description: | + Bad Request. + Invalid request or validation error + schema: + $ref: '#/definitions/Error' + 403: + description: | + Forbidden. + The request must be conditional but no condition has been specified. + schema: + $ref: '#/definitions/Error' + 404: + description: | + Not Found. + The resource to be updated does not exist. + schema: + $ref: '#/definitions/Error' + 412: + description: | + Precondition Failed. + The request has not been performed because one of the preconditions is not met. + schema: + $ref: '#/definitions/Error' + +################################################################ +# The thumbnail resource of "Individual API" resource APIs +################################################################ + + /apis/{apiId}/thumbnail: +#------------------------------------------------------------------------------------------------- +# Downloads a thumbnail image of an API +#------------------------------------------------------------------------------------------------- + get: + x-scope: apim:api_view + x-wso2-curl: "curl -H \"Authorization: Bearer d34baf74-3f02-3929-814e-88b27f750ba9\" http://127.0.0.1:9763/api/am/publisher/v0.10/apis/29c9ec3d-f590-467e-83e6-96d43517080f/thumbnail > image.jpg" + x-wso2-response: "HTTP/1.1 200 OK\r\nContent-Type: image/jpeg\r\n\r\n[image content]" + summary: Get the thumbnail image + description: | + Downloads a thumbnail image of an API + parameters: + - $ref: '#/parameters/apiId' + - $ref: '#/parameters/Accept' + - $ref: '#/parameters/If-None-Match' + - $ref: '#/parameters/If-Modified-Since' + tags: + - APIs + responses: + 200: + description: | + OK. + Thumbnail image returned + headers: + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. + Used by caches, or in conditional requests. + type: string + Last-Modified: + description: | + Date and time the resource has been modifed the last time. + Used by caches, or in conditional reuquests. + type: string + 304: + description: | + Not Modified. + Empty body because the client has already the latest version of the requested resource. + 404: + description: | + Not Found. + Requested Document does not exist. + schema: + $ref: '#/definitions/Error' + 406: + description: | + Not Acceptable. + The requested media type is not supported + schema: + $ref: '#/definitions/Error' + +#---------------------------------------------------------------------------- +# Upload a thumbnail image to a certain API +#---------------------------------------------------------------------------- + post: + consumes: + - multipart/form-data + x-scope: apim:api_create + x-wso2-curl: "curl -X POST -H \"Authorization: Bearer d34baf74-3f02-3929-814e-88b27f750ba9\" http://127.0.0.1:9763/api/am/publisher/v0.10/apis/29c9ec3d-f590-467e-83e6-96d43517080f/thumbnail -F file=@image.jpg" + x-wso2-response: "HTTP/1.1 201 Created\r\nLocation: http://localhost:9763/api/am/publisher/v0.10/apis/29c9ec3d-f590-467e-83e6-96d43517080f/thumbnail\r\nContent-Type: application/json\r\n\r\n{\r\n \"relativePath\": \"/apis/29c9ec3d-f590-467e-83e6-96d43517080f/thumbnail\",\r\n \"mediaType\": \"image/jpeg\"\r\n}" + summary: Upload a thumbnail image + description: | + Upload a thumbnail image to an API. + parameters: + - $ref: '#/parameters/apiId' + - in: formData + name: file + description: Image to upload + type: file + required: true + - $ref: '#/parameters/Content-Type' + - $ref: '#/parameters/If-Match' + - $ref: '#/parameters/If-Unmodified-Since' + tags: + - APIs + responses: + 200: + description: | + OK. + Image updated + schema: + $ref : '#/definitions/FileInfo' + headers: + Location: + description: | + The URL of the uploaded thumbnail image of the API. + type: string + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. + Used by caches, or in conditional request. + type: string + Last-Modified: + description: | + Date and time the resource has been modifed the last time. + Used by caches, or in conditional reuquests. + type: string + 400: + description: | + Bad Request. + Invalid request or validation error. + schema: + $ref: '#/definitions/Error' + 404: + description: | + Not Found. + The resource to be updated does not exist. + schema: + $ref: '#/definitions/Error' + 412: + description: | + Precondition Failed. + The request has not been performed because one of the preconditions is not met. + schema: + $ref: '#/definitions/Error' + +###################################################### +# The "Copy API" Processing Function resource API +###################################################### + /apis/copy-api: + +#----------------------------------------------------- +# Create a new API based on an already existing one +#----------------------------------------------------- + post: + x-scope: apim:api_create + x-wso2-curl: "curl -H \"Authorization: Bearer b0982cd2aacd463ff5f63cd5ebe58f4a\" -X POST \"http://127.0.0.1:9763/api/am/publisher/v0.10/apis/copy-api?apiId=890a4f4d-09eb-4877-a323-57f6ce2ed79b&newVersion=2.0.0\"" + x-wso2-response: "HTTP/1.1 201 Created\nLocation: http://localhost:9763/api/am/publisher/v0.10/apis/6fb74674-4ab8-4b52-9886-f9a376985060\nContent-Type: application/json\n\n{\n \"sequences\": [],\n \"tiers\": [\n \"Bronze\",\n \"Gold\"\n ],\n \"thumbnailUrl\": null,\n \"visibility\": \"PUBLIC\",\n \"visibleRoles\": [],\n \"visibleTenants\": [],\n \"cacheTimeout\": 300,\n \"endpointConfig\": \"{\\\"production_endpoints\\\":{\\\"url\\\":\\\" http://ws.cdyne.com/phoneverify/phoneverify.asmx\\\",\\\"config\\\":null},\\\"endpoint_type\\\":\\\"http\\\"}\",\n \"subscriptionAvailability\": null,\n \"subscriptionAvailableTenants\": [],\n \"destinationStatsEnabled\": \"Disabled\",\n \"apiDefinition\": \"{\\\"paths\\\":{\\\"\\/*\\\":{\\\"get\\\":{\\\"x-auth-type\\\":\\\"Application\\\",\\\"x-throttling-tier\\\":\\\"Unlimited\\\",\\\"responses\\\":{\\\"200\\\":{\\\"description\\\":\\\"OK\\\"}}}}},\\\"x-wso2-security\\\":{\\\"apim\\\":{\\\"x-wso2-scopes\\\":[]}},\\\"swagger\\\":\\\"2.0\\\",\\\"info\\\":{\\\"title\\\":\\\"PhoneVerification\\\",\\\"description\\\":\\\"Verify a phone number\\\",\\\"contact\\\":{\\\"email\\\":\\\"xx@ee.com\\\",\\\"name\\\":\\\"xx\\\"},\\\"version\\\":\\\"2.0.0\\\"}}\",\n \"responseCaching\": \"Disabled\",\n \"isDefaultVersion\": true,\n \"gatewayEnvironments\": \"Production and Sandbox\",\n \"businessInformation\": {\n \"technicalOwner\": \"xx\",\n \"technicalOwnerEmail\": \"ggg@ww.com\",\n \"businessOwner\": \"xx\",\n \"businessOwnerEmail\": \"xx@ee.com\"\n },\n \"transport\": [\n \"http\",\n \"https\"\n ],\n \"tags\": [\n \"phone\",\n \"multimedia\",\n \"mobile\"\n ],\n \"provider\": \"admin\",\n \"version\": \"2.0.0\",\n \"description\": \"Verify a phone number\",\n \"name\": \"PhoneVerification\",\n \"context\": \"/phoneverify\",\n \"id\": \"6fb74674-4ab8-4b52-9886-f9a376985060\",\n \"status\": \"CREATED\"\n}" + summary: Copy API + description: | + Create a new API by copying an existing API + parameters: + - name: newVersion + description: Version of the new API. + type: string + in: query + required: true + - $ref: '#/parameters/apiId-Q' + tags: + - APIs + responses: + 201: + description: | + Created. + Successful response with the newly created API as entity in the body. Location header contains URL of newly created API. + headers: + Location: + description: | + The URL of the newly created API. + type: string + 400: + description: | + Bad Request. + Invalid request or validation error + schema: + $ref: '#/definitions/Error' + 404: + description: | + Not Found. + API to copy does not exist. + schema: + $ref: '#/definitions/Error' + +###################################################### +# The "Change Lifecycle" Processing Function resource API +###################################################### + /apis/change-lifecycle: + +#----------------------------------------------------- +# Change the lifecycle of an API +#----------------------------------------------------- + post: + x-scope: apim:api_publish + x-wso2-curl: "curl -H \"Authorization: Bearer b0982cd2aacd463ff5f63cd5ebe58f4a\" -X POST \"http://127.0.0.1:9763/api/am/publisher/v0.10/apis/change-lifecycle?apiId=890a4f4d-09eb-4877-a323-57f6ce2ed79b&action=Publish\"" + x-wso2-response: "HTTP/1.1 200 OK" + summary: Change API Status + description: | + Change the lifecycle of an API + parameters: + - name: action + description: | + The action to demote or promote the state of the API. + + Supported actions are [ **Publish, Deploy as a Prototype, Demote to Created, Demote to Prototyped, Block, Deprecate, Re-Publish, Retire **] + + in: query + type: string + required: true + enum: + - Publish + - Deploy as a Prototype + - Demote to Created + - Demote to Prototyped + - Block + - Deprecate + - Re-Publish + - Retire + - name: lifecycleChecklist + description: | + + You can specify additional checklist items by using an **"attribute:"** modifier. + + Eg: "Deprecate Old Versions:true" will deprecate older versions of a particular API when it is promoted to + Published state from Created state. Multiple checklist items can be given in "attribute1:true, attribute2:false" + format. + + Supported checklist items are as follows. + 1. **Deprecate Old Versions**: Setting this to true will deprecate older versions of a particular API when it is promoted to Published state from Created state. + 2. **Require Re-Subscription**: If you set this to true, users need to re subscribe to the API although they may have subscribed to an older version. + + type: string + in: query + - $ref: '#/parameters/apiId-Q' + - $ref: '#/parameters/If-Match' + - $ref: '#/parameters/If-Unmodified-Since' + tags: + - APIs + responses: + 200: + description: | + OK. + Lifecycle changed successfully. + headers: + ETag: + description: | + Entity Tag of the changed API. Used by caches, or in conditional request. + type: string + Last-Modified: + description: | + Date and time the API lifecycle has been modified the last time. + Used by caches, or in conditional requests. + type: string + 400: + description: | + Bad Request. + Invalid request or validation error + schema: + $ref: '#/definitions/Error' + 404: + description: | + Not Found. + Requested API does not exist. + schema: + $ref: '#/definitions/Error' + 412: + description: | + Precondition Failed. + The request has not been performed because one of the preconditions is not met. + schema: + $ref: '#/definitions/Error' + +###################################################### +# The "Document Collection" resource APIs +###################################################### + /apis/{apiId}/documents: + +#----------------------------------------------------- +# Retrieve the documents associated with an API that qualify under a search condition +#----------------------------------------------------- + get: + x-scope: apim:api_view + x-wso2-curl: "curl -H \"Authorization: Bearer b0982cd2aacd463ff5f63cd5ebe58f4a\" \"http://127.0.0.1:9763/api/am/publisher/v0.10/apis/890a4f4d-09eb-4877-a323-57f6ce2ed79b/documents\"" + x-wso2-response: "HTTP/1.1 200 OK\nContent-Type: application/json\n\n{\n \"previous\": \"\",\n \"list\": [\n {\n \"visibility\": \"API_LEVEL\",\n \"sourceType\": \"INLINE\",\n \"sourceUrl\": null,\n \"otherTypeName\": null,\n \"documentId\": \"0bcb7f05-599d-4e1a-adce-5cb89bfe58d5\",\n \"summary\": \"This is a sample documentation for v1.0.0\",\n \"name\": \"PhoneVerification API Documentation\",\n \"type\": \"HOWTO\"\n },\n {\n \"visibility\": \"API_LEVEL\",\n \"sourceType\": \"URL\",\n \"sourceUrl\": \"http://wiki.cdyne.com/index.php/Phone_Verification\",\n \"otherTypeName\": null,\n \"documentId\": \"4145df31-04f1-440c-8d08-68952874622c\",\n \"summary\": \"This is the URL for online documentation\",\n \"name\": \"Online Documentation\",\n \"type\": \"SAMPLES\"\n }\n ],\n \"next\": \"\",\n \"count\": 2\n}" + summary: Get API Documents + description: | + Get a list of documents belonging to an API. + parameters: + - $ref: '#/parameters/apiId' + - $ref: '#/parameters/limit' + - $ref: '#/parameters/offset' + - $ref: '#/parameters/Accept' + - $ref: '#/parameters/If-None-Match' + tags: + - API Document + responses: + 200: + description: | + OK. + Document list is returned. + schema: + $ref: '#/definitions/DocumentList' + headers: + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. Used by caches, or in conditional requests. + type: string + 304: + description: | + Not Modified. + Empty body because the client has already the latest version of the requested resource. + 404: + description: | + Not Found. + Requested API does not exist. + schema: + $ref: '#/definitions/Error' + 406: + description: | + Not Acceptable. + The requested media type is not supported + schema: + $ref: '#/definitions/Error' + +#----------------------------------------------------- +# Add a document to a certain API +#----------------------------------------------------- + post: + x-scope: apim:api_create + x-wso2-curl: "curl -H \"Authorization: Bearer cdcc8cf6016ed10620edf3a1d3c5ef2b\" -H \"Content-Type: application/json\" -X POST -d @data.json \"http://127.0.0.1:9763/api/am/publisher/v0.10/apis/96077508-fd01-4fae-bc64-5de0e2baf43c/documents\"" + x-wso2-request: "{\n \"visibility\": \"API_LEVEL\",\n \"sourceType\": \"INLINE\",\n \"sourceUrl\": null,\n \"otherTypeName\": null,\n \"summary\": \"This is a sample documentation\",\n \"name\": \"Introduction to PhoneVerification API\",\n \"type\": \"HOWTO\"\n}" + x-wso2-response: "HTTP/1.1 201 Created\nLocation: http://localhost:9763/api/am/publisher/v0.10/apis/890a4f4d-09eb-4877-a323-57f6ce2ed79b/documents/ffd5790d-b7a9-4cb6-b76a-f8b83ecdd058\nContent-Type: application/json\n\n{\n \"visibility\": \"API_LEVEL\",\n \"sourceType\": \"INLINE\",\n \"sourceUrl\": null,\n \"otherTypeName\": null,\n \"documentId\": \"ffd5790d-b7a9-4cb6-b76a-f8b83ecdd058\",\n \"summary\": \"This is a sample documentation\",\n \"name\": \"Introduction to PhoneVerification API\",\n \"type\": \"HOWTO\"\n}" + summary: Add a new document + description: | + Add a new document to an API + parameters: + - $ref: '#/parameters/apiId' + - in: body + name: body + description: | + Document object that needs to be added + required: true + schema: + $ref: '#/definitions/Document' + - $ref: '#/parameters/Content-Type' + tags: + - API Document + responses: + 201: + description: | + Created. + Successful response with the newly created Document object as entity in the body. + Location header contains URL of newly added document. + schema: + $ref: '#/definitions/Document' + headers: + Location: + description: | + Location to the newly created Document. + type: string + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. + Used by caches, or in conditional request. + type: string + 400: + description: | + Bad Request. + Invalid request or validation error + schema: + $ref: '#/definitions/Error' + 415: + description: | + Unsupported media type. + The entity of the request was in a not supported format. + +###################################################### +# The "Individual Document" resource APIs +###################################################### + '/apis/{apiId}/documents/{documentId}': + +#----------------------------------------------------- +# Retrieve a particular document of a certain API +#----------------------------------------------------- + get: + x-scope: apim:api_view + x-wso2-curl: "curl -H \"Authorization: Bearer b0982cd2aacd463ff5f63cd5ebe58f4a\" \"http://127.0.0.1:9763/api/am/publisher/v0.10/apis/890a4f4d-09eb-4877-a323-57f6ce2ed79b/documents/0bcb7f05-599d-4e1a-adce-5cb89bfe58d5\"" + x-wso2-response: "HTTP/1.1 200 OK\nContent-Type: application/json\n\n{\n \"visibility\": \"API_LEVEL\",\n \"sourceType\": \"INLINE\",\n \"sourceUrl\": null,\n \"otherTypeName\": null,\n \"documentId\": \"0bcb7f05-599d-4e1a-adce-5cb89bfe58d5\",\n \"summary\": \"This is a sample documentation\",\n \"name\": \"PhoneVerification API Documentation\",\n \"type\": \"HOWTO\"\n}" + summary: Get an API Document + description: | + Get a particular document associated with an API. + parameters: + - $ref: '#/parameters/apiId' + - $ref: '#/parameters/documentId' + - $ref: '#/parameters/Accept' + - $ref: '#/parameters/If-None-Match' + - $ref: '#/parameters/If-Modified-Since' + tags: + - API Document + responses: + 200: + description: | + OK. + Document returned. + schema: + $ref: '#/definitions/Document' + headers: + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. + Used by caches, or in conditional requests. + type: string + Last-Modified: + description: | + Date and time the resource has been modifed the last time. + Used by caches, or in conditional reuquests. + type: string + 304: + description: | + Not Modified. + Empty body because the client has already the latest version of the requested resource. + 404: + description: | + Not Found. + Requested Document does not exist. + schema: + $ref: '#/definitions/Error' + 406: + description: | + Not Acceptable. + The requested media type is not supported + schema: + $ref: '#/definitions/Error' + +#----------------------------------------------------- +# Update a particular document of a certain API +#----------------------------------------------------- + put: + x-scope: apim:api_create + x-wso2-curl: "curl -k -H \"Authorization:Bearer b0982cd2aacd463ff5f63cd5ebe58f4a\" -H \"Content-Type: application/json\" -X PUT -d data.json \"http://127.0.0.1:9763/api/am/publisher/v0.10/apis/96077508-fd01-4fae-bc64-5de0e2baf43c/documents/0bcb7f05-599d-4e1a-adce-5cb89bfe58d5\"" + x-wso2-request: "{\n \"visibility\": \"API_LEVEL\",\n \"sourceType\": \"INLINE\",\n \"sourceUrl\": null,\n \"otherTypeName\": null,\n \"documentId\": \"0bcb7f05-599d-4e1a-adce-5cb89bfe58d5\",\n \"summary\": \"This is a sample documentation for v1.0.0\",\n \"name\": \"PhoneVerification API Documentation\",\n \"type\": \"HOWTO\"\n}" + x-wso2-response: "HTTP/1.1 200 OK\nContent-Type: application/json\n\n{\n \"visibility\": \"API_LEVEL\",\n \"sourceType\": \"INLINE\",\n \"sourceUrl\": null,\n \"otherTypeName\": null,\n \"documentId\": \"0bcb7f05-599d-4e1a-adce-5cb89bfe58d5\",\n \"summary\": \"This is a sample documentation for v1.0.0\",\n \"name\": \"PhoneVerification API Documentation\",\n \"type\": \"HOWTO\"\n}" + summary: Update an API Document + description: | + Update document details. + parameters: + - $ref: '#/parameters/apiId' + - $ref: '#/parameters/documentId' + - in: body + name: body + description: | + Document object that needs to be added + required: true + schema: + $ref: '#/definitions/Document' + - $ref: '#/parameters/Content-Type' + - $ref: '#/parameters/If-Match' + - $ref: '#/parameters/If-Unmodified-Since' + tags: + - API Document + responses: + 200: + description: | + OK. + Document updated + schema: + $ref: '#/definitions/Document' + headers: + Location: + description: | + The URL of the updated document. + type: string + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. + Used by caches, or in conditional request. + type: string + Last-Modified: + description: | + Date and time the resource has been modifed the last time. + Used by caches, or in conditional reuquests. + type: string + 400: + description: | + Bad Request. + Invalid request or validation error. + schema: + $ref: '#/definitions/Error' + 404: + description: | + Not Found. + The resource to be updated does not exist. + schema: + $ref: '#/definitions/Error' + 412: + description: | + Precondition Failed. + The request has not been performed because one of the preconditions is not met. + schema: + $ref: '#/definitions/Error' + +#----------------------------------------------------- +# Delete a particular document of a certain API +#----------------------------------------------------- + delete: + x-scope: apim:api_create + x-wso2-curl: "curl -H \"Authorization: Bearer b0982cd2aacd463ff5f63cd5ebe58f4a\" -X DELETE http://127.0.0.1:9763/api/am/publisher/v0.10/apis/890a4f4d-09eb-4877-a323-57f6ce2ed79b/documents/ffd5790d-b7a9-4cb6-b76a-f8b83ecdd058" + x-wso2-response: "HTTP/1.1 200 OK" + summary: Delete an API Document + description: | + Delete a document of an API + parameters: + - $ref: '#/parameters/apiId' + - $ref: '#/parameters/documentId' + - $ref: '#/parameters/If-Match' + - $ref: '#/parameters/If-Unmodified-Since' + tags: + - API Document + responses: + 200: + description: | + OK. + Resource successfully deleted. + 404: + description: | + Not Found. + Resource to be deleted does not exist. + schema: + $ref: '#/definitions/Error' + 412: + description: | + Precondition Failed. + The request has not been performed because one of the preconditions is not met. + schema: + $ref: '#/definitions/Error' + +################################################################ +# The content resource of "Individual Document" resource APIs +################################################################ + + '/apis/{apiId}/documents/{documentId}/content': + + #------------------------------------------------------------------------------------------------- + # Downloads a FILE type document/get the inline content or source url of a certain document + #------------------------------------------------------------------------------------------------- + get: + x-scope: apim:api_view + x-wso2-curl: "curl -k -H \"Authorization:Bearer b0982cd2aacd463ff5f63cd5ebe58f4a\" \"http://127.0.0.1:9763/api/am/publisher/v0.10/apis/890a4f4d-09eb-4877-a323-57f6ce2ed79b/documents/daf732d3-bda2-46da-b381-2c39d901ea61/content\" > sample.pdf" + x-wso2-response: "HTTP/1.1 200 OK\nContent-Disposition: attachment; filename=\"sample.pdf\"\nContent-Type: application/octet-stream\nContent-Length: 7802\n\n%PDF-1.4\n%äüöß\n2 0 obj\n<>\nstream\n..\n>>\nstartxref\n7279\n%%EOF" + summary: Get document content + description: | + Downloads a FILE type document/get the inline content or source url of a certain document. + parameters: + - $ref: '#/parameters/apiId' + - $ref: '#/parameters/documentId' + - $ref: '#/parameters/Accept' + - $ref: '#/parameters/If-None-Match' + - $ref: '#/parameters/If-Modified-Since' + tags: + - API Document + responses: + 200: + description: | + OK. + File or inline content returned. + headers: + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. + Used by caches, or in conditional requests. + type: string + Last-Modified: + description: | + Date and time the resource has been modifed the last time. + Used by caches, or in conditional reuquests. + type: string + 303: + description: | + See Other. + Source can be retrived from the URL specified at the Location header. + headers: + Location: + description: | + The Source URL of the document. + type: string + 304: + description: | + Not Modified. + Empty body because the client has already the latest version of the requested resource. + 404: + description: | + Not Found. + Requested Document does not exist. + schema: + $ref: '#/definitions/Error' + 406: + description: | + Not Acceptable. + The requested media type is not supported + schema: + $ref: '#/definitions/Error' + + #---------------------------------------------------------------------------- + # Upload a file or add inline content to a document of a certain API + #---------------------------------------------------------------------------- + post: + consumes: + - multipart/form-data + x-scope: apim:api_create + x-wso2-curl: "curl -k -H \"Authorization:Bearer b0982cd2aacd463ff5f63cd5ebe58f4a\" -F file=@\"sample.pdf\" -X POST \"http://127.0.0.1:9763/api/am/publisher/v0.10/apis/890a4f4d-09eb-4877-a323-57f6ce2ed79b/documents/daf732d3-bda2-46da-b381-2c39d901ea61/content\"" + x-wso2-response: "HTTP/1.1 201 Created\nLocation: http://localhost:9763/api/am/publisher/v0.10/apis/890a4f4d-09eb-4877-a323-57f6ce2ed79b/documents/daf732d3-bda2-46da-b381-2c39d901ea61/content\nContent-Type: application/json\n\n{\n \"visibility\":\"API_LEVEL\",\n \"sourceType\":\"FILE\",\n \"sourceUrl\":null,\n \"otherTypeName\":null,\n \"documentId\":\"daf732d3-bda2-46da-b381-2c39d901ea61\",\n \"summary\":\"This is a sample documentation pdf\",\n \"name\":\"Introduction to PhoneVerification API PDF\",\n \"type\":\"HOWTO\"\n}" + summary: Update API document content. + description: | + Upload a file to a document or add inline content to the document. + + Document's source type should be **FILE** in order to upload a file to the document using **file** parameter. + Document's source type should be **INLINE** in order to add inline content to the document using **inlineContent** parameter. + + Only one of **file** or **inlineContent** can be specified at one time. + parameters: + - $ref: '#/parameters/apiId' + - $ref: '#/parameters/documentId' + - in: formData + name: file + description: Document to upload + type: file + required: false + - in: formData + name: inlineContent + description: Inline content of the document + type: string + required: false + - $ref: '#/parameters/Content-Type' + - $ref: '#/parameters/If-Match' + - $ref: '#/parameters/If-Unmodified-Since' + tags: + - API Document + responses: + 200: + description: | + OK. + Document updated + schema: + $ref: '#/definitions/Document' + headers: + Location: + description: | + The URL of the updated content of the document. + type: string + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. + Used by caches, or in conditional request. + type: string + Last-Modified: + description: | + Date and time the resource has been modifed the last time. + Used by caches, or in conditional reuquests. + type: string + 400: + description: | + Bad Request. + Invalid request or validation error. + schema: + $ref: '#/definitions/Error' + 404: + description: | + Not Found. + The resource to be updated does not exist. + schema: + $ref: '#/definitions/Error' + 412: + description: | + Precondition Failed. + The request has not been performed because one of the preconditions is not met. + schema: + $ref: '#/definitions/Error' + +###################################################### +# The "Individual Application" resource APIs +###################################################### + '/applications/{applicationId}': + +#----------------------------------------------------- +# Retrieve the details about a certain application +#----------------------------------------------------- + get: + x-scope: apim:api_create + x-wso2-curl: "curl -H \"Authorization: Bearer b0982cd2aacd463ff5f63cd5ebe58f4a\" http://127.0.0.1:9763/api/am/publisher/v0.10/applications/896658a0-b4ee-4535-bbfa-806c894a4015" + x-wso2-response: "HTTP/1.1 200 OK\nContent-Type: application/json\n\n{\n \"groupId\": \"\",\n \"subscriber\": \"admin\",\n \"throttlingTier\": \"Unlimited\",\n \"applicationId\": \"896658a0-b4ee-4535-bbfa-806c894a4015\",\n \"description\": null,\n \"name\": \"DefaultApplication\"\n}" + summary: Get Application + description: | + Get application details + parameters: + - $ref: '#/parameters/applicationId' + - $ref: '#/parameters/Accept' + - $ref: '#/parameters/If-None-Match' + - $ref: '#/parameters/If-Modified-Since' + tags: + - Applications + responses: + 200: + description: | + OK. + Application returned. + schema: + $ref: '#/definitions/Application' + headers: + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. Used by caches, or in conditional requests. + type: string + Last-Modified: + description: | + Date and time the resource has been modifed the last time. + Used by caches, or in conditional reuquests. + type: string + 304: + description: | + Not Modified. + Empty body because the client has already the latest version of the requested resource. + 404: + description: | + Not Found. + Requested application does not exist. + schema: + $ref: '#/definitions/Error' + 406: + description: | + Not Acceptable. + The requested media type is not supported + schema: + $ref: '#/definitions/Error' + +###################################################### +# The "Subscription Collection" resource APIs +###################################################### + /subscriptions: + +#----------------------------------------------------- +# Retrieve all subscriptions of a certain API +#----------------------------------------------------- + get: + x-scope: apim:subscription_view + x-wso2-curl: "curl -H \"Authorization: Bearer b0982cd2aacd463ff5f63cd5ebe58f4a\" \"http://127.0.0.1:9763/api/am/publisher/v0.10/subscriptions?apiId=890a4f4d-09eb-4877-a323-57f6ce2ed79b\"" + x-wso2-response: "HTTP/1.1 200 OK\nContent-Type: application/json\n \n{\n \"previous\": \"\",\n \"list\": [\n {\n \"subscriptionId\": \"64eca60b-2e55-4c38-8603-e9e6bad7d809\",\n \"tier\": \"Gold\",\n \"apiIdentifier\": \"admin-PhoneVerification-1.0.0\",\n \"applicationId\": \"896658a0-b4ee-4535-bbfa-806c894a4015\",\n \"status\": \"UNBLOCKED\"\n },\n {\n \"subscriptionId\": \"7ac22c34-8745-4cfe-91e0-262c50b2f2e3\",\n \"tier\": \"Gold\",\n \"apiIdentifier\": \"admin-PhoneVerification-1.0.0\",\n \"applicationId\": \"367a2361-8db5-4140-8133-c6c8dc7fa0c4\",\n \"status\": \"UNBLOCKED\"\n }\n ],\n \"next\": \"\",\n \"count\": 2\n}" + summary: Get All Subscriptions + description: | + Get subscription list. + The API Identifier and corresponding Application Identifier + the subscriptions of which are to be returned are passed as parameters. + parameters: + - $ref: '#/parameters/apiId-Q' + - $ref: '#/parameters/limit' + - $ref: '#/parameters/offset' + - $ref: '#/parameters/Accept' + - $ref: '#/parameters/If-None-Match' + tags: + - Subscriptions + responses: + 200: + description: | + OK. + Subscription list returned. + schema: + $ref: '#/definitions/SubscriptionList' + headers: + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. + Used by caches, or in conditional requests. + type: string + 304: + description: | + Not Modified. + Empty body because the client has already the latest version of the requested resource. + 406: + description: | + Not Acceptable. The requested media type is not supported + schema: + $ref: '#/definitions/Error' + +###################################################### +# The "Individual Subscription" resource APIs +###################################################### + '/subscriptions/{subscriptionId}': + +#----------------------------------------------------- +# Retrieve a certain subscription +#----------------------------------------------------- + get: + x-scope: apim:subscription_view + x-wso2-curl: "curl -H \"Authorization: Bearer b0982cd2aacd463ff5f63cd5ebe58f4a\" http://127.0.0.1:9763/api/am/publisher/v0.10/subscriptions/64eca60b-2e55-4c38-8603-e9e6bad7d809" + x-wso2-response: "HTTP/1.1 200 OK\nContent-Type: application/json\n\n{\n \"subscriptionId\": \"64eca60b-2e55-4c38-8603-e9e6bad7d809\",\n \"tier\": \"Gold\",\n \"apiIdentifier\": \"admin-PhoneVerification-1.0.0\",\n \"applicationId\": \"896658a0-b4ee-4535-bbfa-806c894a4015\",\n \"status\": \"UNBLOCKED\"\n}" + summary: Get a Subscription + description: | + Get subscription details + parameters: + - $ref: '#/parameters/subscriptionId' + - $ref: '#/parameters/Accept' + - $ref: '#/parameters/If-None-Match' + - $ref: '#/parameters/If-Modified-Since' + tags: + - Subscriptions + responses: + 200: + description: | + OK. + Subscription returned + schema: + $ref: '#/definitions/Subscription' + headers: + Content-Type: + description: The content type of the body. + type: string + ETag: + description: 'Entity Tag of the response resource. Used by caches, or in conditional requests.' + type: string + Last-Modified: + description: 'Date and time the resource has been modifed the last time. Used by caches, or in conditional reuquests.' + type: string + '304': + description: | + Not Modified. + Empty body because the client has already the latest version of the requested resource. + '404': + description: | + Not Found. + Requested Subscription does not exist. + schema: + $ref: '#/definitions/Error' + +###################################################### +# The "Block Subscription" Processing Function resource API +###################################################### + /subscriptions/block-subscription: + +#----------------------------------------------------- +# Block a certain subscription +#----------------------------------------------------- + post: + x-scope: apim:subscription_block + x-wso2-curl: "curl -H \"Authorization: Bearer b0982cd2aacd463ff5f63cd5ebe58f4a\" -X POST \"http://127.0.0.1:9763/api/am/publisher/v0.10/subscriptions/block-subscription?subscriptionId=64eca60b-2e55-4c38-8603-e9e6bad7d809&blockState=PROD_ONLY_BLOCKED\"" + x-wso2-response: "HTTP/1.1 200 OK\nContent-Type: application/json\n \n{\n \"subscriptionId\": \"64eca60b-2e55-4c38-8603-e9e6bad7d809\",\n \"tier\": \"Gold\",\n \"apiIdentifier\": \"admin-PhoneVerification-1.0.0\",\n \"applicationId\": \"896658a0-b4ee-4535-bbfa-806c894a4015\",\n \"status\": \"PROD_ONLY_BLOCKED\"\n}" + summary: Block a subscription + parameters: + - $ref: '#/parameters/subscriptionId-Q' + - name: blockState + in: query + description: | + Subscription block state. + type: string + required: true + enum: + - BLOCKED + - PROD_ONLY_BLOCKED + - $ref: '#/parameters/If-Match' + - $ref: '#/parameters/If-Unmodified-Since' + description: | + Block a subscription. + tags: + - Subscriptions + responses: + 200: + description: | + OK. + Subscription was blocked successfully. + headers: + ETag: + description: | + Entity Tag of the blocked subscription. + Used by caches, or in conditional request. + type: string + Last-Modified: + description: | + Date and time the subscription has been blocked. + Used by caches, or in conditional requests. + type: string + 400: + description: | + Bad Request. + Invalid request or validation error + schema: + $ref: '#/definitions/Error' + 404: + description: | + Not Found. + Requested subscription does not exist. + schema: + $ref: '#/definitions/Error' + 412: + description: | + Precondition Failed. + The request has not been performed because one of the preconditions is not met. + schema: + $ref: '#/definitions/Error' + +###################################################### +# The "Unblock Subscription" Processing Function resource API +###################################################### + /subscriptions/unblock-subscription: + +#----------------------------------------------------- +# Unblock a certain subscription +#----------------------------------------------------- + post: + x-scope: apim:subscription_block + x-wso2-curl: "curl -H \"Authorization: Bearer b0982cd2aacd463ff5f63cd5ebe58f4a\" -X POST \"http://127.0.0.1:9763/api/am/publisher/v0.10/subscriptions/unblock-subscription?subscriptionId=64eca60b-2e55-4c38-8603-e9e6bad7d809\"" + x-wso2-response: "HTTP/1.1 200 OK\nContent-Type: application/json\n\n{\n \"subscriptionId\": \"64eca60b-2e55-4c38-8603-e9e6bad7d809\",\n \"tier\": \"Gold\",\n \"apiIdentifier\": \"admin-PhoneVerification-1.0.0\",\n \"applicationId\": \"896658a0-b4ee-4535-bbfa-806c894a4015\",\n \"status\": \"UNBLOCKED\"\n} " + summary: Unblock a Subscription + parameters: + - $ref: '#/parameters/subscriptionId-Q' + - $ref: '#/parameters/If-Match' + - $ref: '#/parameters/If-Unmodified-Since' + description: | + Unblock a subscription. + tags: + - Subscriptions + responses: + 200: + description: | + OK. + Subscription was unblocked successfully. + headers: + ETag: + description: | + Entity Tag of the unblocked subscription. + Used by caches, or in conditional request. + type: string + Last-Modified: + description: | + Date and time the subscription has been unblocked. + Used by caches, or in conditional requests. + type: string + 400: + description: | + Bad Request. + Invalid request or validation error + schema: + $ref: '#/definitions/Error' + 404: + description: | + Not Found. + Requested subscription does not exist. + schema: + $ref: '#/definitions/Error' + 412: + description: | + Precondition Failed. + The request has not been performed because one of the preconditions is not met. + schema: + $ref: '#/definitions/Error' + +###################################################### +# The "Tier Collection" resource APIs +###################################################### + '/tiers/{tierLevel}': + +#----------------------------------------------------- +# Retrieve the list of all available tiers +#----------------------------------------------------- + get: + x-scope: apim:tier_view + x-wso2-curl: "curl -H \"Authorization: Bearer b0982cd2aacd463ff5f63cd5ebe58f4a\" http://127.0.0.1:9763/api/am/publisher/v0.10/tiers/api" + x-wso2-response: "HTTP/1.1 200 OK\nContent-Type: application/json\n\n\n{\n \"previous\": \"\",\n \"list\": [\n {\n \"unitTime\": 60000,\n \"tierPlan\": \"FREE\",\n \"tierLevel\": \"api\",\n \"stopOnQuotaReach\": true,\n \"requestCount\": 1,\n \"description\": \"Allows 1 request(s) per minute.\",\n \"name\": \"Bronze\",\n \"attributes\": {}\n },\n {\n \"unitTime\": 60000,\n \"tierPlan\": \"FREE\",\n \"tierLevel\": \"api\",\n \"stopOnQuotaReach\": true,\n \"requestCount\": 20,\n \"description\": \"Allows 20 request(s) per minute.\",\n \"name\": \"Gold\",\n \"attributes\": {}\n },\n {\n \"unitTime\": 60000,\n \"tierPlan\": \"FREE\",\n \"tierLevel\": \"api\",\n \"stopOnQuotaReach\": true,\n \"requestCount\": 5,\n \"description\": \"Allows 5 request(s) per minute.\",\n \"name\": \"Silver\",\n \"attributes\": {}\n },\n {\n \"unitTime\": 0,\n \"tierPlan\": null,\n \"tierLevel\": \"api\",\n \"stopOnQuotaReach\": true,\n \"requestCount\": 0,\n \"description\": \"Allows unlimited requests\",\n \"name\": \"Unlimited\",\n \"attributes\": {}\n }\n ],\n \"next\": \"\",\n \"count\": 4\n}" + summary: List Tiers + description: | + Get available tiers + parameters: + - $ref: '#/parameters/limit' + - $ref: '#/parameters/offset' + - $ref: '#/parameters/tierLevel' + - $ref: '#/parameters/Accept' + - $ref: '#/parameters/If-None-Match' + tags: + - Tiers + responses: + 200: + description: | + OK. + List of tiers returned. + schema: + $ref: '#/definitions/TierList' + headers: + Content-Type: + description: The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. + Used by caches, or in conditional requests. + type: string + 304: + description: | + Not Modified. + Empty body because the client has already the latest version of the requested resource. + 406: + description: | + Not Acceptable. + The requested media type is not supported + schema: + $ref: '#/definitions/Error' + +#----------------------------------------------------- +# Create a new tier +#----------------------------------------------------- + post: + x-scope: apim:tier_manage + x-wso2-curl: "curl -H \"Authorization: Bearer b0982cd2aacd463ff5f63cd5ebe58f4a\" -H \"Content-Type: application/json\" -X POST -d @data.json \"http://127.0.0.1:9763/api/am/publisher/v0.10/tiers/api\"" + x-wso2-request: "{\n \"unitTime\": 60000,\n \"tierPlan\": \"FREE\",\n \"tierLevel\": \"api\",\n \"stopOnQuotaReach\": true,\n \"requestCount\": 5,\n \"description\": \"Allows 5 request(s) per minute.\",\n \"name\": \"Low\",\n \"attributes\": {\n \"a\":10,\n \"b\":30\n }\n}" + x-wso2-response: "HTTP/1.1 201 Created\nLocation: http://localhost:9763/api/am/publisher/v0.10/tiers/Low\nContent-Type: application/json\n\n{\n \"unitTime\": 60000,\n \"tierPlan\": \"FREE\",\n \"tierLevel\": \"api\",\n \"stopOnQuotaReach\": true,\n \"requestCount\": 5,\n \"description\": \"Allows 5 request(s) per minute.\",\n \"name\": \"Low\",\n \"attributes\": {\n \"b\": \"30\",\n \"a\": \"10\"\n }\n}" + summary: Add a new Tier + description: | + Add a new tier + parameters: + - in: body + name: body + description: | + Tier object that should to be added + required: true + schema: + $ref: '#/definitions/Tier' + - $ref: '#/parameters/tierLevel' + - $ref: '#/parameters/Content-Type' + tags: + - Tiers + responses: + 201: + description: | + Created. + Successful response with the newly created object as entity in the body. + Location header contains URL of newly created entity. + schema: + $ref: '#/definitions/Tier' + headers: + Location: + description: | + Location of the newly created tier. + type: string + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. + Used by caches, or in conditional request' + type: string + 400: + description: | + Bad Request. + Invalid request or validation error + schema: + $ref: '#/definitions/Error' + 415: + description: | + Unsupported media type. + The entity of the request was in a not supported format. + +###################################################### +# The "Individual Tier" resource APIs +###################################################### + '/tiers/{tierLevel}/{tierName}': + +#----------------------------------------------------- +# Retrieve a certain tier +#----------------------------------------------------- + get: + x-scope: apim:tier_view + x-wso2-curl: "curl -H \"Authorization: Bearer b0982cd2aacd463ff5f63cd5ebe58f4a\" http://127.0.0.1:9763/api/am/publisher/v0.10/tiers/api/Bronze" + x-wso2-response: "HTTP/1.1 200 OK\nContent-Type: application/json\n\n{\n \"unitTime\": 60000,\n \"tierPlan\": \"FREE\",\n \"tierLevel\": \"api\",\n \"stopOnQuotaReach\": true,\n \"requestCount\": 1,\n \"description\": \"Allows 1 request(s) per minute.\",\n \"name\": \"Bronze\",\n \"attributes\": {}\n}" + summary: Get a Tier + description: | + Get tier details + parameters: + - $ref: '#/parameters/tierName' + - $ref: '#/parameters/tierLevel' + - $ref: '#/parameters/Accept' + - $ref: '#/parameters/If-None-Match' + - $ref: '#/parameters/If-Modified-Since' + tags: + - Tiers + responses: + 200: + description: | + OK. + Tier returned + schema: + $ref: '#/definitions/Tier' + headers: + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. + Used by caches, or in conditional requests. + type: string + Last-Modified: + description: | + Date and time the resource has been modifed the last time. + Used by caches, or in conditional reuquests. + type: string + 304: + description: | + Not Modified. + Empty body because the client has already the latest version of the requested resource. + 404: + description: | + Not Found. + Requested Tier does not exist. + schema: + $ref: '#/definitions/Error' + 406: + description: | + Not Acceptable. + The requested media type is not supported. + schema: + $ref: '#/definitions/Error' + +#----------------------------------------------------- +# Update a certain tier +#----------------------------------------------------- + put: + x-scope: apim:tier_manage + x-wso2-curl: "curl -H \"Authorization: Bearer b0982cd2aacd463ff5f63cd5ebe58f4a\" -H \"Content-Type: application/json\" -X PUT -d @data.json \"http://127.0.0.1:9763/api/am/publisher/v0.10/tiers/api/Low\"" + x-wso2-request: "{\n \"unitTime\": 60000,\n \"tierPlan\": \"FREE\",\n \"tierLevel\": \"api\",\n \"stopOnQuotaReach\": true,\n \"requestCount\": 10,\n \"description\": \"Allows 10 request(s) per minute.\",\n \"name\": \"Low\",\n \"attributes\": {\n \"a\": \"30\",\n \"b\": \"10\",\n \"c\": \"20\"\n }\n}\n" + x-wso2-response: "HTTP/1.1 200 OK\nContent-Type: application/json\n\n{\n \"unitTime\": 60000,\n \"tierPlan\": \"FREE\",\n \"tierLevel\": \"api\",\n \"stopOnQuotaReach\": true,\n \"requestCount\": 10,\n \"description\": \"Allows 10 request(s) per minute.\",\n \"name\": \"Low\",\n \"attributes\": {\n \"b\": \"10\",\n \"c\": \"20\",\n \"a\": \"30\"\n }\n}" + summary: Update a Tier + description: | + Update tier details + parameters: + - $ref: '#/parameters/tierName' + - in: body + name: body + description: | + Tier object that needs to be modified + required: true + schema: + $ref: '#/definitions/Tier' + - $ref: '#/parameters/tierLevel' + - $ref: '#/parameters/Content-Type' + - $ref: '#/parameters/If-Match' + - $ref: '#/parameters/If-Unmodified-Since' + tags: + - Tiers + responses: + 200: + description: | + OK. + Subscription updated. + schema: + $ref: '#/definitions/Tier' + headers: + Location: + description: | + The URL of the newly created resource. + type: string + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. + Used by caches, or in conditional request. + type: string + Last-Modified: + description: | + Date and time the resource has been modifed the last time. + Used by caches, or in conditional reuquests. + type: string + 400: + description: | + Bad Request. + Invalid request or validation error. + schema: + $ref: '#/definitions/Error' + 404: + description: | + Not Found. + The resource to be updated does not exist. + schema: + $ref: '#/definitions/Error' + 412: + description: | + Precondition Failed. + The request has not been performed because one of the preconditions is not met. + schema: + $ref: '#/definitions/Error' + +#----------------------------------------------------- +# Delete a certain tier +#----------------------------------------------------- + delete: + x-scope: apim:tier_manage + x-wso2-curl: "curl -H \"Authorization: Bearer b0982cd2aacd463ff5f63cd5ebe58f4a\" -X POST \"http://127.0.0.1:9763/api/am/publisher/v0.10/tiers/api/Low\"" + x-wso2-response: "HTTP/1.1 200 OK" + summary: Delete a Tier + description: | + Remove a tier + parameters: + - $ref: '#/parameters/tierName' + - $ref: '#/parameters/tierLevel' + - $ref: '#/parameters/If-Match' + - $ref: '#/parameters/If-Unmodified-Since' + tags: + - Tiers + responses: + 200: + description: | + OK. + Resource successfully deleted. + 404: + description: | + Not Found. + Resource to be deleted does not exist. + schema: + $ref: '#/definitions/Error' + 412: + description: | + Precondition Failed. + The request has not been performed because one of the preconditions is not met. + schema: + $ref: '#/definitions/Error' + +###################################################### +# The "Update Permission" Processing Function resource API +###################################################### + '/tiers/update-permission': + +#----------------------------------------------------- +# Update the permission of a certain tier +#----------------------------------------------------- + post: + x-scope: apim:tier_manage + x-wso2-curl: "curl -H \"Authorization: Bearer b0982cd2aacd463ff5f63cd5ebe58f4a\" -H \"Content-Type: application/json\" -X POST -d @data.json \"http://127.0.0.1:9763/api/am/publisher/v0.10/tiers/update-permission?tierName=Bronze&tierLevel=api\"" + x-wso2-request: "{\n \"permissionType\":\"deny\",\n \"roles\": [\"Internal/everyone\",\"admin\"]\n}" + x-wso2-response: "HTTP/1.1 200 OK" + summary: Update Tier Permission + description: | + Update tier permission + parameters: + - $ref: '#/parameters/tierName-Q' + - $ref: '#/parameters/tierLevel-Q' + - $ref: '#/parameters/If-Match' + - $ref: '#/parameters/If-Unmodified-Since' + - in: body + name: permissions + schema: + $ref: '#/definitions/TierPermission' + tags: + - Tiers + responses: + 200: + description: | + OK. + Successfully updated tier permissions + schema: + type: array + items: + $ref: '#/definitions/Tier' + headers: + ETag: + description: | + Entity Tag of the modified tier. + Used by caches, or in conditional request. + type: string + Last-Modified: + description: | + Date and time the tier has been modified. + Used by caches, or in conditional requests. + type: string + 400: + description: | + Bad Request. + Invalid request or validation error. + schema: + $ref: '#/definitions/Error' + 403: + description: | + Forbidden. + The request must be conditional but no condition has been specified. + schema: + $ref: '#/definitions/Error' + 404: + description: | + Not Found. + Requested tier does not exist. + schema: + $ref: '#/definitions/Error' + 412: + description: | + Precondition Failed. + The request has not been performed because one of the preconditions is not met. + schema: + $ref: '#/definitions/Error' + + +###################################################### +# The "Environment Collection" resource API +###################################################### + /environments: + +#----------------------------------------------------- +# Retrieve the list of environments configured for a certain API +#----------------------------------------------------- + get: + x-scope: apim:api_view + x-wso2-curl: "curl -H \"Authorization: Bearer b0982cd2aacd463ff5f63cd5ebe58f4a\" \"http://127.0.0.1:9763/api/am/publisher/v0.10/environments\"" + x-wso2-response: "HTTP/1.1 200 OK\nContent-Type: application/json\n\n{\n \"list\": [ {\n \"showInApiConsole\": true,\n \"serverUrl\": \"https://192.168.56.1:9444//services/\",\n \"endpoints\": {\n \"http\": \"http://192.168.56.1:8281\",\n \"https\": \"https://192.168.56.1:8244\"\n },\n \"name\": \"Production and Sandbox\",\n \"type\": \"hybrid\"\n }],\n \"count\": 1\n}" + summary: Get gateway environments + description: | + Get a list of gateway environments configured previously. + parameters: + - in: query + name: apiId + description: | + Will return environment list for the provided API. + type: string + tags: + - Environments + responses: + 200: + description: | + OK. + Environment list is returned. + schema: + $ref: '#/definitions/EnvironmentList' + headers: + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. + Used by caches, or in conditional requests. + type: string + 304: + description: | + Not Modified. + Empty body because the client has already the latest version of the requested resource. + 404: + description: | + Not Found. + Requested API does not exist. + schema: + $ref: '#/definitions/Error' +###################################################### +# Parameters - required by some of the APIs above +###################################################### +parameters: + +# API Identifier +# Specified as part of the path expression + apiId: + name: apiId + in: path + description: | + **API ID** consisting of the **UUID** of the API. + The combination of the provider of the API, name of the API and the version is also accepted as a valid API ID. + Should be formatted as **provider-name-version**. + required: true + type: string + +# API Identifier +# Specified as part of the query string + apiId-Q: + name: apiId + in: query + description: | + **API ID** consisting of the **UUID** of the API. + The combination of the provider of the API, name of the API and the version is also accepted as a valid API I. + Should be formatted as **provider-name-version**. + required: true + type: string + + +# Document Identifier +# Specified as part of the path expression + documentId: + name: documentId + in: path + description: | + **Document Identifier** + required: true + type: string + +# Application Identifier +# Specified as part of the path expression + applicationId: + name: applicationId + in: path + description: | + **Application Identifier** consisting of the UUID of the Application. + required: true + type: string + +# Subscription Identifier +# Specified as part of the path expression + subscriptionId: + name: subscriptionId + in: path + description: | + Subscription Id + required: true + type: string + +# Subscription Identifier +# Specified as part of the query string + subscriptionId-Q: + name: subscriptionId + in: query + description: | + Subscription Id + required: true + type: string + +# Tier Name +# Specified as part of the path expression + tierName: + name: tierName + in: path + description: | + Tier name + required: true + type: string + +# Tier Name +# Specified as part of the query string + tierName-Q: + name: tierName + in: query + description: | + Name of the tier + required: true + type: string + +# Tier Type +# Specified as part of the path expression + tierLevel: + name: tierLevel + in: path + description: | + List API or Application or Resource type tiers. + type: string + enum: + - api + - application + - resource + required: true + +# Tier Type +# Specified as part of the query string + tierLevel-Q: + name: tierLevel + in: query + description: | + List API or Application or Resource type tiers. + type: string + enum: + - api + - application + - resource + required: true + +# Used for pagination: +# The maximum number of resoures to be returned by a GET + limit: + name: limit + in: query + description: | + Maximum size of resource array to return. + default: 25 + type: integer + +# Used for pagination: +# The order number of an instance in a qualified set of resoures +# at which to start to return the next batch of qualified resources + offset: + name: offset + in: query + description: | + Starting point within the complete list of items qualified. + default: 0 + type: integer + +# The HTTP Accept header + Accept: + name: Accept + in: header + description: | + Media types acceptable for the response. Default is JSON. + default: JSON + type: string + +# The HTTP Content-Type header + Content-Type: + name: Content-Type + in: header + description: | + Media type of the entity in the body. Default is JSON. + default: JSON + required: true + type : string + +# The HTTP If-None-Match header +# Used to avoid retrieving data that are already cached + If-None-Match: + name: If-None-Match + in: header + description: | + Validator for conditional requests; based on the ETag of the formerly retrieved + variant of the resourec. + type : string + +# The HTTP If-Modified-Since header +# Used to avoid retrieving data that are already cached + If-Modified-Since: + name: If-Modified-Since + in: header + description: | + Validator for conditional requests; based on Last Modified header of the + formerly retrieved variant of the resource. + type: string + +# The HTTP If-Match header +# Used to avoid concurrent updates + If-Match: + name: If-Match + in: header + description: | + Validator for conditional requests; based on ETag. + type: string + +# The HTTP If-Unmodified-Since header +# Used to avoid concurrent updates + If-Unmodified-Since: + name: If-Unmodified-Since + in: header + description: | + Validator for conditional requests; based on Last Modified header. + type: string + +###################################################### +# The resources used by some of the APIs above within the message body +###################################################### +definitions: + +#----------------------------------------------------- +# The API List resource +#----------------------------------------------------- + APIList: + title: API List + properties: + count: + type: integer + description: | + Number of APIs returned. + example: 1 + next: + type: string + description: | + Link to the next subset of resources qualified. + Empty if no more resources are to be returned. + example: "/apis?limit=1&offset=2&query=" + previous: + type: string + description: | + Link to the previous subset of resources qualified. + Empty if current subset is the first subset returned. + example: "/apis?limit=1&offset=0&query=" + list: + type: array + items: + $ref: '#/definitions/APIInfo' + +#----------------------------------------------------- +# The API Info resource +#----------------------------------------------------- + APIInfo: + title: API Info object with basic API details. + properties: + id: + type: string + example: 01234567-0123-0123-0123-012345678901 + name: + type: string + example: CalculatorAPI + description: + type: string + example: A calculator API that supports basic operations + context: + type: string + example: CalculatorAPI + version: + type: string + example: 1.0.0 + provider: + description: | + If the provider value is not given, the user invoking the API will be used as the provider. + type: string + example: admin + status: + type: string + example: CREATED + +#----------------------------------------------------- +# The API resource +#----------------------------------------------------- + API: + title: API object + required: + - name + - context + - version + - apiDefinition + - tiers + - isDefaultVersion + - transport + - endpointConfig + - visibility + properties: + id: + type: string + description: | + UUID of the api registry artifact + example: 01234567-0123-0123-0123-012345678901 + name: + type: string + example: CalculatorAPI + description: + type: string + example: A calculator API that supports basic operations + context: + type: string + example: CalculatorAPI + version: + type: string + example: 1.0.0 + provider: + description: | + If the provider value is not given user invoking the api will be used as the provider. + type: string + example: admin + apiDefinition: + description: | + Swagger definition of the API which contains details about URI templates and scopes + type: string + wsdlUri: + description: | + WSDL URL if the API is based on a WSDL endpoint + type: string + example: "http://www.webservicex.com/globalweather.asmx?wsdl" + status: + type: string + example: CREATED + responseCaching: + type: string + example: Disabled + cacheTimeout: + type: integer + example: 300 + destinationStatsEnabled: + type: string + example: Disabled + isDefaultVersion: + type: boolean + example: false + transport: + description: | + Supported transports for the API (http and/or https). + type: array + items: + type: string + example: ["http","https"] + tags: + type: array + items: + type: string + example: ["substract","add"] + tiers: + type: array + items: + type: string + example: ["Unlimited"] + maxTps: + properties: + production: + type: integer + format: int64 + example: 1000 + sandbox: + type: integer + format: int64 + example: 1000 + thumbnailUri: + type: string + example: "/apis/01234567-0123-0123-0123-012345678901/thumbnail" + visibility: + type: string + enum: + - PUBLIC + - PRIVATE + - RESTRICTED + - CONTROLLED + example: PUBLIC + visibleRoles: + type: array + items: + type: string + example: [] + visibleTenants: + type: array + items: + type: string + example: [] + endpointConfig: + type: string + example: "{\"production_endpoints\":{\"url\":\"http://localhost:9763/am/sample/calculator/v1/api\",\"config\":null},\"implementation_status\":\"managed\",\"endpoint_type\":\"http\"}" + endpointSecurity: + properties: + type: + type: string + example: basic + enum: + - basic + - digest + username: + type: string + example: admin + password: + type: string + example: password + gatewayEnvironments: + description: | + Comma separated list of gateway environments. + type: string + example: Production and Sandbox + sequences: + type: array + items: + $ref: '#/definitions/Sequence' + example: [] + subscriptionAvailability: + type: string + enum: + - current_tenant + - all_tenants + - specific_tenants + example: current_tenant + subscriptionAvailableTenants: + type: array + items: + type: string + example: [] + businessInformation: + properties: + businessOwner: + type: string + example: businessowner + businessOwnerEmail: + type: string + example: businessowner@wso2.com + technicalOwner: + type: string + example: technicalowner + technicalOwnerEmail: + type: string + example: technicalowner@wso2.com + corsConfiguration: + description: | + CORS configuration for the API + properties: + corsConfigurationEnabled: + type: boolean + default: false + accessControlAllowOrigins: + type: array + items: + type: string + accessControlAllowCredentials: + type: boolean + default: false + accessControlAllowHeaders: + type: array + items: + type: string + accessControlAllowMethods: + type: array + items: + type: string + +#----------------------------------------------------- +# The Application resource +#----------------------------------------------------- + Application: + title: Application + required: + - name + - throttlingTier + properties: + applicationId: + type: string + example: 01234567-0123-0123-0123-012345678901 + name: + type: string + example: CalculatorApp + subscriber: + type: string + example: admin + throttlingTier: + type: string + example: Unlimited + description: + type: string + example: Sample calculator application + groupId: + type: string + example: "" + +#----------------------------------------------------- +# The Document List resource +#----------------------------------------------------- + DocumentList: + title: Document List + properties: + count: + type: integer + description: | + Number of Documents returned. + example: 1 + next: + type: string + description: | + Link to the next subset of resources qualified. + Empty if no more resources are to be returned. + example: "/apis/01234567-0123-0123-0123-012345678901/documents?limit=1&offset=2" + previous: + type: string + description: | + Link to the previous subset of resources qualified. + Empty if current subset is the first subset returned. + example: "/apis/01234567-0123-0123-0123-012345678901/documents?limit=1&offset=0" + list: + type: array + items: + $ref: '#/definitions/Document' + +#----------------------------------------------------- +# The Document resource +#----------------------------------------------------- + Document: + title: Document + required: + - name + - type + - sourceType + - visibility + properties: + documentId: + type: string + example: 01234567-0123-0123-0123-012345678901 + name: + type: string + example: CalculatorDoc + type: + type: string + enum: + - HOWTO + - SAMPLES + - PUBLIC_FORUM + - SUPPORT_FORUM + - API_MESSAGE_FORMAT + - SWAGGER_DOC + - OTHER + example: HOWTO + summary: + type: string + example: "Summary of Calculator Documentation" + sourceType: + type: string + enum: + - INLINE + - URL + - FILE + example: INLINE + sourceUrl: + type: string + example: "" + otherTypeName: + type: string + example: "" + visibility: + type: string + enum: + - OWNER_ONLY + - PRIVATE + - API_LEVEL + example: API_LEVEL + +#----------------------------------------------------- +# The Tier List resource +#----------------------------------------------------- + TierList: + title: Tier List + properties: + count: + type: integer + description: | + Number of Tiers returned. + example: 1 + next: + type: string + description: | + Link to the next subset of resources qualified. + Empty if no more resources are to be returned. + example: "/tiers/api?limit=1&offset=2" + previous: + type: string + description: | + Link to the previous subset of resources qualified. + Empty if current subset is the first subset returned. + example: "/tiers/api?limit=1&offset=0" + list: + type: array + items: + $ref: '#/definitions/Tier' + +#----------------------------------------------------- +# The Tier resource +#----------------------------------------------------- + Tier: + title: Tier + required: + - name + - tierPlan + - requestCount + - unitTime + - stopOnQuotaReach + properties: + name: + type: string + example: Platinum + description: + type: string + example: "Allows 50 request(s) per minute." + tierLevel: + type: string + enum: + - api + - application + - resource + example: api + attributes: + description: | + Custom attributes added to the tier policy + type: object + additionalProperties: + type: string + example: {} + requestCount: + description: | + Maximum number of requests which can be sent within a provided unit time + type: integer + format: int64 + example: 50 + unitTime: + type: integer + format: int64 + example: 60000 + timeUnit: + type: string + example: "min" + tierPlan: + description: | + This attribute declares whether this tier is available under commercial or free + type: string + enum: + - FREE + - COMMERCIAL + example: FREE + stopOnQuotaReach: + description: | + By making this attribute to false, you are capabale of sending requests + even if the request count exceeded within a unit time + type: boolean + example: true + +#----------------------------------------------------- +# The Tier Permission resource +#----------------------------------------------------- + TierPermission: + title: tierPermission + required: + - permissionType + - roles + properties: + permissionType: + type: string + enum: + - allow + - deny + example: deny + roles: + type: array + items: + type: string + example: ["Internal/everyone"] + +#----------------------------------------------------- +# The Subscription List resource +#----------------------------------------------------- + SubscriptionList: + title: Subscription List + properties: + count: + type: integer + description: | + Number of Subscriptions returned. + example: 1 + next: + type: string + description: | + Link to the next subset of resources qualified. + Empty if no more resources are to be returned. + example: "/subscriptions?limit=1&offset=2&apiId=01234567-0123-0123-0123-012345678901&groupId=" + previous: + type: string + description: | + Link to the previous subset of resources qualified. + Empty if current subset is the first subset returned. + example: "/subscriptions?limit=1&offset=0&apiId=01234567-0123-0123-0123-012345678901&groupId=" + list: + type: array + items: + $ref: '#/definitions/Subscription' + +#----------------------------------------------------- +# The Subscription resource +#----------------------------------------------------- + Subscription: + title: Subscription + required: + - applicationId + - apiIdentifier + - tier + properties: + subscriptionId: + type: string + example: 01234567-0123-0123-0123-012345678901 + applicationId: + type: string + example: 01234567-0123-0123-0123-012345678901 + apiIdentifier: + type: string + example: 01234567-0123-0123-0123-012345678901 + tier: + type: string + example: Unlimited + status: + type: string + enum: + - BLOCKED + - PROD_ONLY_BLOCKED + - UNBLOCKED + - ON_HOLD + - REJECTED + example: UNBLOCKED + +#----------------------------------------------------- +# The Sequence resource +#----------------------------------------------------- + Sequence: + title: Sequence + required: + - name + properties: + name: + type: string + example: log_in_message + config: + type: string + example: "" + type: + type: string + example: in + +#----------------------------------------------------- +# The Error resource +#----------------------------------------------------- + Error: + title: Error object returned with 4XX HTTP status + required: + - code + - message + properties: + code: + type: integer + format: int64 + message: + type: string + description: Error message. + description: + type: string + description: | + A detail description about the error message. + moreInfo: + type: string + description: | + Preferably an url with more details about the error. + error: + type: array + description: | + If there are more than one error list them out. + For example, list out validation errors by each field. + items: + $ref: '#/definitions/ErrorListItem' + +#----------------------------------------------------- +# The Error List Item resource +#----------------------------------------------------- + ErrorListItem: + title: Description of individual errors that may have occurred during a request. + required: + - code + - message + properties: + code: + type: string + message: + type: string + description: | + Description about individual errors occurred + +#----------------------------------------------------- +# The Environment resource +#----------------------------------------------------- + Environment: + title: Environment + required: + - name + - type + - serverUrl + - endpoints + - showInApiConsole + properties: + name: + type: string + example: Production and Sandbox + type: + type: string + example: hybrid + serverUrl: + type: string + example: "https://localhost:9443//services/" + showInApiConsole: + type: boolean + example: true + endpoints: + $ref: '#/definitions/EnvironmentEndpoints' + +#----------------------------------------------------- +# The Environment List resource +#----------------------------------------------------- + EnvironmentList: + title: Environment List + properties: + count: + type: integer + description: | + Number of Environments returned. + example: 1 + list: + type: array + items: + $ref: '#/definitions/Environment' + + +#----------------------------------------------------- +# The Environment Endpoint resource +#----------------------------------------------------- + EnvironmentEndpoints : + title: Environment Endpoints + properties: + http: + type: string + description: HTTP environment URL + example: "http://localhost:8280" + https: + type: string + description: HTTPS environment URL + example: "https://localhost:8244" + +#----------------------------------------------------- +# The File Information resource +#----------------------------------------------------- + FileInfo : + title: File Information including meta data + properties: + relativePath: + type: string + description: relative location of the file (excluding the base context and host of the Publisher API) + example: "apis/01234567-0123-0123-0123-012345678901/thumbnail" + mediaType: + type: string + description: media-type of the file + example: "image/jpeg" \ No newline at end of file diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.generated.client/src/main/resources/store-api.yaml b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.generated.client/src/main/resources/store-api.yaml new file mode 100644 index 0000000000..eed49e831e --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.generated.client/src/main/resources/store-api.yaml @@ -0,0 +1,2311 @@ +swagger: '2.0' +###################################################### +# Prolog +###################################################### +info: + version: "0.11.0" + title: "WSO2 API Manager - Store" + description: | + This specifies a **RESTful API** for WSO2 **API Manager** - Store. + + Please see [full swagger definition](https://raw.githubusercontent.com/wso2/carbon-apimgt/v6.0.4/components/apimgt/org.wso2.carbon.apimgt.rest.api.store/src/main/resources/store-api.yaml) of the API which is written using [swagger 2.0](http://swagger.io/) specification. + contact: + name: "WSO2" + url: "http://wso2.com/products/api-manager/" + email: "architecture@wso2.com" + license: + name: "Apache 2.0" + url: "http://www.apache.org/licenses/LICENSE-2.0.html" + +###################################################### +# The fixed parts of the URLs of the API +###################################################### + +# The schemes supported by the API +schemes: + - https + +# The domain of the API. +# This is configured by the customer during deployment. +# The given host is just an example. +host: apis.wso2.com + +# The base path of the API. +# Will be prefixed to all paths. +basePath: /api/am/store/v0.11 + +# The following media types can be passed as input in message bodies of the API. +# The actual media type must be specified in the Content-Type header field of the request. +# The default is json, i.e. the Content-Type header is not needed to +# be set, but supporting it serves extensibility. +consumes: + - application/json + +# The following media types may be passed as output in message bodies of the API. +# The media type(s) consumable by the requestor is specified in the Accept header field +# of the corresponding request. +# The actual media type returned will be specfied in the Content-Type header field +# of the of the response. +# The default of the Accept header is json, i.e. there is not needed to +# set the value, but supporting it serves extensibility. +produces: + - application/json + +x-wso2-security: + apim: + x-wso2-scopes: + - description: "" + roles: Internal/subscriber + name: apim:subscribe + key: apim:subscribe + +###################################################### +# The "API Collection" resource APIs +###################################################### +paths: + /apis: + +#----------------------------------------------------- +# Retrieving the list of all APIs qualifying under a given search condition +#----------------------------------------------------- + get: + x-wso2-curl: "curl https://127.0.0.1:9443/api/am/store/v0.11/apis" + x-wso2-request: | + GET https://127.0.0.1:9443/api/am/store/v0.11/apis + x-wso2-response: "HTTP/1.1 200 OK\nContent-Type: application/json\n\n{\n \"previous\": \"\",\n \"list\": [\n {\n \"provider\": \"admin\",\n \"version\": \"1.0.0\",\n \"description\": \"This API provide Account Status Validation.\",\n \"status\": \"PUBLISHED\",\n \"name\": \"AccountVal\",\n \"context\": \"/account/1.0.0\",\n \"id\": \"2e81f147-c8a8-4f68-b4f0-69e0e7510b01\"\n },\n {\n \"provider\": \"admin\",\n \"version\": \"1.0.0\",\n \"description\": null,\n \"status\": \"PUBLISHED\",\n \"name\": \"api1\",\n \"context\": \"/api1/1.0.0\",\n \"id\": \"3e22d2fb-277a-4e9e-8c7e-1c0f7f73960e\"\n },\n {\n \"provider\": \"admin\",\n \"version\": \"2.0.0\",\n \"description\": \"Verify a phone number\",\n \"status\": \"PUBLISHED\",\n \"name\": \"PhoneVerification\",\n \"context\": \"/phoneverify/2.0.0\",\n \"id\": \"c43a325c-260b-4302-81cb-768eafaa3aed\"\n }\n ],\n \"count\": 3,\n \"next\": \"\"\n}" + summary: | + Retrieve/Search APIs + description: | + This operation provides you a list of available APIs qualifying under a given search condition. + + Each retrieved API is represented with a minimal amount of attributes. If you want to get complete details of an API, you need to use **Get details of an API** operation. + + This operation supports retriving APIs of other tenants. The required tenant domain need to be specified as a header `X-WSO2-Tenant`. If not specified super tenant's APIs will be retrieved. If you used an Authorization header, the user's tenant associated with the access token will be used. + + **NOTE:** + * By default, this operation retrieves Published APIs. In order to retrieve Prototyped APIs, you need to use **query** parameter and specify **status:PROTOTYPED**. + * This operation does not require an Authorization header by default. But if it is provided, it will be validated and checked for permissions of the user, hence you may be able to see APIs which are restricted for special permissions/roles. + parameters: + - $ref : '#/parameters/limit' + - $ref : '#/parameters/offset' + - $ref : '#/parameters/requestedTenant' + - name : query + in: query + description: | + **Search condition**. + + You can search in attributes by using an **":"** modifier. + + Eg. + "provider:wso2" will match an API if the provider of the API is exactly "wso2". + + Additionally you can use wildcards. + + Eg. + "provider:wso2*" will match an API if the provider of the API starts with "wso2". + + Supported attribute modifiers are [**version, context, status, + description, subcontext, doc, provider, tag**] + + If no advanced attribute modifier has been specified, search will match the + given query string against API Name. + + type: string + - $ref : "#/parameters/Accept" + - $ref : "#/parameters/If-None-Match" + tags: + - API (Collection) + responses: + 200: + description: | + OK. + List of qualifying APIs is returned. + schema: + $ref: '#/definitions/APIList' + headers: + Content-Type: + description: The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. Used by caches, or in conditional requests (Will be supported in future). + type: string + 304: + description: | + Not Modified. + Empty body because the client has already the latest version of the requested resource (Will be supported in future). + 406: + description: | + Not Acceptable. + The requested media type is not supported + schema: + $ref: '#/definitions/Error' + +###################################################### +# The "Individual API" resource APIs +###################################################### + /apis/{apiId}: + +#----------------------------------------------------- +# Retrieve the details of an API definition +#----------------------------------------------------- + get: + x-wso2-curl: "curl https://127.0.0.1:9443/api/am/store/v0.11/apis/c43a325c-260b-4302-81cb-768eafaa3aed" + x-wso2-request: | + GET https://127.0.0.1:9443/api/am/store/v0.11/apis/c43a325c-260b-4302-81cb-768eafaa3aed + x-wso2-response: "HTTP/1.1 200 OK\nContent-Type: application/json\n\n{\r\n \"thumbnailUrl\": null,\r\n \"tiers\": [\"Unlimited\"],\r\n \"businessInformation\": {\r\n \"technicalOwner\": \"John Doe\",\r\n \"technicalOwnerEmail\": \"architecture@pizzashack.com\",\r\n \"businessOwner\": \"Jane Roe\",\r\n \"businessOwnerEmail\": \"marketing@pizzashack.com\"\r\n },\r\n \"apiDefinition\": \"{\\\"paths\\\":{\\\"/order\\\":{\\\"post\\\":{\\\"x-auth-type\\\":\\\"Application & Application User\\\",\\\"x-throttling-tier\\\":\\\"Unlimited\\\",\\\"description\\\":\\\"Create a new Order\\\",\\\"parameters\\\":[{\\\"schema\\\":{\\\"$ref\\\":\\\"#/definitions/Order\\\"},\\\"description\\\":\\\"Order object that needs to be added\\\",\\\"name\\\":\\\"body\\\",\\\"required\\\":true,\\\"in\\\":\\\"body\\\"}],\\\"responses\\\":{\\\"201\\\":{\\\"headers\\\":{\\\"Location\\\":{\\\"description\\\":\\\"The URL of the newly created resource.\\\",\\\"type\\\":\\\"string\\\"},\\\"Content-Type\\\":{\\\"description\\\":\\\"The content type of the body.\\\",\\\"type\\\":\\\"string\\\"}},\\\"schema\\\":{\\\"$ref\\\":\\\"#/definitions/Order\\\"},\\\"description\\\":\\\"Created. Successful response with the newly created object as entity in the body. Location header contains URL of newly created entity.\\\"}}}},\\\"/order/{orderId}\\\":{\\\"get\\\":{\\\"x-auth-type\\\":\\\"Application & Application User\\\",\\\"x-throttling-tier\\\":\\\"Unlimited\\\",\\\"description\\\":\\\"Get details of an Order\\\",\\\"parameters\\\":[{\\\"description\\\":\\\"Order Id\\\",\\\"name\\\":\\\"orderId\\\",\\\"format\\\":\\\"integer\\\",\\\"type\\\":\\\"number\\\",\\\"required\\\":true,\\\"in\\\":\\\"path\\\"}],\\\"responses\\\":{\\\"200\\\":{\\\"schema\\\":{\\\"$ref\\\":\\\"#/definitions/Order\\\"},\\\"headers\\\":{},\\\"description\\\":\\\"OK Requested Order will be returned\\\"}}}}},\\\"schemes\\\":[\\\"https\\\"],\\\"produces\\\":[\\\"application/json\\\"],\\\"swagger\\\":\\\"2.0\\\",\\\"definitions\\\":{\\\"Order\\\":{\\\"title\\\":\\\"Pizza Order\\\",\\\"properties\\\":{\\\"customerName\\\":{\\\"type\\\":\\\"string\\\"},\\\"delivered\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"address\\\":{\\\"type\\\":\\\"string\\\"},\\\"pizzaType\\\":{\\\"type\\\":\\\"string\\\"},\\\"creditCardNumber\\\":{\\\"type\\\":\\\"string\\\"},\\\"quantity\\\":{\\\"type\\\":\\\"number\\\"},\\\"orderId\\\":{\\\"type\\\":\\\"integer\\\"}},\\\"required\\\":[\\\"orderId\\\"]}},\\\"consumes\\\":[\\\"application/json\\\"],\\\"info\\\":{\\\"title\\\":\\\"PizzaShackAPI\\\",\\\"description\\\":\\\"This document describe a RESTFul API for Pizza Shack online pizza delivery store.\\\\n\\\",\\\"license\\\":{\\\"name\\\":\\\"Apache 2.0\\\",\\\"url\\\":\\\"http://www.apache.org/licenses/LICENSE-2.0.html\\\"},\\\"contact\\\":{\\\"email\\\":\\\"architecture@pizzashack.com\\\",\\\"name\\\":\\\"John Doe\\\",\\\"url\\\":\\\"http://www.pizzashack.com\\\"},\\\"version\\\":\\\"1.0.0\\\"}}\",\r\n \"wsdlUri\": null,\r\n \"isDefaultVersion\": false,\r\n \"endpointURLs\": [ {\r\n \"environmentName\": \"Production and Sandbox\",\r\n \"environmentType\": \"hybrid\",\r\n \"environmentURLs\": {\r\n \"http\": \"http://10.100.7.77:8280//pizzashack/1.0.0\",\r\n \"https\": \"https://10.100.7.77:8243//pizzashack/1.0.0\"\r\n }\r\n }],\r\n \"transport\": [\r\n \"http\",\r\n \"https\"\r\n ],\r\n \"tags\": [\"pizza\"],\r\n \"version\": \"1.0.0\",\r\n \"description\": \"This document describe a RESTFul API for Pizza Shack online pizza delivery store.\\r\\n\",\r\n \"provider\": \"admin\",\r\n \"name\": \"PizzaShackAPI\",\r\n \"context\": \"/pizzashack/1.0.0\",\r\n \"id\": \"8848faaa-7fd1-478a-baa2-48a4ebb92c98\",\r\n \"status\": \"PUBLISHED\"\r\n} " + summary: | + Get details of an API + description: | + Using this operation, you can retrieve complete details of a single API. You need to provide the Id of the API to retrive it. + + `X-WSO2-Tenant` header can be used to retrive an API of a different tenant domain. If not specified super tenant will be used. If Authorization header is present in the request, the user's tenant associated with the access token will be used. + + **NOTE:** + * This operation does not require an Authorization header by default. But if it is provided, it will be validated and checked for permissions of the user, hence you may be able to see APIs which are restricted for special permissions/roles. \n + parameters: + - $ref: '#/parameters/apiId' + - $ref: '#/parameters/Accept' + - $ref: '#/parameters/If-None-Match' + - $ref: '#/parameters/If-Modified-Since' + - $ref: '#/parameters/requestedTenant' + tags: + - API (Individual) + responses: + 200: + description: | + OK. + Requested API is returned + headers: + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. Used by caches, or in conditional requests (Will be supported in future). + type: string + Last-Modified: + description: | + Date and time the resource has been modifed the last time. + Used by caches, or in conditional requests (Will be supported in future). + type: string + schema: + $ref: '#/definitions/API' + 304: + description: | + Not Modified. + Empty body because the client has already the latest version of the requested resource (Will be supported in future). + 404: + description: | + Not Found. + Requested API does not exist. + schema: + $ref: '#/definitions/Error' + 406: + description: | + Not Acceptable. + The requested media type is not supported + schema: + $ref: '#/definitions/Error' + + + /apis/{apiId}/swagger: +#----------------------------------------------------- +# Retrieve the API swagger definition +#----------------------------------------------------- + get: + x-wso2-request: | + GET https://127.0.0.1:9443/api/am/store/v0.11/apis/c43a325c-260b-4302-81cb-768eafaa3aed/swagger + x-wso2-curl: "curl https://127.0.0.1:9443/api/am/store/v0.11/apis/c43a325c-260b-4302-81cb-768eafaa3aed/swagger" + x-wso2-response: "HTTP/1.1 200 OK\nContent-Type: application/json\n\n{\n \"paths\": {\"/*\": {\"get\": {\n \"x-auth-type\": \"Application\",\n \"x-throttling-tier\": \"Unlimited\",\n \"responses\": {\"200\": {\"description\": \"OK\"}}\n }}},\n \"x-wso2-security\": {\"apim\": {\"x-wso2-scopes\": []}},\n \"swagger\": \"2.0\",\n \"info\": {\n \"title\": \"PhoneVerification\",\n \"description\": \"Verify a phone number\",\n \"contact\": {\n \"email\": \"xx@ee.com\",\n \"name\": \"xx\"\n },\n \"version\": \"2.0.0\"\n }\n}\n" + summary: | + Get swagger definition + description: | + You can use this operation to retrieve the swagger definition of an API. + + `X-WSO2-Tenant` header can be used to retrive the swagger definition an API of a different tenant domain. If not specified super tenant will be used. If Authorization header is present in the request, the user's tenant associated with the access token will be used. + + **NOTE:** + * This operation does not require an Authorization header by default. But in order to see a restricted API's swagger definition, you need to provide Authorization header. + parameters: + - $ref: '#/parameters/apiId' + - $ref: '#/parameters/Accept' + - $ref: '#/parameters/If-None-Match' + - $ref: '#/parameters/If-Modified-Since' + - $ref: '#/parameters/requestedTenant' + tags: + - API (Individual) + responses: + 200: + description: | + OK. + Requested swagger document of the API is returned + headers: + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. Used by caches, or in conditional requests (Will be supported in future). + type: string + Last-Modified: + description: | + Date and time the resource has been modifed the last time. + Used by caches, or in conditional requests (Will be supported in future). + type: string + 304: + description: | + Not Modified. + Empty body because the client has already the latest version of the requested resource (Will be supported in future). + 404: + description: | + Not Found. + Requested API does not exist. + schema: + $ref: '#/definitions/Error' + 406: + description: | + Not Acceptable. + The requested media type is not supported + schema: + $ref: '#/definitions/Error' + +#----------------------------------------------------- +# Generate SDK for an API +#----------------------------------------------------- + /apis/generate-sdk/: + post: + x-scope: apim:subscribe + x-wso2-request: | + GET https://127.0.0.1:9443/api/am/store/v0.11/apis/generate-sdk + x-wso2-curl: "curl https://127.0.0.1:9443/api/am/store/v0.11/apis/generate-sdk" + x-wso2-response: "HTTP/1.1 200 OK \n Content-Disposition: attachment; filename=\"PizzaShackAPI_1.0.0_java.zip\" \n Date: Wed, 12 Oct 2016 11:10:49 GMT \n Content-Type: application/zip \n Transfer-Encoding: chunked \n Server: WSO2 Carbon Server" + summary: | + Generate SDK for an API + description: | + This operation can be used to generate SDK for an API by providing the id of the API along with the preferred language. + parameters: + - $ref: '#/parameters/apiId-Q' + - $ref: '#/parameters/language' + - $ref : '#/parameters/requestedTenant' + tags: + - API (Individual) + responses: + 200: + description: | + OK. + SDK generated successfully. + headers: + Content-Type: + description: | + The content type of the body. + type: string + 400: + description: | + Bad request. + SDK language is not supported. + schema: + $ref: '#/definitions/Error' + 404: + description: | + Not Found. + Requested API does not exist. + schema: + $ref: '#/definitions/Error' + 406: + description: | + Not Acceptable. + The requested media type is not supported + schema: + $ref: '#/definitions/Error' + +###################################################### +# The "Document Collection" resource APIs +###################################################### + /apis/{apiId}/documents: + +#----------------------------------------------------- +# Retrieve the documents associated with an API that qualify under a search condition +#----------------------------------------------------- + get: + x-wso2-request: | + GET https://127.0.0.1:9443/api/am/store/v0.11/apis/c43a325c-260b-4302-81cb-768eafaa3aed/documents + x-wso2-curl: "curl https://127.0.0.1:9443/api/am/store/v0.11/apis/c43a325c-260b-4302-81cb-768eafaa3aed/documents" + x-wso2-response: "HTTP/1.1 200 OK\nContent-Type: application/json\n\n{\n \"previous\": \"\",\n \"list\": [\n {\n \"sourceType\": \"INLINE\",\n \"sourceUrl\": null,\n \"otherTypeName\": null,\n \"documentId\": \"850a4f34-db2c-4d23-9d85-3f95fbfb082c\",\n \"summary\": \"This is a sample documentation for v1.0.0\",\n \"name\": \"PhoneVerification API Documentation\",\n \"type\": \"HOWTO\"\n },\n {\n \"sourceType\": \"URL\",\n \"sourceUrl\": \"http://wiki.cdyne.com/index.php/Phone_Verification\",\n \"otherTypeName\": null,\n \"documentId\": \"98e18be8-5861-43c7-ba26-8cbbccd3a76f\",\n \"summary\": \"This is the URL for online documentation\",\n \"name\": \"Online Documentation\",\n \"type\": \"SAMPLES\"\n },\n {\n \"sourceType\": \"FILE\",\n \"sourceUrl\": null,\n \"otherTypeName\": null,\n \"documentId\": \"b66451ff-c6c2-4f6a-b91d-3821dc119b04\",\n \"summary\": \"This is a sample documentation pdf\",\n \"name\": \"Introduction to PhoneVerification API PDF\",\n \"type\": \"HOWTO\"\n }\n ],\n \"count\": 3,\n \"next\": \"\"\n}" + summary: | + Get a list of documents of an API + description: | + This operation can be used to retrive a list of documents belonging to an API by providing the id of the API. + + `X-WSO2-Tenant` header can be used to retrive documents of an API that belongs to a different tenant domain. If not specified super tenant will be used. If Authorization header is present in the request, the user's tenant associated with the access token will be used. + + **NOTE:** + * This operation does not require an Authorization header by default. But in order to see a restricted API's documents, you need to provide Authorization header. + parameters: + - $ref: '#/parameters/apiId' + - $ref: '#/parameters/limit' + - $ref: '#/parameters/offset' + - $ref: '#/parameters/requestedTenant' + - $ref: '#/parameters/Accept' + - $ref: '#/parameters/If-None-Match' + tags: + - Document (Collection) + responses: + 200: + description: | + OK. + Document list is returned. + schema: + $ref: '#/definitions/DocumentList' + headers: + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. Used by caches, or in conditional requests (Will be supported in future). + type: string + 304: + description: | + Not Modified. + Empty body because the client has already the latest version of the requested resource (Will be supported in future). + 404: + description: | + Not Found. + Requested API does not exist. + schema: + $ref: '#/definitions/Error' + 406: + description: | + Not Acceptable. + The requested media type is not supported + schema: + $ref: '#/definitions/Error' + +###################################################### +# The "Individual Document" resource APIs +###################################################### + '/apis/{apiId}/documents/{documentId}': + +#----------------------------------------------------- +# Retrieve a particular document of a certain API +#----------------------------------------------------- + get: + x-wso2-request: | + GET https://127.0.0.1:9443/api/am/store/v0.11/apis/c43a325c-260b-4302-81cb-768eafaa3aed/documents/850a4f34-db2c-4d23-9d85-3f95fbfb082c + x-wso2-curl: "curl \"https://127.0.0.1:9443/api/am/store/v0.11/apis/c43a325c-260b-4302-81cb-768eafaa3aed/documents/850a4f34-db2c-4d23-9d85-3f95fbfb082c\"" + x-wso2-response: "HTTP/1.1 200 OK\nContent-Type: application/json\n\n{\n \"sourceType\": \"INLINE\",\n \"sourceUrl\": null,\n \"otherTypeName\": null,\n \"documentId\": \"850a4f34-db2c-4d23-9d85-3f95fbfb082c\",\n \"summary\": \"This is a sample documentation for v1.0.0\",\n \"name\": \"PhoneVerification API Documentation\",\n \"type\": \"HOWTO\"\n}" + summary: | + Get a document of an API + description: | + This operation can be used to retrieve a particular document's metadata associated with an API. + + `X-WSO2-Tenant` header can be used to retrive a document of an API that belongs to a different tenant domain. If not specified super tenant will be used. If Authorization header is present in the request, the user's tenant associated with the access token will be used. + + **NOTE:** + * This operation does not require an Authorization header by default. But in order to see a restricted API's document, you need to provide Authorization header. + parameters: + - $ref: '#/parameters/apiId' + - $ref: '#/parameters/documentId' + - $ref: '#/parameters/requestedTenant' + - $ref: '#/parameters/Accept' + - $ref: '#/parameters/If-None-Match' + - $ref: '#/parameters/If-Modified-Since' + tags: + - Document (Individual) + responses: + 200: + description: | + OK. + Document returned. + schema: + $ref: '#/definitions/Document' + headers: + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. + Used by caches, or in conditional requests (Will be supported in future). + type: string + Last-Modified: + description: | + Date and time the resource has been modifed the last time. + Used by caches, or in conditional requests (Will be supported in future). + type: string + 304: + description: | + Not Modified. + Empty body because the client has already the latest version of the requested resource (Will be supported in future). + 404: + description: | + Not Found. + Requested Document does not exist. + schema: + $ref: '#/definitions/Error' + 406: + description: | + Not Acceptable. + The requested media type is not supported + schema: + $ref: '#/definitions/Error' + + +################################################################ +# The content resource of "Individual Document" resource APIs +################################################################ + + '/apis/{apiId}/documents/{documentId}/content': + + #------------------------------------------------------------------------------------------------- + # Downloads a FILE type document/get the inline content or source url of a certain document + #------------------------------------------------------------------------------------------------- + get: + x-wso2-request: | + GET https://127.0.0.1:9443/api/am/store/v0.11/apis/890a4f4d-09eb-4877-a323-57f6ce2ed79b/documents/0bcb7f05-599d-4e1a-adce-5cb89bfe58d5/content + x-wso2-curl: "curl \"https://127.0.0.1:9443/api/am/store/v0.11/apis/890a4f4d-09eb-4877-a323-57f6ce2ed79b/documents/0bcb7f05-599d-4e1a-adce-5cb89bfe58d5/content\" > sample.pdf" + x-wso2-response: "HTTP/1.1 200 OK\nContent-Disposition: attachment; filename=\"sample.pdf\"\nContent-Type: application/octet-stream\nContent-Length: 7802\n\n%PDF-1.4\n%äüöß\n2 0 obj\n<>\nstream\n..\n>>\nstartxref\n7279\n%%EOF" + + summary: | + Get the content of an API document + description: | + This operation can be used to retrive the content of an API's document. + + The document can be of 3 types. In each cases responses are different. + + 1. **Inline type**: + The content of the document will be retrieved in `text/plain` content type + 2. **FILE type**: + The file will be downloaded with the related content type (eg. `application/pdf`) + 3. **URL type**: + The client will recieve the URL of the document as the Location header with the response with - `303 See Other` + + `X-WSO2-Tenant` header can be used to retrive the content of a document of an API that belongs to a different tenant domain. If not specified super tenant will be used. If Authorization header is present in the request, the user's tenant associated with the access token will be used. + + **NOTE:** + * This operation does not require an Authorization header by default. But in order to see a restricted API's document content, you need to provide Authorization header. + parameters: + - $ref: '#/parameters/apiId' + - $ref: '#/parameters/documentId' + - $ref: '#/parameters/requestedTenant' + - $ref: '#/parameters/Accept' + - $ref: '#/parameters/If-None-Match' + - $ref: '#/parameters/If-Modified-Since' + tags: + - Document (Individual) + responses: + 200: + description: | + OK. + File or inline content returned. + headers: + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. + Used by caches, or in conditional requests (Will be supported in future). + type: string + Last-Modified: + description: | + Date and time the resource has been modifed the last time. + Used by caches, or in conditional requests (Will be supported in future). + type: string + 303: + description: | + See Other. + Source can be retrived from the URL specified at the Location header. + headers: + Location: + description: | + The Source URL of the document. + type: string + 304: + description: | + Not Modified. + Empty body because the client has already the latest version of the requested resource (Will be supported in future). + 404: + description: | + Not Found. + Requested Document does not exist. + schema: + $ref: '#/definitions/Error' + 406: + description: | + Not Acceptable. + The requested media type is not supported + schema: + $ref: '#/definitions/Error' + +################################################################ +# The thumbnail resource of "Individual API" resource APIs +################################################################ + + /apis/{apiId}/thumbnail: +#------------------------------------------------------------------------------------------------- +# Downloads a thumbnail image of an API +#------------------------------------------------------------------------------------------------- + get: + x-wso2-request: | + GET https://127.0.0.1:9443/api/am/store/v0.11/apis/e93fb282-b456-48fc-8981-003fb89086ae/thumbnail + x-wso2-curl: "curl https://127.0.0.1:9443/api/am/store/v0.11/apis/e93fb282-b456-48fc-8981-003fb89086ae/thumbnail > image.jpg" + x-wso2-response: "HTTP/1.1 200 OK\r\nContent-Type: image/jpeg\r\n\r\n[image content]" + summary: Get thumbnail image + description: | + This operation can be used to download a thumbnail image of an API. + + **NOTE:** + * This operation does not require an Authorization header by default. But in order to see a restricted API's thumbnail, you need to provide Authorization header. + parameters: + - $ref: '#/parameters/apiId' + - $ref: '#/parameters/requestedTenant' + - $ref: '#/parameters/Accept' + - $ref: '#/parameters/If-None-Match' + - $ref: '#/parameters/If-Modified-Since' + tags: + - API (Individual) + responses: + 200: + description: | + OK. + Thumbnail image returned + headers: + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. + Used by caches, or in conditional requests (Will be supported in future). + type: string + Last-Modified: + description: | + Date and time the resource has been modifed the last time. + Used by caches, or in conditional requests (Will be supported in future). + type: string + 304: + description: | + Not Modified. + Empty body because the client has already the latest version of the requested resource (Will be supported in future). + 404: + description: | + Not Found. + Requested Document does not exist. + schema: + $ref: '#/definitions/Error' + 406: + description: | + Not Acceptable. + The requested media type is not supported + schema: + $ref: '#/definitions/Error' + +###################################################### +# The "Application Collection" resource APIs +###################################################### + /applications: + +#----------------------------------------------------- +# Retrieve a list of all applications of a certain subscriber +#----------------------------------------------------- + get: + x-scope: apim:subscribe + x-wso2-request: | + GET https://127.0.0.1:9443/api/am/store/v0.11/applications + Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8 + x-wso2-curl: "curl -k -H \"Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8\" \"https://127.0.0.1:9443/api/am/store/v0.11/applications\"" + x-wso2-response: "HTTP/1.1 200 OK\nContent-Type: application/json\n\n{\n \"previous\": \"\",\n \"list\": [\n {\n \"groupId\": \"\",\n \"subscriber\": \"admin\",\n \"throttlingTier\": \"Unlimited\",\n \"applicationId\": \"367a2361-8db5-4140-8133-c6c8dc7fa0c4\",\n \"description\": \"\",\n \"status\": \"APPROVED\",\n \"name\": \"app1\"\n },\n {\n \"groupId\": \"\",\n \"subscriber\": \"admin\",\n \"throttlingTier\": \"Unlimited\",\n \"applicationId\": \"896658a0-b4ee-4535-bbfa-806c894a4015\",\n \"description\": null,\n \"status\": \"APPROVED\",\n \"name\": \"DefaultApplication\"\n }\n ],\n \"count\": 2,\n \"next\": \"\"\n}" + summary: | + Retrieve/Search applications + description: | + This operation can be used to retrieve list of applications that is belonged to the user associated with the provided access token. + parameters: + - $ref: '#/parameters/groupId' + - name : query + in: query + description: | + **Search condition**. + + You can search for an application by specifying the name as "query" attribute. + + Eg. + "app1" will match an application if the name is exactly "app1". + + Currently this does not support wildcards. Given name must exactly match the application name. + type: string + - $ref: '#/parameters/limit' + - $ref: '#/parameters/offset' + - $ref: '#/parameters/Accept' + - $ref: '#/parameters/If-None-Match' + tags: + - Application (Collection) + responses: + 200: + description: | + OK. + Application list returned. + schema: + $ref: '#/definitions/ApplicationList' + headers: + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. + Used by caches, or in conditional requests (Will be supported in future). + type: string + 304: + description: | + Not Modified. + Empty body because the client has already the latest version of the requested resource (Will be supported in future). + 400: + description: | + Bad Request. + Invalid request or validation error. + schema: + $ref: '#/definitions/Error' + 406: + description: | + Not Acceptable. + The requested media type is not supported. + schema: + $ref: '#/definitions/Error' + +#----------------------------------------------------- +# Create a new application +#----------------------------------------------------- + post: + x-scope: apim:subscribe + x-wso2-curl: "curl -k -H \"Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8\" -H \"Content-Type: application/json\" -X POST -d @data.json \"https://127.0.0.1:9443/api/am/store/v0.11/applications\"" + x-wso2-request: "POST https://127.0.0.1:9443/api/am/store/v0.11/applications\nAuthorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8\n\n{\n \"throttlingTier\": \"Unlimited\",\n \"description\": \"sample app description\",\n \"name\": \"sampleapp\",\n \"callbackUrl\": \"http://my.server.com/callback\"\n}" + x-wso2-response: "HTTP/1.1 201 Created\nLocation: https://localhost:9443/api/am/store/v0.11/applications/c30f3a6e-ffa4-4ae7-afce-224d1f820524\nContent-Type: application/json\n\n{\n \"groupId\": null,\n \"callbackUrl\": \"http://my.server.com/callback\",\n \"subscriber\": \"admin\",\n \"throttlingTier\": \"Unlimited\",\n \"applicationId\": \"c30f3a6e-ffa4-4ae7-afce-224d1f820524\",\n \"description\": \"sample app description\",\n \"status\": \"APPROVED\",\n \"name\": \"sampleapp\",\n \"keys\": []\n}" + summary: | + Create a new application + description: | + This operation can be used to create a new application specifying the details of the application in the payload. + parameters: + - in: body + name: body + description: | + Application object that is to be created. + required: true + schema: + $ref: '#/definitions/Application' + - $ref: '#/parameters/Content-Type' + tags: + - Application (Individual) + responses: + 201: + description: | + Created. + Successful response with the newly created object as entity in the body. + Location header contains URL of newly created entity. + schema: + $ref: '#/definitions/Application' + headers: + Location: + description: | + Location of the newly created Application. + type: string + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. Used by caches, or in conditional requests (Will be supported in future). + type: string + 400: + description: | + Bad Request. + Invalid request or validation error + schema: + $ref: '#/definitions/Error' + 409: + description: | + Conflict. + Application already exists. + schema: + $ref: '#/definitions/Error' + 415: + description: | + Unsupported media type. + The entity of the request was in a not supported format. + schema: + $ref: '#/definitions/Error' + +###################################################### +# The "Individual Application" resource APIs +###################################################### + '/applications/{applicationId}': + +#----------------------------------------------------- +# Retrieve the details about a certain application +#----------------------------------------------------- + get: + x-scope: apim:subscribe + x-wso2-curl: "curl -k -H \"Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8\" \"https://127.0.0.1:9443/api/am/store/v0.11/applications/896658a0-b4ee-4535-bbfa-806c894a4015\"" + x-wso2-request: | + GET https://127.0.0.1:9443/api/am/store/v0.11/applications/896658a0-b4ee-4535-bbfa-806c894a4015 + Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8 + x-wso2-response: "HTTP/1.1 200 OK\nContent-Type: application/json\n\n{\n \"groupId\": \"\",\n \"callbackUrl\": null,\n \"subscriber\": \"admin\",\n \"throttlingTier\": \"Unlimited\",\n \"applicationId\": \"896658a0-b4ee-4535-bbfa-806c894a4015\",\n \"description\": null,\n \"status\": \"APPROVED\",\n \"name\": \"DefaultApplication\",\n \"keys\": [ {\n \"consumerKey\": \"AVoREWiB16kY_GTIzscl40GYYZQa\",\n \"consumerSecret\": \"KXQxmS8W3xDvvJH4AfR6xrhKIeIa\",\n \"keyState\": \"COMPLETED\",\n \"keyType\": \"PRODUCTION\",\n \"supportedGrantTypes\": null,\n \"token\": {\n \"validityTime\": 3600,\n \"accessToken\": \"3887da6d111f0429c6dff47a46e87209\",\n \"tokenScopes\": [\n \"am_application_scope\",\n \"default\"\n ]\n }\n }]\n}" + summary: | + Get details of an application + description: | + This operation can be used to retrieve details of an individual application specifying the application id in the URI. + parameters: + - $ref: '#/parameters/applicationId' + - $ref: '#/parameters/Accept' + - $ref: '#/parameters/If-None-Match' + - $ref: '#/parameters/If-Modified-Since' + tags: + - Application (Individual) + responses: + 200: + description: | + OK. + Application returned. + schema: + $ref: '#/definitions/Application' + headers: + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. Used by caches, or in conditional requests (Will be supported in future). + type: string + Last-Modified: + description: | + Date and time the resource has been modifed the last time. + Used by caches, or in conditional requests (Will be supported in future). + type: string + 304: + description: | + Not Modified. + Empty body because the client has already the latest version of the requested resource (Will be supported in future). + 404: + description: | + Not Found. + Requested application does not exist. + schema: + $ref: '#/definitions/Error' + 406: + description: | + Not Acceptable. + The requested media type is not supported + schema: + $ref: '#/definitions/Error' + +#----------------------------------------------------- +# Update a certain application +#----------------------------------------------------- + put: + x-scope: apim:subscribe + x-wso2-curl: "curl -k -H \"Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8\" -H \"Content-Type: application/json\" -X PUT -d @data.json \"https://127.0.0.1:9443/api/am/store/v0.11/applications/c30f3a6e-ffa4-4ae7-afce-224d1f820524\"" + x-wso2-request: "PUT https://127.0.0.1:9443/api/am/store/v0.11/applications/c30f3a6e-ffa4-4ae7-afce-224d1f820524\nAuthorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8\n\n{\n \"callbackUrl\": \"\",\n \"throttlingTier\": \"Bronze\",\n \"description\": \"sample app description updated\",\n \"name\": \"sampleapp\"\n}" + x-wso2-response: "HTTP/1.1 200 OK\nContent-Type: application/json\n\n{\n \"groupId\": null,\n \"callbackUrl\": \"\",\n \"subscriber\": \"admin\",\n \"throttlingTier\": \"Bronze\",\n \"applicationId\": \"c30f3a6e-ffa4-4ae7-afce-224d1f820524\",\n \"description\": \"sample app description updated\",\n \"status\": \"APPROVED\",\n \"name\": \"sampleapp\",\n \"keys\": []\n}" + summary: | + Update an application + description: | + This operation can be used to update an application. Upon succesfull you will retrieve the updated application as the response. + parameters: + - $ref: '#/parameters/applicationId' + - in: body + name: body + description: | + Application object that needs to be updated + required: true + schema: + $ref: '#/definitions/Application' + - $ref: '#/parameters/Content-Type' + - $ref: '#/parameters/If-Match' + - $ref: '#/parameters/If-Unmodified-Since' + tags: + - Application (Individual) + responses: + 200: + description: | + OK. + Application updated. + schema: + $ref: '#/definitions/Application' + headers: + Location: + description: | + The URL of the newly created resource. + type: string + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. Used by caches, or in conditional requests (Will be supported in future). + type: string + Last-Modified: + description: | + Date and time the resource has been modifed the last time. + Used by caches, or in conditional requests (Will be supported in future). + type: string + 400: + description: | + Bad Request. + Invalid request or validation error + schema: + $ref: '#/definitions/Error' + 404: + description: | + Not Found. + The resource to be updated does not exist. + schema: + $ref: '#/definitions/Error' + 412: + description: | + Precondition Failed. + The request has not been performed because one of the preconditions is not met (Will be supported in future). + schema: + $ref: '#/definitions/Error' + +#----------------------------------------------------- +# Delete a certain application +#----------------------------------------------------- + delete: + x-scope: apim:subscribe + x-wso2-curl: "curl -k -H \"Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8\" -X DELETE \"https://127.0.0.1:9443/api/am/store/v0.11/applications/367a2361-8db5-4140-8133-c6c8dc7fa0c4\"" + x-wso2-request: | + DELETE https://127.0.0.1:9443/api/am/store/v0.11/applications/367a2361-8db5-4140-8133-c6c8dc7fa0c4 + Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8 + x-wso2-response: "HTTP/1.1 200 OK" + summary: | + Remove an application + description: | + This operation can be used to remove an application specifying its id. + parameters: + - $ref: '#/parameters/applicationId' + - $ref: '#/parameters/If-Match' + - $ref: '#/parameters/If-Unmodified-Since' + tags: + - Application (Individual) + responses: + 200: + description: | + OK. + Resource successfully deleted. + 404: + description: | + Not Found. + Resource to be deleted does not exist. + schema: + $ref: '#/definitions/Error' + 412: + description: | + Precondition Failed. + The request has not been performed because one of the preconditions is not met (Will be supported in future). + schema: + $ref: '#/definitions/Error' + +###################################################### +# The "Generate Keys" Processing Function resource API +###################################################### + '/applications/generate-keys': + +#----------------------------------------------------- +# Generate keys for an application +#----------------------------------------------------- + post: + x-scope: apim:subscribe + x-wso2-curl: "curl -k -H \"Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8\" -H \"Content-Type: application/json\" -X POST -d @data.json \"https://127.0.0.1:9443/api/am/store/v0.11/applications/generate-keys?applicationId=c30f3a6e-ffa4-4ae7-afce-224d1f820524\"" + x-wso2-request: "POST https://127.0.0.1:9443/api/am/store/v0.11/applications/generate-keys?applicationId=c30f3a6e-ffa4-4ae7-afce-224d1f820524\nAuthorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8\n\n{\n \"validityTime\": \"3600\",\n \"keyType\": \"PRODUCTION\",\n \"accessAllowDomains\": [\"ALL\"\n ]\n}" + x-wso2-response: "HTTP/1.1 200 OK\nContent-Type: application/json\n\n{\n \"consumerSecret\": \"8V7DDKtKGtuG_9GDjaOJ5sijdX0a\",\n \"consumerKey\": \"LOFL8He72MSGVil4SS_bsh9O8MQa\",\n \"keyState\": \"APPROVED\",\n \"keyType\": \"PRODUCTION\",\n \"supportedGrantTypes\": [\n \"urn:ietf:params:oauth:grant-type:saml2-bearer\",\n \"iwa:ntlm\",\n \"refresh_token\",\n \"client_credentials\",\n \"password\"\n ],\n \"token\": {\n \"validityTime\": 3600,\n \"accessToken\": \"fd2cdc4906fbc162e033d57f85a71c21\",\n \"tokenScopes\": [\n \"am_application_scope\",\n \"default\"\n ]\n }\n}" + summary: | + Generate keys for application + description: | + This operation can be used to generate client Id and client secret for an application + parameters: + - $ref: '#/parameters/applicationId-Q' + - in: body + name: body + description: | + Application object the keys of which are to be generated + required: true + schema: + $ref: '#/definitions/ApplicationKeyGenerateRequest' + - $ref: '#/parameters/Content-Type' + - $ref: '#/parameters/If-Match' + - $ref: '#/parameters/If-Unmodified-Since' + tags: + - Application (Individual) + responses: + 200: + description: | + OK. + Keys are generated. + schema: + $ref: '#/definitions/ApplicationKey' + headers: + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. + Used by caches, or in conditional requests (Will be supported in future). + type: string + Last-Modified: + description: | + Date and time the resource has been modifed the last time. + Used by caches, or in conditional requests (Will be supported in future).‚ + type: string + 400: + description: | + Bad Request. + Invalid request or validation error + schema: + $ref: '#/definitions/Error' + 404: + description: | + Not Found. + The resource to be updated does not exist. + schema: + $ref: '#/definitions/Error' + 412: + description: | + Precondition Failed. + The request has not been performed because one of the preconditions is not met (Will be supported in future). + schema: + $ref: '#/definitions/Error' + +###################################################### +# The "Subscription Collection" resource APIs +###################################################### + /subscriptions: + +#----------------------------------------------------- +# Retrieve all subscriptions of a certain API and application +#----------------------------------------------------- + get: + x-scope: apim:subscribe + x-wso2-curl: "curl -k -H \"Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8\" \"https://127.0.0.1:9443/api/am/store/v0.11/subscriptions?apiId=c43a325c-260b-4302-81cb-768eafaa3aed\"" + x-wso2-request: | + GET https://127.0.0.1:9443/api/am/store/v0.11/subscriptions?apiId=c43a325c-260b-4302-81cb-768eafaa3aed + Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8 + x-wso2-response: "HTTP/1.1 200 OK\nContent-Type: application/json\n\n{\n \"previous\": \"\",\n \"list\": [\n {\n \"tier\": \"Bronze\",\n \"subscriptionId\": \"03b8ef2b-5ae5-41f5-968e-52fa7fbd5d33\",\n \"apiIdentifier\": \"admin-PhoneVerification-2.0.0\",\n \"applicationId\": \"896658a0-b4ee-4535-bbfa-806c894a4015\",\n \"status\": \"UNBLOCKED\"\n },\n {\n \"tier\": \"Bronze\",\n \"subscriptionId\": \"5ed42650-9f5e-4dd4-94f3-3f09f1b17354\",\n \"apiIdentifier\": \"admin-PhoneVerification-2.0.0\",\n \"applicationId\": \"846118a5-3b25-4c22-a983-2d0278936f09\",\n \"status\": \"UNBLOCKED\"\n }\n ],\n \"count\": 2,\n \"next\": \"\"\n}" + summary: | + Get all subscriptions + description: | + This operation can be used to retrieve a list of subscriptions of the user associated with the provided access token. This operation is capable of + + 1. Retrieving applications which are subscibed to a specific API. + `GET https://127.0.0.1:9443/api/am/store/v0.11/subscriptions?apiId=c43a325c-260b-4302-81cb-768eafaa3aed` + + 2. Retrieving APIs which are subscribed by a specific application. + `GET https://127.0.0.1:9443/api/am/store/v0.11/subscriptions?applicationId=c43a325c-260b-4302-81cb-768eafaa3aed` + + **IMPORTANT:** + * It is mandatory to provide either **apiId** or **applicationId**. + parameters: + - $ref: '#/parameters/apiId-Q' + - $ref: '#/parameters/applicationId-Q' + - $ref: '#/parameters/groupId' + - $ref: '#/parameters/offset' + - $ref: '#/parameters/limit' + - $ref: '#/parameters/Accept' + - $ref: '#/parameters/If-None-Match' + tags: + - Subscription (Collection) + responses: + 200: + description: | + OK. + Subscription list returned. + schema: + $ref: '#/definitions/SubscriptionList' + headers: + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. + Used by caches, or in conditional requests (Will be supported in future). + type: string + 304: + description: | + Not Modified. + Empty body because the client has already the latest version of the requested resource (Will be supported in future). + 406: + description: | + Not Acceptable. The requested media type is not supported + schema: + $ref: '#/definitions/Error' + +#----------------------------------------------------- +# Create a new subscription +#----------------------------------------------------- + post: + x-scope: apim:subscribe + x-wso2-curl: "curl -k -H \"Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8\" -H \"Content-Type: application/json\" -X POST -d @data.json \"https://127.0.0.1:9443/api/am/store/v0.11/subscriptions\"" + x-wso2-request: "POST https://127.0.0.1:9443/api/am/store/v0.11/subscriptions\nAuthorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8\n\n{\n \"tier\": \"Gold\",\n \"apiIdentifier\": \"c43a325c-260b-4302-81cb-768eafaa3aed\",\n \"applicationId\": \"c30f3a6e-ffa4-4ae7-afce-224d1f820524\"\n}" + x-wso2-response: "HTTP/1.1 201 Created\nLocation: https://localhost:9443/api/am/store/v0.11/subscriptions/5b65808c-cdf2-43e1-a695-de63e3ad0ae9\nContent-Type: application/json\n\n{\n \"tier\": \"Gold\",\n \"subscriptionId\": \"5b65808c-cdf2-43e1-a695-de63e3ad0ae9\",\n \"apiIdentifier\": \"admin-PhoneVerification-2.0.0\",\n \"applicationId\": \"c30f3a6e-ffa4-4ae7-afce-224d1f820524\",\n \"status\": \"UNBLOCKED\"\n}" + summary: | + Add a new subscription + description: | + This operation can be used to add a new subscription providing the id of the API and the application. + parameters: + - in: body + name: body + description: | + Subscription object that should to be added + required: true + schema: + $ref: '#/definitions/Subscription' + - $ref: '#/parameters/Content-Type' + tags: + - Subscription (Individual) + responses: + 201: + description: | + Created. + Successful response with the newly created object as entity in the body. + Location header contains URL of newly created entity. + schema: + $ref: '#/definitions/Subscription' + headers: + Location: + description: | + Location to the newly created subscription. + type: string + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. Used by caches, or in conditional requests (Will be supported in future). + type: string + 400: + description: | + Bad Request. + Invalid request or validation error. + schema: + $ref: '#/definitions/Error' + 415: + description: | + Unsupported media type. + The entity of the request was in a not supported format. + +###################################################### +# The "Multiple Subscriptions" resource API +###################################################### + '/subscriptions/multiple': +#----------------------------------------------------- +# Create a batch of Subscriptions +#----------------------------------------------------- + post: + x-scope: apim:subscribe + x-wso2-curl: "curl -k -H \"Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8\" -H \"Content-Type: application/json\" -X POST -d @data.json \"https://127.0.0.1:9443/api/am/store/v0.11/subscriptions/multiple\"" + x-wso2-request: "POST https://127.0.0.1:9443/api/am/store/v0.11/subscriptions/multiple\nAuthorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8\n\n{\n \"tier\": \"Gold\",\n \"apiIdentifier\": \"c43a325c-260b-4302-81cb-768eafaa3aed\",\n \"applicationId\": \"c30f3a6e-ffa4-4ae7-afce-224d1f820524\"\n}" + x-wso2-response: "HTTP/1.1 201 Created\nLocation: https://localhost:9443/api/am/store/v0.11/subscriptions/5b65808c-cdf2-43e1-a695-de63e3ad0ae9\nContent-Type: application/json\n\n{\n \"tier\": \"Gold\",\n \"subscriptionId\": \"5b65808c-cdf2-43e1-a695-de63e3ad0ae9\",\n \"apiIdentifier\": \"admin-PhoneVerification-2.0.0\",\n \"applicationId\": \"c30f3a6e-ffa4-4ae7-afce-224d1f820524\",\n \"status\": \"UNBLOCKED\"\n}" + summary: | + Add new subscriptions + description: | + This operation can be used to add a new subscriptions providing the ids of the APIs and the applications. + parameters: + - in: body + name: body + description: | + Subscription objects that should to be added + required: true + schema: + type: array + items: + $ref: '#/definitions/Subscription' + - $ref: '#/parameters/Content-Type' + tags: + - Subscription (Multitple) + responses: + 200: + description: | + OK. + Successful response with the newly created objects as entity in the body. + schema: + type: array + items: + $ref: '#/definitions/Subscription' + headers: + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. Used by caches, or in conditional requests (Will be supported in future). + type: string + 400: + description: | + Bad Request. + Invalid request or validation error. + schema: + $ref: '#/definitions/Error' + 415: + description: | + Unsupported media type. + The entity of the request was in a not supported format. + +###################################################### +# The "Individual Subscription" resource APIs +###################################################### + '/subscriptions/{subscriptionId}': + +#----------------------------------------------------- +# Retrieve a certain subscription +#----------------------------------------------------- + get: + x-scope: apim:subscribe + x-wso2-curl: "curl -k -H \"Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8\" \"https://127.0.0.1:9443/api/am/store/v0.11/subscriptions/5b65808c-cdf2-43e1-a695-de63e3ad0ae9\"" + x-wso2-request: | + GET https://127.0.0.1:9443/api/am/store/v0.11/subscriptions/5b65808c-cdf2-43e1-a695-de63e3ad0ae9 + Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8 + x-wso2-response: "HTTP/1.1 200 OK\nContent-Type: application/json\n\n{\n \"tier\": \"Gold\",\n \"subscriptionId\": \"5b65808c-cdf2-43e1-a695-de63e3ad0ae9\",\n \"apiIdentifier\": \"admin-PhoneVerification-2.0.0\",\n \"applicationId\": \"c30f3a6e-ffa4-4ae7-afce-224d1f820524\",\n \"status\": \"UNBLOCKED\"\n}" + summary: | + Get details of a subscription + description: | + This operation can be used to get details of a single subscription. + parameters: + - $ref: '#/parameters/subscriptionId' + - $ref: '#/parameters/Accept' + - $ref: '#/parameters/If-None-Match' + - $ref: '#/parameters/If-Modified-Since' + tags: + - Subscription (Individual) + responses: + 200: + description: | + OK. + Subscription returned + schema: + $ref: '#/definitions/Subscription' + headers: + Content-Type: + description: The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. Used by caches, or in conditional requests (Will be supported in future). + type: string + Last-Modified: + description: | + Date and time the resource has been modifed the last time. Used by caches, or in conditional requests (Will be supported in future). + type: string + '304': + description: | + Not Modified. + Empty body because the client has already the latest version of the requested resource (Will be supported in future). + '404': + description: | + Not Found. + Requested Subscription does not exist. + schema: + $ref: '#/definitions/Error' + +#----------------------------------------------------- +# Delete a certain subscription +#----------------------------------------------------- + delete: + x-scope: apim:subscribe + x-wso2-curl: "curl -k -H \"Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8\" -X DELETE \"https://127.0.0.1:9443/api/am/store/v0.11/subscriptions/5b65808c-cdf2-43e1-a695-de63e3ad0ae9\"" + x-wso2-request: | + DELETE https://127.0.0.1:9443/api/am/store/v0.11/subscriptions/5b65808c-cdf2-43e1-a695-de63e3ad0ae9 + x-wso2-response: "HTTP/1.1 200 OK" + summary: | + Remove a subscription + description: | + This operation can be used to remove a subscription. + parameters: + - $ref: '#/parameters/subscriptionId' + - $ref: '#/parameters/If-Match' + - $ref: '#/parameters/If-Unmodified-Since' + tags: + - Subscription (Individual) + responses: + 200: + description: | + OK. + Resource successfully deleted. + 404: + description: | + Not Found. + Resource to be deleted does not exist. + schema: + $ref: '#/definitions/Error' + 412: + description: | + Precondition Failed. + The request has not been performed because one of the preconditions is not met (Will be supported in future). + schema: + $ref: '#/definitions/Error' + +###################################################### +# The "Tier Collection" resource APIs +###################################################### + /tiers/{tierLevel}: + +#----------------------------------------------------- +# Retrieve the list of all available tiers +#----------------------------------------------------- + get: + x-wso2-curl: "curl \"https://127.0.0.1:9443/api/am/store/v0.11/tiers/api\"" + x-wso2-request: | + GET https://127.0.0.1:9443/api/am/store/v0.11/tiers/api + x-wso2-response: "HTTP/1.1 200 OK\nContent-Type: application/json\n\n{\n \"previous\": \"\",\n \"list\": [\n {\n \"unitTime\": 60000,\n \"tierPlan\": \"FREE\",\n \"stopOnQuotaReach\": true,\n \"tierLevel\": \"api\",\n \"requestCount\": 1,\n \"description\": \"Allows 1 request(s) per minute.\",\n \"name\": \"Bronze\",\n \"attributes\": {}\n },\n {\n \"unitTime\": 60000,\n \"tierPlan\": \"FREE\",\n \"stopOnQuotaReach\": true,\n \"tierLevel\": \"api\",\n \"requestCount\": 20,\n \"description\": \"Allows 20 request(s) per minute.\",\n \"name\": \"Gold\",\n \"attributes\": {}\n },\n {\n \"unitTime\": 60000,\n \"tierPlan\": \"FREE\",\n \"stopOnQuotaReach\": true,\n \"tierLevel\": \"api\",\n \"requestCount\": 5,\n \"description\": \"Allows 5 request(s) per minute.\",\n \"name\": \"Silver\",\n \"attributes\": {}\n },\n {\n \"unitTime\": 0,\n \"tierPlan\": null,\n \"stopOnQuotaReach\": true,\n \"tierLevel\": \"api\",\n \"requestCount\": 0,\n \"description\": \"Allows unlimited requests\",\n \"name\": \"Unlimited\",\n \"attributes\": {}\n }\n ],\n \"count\": 4,\n \"next\": \"\"\n}" + summary: | + Get available tiers + description: | + This operation can be used to retrieve all the tiers available for the provided tier level. Tier level should be specified as a path parameter and should be one of `api` and `application`. + + **NOTE**: + * API tiers are the ones that is available during subscription of an application to an API. Hence they are also called subscription tiers and are same as the subscription policies in Admin REST API. + parameters: + - $ref: '#/parameters/limit' + - $ref: '#/parameters/offset' + - $ref: '#/parameters/tierLevel' + - $ref: '#/parameters/requestedTenant' + - $ref: '#/parameters/Accept' + - $ref: '#/parameters/If-None-Match' + tags: + - Throttling Tier (Collection) + responses: + 200: + description: | + OK. + List of tiers returned. + schema: + type: array + items: + $ref: '#/definitions/TierList' + headers: + Content-Type: + description: The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. + Used by caches, or in conditional requests (Will be supported in future). + type: string + 304: + description: | + Not Modified. + Empty body because the client has already the latest version of the requested resource (Will be supported in future). + 406: + description: | + Not Acceptable. + The requested media type is not supported + schema: + $ref: '#/definitions/Error' + +###################################################### +# The "Individual Tier" resource APIs +###################################################### + '/tiers/{tierLevel}/{tierName}': + +#----------------------------------------------------- +# Retrieve a certain tier +#----------------------------------------------------- + get: + x-wso2-curl: "curl \"https://127.0.0.1:9443/api/am/store/v0.11/tiers/api/Bronze\"" + x-wso2-request: | + GET https://127.0.0.1:9443/api/am/store/v0.11/tiers/api/Bronze + x-wso2-response: "HTTP/1.1 200 OK\nContent-Type: application/json\n\n{\n \"unitTime\": 60000,\n \"tierPlan\": \"FREE\",\n \"stopOnQuotaReach\": true,\n \"tierLevel\": \"api\",\n \"requestCount\": 1,\n \"description\": \"Allows 1 request(s) per minute.\",\n \"name\": \"Bronze\",\n \"attributes\": {}\n}" + summary: | + Get details of a tier + description: | + This operation can be used to retrieve details of a single tier by specifying the tier level and tier name. + parameters: + - $ref: '#/parameters/tierName' + - $ref: '#/parameters/tierLevel' + - $ref: '#/parameters/requestedTenant' + - $ref: '#/parameters/Accept' + - $ref: '#/parameters/If-None-Match' + - $ref: '#/parameters/If-Modified-Since' + tags: + - Throttling Tier (Individual) + responses: + 200: + description: | + OK. + Tier returned + schema: + $ref: '#/definitions/Tier' + headers: + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. + Used by caches, or in conditional requests (Will be supported in future). + type: string + Last-Modified: + description: | + Date and time the resource has been modifed the last time. + Used by caches, or in conditional requests (Will be supported in future). + type: string + 304: + description: | + Not Modified. + Empty body because the client has already the latest version of the requested resource (Will be supported in future). + 404: + description: | + Not Found. + Requested Tier does not exist. + schema: + $ref: '#/definitions/Error' + 406: + description: | + Not Acceptable. + The requested media type is not supported. + schema: + $ref: '#/definitions/Error' + +###################################################### +# The "Tag Collection" resource API +###################################################### + /tags: + +#----------------------------------------------------- +# Retrieve the list of tags qualifying under a search condition +#----------------------------------------------------- + get: + x-wso2-curl: "curl \"https://127.0.0.1:9443/api/am/store/v0.11/tags\"" + x-wso2-request: | + GET https://127.0.0.1:9443/api/am/store/v0.11/tags + x-wso2-response: "HTTP/1.1 200 OK\nContent-Type: application/json\n\n{\n \"previous\": \"\",\n \"list\": [\n {\n \"weight\": 1,\n \"name\": \"mobile\"\n },\n {\n \"weight\": 1,\n \"name\": \"multimedia\"\n },\n {\n \"weight\": 1,\n \"name\": \"phone\"\n }\n ],\n \"count\": 3,\n \"next\": \"\"\n}" + summary: | + Get all tags + description: | + This operation can be used to retrieve a list of tags that are already added to APIs. + parameters: + - $ref: '#/parameters/limit' + - $ref: '#/parameters/offset' + - $ref: '#/parameters/requestedTenant' + - $ref: '#/parameters/Accept' + - $ref: '#/parameters/If-None-Match' + tags: + - Tag (Collection) + responses: + 200: + description: | + OK. + Tag list is returned. + schema: + $ref: '#/definitions/TagList' + headers: + Content-Type: + description: | + The content type of the body. + type: string + ETag: + description: | + Entity Tag of the response resource. + Used by caches, or in conditional requests (Will be supported in future). + type: string + 304: + description: | + Not Modified. + Empty body because the client has already the latest version of the requested resource (Will be supported in future). + 404: + description: | + Not Found. Requested API does not exist. + schema: + $ref: '#/definitions/Error' + 406: + description: | + Not Acceptable. The requested media type is not supported + schema: + $ref: '#/definitions/Error' + +###################################################### +# Parameters - required by some of the APIs above +###################################################### +parameters: + +# Requested Tenant domain +# Specified as a header parameter + requestedTenant: + name: X-WSO2-Tenant + in: header + description: | + For cross-tenant invocations, this is used to specify the tenant domain, where the resource need to be + retirieved from. + required: false + type: string + +# API Identifier +# Specified as part of the path expression + apiId: + name: apiId + in: path + description: | + **API ID** consisting of the **UUID** of the API. + The combination of the provider of the API, name of the API and the version is also accepted as a valid API ID. + Should be formatted as **provider-name-version**. + required: true + type: string + +# API Identifier +# Specified as part of the query string + apiId-Q: + name: apiId + in: query + description: | + **API ID** consisting of the **UUID** of the API. + The combination of the provider of the API, name of the API and the version is also accepted as a valid API I. + Should be formatted as **provider-name-version**. + required: true + type: string + +# API Identifier +# Specified as part of the path expression + language: + name: language + in: query + description: | + Programming language to generate SDK. + required: true + type: string + + +# Document Identifier +# Specified as part of the path expression + documentId: + name: documentId + in: path + description: | + Document Identifier + required: true + type: string + +# Application Identifier +# Specified as part of the path expression + applicationId: + name: applicationId + in: path + description: | + Application Identifier consisting of the UUID of the Application. + required: true + type: string + +# Application Identifier +# Specified as part of the query string + applicationId-Q: + name: applicationId + in: query + description: | + Application Identifier consisting of the UUID of the Application. + required: true + type: string + +# Group Identifier of the application + groupId: + name: groupId + in: query + description: | + Application Group Id + required: false + type: string + +# Subscription Identifier +# Specified as part of the path expression + subscriptionId: + name: subscriptionId + in: path + description: | + Subscription Id + required: true + type: string + +# Tier Name +# Specified as part of the path expression + tierName: + name: tierName + in: path + description: | + Tier name + required: true + type: string + +# Tier Type +# Specified as part of the path expression + tierLevel: + name: tierLevel + in: path + description: | + List API or Application type tiers. + type: string + enum: + - api + - application + required: true + +# Used for pagination: +# The maximum number of resoures to be returned by a GET + limit: + name: limit + in: query + description: | + Maximum size of resource array to return. + default: 25 + type: integer + +# Used for pagination: +# The order number of an instance in a qualified set of resoures +# at which to start to return the next batch of qualified resources + offset: + name: offset + in: query + description: | + Starting point within the complete list of items qualified. + default: 0 + type: integer + +# The HTTP Accept header + Accept: + name: Accept + in: header + description: | + Media types acceptable for the response. Default is application/json. + default: application/json + type: string + +# The HTTP Content-Type header + Content-Type: + name: Content-Type + in: header + description: | + Media type of the entity in the body. Default is application/json. + default: application/json + required: true + type : string + +# The HTTP If-None-Match header +# Used to avoid retrieving data that are already cached + If-None-Match: + name: If-None-Match + in: header + description: | + Validator for conditional requests; based on the ETag of the formerly retrieved + variant of the resourec. + type : string + +# The HTTP If-Modified-Since header +# Used to avoid retrieving data that are already cached + If-Modified-Since: + name: If-Modified-Since + in: header + description: | + Validator for conditional requests; based on Last Modified header of the + formerly retrieved variant of the resource. + type: string + +# The HTTP If-Match header +# Used to avoid concurrent updates + If-Match: + name: If-Match + in: header + description: | + Validator for conditional requests; based on ETag. + type: string + +# The HTTP If-Unmodified-Since header +# Used to avoid concurrent updates + If-Unmodified-Since: + name: If-Unmodified-Since + in: header + description: | + Validator for conditional requests; based on Last Modified header. + type: string + +###################################################### +# The resources used by some of the APIs above within the message body +###################################################### +definitions: + +#----------------------------------------------------- +# The API List resource +#----------------------------------------------------- + APIList: + title: API List + properties: + count: + type: integer + description: | + Number of APIs returned. + example: 1 + next: + type: string + description: | + Link to the next subset of resources qualified. + Empty if no more resources are to be returned. + example: "/apis?limit=1&offset=2&query=" + previous: + type: string + description: | + Link to the previous subset of resources qualified. + Empty if current subset is the first subset returned. + example: "/apis?limit=1&offset=0&query=" + list: + type: array + items: + $ref: '#/definitions/APIInfo' + +#----------------------------------------------------- +# The API Info resource +#----------------------------------------------------- + APIInfo: + title: API Info object with basic API details. + properties: + id: + type: string + example: 01234567-0123-0123-0123-012345678901 + name: + type: string + example: CalculatorAPI + description: + type: string + example: A calculator API that supports basic operations + context: + type: string + example: CalculatorAPI + version: + type: string + example: 1.0.0 + provider: + description: | + If the provider value is not given, the user invoking the API will be used as the provider. + type: string + example: admin + status: + type: string + example: PUBLISHED + +#----------------------------------------------------- +# The API resource +#----------------------------------------------------- + API: + title: API object + required: + - name + - context + - version + - provider + - status + - apiDefinition + properties: + id: + type: string + description: | + UUID of the api registry artifact + example: 01234567-0123-0123-0123-012345678901 + name: + type: string + example: CalculatorAPI + description: + type: string + example: A calculator API that supports basic operations + context: + type: string + example: CalculatorAPI + version: + type: string + example: 1.0.0 + provider: + description: | + If the provider value is not given user invoking the api will be used as the provider. + type: string + example: admin + apiDefinition: + description: | + Swagger definition of the API which contains details about URI templates and scopes + type: string + example: "{\"paths\":{\"/substract\":{\"get\":{\"x-auth-type\":\"Application & Application User\",\"x-throttling-tier\":\"Unlimited\",\"parameters\":[{\"name\":\"x\",\"required\":true,\"type\":\"string\",\"in\":\"query\"},{\"name\":\"y\",\"required\":true,\"type\":\"string\",\"in\":\"query\"}],\"responses\":{\"200\":{}}}},\"/add\":{\"get\":{\"x-auth-type\":\"Application & Application User\",\"x-throttling-tier\":\"Unlimited\",\"parameters\":[{\"name\":\"x\",\"required\":true,\"type\":\"string\",\"in\":\"query\"},{\"name\":\"y\",\"required\":true,\"type\":\"string\",\"in\":\"query\"}],\"responses\":{\"200\":{}}}}},\"swagger\":\"2.0\",\"info\":{\"title\":\"CalculatorAPI\",\"version\":\"1.0.0\"}}" + wsdlUri: + description: | + WSDL URL if the API is based on a WSDL endpoint + type: string + example: "http://www.webservicex.com/globalweather.asmx?wsdl" + status: + type: string + example: PUBLISHED + isDefaultVersion: + type: boolean + example: false + transport: + type: array + items: + description: | + Supported transports for the API (http and/or https). + type: string + example: ["http","https"] + tags: + type: array + items: + type: string + example: ["substract","add"] + tiers: + type: array + items: + type: string + example: ["Unlimited"] + thumbnailUrl: + type: string + example: "" + endpointURLs: + type: array + items: + properties: + environmentName: + type: string + example: Production and Sandbox + environmentType: + type: string + example: hybrid + environmentURLs: + properties: + http: + type: string + description: HTTP environment URL + example: "http://192.168.56.1:8280/phoneverify/1.0.0" + https: + type: string + description: HTTPS environment URL + example: "https://192.168.56.1:8243/phoneverify/1.0.0" + businessInformation: + properties: + businessOwner: + type: string + example: businessowner + businessOwnerEmail: + type: string + example: businessowner@wso2.com + technicalOwner: + type: string + example: technicalowner + technicalOwnerEmail: + type: string + example: technicalowner@wso2.com + +#----------------------------------------------------- +# The Application List resource +#----------------------------------------------------- + ApplicationList: + title: Application List + properties: + count: + type: integer + description: | + Number of applications returned. + example: 1 + next: + type: string + description: | + Link to the next subset of resources qualified. + Empty if no more resources are to be returned. + example: "/applications?limit=1&offset=2&groupId=" + previous: + type: string + description: | + Link to the previous subset of resources qualified. + Empty if current subset is the first subset returned. + example: "/applications?limit=1&offset=0&groupId=" + list: + type: array + items: + $ref: '#/definitions/ApplicationInfo' + +#----------------------------------------------------- +# The Application resource +#----------------------------------------------------- + Application: + title: Application + required: + - name + - throttlingTier + properties: + applicationId: + type: string + example: 01234567-0123-0123-0123-012345678901 + name: + type: string + example: CalculatorApp + subscriber: + description: | + If subscriber is not given user invoking the API will be taken as the subscriber. + type: string + example: admin + throttlingTier: + type: string + example: Unlimited + callbackUrl: + type: string + example: "" + description: + type: string + example: Sample calculator application + status: + type: string + example: APPROVED + default: "" + groupId: + type: string + example: "" + keys: + type: array + items: + $ref: '#/definitions/ApplicationKey' + example: [] + +#----------------------------------------------------- +# The Application Info resource +#----------------------------------------------------- + ApplicationInfo: + title: Application info object with basic application details + properties: + applicationId: + type: string + example: 01234567-0123-0123-0123-012345678901 + name: + type: string + example: CalculatorApp + subscriber: + type: string + example: admin + throttlingTier: + type: string + example: Unlimited + description: + type: string + example: Sample calculator application + status: + type: string + example: APPROVED + groupId: + type: string + example: "" + +#----------------------------------------------------- +# The Document List resource +#----------------------------------------------------- + DocumentList: + title: Document List + properties: + count: + type: integer + description: | + Number of Documents returned. + example: 1 + next: + type: string + description: | + Link to the next subset of resources qualified. + Empty if no more resources are to be returned. + example: "/apis/01234567-0123-0123-0123-012345678901/documents?limit=1&offset=2" + previous: + type: string + description: | + Link to the previous subset of resources qualified. + Empty if current subset is the first subset returned. + example: "/apis/01234567-0123-0123-0123-012345678901/documents?limit=1&offset=0" + list: + type: array + items: + $ref: '#/definitions/Document' + +#----------------------------------------------------- +# The Document resource +#----------------------------------------------------- + Document: + title: Document + required: + - name + - type + - sourceType + properties: + documentId: + type: string + example: 01234567-0123-0123-0123-012345678901 + name: + type: string + example: CalculatorDoc + type: + type: string + enum: + - HOWTO + - SAMPLES + - PUBLIC_FORUM + - SUPPORT_FORUM + - API_MESSAGE_FORMAT + - SWAGGER_DOC + - OTHER + example: HOWTO + summary: + type: string + example: "Summary of Calculator Documentation" + sourceType: + type: string + enum: + - INLINE + - URL + - FILE + example: INLINE + sourceUrl: + type: string + example: "" + otherTypeName: + type: string + example: "" + +#----------------------------------------------------- +# The Tier List resource +#----------------------------------------------------- + TierList: + title: Tier List + properties: + count: + type: integer + description: | + Number of Tiers returned. + example: 1 + next: + type: string + description: | + Link to the next subset of resources qualified. + Empty if no more resources are to be returned. + example: "/tiers/api?limit=1&offset=2" + previous: + type: string + description: | + Link to the previous subset of resources qualified. + Empty if current subset is the first subset returned. + example: "/tiers/api?limit=1&offset=0" + list: + type: array + items: + $ref: '#/definitions/Tier' + +#----------------------------------------------------- +# The Tier resource +#----------------------------------------------------- + Tier: + title: Tier + required: + - name + - tierPlan + - requestCount + - unitTime + - stopOnQuotaReach + properties: + name: + type: string + example: Platinum + description: + type: string + example: "Allows 50 request(s) per minute." + tierLevel: + type: string + enum: + - api + - application + example: api + attributes: + description: | + Custom attributes added to the tier policy + type: object + additionalProperties: + type: string + example: {} + requestCount: + description: | + Maximum number of requests which can be sent within a provided unit time + type: integer + format: int64 + example: 50 + unitTime: + type: integer + format: int64 + example: 60000 + tierPlan: + description: | + This attribute declares whether this tier is available under commercial or free + type: string + enum: + - FREE + - COMMERCIAL + example: FREE + stopOnQuotaReach: + description: | + If this attribute is set to false, you are capabale of sending requests + even if the request count exceeded within a unit time + type: boolean + example: true + +#----------------------------------------------------- +# The Subscription List resource +#----------------------------------------------------- + SubscriptionList: + title: Subscription List + properties: + count: + type: integer + description: | + Number of Subscriptions returned. + example: 1 + next: + type: string + description: | + Link to the next subset of resources qualified. + Empty if no more resources are to be returned. + example: "/subscriptions?limit=1&offset=2&apiId=01234567-0123-0123-0123-012345678901&groupId=" + previous: + type: string + description: | + Link to the previous subset of resources qualified. + Empty if current subset is the first subset returned. + example: "/subscriptions?limit=1&offset=0&apiId=01234567-0123-0123-0123-012345678901&groupId=" + list: + type: array + items: + $ref: '#/definitions/Subscription' + +#----------------------------------------------------- +# The Subscription resource +#----------------------------------------------------- + Subscription: + title: Subscription + required: + - applicationId + - apiIdentifier + - tier + properties: + subscriptionId: + type: string + example: 01234567-0123-0123-0123-012345678901 + applicationId: + type: string + example: 01234567-0123-0123-0123-012345678901 + apiIdentifier: + type: string + example: 01234567-0123-0123-0123-012345678901 + tier: + type: string + example: Unlimited + status: + type: string + enum: + - BLOCKED + - PROD_ONLY_BLOCKED + - UNBLOCKED + - ON_HOLD + - REJECTED + example: UNBLOCKED + +#----------------------------------------------------- +# The Tag resource +#----------------------------------------------------- + Tag: + title: Tag + required: + - name + - weight + properties: + name: + type: string + example: tag1 + weight: + type: integer + example: 5 + +#----------------------------------------------------- +# The Tag List resource +#----------------------------------------------------- + TagList: + title: Tag List + properties: + count: + type: integer + description: | + Number of Tags returned. + example: 1 + next: + type: string + description: | + Link to the next subset of resources qualified. + Empty if no more resources are to be returned. + example: "/tags?limit=1&offset=2" + previous: + type: string + description: | + Link to the previous subset of resources qualified. + Empty if current subset is the first subset returned. + example: "/tags?limit=1&offset=0" + list: + type: array + items: + $ref: '#/definitions/Tag' + +#----------------------------------------------------- +# The Error resource +#----------------------------------------------------- + Error: + title: Error object returned with 4XX HTTP status + required: + - code + - message + properties: + code: + type: integer + format: int64 + message: + type: string + description: Error message. + description: + type: string + description: | + A detail description about the error message. + moreInfo: + type: string + description: | + Preferably an url with more details about the error. + error: + type: array + description: | + If there are more than one error list them out. + For example, list out validation errors by each field. + items: + $ref: '#/definitions/ErrorListItem' + +#----------------------------------------------------- +# The Error List Item resource +#----------------------------------------------------- + ErrorListItem: + title: Description of Individual errors that may have occurred during a request. + required: + - code + - message + properties: + code: + type: string + message: + type: string + description: | + Description about Individual errors occurred + +#----------------------------------------------------- +# The Token resource +#----------------------------------------------------- + Token : + title: Token details for invoking APIs + properties: + accessToken: + type: string + description: Access token + example: 01234567890123456789012345678901 + tokenScopes: + type: array + items: + type: string + description: Valid scopes for the access token + example: ["default"] + validityTime: + type: integer + format: int64 + description: Maximum validity time for the access token + example: 3600 + +#----------------------------------------------------- +# The Application Key resource +#----------------------------------------------------- + ApplicationKey : + title: Application key details + properties: + consumerKey: + type: string + description: Consumer key of the application + example: vYDoc9s7IgAFdkSyNDaswBX7ejoa + consumerSecret: + type: string + description: Consumer secret of the application + example: TIDlOFkpzB7WjufO3OJUhy1fsvAa + supportedGrantTypes: + type: array + items: + type: string + description: Supported grant types for the application + example: ["client_credentials","password"] + keyState: + type: string + description: State of the key generation of the application + example: APPROVED + keyType: + description: Key type + type: string + enum: + - PRODUCTION + - SANDBOX + example: PRODUCTION + token: + $ref: '#/definitions/Token' + +#----------------------------------------------------- +# The Application Key Generation Request schema +#----------------------------------------------------- + ApplicationKeyGenerateRequest : + title: Application key generation request object + required: + - keyType + - validityTime + - accessAllowDomains + properties: + keyType: + type: string + enum: + - PRODUCTION + - SANDBOX + example: PRODUCTION + validityTime: + type: string + example: 3600 + callbackUrl: + type: string + description: Callback URL + example: "" + accessAllowDomains: + type: array + items: + type: string + description: Allowed domains for the access token + example: ["ALL"] + scopes: + type: array + items: + type: string + description: Allowed scopes for the access token + example: ["am_application_scope","default"] + +#----------------------------------------------------- +# END-OF-FILE +#----------------------------------------------------- \ No newline at end of file diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/pom.xml b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/pom.xml index 6295201a62..dc9b6a16a4 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/pom.xml +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/pom.xml @@ -22,13 +22,13 @@ apimgt-extensions org.wso2.carbon.devicemgt - 2.0.18-SNAPSHOT + 2.0.37-SNAPSHOT ../pom.xml 4.0.0 org.wso2.carbon.apimgt.webapp.publisher - 2.0.18-SNAPSHOT + 2.0.37-SNAPSHOT bundle WSO2 Carbon - API Management Webapp Publisher WSO2 Carbon - API Management Webapp Publisher @@ -47,14 +47,6 @@ org.testng testng - - org.wso2.carbon.apimgt - org.wso2.carbon.apimgt.api - - - org.wso2.carbon.apimgt - org.wso2.carbon.apimgt.impl - org.wso2.tomcat tomcat @@ -111,6 +103,10 @@ org.wso2.carbon.devicemgt org.wso2.carbon.device.mgt.common + + org.wso2.carbon.devicemgt + org.wso2.carbon.apimgt.integration.client + @@ -147,22 +143,32 @@ com.google.gson.*, org.apache.catalina, org.apache.catalina.core, - org.wso2.carbon.apimgt.api, - org.wso2.carbon.apimgt.api.model, - org.wso2.carbon.apimgt.impl, org.apache.axis2.*;version="${axis2.osgi.version.range}", org.wso2.carbon.core, org.apache.commons.lang, org.wso2.carbon.utils, org.wso2.carbon.apimgt.annotations.*, org.wso2.carbon.governance.lcm.util.*, - org.wso2.carbon.registry.core.* + org.wso2.carbon.registry.core.*, + io.swagger.annotations, + javax.net.ssl, + org.scannotation, + org.scannotation.archiveiterator, + org.w3c.dom, + org.wso2.carbon.apimgt.integration.client.*, + org.wso2.carbon.context, + org.wso2.carbon.core.util, + org.wso2.carbon.user.api, + org.wso2.carbon.user.core.*, + org.wso2.carbon.utils.multitenancy, + org.wso2.carbon.apimgt.integration.generated.client.publisher.api, + org.wso2.carbon.apimgt.integration.generated.client.publisher.model javax.ws.rs-api, scribe;scope=compile|runtime;inline=false; - * + * diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIConfig.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIConfig.java index 02200f1c76..ca020bd83a 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIConfig.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIConfig.java @@ -18,17 +18,11 @@ */ package org.wso2.carbon.apimgt.webapp.publisher; -import org.wso2.carbon.apimgt.api.APIManagementException; -import org.wso2.carbon.apimgt.api.APIProvider; -import org.wso2.carbon.apimgt.api.model.URITemplate; -import org.wso2.carbon.apimgt.impl.APIConstants; -import org.wso2.carbon.apimgt.impl.APIManagerFactory; -import org.wso2.carbon.utils.multitenancy.MultitenantUtils; +import org.wso2.carbon.apimgt.webapp.publisher.dto.ApiScope; +import org.wso2.carbon.apimgt.webapp.publisher.dto.ApiUriTemplate; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlTransient; -import java.util.List; import java.util.Set; /** @@ -53,26 +47,16 @@ public class APIConfig { private String name; private String owner; private String context; - private String contextTemplate; private String endpoint; private String version; private String policy; private String transports; - private APIProvider provider; private boolean isSecured; - private Set uriTemplates; - private List tenants; + private Set uriTemplates; private boolean isSharedWithAllTenants; private String tenantDomain; private String[] tags; - - public void init() throws APIManagementException { - try { - this.provider = APIManagerFactory.getInstance().getAPIProvider(owner); - } catch (APIManagementException e) { - throw new APIManagementException("Error occurred while initializing API provider", e); - } - } + private Set scopes; @XmlElement(name = "Policy", required = true) public String getPolicy() { @@ -84,20 +68,6 @@ public class APIConfig { this.policy = policy; } - @XmlElement(name = "ContextTemplate", required = true) - public String getContextTemplate() { - return contextTemplate; - } - - public void setContextTemplate(String contextTemplate) { - this.contextTemplate = contextTemplate; - } - - @XmlTransient - public APIProvider getProvider() { - return provider; - } - @XmlElement(name = "Name", required = true) public String getName() { return name; @@ -168,12 +138,12 @@ public class APIConfig { } @XmlElement(name = "UriTemplates", required = false) - public Set getUriTemplates() { + public Set getUriTemplates() { return uriTemplates; } @SuppressWarnings("unused") - public void setUriTemplates(Set uriTemplates) { + public void setUriTemplates(Set uriTemplates) { this.uriTemplates = uriTemplates; } @@ -206,4 +176,12 @@ public class APIConfig { public void setTags(String[] tags) { this.tags = tags; } + + public Set getScopes() { + return scopes; + } + + public void setScopes(Set scopes) { + this.scopes = scopes; + } } diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherService.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherService.java index c41a684968..81a3a60859 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherService.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherService.java @@ -18,18 +18,12 @@ */ package org.wso2.carbon.apimgt.webapp.publisher; -import org.wso2.carbon.apimgt.api.APIManagementException; -import org.wso2.carbon.apimgt.api.FaultGatewaysException; -import org.wso2.carbon.apimgt.api.model.API; -import org.wso2.carbon.apimgt.api.model.APIIdentifier; -import java.util.List; + +import org.wso2.carbon.apimgt.webapp.publisher.exception.APIManagerPublisherException; /** * This interface represents all methods related to API manipulation that's done as part of API-Management tasks. * - * Note: Ideally, this has to come from the API-Management components. However, due to lack of clean APIs - * (as OSGi declarative services, etc) provided for API publishing and related tasks, this was introduced at the device - * management core implementation layer. */ public interface APIPublisherService { @@ -37,23 +31,8 @@ public interface APIPublisherService { * This method registers an API within the underlying API-Management infrastructure. * * @param api An instance of the bean that passes metadata related to the API being published - * @throws APIManagementException Is thrown if some unexpected event occurs while publishing the API - */ - void publishAPI(API api) throws APIManagementException, FaultGatewaysException; - - /** - * This method removes an API that's already published within the underlying API-Management infrastructure. - * - * @param id An instance of the bean that carries API identification related metadata - * @throws APIManagementException Is thrown if some unexpected event occurs while removing the API + * @throws APIManagerPublisherException Is thrown if some unexpected event occurs while publishing the API */ - void removeAPI(APIIdentifier id) throws APIManagementException; + void publishAPI(APIConfig api) throws APIManagerPublisherException; - /** - * This method registers a collection of APIs within the underlying API-Management infrastructure. - * - * @param apis A list of the beans that passes metadata related to the APIs being published - * @throws APIManagementException Is thrown if some unexpected event occurs while publishing the APIs - */ - void publishAPIs(List apis) throws APIManagementException, FaultGatewaysException; } diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherServiceImpl.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherServiceImpl.java index 14a922b355..f7914d3d52 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherServiceImpl.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherServiceImpl.java @@ -18,28 +18,14 @@ */ package org.wso2.carbon.apimgt.webapp.publisher; -import com.google.gson.Gson; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.reflect.TypeToken; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.wso2.carbon.apimgt.api.APIManagementException; -import org.wso2.carbon.apimgt.api.APIProvider; -import org.wso2.carbon.apimgt.api.FaultGatewaysException; -import org.wso2.carbon.apimgt.api.model.*; -import org.wso2.carbon.apimgt.impl.APIManagerFactory; +import feign.FeignException; +import org.wso2.carbon.apimgt.integration.generated.client.publisher.model.*; +import org.wso2.carbon.apimgt.integration.client.publisher.PublisherClient; import org.wso2.carbon.apimgt.webapp.publisher.config.WebappPublisherConfig; +import org.wso2.carbon.apimgt.webapp.publisher.exception.APIManagerPublisherException; import org.wso2.carbon.apimgt.webapp.publisher.internal.APIPublisherDataHolder; import org.wso2.carbon.context.PrivilegedCarbonContext; -import org.wso2.carbon.governance.lcm.util.CommonUtil; -import org.wso2.carbon.registry.core.exceptions.RegistryException; -import org.wso2.carbon.registry.core.service.RegistryService; import org.wso2.carbon.utils.multitenancy.MultitenantUtils; - -import javax.xml.stream.XMLStreamException; -import java.io.FileNotFoundException; import java.util.*; /** @@ -47,176 +33,122 @@ import java.util.*; * API publishing related operations. */ public class APIPublisherServiceImpl implements APIPublisherService { - - private static final Log log = LogFactory.getLog(APIPublisherServiceImpl.class); + private static final String UNLIMITED_TIER = "Unlimited"; + private static final String API_PUBLISH_ENVIRONMENT = "Production and Sandbox"; + private static final String CONTENT_TYPE = "application/json"; + private static final String PUBLISHED_STATUS = "PUBLISHED"; + private static final String CREATED_STATUS = "CREATED"; private static final String PUBLISH_ACTION = "Publish"; @Override - public void publishAPI(final API api) throws APIManagementException, FaultGatewaysException { - String tenantDomain = MultitenantUtils.getTenantDomain(api.getApiOwner()); + public void publishAPI(APIConfig apiConfig) throws APIManagerPublisherException { + String tenantDomain = MultitenantUtils.getTenantDomain(apiConfig.getOwner()); PrivilegedCarbonContext.startTenantFlow(); PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(apiConfig.getOwner()); try { - int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); - // Below code snippet is added to load API Lifecycle in tenant mode. - RegistryService registryService = APIPublisherDataHolder.getInstance().getRegistryService(); - CommonUtil.addDefaultLifecyclesIfNotAvailable(registryService.getConfigSystemRegistry(tenantId), - CommonUtil.getRootSystemRegistry(tenantId)); - APIProvider provider = APIManagerFactory.getInstance().getAPIProvider(api.getApiOwner()); - MultitenantUtils.getTenantDomain(api.getApiOwner()); - processHttpVerbs(api); - if (provider != null) { - if (provider.isDuplicateContextTemplate(api.getContext())) { - throw new APIManagementException( - "Error occurred while adding the API. A duplicate API" + - " context already exists for " + api.getContext()); + PublisherClient publisherClient = APIPublisherDataHolder.getInstance().getIntegrationClientService() + .getPublisherClient(); + API api = getAPI(apiConfig); + APIList apiList = publisherClient.getApi().apisGet(100, 0, "name:" + api.getName(), CONTENT_TYPE, null); + + if (!isExist(api, apiList)) { + api = publisherClient.getApi().apisPost(api, CONTENT_TYPE); + if (CREATED_STATUS.equals(api.getStatus())) { + publisherClient.getApi().apisChangeLifecyclePost(PUBLISH_ACTION, api.getId(), null, null, null); } - if (!provider.isAPIAvailable(api.getId())) { - provider.addAPI(api); - provider.changeLifeCycleStatus(api.getId(), PUBLISH_ACTION); - if (log.isDebugEnabled()) { - log.debug("Successfully published API '" + api.getId().getApiName() + - "' with context '" + api.getContext() + "' and version '" - + api.getId().getVersion() + "'"); - } - } else { - if (WebappPublisherConfig.getInstance().isEnabledUpdateApi()) { - if (provider.getAPI(api.getId()).getStatus() == APIStatus.CREATED) { - provider.changeLifeCycleStatus(api.getId(), PUBLISH_ACTION); - } - api.setStatus(APIStatus.PUBLISHED); - provider.updateAPI(api); - if (log.isDebugEnabled()) { - log.debug("An API already exists with the name '" + api.getId().getApiName() + - "', context '" + api.getContext() + "' and version '" - + api.getId().getVersion() + "'. Thus, the API config is updated"); + } else { + if (WebappPublisherConfig.getInstance().isEnabledUpdateApi()) { + for (APIInfo apiInfo : apiList.getList()) { + if (api.getName().equals(apiInfo.getName()) && api.getVersion().equals(apiInfo.getVersion())) { + api = publisherClient.getApi().apisApiIdPut(apiInfo.getId(), api, CONTENT_TYPE, null, null); + if (CREATED_STATUS.equals(api.getStatus())) { + publisherClient.getApi().apisChangeLifecyclePost(PUBLISH_ACTION, api.getId(), null, null, + null); + } } + } } - provider.saveSwagger20Definition(api.getId(), createSwaggerDefinition(api)); - } else { - throw new APIManagementException("API provider configured for the given API configuration " + - "is null. Thus, the API is not published"); } - } catch (FileNotFoundException e) { - throw new APIManagementException("Failed to retrieve life cycle file ", e); - } catch (RegistryException e) { - throw new APIManagementException("Failed to access the registry ", e); - } catch (XMLStreamException e) { - throw new APIManagementException("Failed parsing the lifecycle xml.", e); + } catch (FeignException e) { + throw new APIManagerPublisherException(e); } finally { PrivilegedCarbonContext.endTenantFlow(); } } - private String createSwaggerDefinition(API api) { - Map httpVerbsMap = new HashMap<>(); - List scopes = new ArrayList<>(); - - for (URITemplate uriTemplate : api.getUriTemplates()) { - JsonObject response = new JsonObject(); - response.addProperty("200", ""); - - JsonObject responses = new JsonObject(); - responses.add("responses", response); - JsonObject httpVerbs = httpVerbsMap.get(uriTemplate.getUriTemplate()); - if (httpVerbs == null) { - httpVerbs = new JsonObject(); - } - JsonObject httpVerb = new JsonObject(); - httpVerb.add("responses", response); - - httpVerb.addProperty("x-auth-type", "Application%20%26%20Application%20User"); - httpVerb.addProperty("x-throttling-tier", "Unlimited"); - if (uriTemplate.getScope() != null) { - httpVerb.addProperty("x-scope", uriTemplate.getScope().getName()); - scopes.add(uriTemplate.getScope()); - } - httpVerbs.add(uriTemplate.getHTTPVerb().toLowerCase(), httpVerb); - httpVerbsMap.put(uriTemplate.getUriTemplate(), httpVerbs); - } - - Iterator it = httpVerbsMap.entrySet().iterator(); - JsonObject paths = new JsonObject(); - while (it.hasNext()) { - Map.Entry pair = (Map.Entry) it.next(); - paths.add(pair.getKey(), pair.getValue()); - it.remove(); - } - - JsonObject info = new JsonObject(); - info.addProperty("title", api.getId().getApiName()); - info.addProperty("version", api.getId().getVersion()); - - JsonObject swaggerDefinition = new JsonObject(); - swaggerDefinition.add("paths", paths); - swaggerDefinition.addProperty("swagger", "2.0"); - swaggerDefinition.add("info", info); - - // adding scopes to swagger definition - if (!api.getScopes().isEmpty()) { - Gson gson = new Gson(); - JsonElement element = gson.toJsonTree(api.getScopes(), new TypeToken>() { - }.getType()); - if (element != null) { - JsonArray apiScopes = element.getAsJsonArray(); - JsonObject apim = new JsonObject(); - apim.add("x-wso2-scopes", apiScopes); - JsonObject wso2Security = new JsonObject(); - wso2Security.add("apim", apim); - swaggerDefinition.add("x-wso2-security", wso2Security); - } - } - if (log.isDebugEnabled()) { - log.debug("API swagger definition: " + swaggerDefinition.toString()); + private boolean isExist(API api, APIList apiList) { + if (apiList == null || apiList.getList() == null || apiList.getList().size() == 0) { + return false; } - return swaggerDefinition.toString(); - } - - /** - * Sometimes the httpVerb string attribute is not existing in - * the list of httpVerbs attribute of uriTemplate. In such cases when creating the api in the - * synapse configuration, it doesn't have http methods correctly assigned for the resources. - * Therefore this method takes care of such inconsistency issue. - * - * @param api The actual API model object - */ - private void processHttpVerbs(API api) { - for (URITemplate uriTemplate : api.getUriTemplates()) { - String httpVerbString = uriTemplate.getHTTPVerb(); - if (httpVerbString != null && !httpVerbString.isEmpty()) { - uriTemplate.setHttpVerbs(httpVerbString); + for (APIInfo existingApi : apiList.getList()) { + if (existingApi.getName().equals(api.getName()) && existingApi.getVersion().equals(api.getVersion())) { + return true; } } + return false; } - @Override - public void removeAPI(APIIdentifier id) throws APIManagementException { - if (log.isDebugEnabled()) { - log.debug("Removing API '" + id.getApiName() + "'"); - } - APIProvider provider = APIManagerFactory.getInstance().getAPIProvider(id.getProviderName()); - provider.deleteAPI(id); - if (log.isDebugEnabled()) { - log.debug("API '" + id.getApiName() + "' has been successfully removed"); - } - } - - @Override - public void publishAPIs(List apis) throws APIManagementException, FaultGatewaysException { - if (log.isDebugEnabled()) { - log.debug("Publishing a batch of APIs"); - } - for (API api : apis) { - try { - this.publishAPI(api); - } catch (APIManagementException e) { - log.error("Error occurred while publishing API '" + api.getId().getApiName() + "'", e); - } - } - if (log.isDebugEnabled()) { - log.debug("End of publishing the batch of APIs"); + private API getAPI(APIConfig config) { + + API api = new API(); + api.setName(config.getName()); + api.setDescription(""); + + String context = config.getContext(); + context = context.startsWith("/") ? context : ("/" + context); + api.setContext(context); + api.setVersion(config.getVersion()); + api.setProvider(config.getOwner()); + api.setApiDefinition(APIPublisherUtil.getSwaggerDefinition(config)); + api.setWsdlUri(null); + api.setStatus(PUBLISHED_STATUS); + api.setResponseCaching("DISABLED"); + api.setDestinationStatsEnabled("false"); + api.isDefaultVersion(true); + List transport = new ArrayList<>(); + transport.add("https"); + transport.add("http"); + api.transport(transport); + api.setTags(Arrays.asList(config.getTags())); + api.addTiersItem(UNLIMITED_TIER); + api.setGatewayEnvironments(API_PUBLISH_ENVIRONMENT); + if (config.isSharedWithAllTenants()) { + api.setSubscriptionAvailability(API.SubscriptionAvailabilityEnum.all_tenants); + api.setVisibility(API.VisibilityEnum.PUBLIC); + } else { + api.setSubscriptionAvailability(API.SubscriptionAvailabilityEnum.current_tenant); + api.setVisibility(API.VisibilityEnum.PRIVATE); } + String endpointConfig = "{\"production_endpoints\":{\"url\":\"" + config.getEndpoint() + + "\",\"config\":null},\"implementation_status\":\"managed\",\"endpoint_type\":\"http\"}"; + + + api.setEndpointConfig(endpointConfig); + APICorsConfiguration apiCorsConfiguration = new APICorsConfiguration(); + List accessControlAllowOrigins = new ArrayList<>(); + accessControlAllowOrigins.add("*"); + apiCorsConfiguration.setAccessControlAllowOrigins(accessControlAllowOrigins); + + List accessControlAllowHeaders = new ArrayList<>(); + accessControlAllowHeaders.add("authorization"); + accessControlAllowHeaders.add("Access-Control-Allow-Origin"); + accessControlAllowHeaders.add("Content-Type"); + accessControlAllowHeaders.add("SOAPAction"); + apiCorsConfiguration.setAccessControlAllowHeaders(accessControlAllowHeaders); + + List accessControlAllowMethods = new ArrayList<>(); + accessControlAllowMethods.add("GET"); + accessControlAllowMethods.add("PUT"); + accessControlAllowMethods.add("DELETE"); + accessControlAllowMethods.add("POST"); + accessControlAllowMethods.add("PATCH"); + accessControlAllowMethods.add("OPTIONS"); + apiCorsConfiguration.setAccessControlAllowMethods(accessControlAllowMethods); + apiCorsConfiguration.setAccessControlAllowCredentials(false); + apiCorsConfiguration.corsConfigurationEnabled(false); + api.setCorsConfiguration(apiCorsConfiguration); + return api; } - } diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherStartupHandler.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherStartupHandler.java index df9102e351..928b6d22be 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherStartupHandler.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherStartupHandler.java @@ -21,7 +21,7 @@ package org.wso2.carbon.apimgt.webapp.publisher; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.wso2.carbon.apimgt.api.model.API; +import org.wso2.carbon.apimgt.webapp.publisher.exception.APIManagerPublisherException; import org.wso2.carbon.apimgt.webapp.publisher.internal.APIPublisherDataHolder; import org.wso2.carbon.core.ServerStartupObserver; @@ -33,8 +33,8 @@ public class APIPublisherStartupHandler implements ServerStartupObserver { private static int retryTime = 2000; private static final int CONNECTION_RETRY_FACTOR = 2; private static final int MAX_RETRY_COUNT = 5; - private static Stack failedAPIsStack = new Stack<>(); - private static Stack currentAPIsStack; + private static Stack failedAPIsStack = new Stack<>(); + private static Stack currentAPIsStack; private APIPublisherService publisher; @@ -64,7 +64,7 @@ public class APIPublisherStartupHandler implements ServerStartupObserver { } catch (InterruptedException te) { //do nothing. } - Stack failedApis; + Stack failedApis; if (!APIPublisherDataHolder.getInstance().getUnpublishedApis().isEmpty()) { publishAPIs(currentAPIsStack, failedAPIsStack); failedApis = failedAPIsStack; @@ -77,8 +77,8 @@ public class APIPublisherStartupHandler implements ServerStartupObserver { StringBuilder error = new StringBuilder(); error.append("Error occurred while publishing API ['"); while (!failedApis.isEmpty()) { - API api = failedApis.pop(); - error.append(api.getId().getApiName() + ","); + APIConfig api = failedApis.pop(); + error.append(api.getName() + ","); } error.append("']"); log.error(error.toString()); @@ -90,12 +90,13 @@ public class APIPublisherStartupHandler implements ServerStartupObserver { t.start(); } - private void publishAPIs(Stack apis, Stack failedStack) { + private void publishAPIs(Stack apis, Stack failedStack) { while (!apis.isEmpty()) { - API api = apis.pop(); + APIConfig api = apis.pop(); try { publisher.publishAPI(api); - } catch (Exception e) { + } catch (APIManagerPublisherException e) { + log.error("failed to publish api.", e); failedStack.push(api); } } diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherUtil.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherUtil.java index 8ae3c531c1..a3f8608de4 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherUtil.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherUtil.java @@ -18,22 +18,24 @@ package org.wso2.carbon.apimgt.webapp.publisher; +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.reflect.TypeToken; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.wso2.carbon.apimgt.api.APIManagementException; -import org.wso2.carbon.apimgt.api.APIProvider; -import org.wso2.carbon.apimgt.api.model.*; -import org.wso2.carbon.apimgt.impl.APIConstants; -import org.wso2.carbon.apimgt.impl.utils.APIUtil; +import org.wso2.carbon.apimgt.annotations.api.Scope; import org.wso2.carbon.apimgt.webapp.publisher.config.APIResource; import org.wso2.carbon.apimgt.webapp.publisher.config.APIResourceConfiguration; 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.lifecycle.util.AnnotationProcessor; import org.wso2.carbon.base.MultitenantConstants; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.core.util.Utils; import org.wso2.carbon.user.api.UserStoreException; -import org.wso2.carbon.utils.multitenancy.MultitenantUtils; import javax.servlet.ServletContext; import java.util.*; @@ -41,7 +43,6 @@ import java.util.*; public class APIPublisherUtil { public static final String API_VERSION_PARAM = "{version}"; - public static final String API_PUBLISH_ENVIRONMENT = "Production and Sandbox"; private static final Log log = LogFactory.getLog(APIPublisherUtil.class); private static final String DEFAULT_API_VERSION = "1.0.0"; private static final String API_CONFIG_DEFAULT_VERSION = "1.0.0"; @@ -55,101 +56,6 @@ public class APIPublisherUtil { private static final String NON_SECURED_RESOURCES = "nonSecuredEndPoints"; private static final String AUTH_TYPE_NON_SECURED = "None"; - - public static API getAPI(APIConfig config) throws APIManagementException { - - APIProvider provider = config.getProvider(); - String apiVersion = config.getVersion(); - APIIdentifier id = new APIIdentifier(replaceEmailDomain(config.getOwner()), config.getName(), apiVersion); - API api = new API(id); - - api.setApiOwner(config.getOwner()); - String context = config.getContext(); - context = context.startsWith("/") ? context : ("/" + context); - String providerDomain = config.getTenantDomain(); - if (!MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equalsIgnoreCase(providerDomain)) { - //Create tenant aware context for API - context = "/t/" + providerDomain + context; - } - - // This is to support the new Pluggable version strategy - // if the context does not contain any {version} segment, we use the default version strategy. - context = checkAndSetVersionParam(context); - api.setContextTemplate(context); - context = updateContextWithVersion(config.getVersion(), context); - api.setContext(context); - - api.setUrl(config.getEndpoint()); - api.addAvailableTiers(provider.getTiers()); - api.setEndpointSecured(false); - api.setStatus(APIStatus.CREATED); - api.setTransports(config.getTransports()); - api.setApiLevelPolicy(config.getPolicy()); - api.setContextTemplate(config.getContextTemplate()); - Set environments = new HashSet<>(); - environments.add(API_PUBLISH_ENVIRONMENT); - api.setEnvironments(environments); - Set tiers = new HashSet<>(); - - tiers.add(new Tier(APIConstants.UNLIMITED_TIER)); - api.addAvailableTiers(tiers); - - if (config.isSharedWithAllTenants()) { - api.setSubscriptionAvailability(APIConstants.SUBSCRIPTION_TO_ALL_TENANTS); - api.setVisibility(APIConstants.API_GLOBAL_VISIBILITY); - } else { - api.setSubscriptionAvailability(APIConstants.SUBSCRIPTION_TO_CURRENT_TENANT); - api.setVisibility(APIConstants.API_PRIVATE_VISIBILITY); - } - api.setResponseCache(APIConstants.DISABLED); - - String endpointConfig = "{\"production_endpoints\":{\"url\":\"" + config.getEndpoint() + - "\",\"config\":null},\"implementation_status\":\"managed\",\"endpoint_type\":\"http\"}"; - - api.setEndpointConfig(endpointConfig); - - if ("".equals(id.getVersion()) || (DEFAULT_API_VERSION.equals(id.getVersion()))) { - api.setAsDefaultVersion(Boolean.TRUE); - api.setAsPublishedDefaultVersion(Boolean.TRUE); - } - if (config.getTags() != null && config.getTags().length > 0) { - Set tags = new HashSet<>(Arrays.asList(config.getTags())); - api.addTags(tags); - } - - // adding scopes to the api - Set uriTemplates = config.getUriTemplates(); - Map apiScopes = new HashMap<>(); - if (uriTemplates != null) { - // this creates distinct scopes list - for (URITemplate template : uriTemplates) { - Scope scope = template.getScope(); - if (scope != null) { - if (apiScopes.get(scope.getKey()) == null) { - apiScopes.put(scope.getKey(), scope); - } - } - } - Set scopes = new HashSet<>(apiScopes.values()); - // set current scopes to API - api.setScopes(scopes); - - // this has to be done because of the use of pass by reference - // where same object reference of scope should be available for both - // api scope and uri template scope - for (Scope scope : scopes) { - for (URITemplate template : uriTemplates) { - if (template.getScope() != null && scope.getKey().equals(template.getScope().getKey())) { - template.setScope(scope); - } - } - } - api.setUriTemplates(uriTemplates); - } - api.setCorsConfiguration(APIUtil.getDefaultCorsConfiguration()); - return api; - } - public static String getServerBaseUrl() { WebappPublisherConfig webappPublisherConfig = WebappPublisherConfig.getInstance(); return Utils.replaceSystemProperty(webappPublisherConfig.getHost()); @@ -159,39 +65,6 @@ public class APIPublisherUtil { return getServerBaseUrl() + context; } - /** - * When an input is having '@',replace it with '-AT-' - * [This is required to persist API data in registry,as registry paths don't allow '@' sign.] - * - * @param input inputString - * @return String modifiedString - */ - private static String replaceEmailDomain(String input) { - if (input != null && input.contains(APIConstants.EMAIL_DOMAIN_SEPARATOR)) { - input = input.replace(APIConstants.EMAIL_DOMAIN_SEPARATOR, APIConstants.EMAIL_DOMAIN_SEPARATOR_REPLACEMENT); - } - return input; - } - - private static String updateContextWithVersion(String version, String context) { - // This condition should not be true for any occasion but we keep it so that there are no loopholes in - // the flow. - context = context.replace(API_VERSION_PARAM, version); - return context; - } - - private static String checkAndSetVersionParam(String context) { - // This is to support the new Pluggable version strategy - // if the context does not contain any {version} segment, we use the default version strategy. - if (!context.contains(API_VERSION_PARAM)) { - if (!context.endsWith("/")) { - context = context + "/"; - } - context = context + API_VERSION_PARAM; - } - return context; - } - /** * Build the API Configuration to be passed to APIM, from a given list of URL templates * @@ -245,11 +118,6 @@ public class APIPublisherUtil { tenantDomain = (tenantDomain != null && !tenantDomain.isEmpty()) ? tenantDomain : MultitenantConstants.SUPER_TENANT_DOMAIN_NAME; apiConfig.setTenantDomain(tenantDomain); - String contextTemplate = context + "/" + APIConstants.VERSION_PLACEHOLDER; - if (!MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) { - contextTemplate = context + "/t/" + tenantDomain + "/" + APIConstants.VERSION_PLACEHOLDER; - } - apiConfig.setContextTemplate(contextTemplate); String endpoint = servletContext.getInitParameter(PARAM_MANAGED_API_ENDPOINT); if (endpoint == null || endpoint.isEmpty()) { @@ -292,17 +160,33 @@ public class APIPublisherUtil { } apiConfig.setSharedWithAllTenants(isSharedWithAllTenants); - Set uriTemplates = new LinkedHashSet<>(); + Set uriTemplates = new LinkedHashSet<>(); for (APIResource apiResource : apiDef.getResources()) { - URITemplate template = new URITemplate(); + ApiUriTemplate template = new ApiUriTemplate(); template.setAuthType(apiResource.getAuthType()); - template.setHTTPVerb(apiResource.getHttpVerb()); + template.setHttpVerb(apiResource.getHttpVerb()); template.setResourceURI(apiResource.getUri()); template.setUriTemplate(apiResource.getUriTemplate()); template.setScope(apiResource.getScope()); uriTemplates.add(template); } apiConfig.setUriTemplates(uriTemplates); + // adding scopes to the api + Map apiScopes = new HashMap<>(); + if (uriTemplates != null) { + // this creates distinct scopes list + for (ApiUriTemplate template : uriTemplates) { + ApiScope scope = template.getScope(); + if (scope != null) { + if (apiScopes.get(scope.getKey()) == null) { + apiScopes.put(scope.getKey(), scope); + } + } + } + Set scopes = new HashSet<>(apiScopes.values()); + // set current scopes to API + apiConfig.setScopes(scopes); + } String policy = servletContext.getInitParameter(PARAM_MANAGED_API_POLICY); if (policy == null || policy.isEmpty()) { @@ -317,6 +201,70 @@ public class APIPublisherUtil { return apiConfig; } + public static String getSwaggerDefinition(APIConfig apiConfig) { + Map httpVerbsMap = new HashMap<>(); + List scopes = new ArrayList<>(); + + for (ApiUriTemplate uriTemplate : apiConfig.getUriTemplates()) { + JsonObject response = new JsonObject(); + response.addProperty("200", ""); + + JsonObject responses = new JsonObject(); + responses.add("responses", response); + JsonObject httpVerbs = httpVerbsMap.get(uriTemplate.getUriTemplate()); + if (httpVerbs == null) { + httpVerbs = new JsonObject(); + } + JsonObject httpVerb = new JsonObject(); + httpVerb.add("responses", response); + + httpVerb.addProperty("x-auth-type", uriTemplate.getAuthType()); + httpVerb.addProperty("x-throttling-tier", "Unlimited"); + if (uriTemplate.getScope() != null) { + httpVerb.addProperty("x-scope", uriTemplate.getScope().getKey()); + scopes.add(uriTemplate.getScope()); + } + httpVerbs.add(uriTemplate.getHttpVerb().toLowerCase(), httpVerb); + httpVerbsMap.put(uriTemplate.getUriTemplate(), httpVerbs); + } + + Iterator it = httpVerbsMap.entrySet().iterator(); + JsonObject paths = new JsonObject(); + while (it.hasNext()) { + Map.Entry pair = (Map.Entry) it.next(); + paths.add(pair.getKey(), pair.getValue()); + it.remove(); + } + + JsonObject info = new JsonObject(); + info.addProperty("title", apiConfig.getName()); + info.addProperty("version", apiConfig.getVersion()); + + JsonObject swaggerDefinition = new JsonObject(); + swaggerDefinition.add("paths", paths); + swaggerDefinition.addProperty("swagger", "2.0"); + swaggerDefinition.add("info", info); + + // adding scopes to swagger definition + if (!apiConfig.getScopes().isEmpty()) { + Gson gson = new Gson(); + JsonElement element = gson.toJsonTree(apiConfig.getScopes(), new TypeToken>() { + }.getType()); + if (element != null) { + JsonArray apiScopes = element.getAsJsonArray(); + JsonObject apim = new JsonObject(); + apim.add("x-wso2-scopes", apiScopes); + JsonObject wso2Security = new JsonObject(); + wso2Security.add("apim", apim); + swaggerDefinition.add("x-wso2-security", wso2Security); + } + } + if (log.isDebugEnabled()) { + log.debug("API swagger definition: " + swaggerDefinition.toString()); + } + return swaggerDefinition.toString(); + } + public static void setResourceAuthTypes(ServletContext servletContext, APIConfig apiConfig) { List resourcesList = null; @@ -324,9 +272,9 @@ public class APIPublisherUtil { if(null != nonSecuredResources){ resourcesList = Arrays.asList(nonSecuredResources.split(",")); } - Set templates = apiConfig.getUriTemplates(); + Set templates = apiConfig.getUriTemplates(); if(null != resourcesList) { - for (URITemplate template : templates) { + for (ApiUriTemplate template : templates) { String fullPaath = ""; if( template.getUriTemplate() != AnnotationProcessor.WILD_CARD ) { fullPaath = apiConfig.getContext() + template.getUriTemplate(); @@ -341,5 +289,6 @@ public class APIPublisherUtil { } } } + apiConfig.setUriTemplates(templates); } } diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/config/APIResource.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/config/APIResource.java index 577f4efecb..ff439e68cf 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/config/APIResource.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/config/APIResource.java @@ -18,7 +18,7 @@ package org.wso2.carbon.apimgt.webapp.publisher.config; -import org.wso2.carbon.apimgt.api.model.Scope; +import org.wso2.carbon.apimgt.webapp.publisher.dto.ApiScope; public class APIResource { @@ -28,7 +28,7 @@ public class APIResource { private String UriTemplate; private String consumes; private String produces; - private Scope scope; + private ApiScope scope; public String getAuthType() { return AuthType; @@ -78,11 +78,11 @@ public class APIResource { this.produces = produces; } - public Scope getScope() { + public ApiScope getScope() { return scope; } - public void setScope(Scope scope) { + public void setScope(ApiScope scope) { this.scope = scope; } } diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/dto/ApiScope.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/dto/ApiScope.java new file mode 100644 index 0000000000..016dbff37f --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/dto/ApiScope.java @@ -0,0 +1,64 @@ +/* + * 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. + */ + +package org.wso2.carbon.apimgt.webapp.publisher.dto; + +public class ApiScope { + + String key; + String name; + String roles; + String description; + int id; + + public ApiScope() { + } + + public String getKey() { + return this.key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public String getRoles() { + return this.roles; + } + + public void setRoles(String roles) { + this.roles = roles; + } + + public String getDescription() { + return this.description; + } + + public void setDescription(String description) { + this.description = description; + } + +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/dto/ApiUriTemplate.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/dto/ApiUriTemplate.java new file mode 100644 index 0000000000..89ef7900cc --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/dto/ApiUriTemplate.java @@ -0,0 +1,73 @@ +/* + * 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. + */ + +package org.wso2.carbon.apimgt.webapp.publisher.dto; + +/** + * This hold the api uri template information. + */ +public class ApiUriTemplate { + + private String authType; + private String httpVerb; + private String resourceURI; + private String uriTemplate; + private ApiScope scope; + + public ApiUriTemplate() {} + + public String getAuthType() { + return authType; + } + + public void setAuthType(String authType) { + this.authType = authType; + } + + public String getHttpVerb() { + return httpVerb; + } + + public void setHttpVerb(String httpVerb) { + this.httpVerb = httpVerb; + } + + public String getResourceURI() { + return resourceURI; + } + + public void setResourceURI(String resourceURI) { + this.resourceURI = resourceURI; + } + + public String getUriTemplate() { + return uriTemplate; + } + + public void setUriTemplate(String uriTemplate) { + this.uriTemplate = uriTemplate; + } + + public ApiScope getScope() { + return scope; + } + + public void setScope(ApiScope scope) { + this.scope = scope; + } +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/exception/APIManagerPublisherException.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/exception/APIManagerPublisherException.java new file mode 100644 index 0000000000..b98aef3c9a --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/exception/APIManagerPublisherException.java @@ -0,0 +1,48 @@ +/* + * 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. + */ + +package org.wso2.carbon.apimgt.webapp.publisher.exception; + +/** + * Handles the exceptions related to API management. + */ +public class APIManagerPublisherException extends Exception { + + private static final long serialVersionUID = -8933142342423122660L; + + public APIManagerPublisherException(String msg, Exception nestedEx) { + super(msg, nestedEx); + } + + public APIManagerPublisherException(String message, Throwable cause) { + super(message, cause); + } + + public APIManagerPublisherException(String msg) { + super(msg); + } + + public APIManagerPublisherException() { + super(); + } + + public APIManagerPublisherException(Throwable cause) { + super(cause); + } + +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/internal/APIPublisherDataHolder.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/internal/APIPublisherDataHolder.java index b06bc1a4ca..639c2fe217 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/internal/APIPublisherDataHolder.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/internal/APIPublisherDataHolder.java @@ -18,8 +18,8 @@ */ package org.wso2.carbon.apimgt.webapp.publisher.internal; - -import org.wso2.carbon.apimgt.api.model.API; +import org.wso2.carbon.apimgt.integration.client.service.IntegrationClientService; +import org.wso2.carbon.apimgt.webapp.publisher.APIConfig; import org.wso2.carbon.apimgt.webapp.publisher.APIPublisherService; import org.wso2.carbon.registry.core.service.RegistryService; import org.wso2.carbon.user.core.service.RealmService; @@ -36,7 +36,8 @@ public class APIPublisherDataHolder { private TenantManager tenantManager; private RegistryService registryService; private boolean isServerStarted; - private Stack unpublishedApis = new Stack<>(); + private Stack unpublishedApis = new Stack<>(); + private IntegrationClientService integrationClientService; private static APIPublisherDataHolder thisInstance = new APIPublisherDataHolder(); @@ -108,11 +109,20 @@ public class APIPublisherDataHolder { isServerStarted = serverStarted; } - public Stack getUnpublishedApis() { + public Stack getUnpublishedApis() { return unpublishedApis; } - public void setUnpublishedApis(Stack unpublishedApis) { + public void setUnpublishedApis(Stack unpublishedApis) { this.unpublishedApis = unpublishedApis; } + + public IntegrationClientService getIntegrationClientService() { + return integrationClientService; + } + + public void setIntegrationClientService( + IntegrationClientService integrationClientService) { + this.integrationClientService = integrationClientService; + } } diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/internal/APIPublisherServiceComponent.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/internal/APIPublisherServiceComponent.java index 44c2c6d799..dd5736570c 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/internal/APIPublisherServiceComponent.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/internal/APIPublisherServiceComponent.java @@ -22,7 +22,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.osgi.framework.BundleContext; import org.osgi.service.component.ComponentContext; -import org.wso2.carbon.apimgt.impl.APIManagerConfigurationService; +import org.wso2.carbon.apimgt.integration.client.service.IntegrationClientService; import org.wso2.carbon.apimgt.webapp.publisher.APIPublisherService; import org.wso2.carbon.apimgt.webapp.publisher.APIPublisherServiceImpl; import org.wso2.carbon.apimgt.webapp.publisher.APIPublisherStartupHandler; @@ -30,16 +30,9 @@ import org.wso2.carbon.apimgt.webapp.publisher.config.WebappPublisherConfig; import org.wso2.carbon.core.ServerStartupObserver; import org.wso2.carbon.registry.core.service.RegistryService; import org.wso2.carbon.user.core.service.RealmService; -import org.wso2.carbon.utils.ConfigurationContextService; /** * @scr.component name="org.wso2.carbon.apimgt.webapp.publisher" immediate="true" - * @scr.reference name="config.context.service" - * interface="org.wso2.carbon.utils.ConfigurationContextService" - * cardinality="0..1" - * policy="dynamic" - * bind="setConfigurationContextService" - * unbind="unsetConfigurationContextService" * @scr.reference name="user.realmservice.default" * interface="org.wso2.carbon.user.core.service.RealmService" * cardinality="1..1" @@ -52,6 +45,11 @@ import org.wso2.carbon.utils.ConfigurationContextService; * policy="dynamic" * bind="setRegistryService" * unbind="unsetRegistryService" + * interface="org.wso2.carbon.apimgt.integration.client.service.IntegrationClientService" + * cardinality="1..1" + * policy="dynamic" + * bind="setIntegrationClientService" + * unbind="unsetIntegrationClientService" */ public class APIPublisherServiceComponent { @@ -97,28 +95,6 @@ public class APIPublisherServiceComponent { bundleContext.registerService(ServerStartupObserver.class, new APIPublisherStartupHandler(), null); } - protected void setAPIManagerConfigurationService(APIManagerConfigurationService service) { - //do nothing - } - - protected void unsetAPIManagerConfigurationService(APIManagerConfigurationService service) { - //do nothing - } - - protected void setConfigurationContextService(ConfigurationContextService configurationContextService) { - if (log.isDebugEnabled()) { - log.debug("Setting ConfigurationContextService"); - } - APIPublisherDataHolder.getInstance().setConfigurationContextService(configurationContextService); - } - - protected void unsetConfigurationContextService(ConfigurationContextService configurationContextService) { - if (log.isDebugEnabled()) { - log.debug("Un-setting ConfigurationContextService"); - } - APIPublisherDataHolder.getInstance().setConfigurationContextService(null); - } - protected void setRealmService(RealmService realmService) { if (log.isDebugEnabled()) { log.debug("Setting Realm Service"); @@ -143,4 +119,15 @@ public class APIPublisherServiceComponent { protected void unsetRegistryService(RegistryService registryService) { APIPublisherDataHolder.getInstance().setRegistryService(null); } + + protected void setIntegrationClientService(IntegrationClientService integrationClientService) { + if (integrationClientService != null && log.isDebugEnabled()) { + log.debug("integrationClientService initialized"); + } + APIPublisherDataHolder.getInstance().setIntegrationClientService(integrationClientService); + } + + protected void unsetIntegrationClientService(IntegrationClientService integrationClientService) { + APIPublisherDataHolder.getInstance().setIntegrationClientService(null); + } } diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/lifecycle/listener/APIPublisherLifecycleListener.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/lifecycle/listener/APIPublisherLifecycleListener.java index adf73f0d17..3f0730b36a 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/lifecycle/listener/APIPublisherLifecycleListener.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/lifecycle/listener/APIPublisherLifecycleListener.java @@ -24,7 +24,6 @@ import org.apache.catalina.LifecycleListener; import org.apache.catalina.core.StandardContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.wso2.carbon.apimgt.api.model.API; import org.wso2.carbon.apimgt.webapp.publisher.APIConfig; import org.wso2.carbon.apimgt.webapp.publisher.APIPublisherService; import org.wso2.carbon.apimgt.webapp.publisher.APIPublisherUtil; @@ -77,8 +76,6 @@ public class APIPublisherLifecycleListener implements LifecycleListener { boolean isTenantActive = APIPublisherDataHolder.getInstance(). getTenantManager().isTenantActive(tenantId); if (isTenantActive) { - apiConfig.init(); - API api = APIPublisherUtil.getAPI(apiConfig); boolean isServerStarted = APIPublisherDataHolder.getInstance().isServerStarted(); if (isServerStarted) { APIPublisherService apiPublisherService = @@ -87,13 +84,13 @@ public class APIPublisherLifecycleListener implements LifecycleListener { throw new IllegalStateException( "API Publisher service is not initialized properly"); } - apiPublisherService.publishAPI(api); + apiPublisherService.publishAPI(apiConfig); } else { if (log.isDebugEnabled()) { log.debug("Server has not started yet. Hence adding API '" + - api.getId().getApiName() + "' to the queue"); + apiConfig.getName() + "' to the queue"); } - APIPublisherDataHolder.getInstance().getUnpublishedApis().push(api); + APIPublisherDataHolder.getInstance().getUnpublishedApis().push(apiConfig); } } else { log.error("No tenant [" + apiConfig.getTenantDomain() + "] " + @@ -112,14 +109,11 @@ public class APIPublisherLifecycleListener implements LifecycleListener { } catch (UserStoreException e) { log.error("Error while retrieving tenant admin user for the tenant domain" + PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(), e); + } catch (Throwable e) { + // This is done to stop tomcat failure if a webapp failed to publish apis. + log.error("Failed to Publish api from " + servletContext.getContextPath(), e); } } } } - - //TODO : Need to implemented, to merge API Definitions in cases where implementation of an API Lies in two classes - private List mergeAPIDefinitions(List inputList) { - return null; - } - } diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/lifecycle/util/AnnotationProcessor.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/lifecycle/util/AnnotationProcessor.java index 2c2f21f19c..dfc8dd7454 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/lifecycle/util/AnnotationProcessor.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/lifecycle/util/AnnotationProcessor.java @@ -21,10 +21,10 @@ import io.swagger.annotations.SwaggerDefinition; import org.apache.catalina.core.StandardContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.wso2.carbon.apimgt.api.model.Scope; import org.wso2.carbon.apimgt.webapp.publisher.APIPublisherUtil; import org.wso2.carbon.apimgt.webapp.publisher.config.APIResource; import org.wso2.carbon.apimgt.webapp.publisher.config.APIResourceConfiguration; +import org.wso2.carbon.apimgt.webapp.publisher.dto.ApiScope; import javax.servlet.ServletContext; import javax.ws.rs.Consumes; @@ -53,7 +53,7 @@ public class AnnotationProcessor { private static final Log log = LogFactory.getLog(AnnotationProcessor.class); - private static final String AUTH_TYPE = "Any"; + private static final String AUTH_TYPE = "Application & Application User"; private static final String STRING_ARR = "string_arr"; private static final String STRING = "string"; private static final String PACKAGE_ORG_APACHE = "org.apache"; @@ -96,7 +96,7 @@ public class AnnotationProcessor { private Class apiOperation; private Class scopeClass; private Class scopesClass; - private Map apiScopes; + private Map apiScopes; public AnnotationProcessor(final StandardContext context) { servletContext = context.getServletContext(); @@ -206,20 +206,20 @@ public class AnnotationProcessor { return apiResourceConfigs; } - private Map processAPIScopes(Annotation annotation) throws Throwable { - Map scopes = new HashMap<>(); + private Map processAPIScopes(Annotation annotation) throws Throwable { + Map scopes = new HashMap<>(); InvocationHandler methodHandler = Proxy.getInvocationHandler(annotation); Annotation[] annotatedScopes = (Annotation[]) methodHandler.invoke(annotation, scopesClass .getMethod(ANNOTATIONS_SCOPES, null), null); - Scope scope; + ApiScope scope; String permissions[]; StringBuilder aggregatedPermissions; for(int i=0; i org.wso2.carbon.devicemgt carbon-devicemgt - 2.0.18-SNAPSHOT + 2.0.37-SNAPSHOT ../../pom.xml 4.0.0 apimgt-extensions - 2.0.18-SNAPSHOT + 2.0.37-SNAPSHOT pom WSO2 Carbon - API Management Extensions Component http://wso2.org + org.wso2.carbon.apimgt.integration.generated.client + org.wso2.carbon.apimgt.integration.client org.wso2.carbon.apimgt.webapp.publisher org.wso2.carbon.apimgt.application.extension org.wso2.carbon.apimgt.application.extension.api diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.api/pom.xml b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.api/pom.xml index ebf07a65bd..5664de26cf 100644 --- a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.api/pom.xml +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.api/pom.xml @@ -22,7 +22,7 @@ certificate-mgt org.wso2.carbon.devicemgt - 2.0.18-SNAPSHOT + 2.0.37-SNAPSHOT ../pom.xml diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.api/src/main/webapp/WEB-INF/web.xml b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.api/src/main/webapp/WEB-INF/web.xml index 62a814568e..58aa02917c 100644 --- a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.api/src/main/webapp/WEB-INF/web.xml +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.api/src/main/webapp/WEB-INF/web.xml @@ -47,5 +47,9 @@ managed-api-owner admin + + isSharedWithAllTenants + true + diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/pom.xml b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/pom.xml index 839b70e0a3..7aeb196308 100644 --- a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/pom.xml +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/pom.xml @@ -22,7 +22,7 @@ certificate-mgt org.wso2.carbon.devicemgt - 2.0.18-SNAPSHOT + 2.0.37-SNAPSHOT ../pom.xml diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/webapp/WEB-INF/web.xml b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/webapp/WEB-INF/web.xml index 72020e147e..1d59c04b17 100644 --- a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/webapp/WEB-INF/web.xml +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/webapp/WEB-INF/web.xml @@ -52,6 +52,10 @@ managed-api-owner admin + + isSharedWithAllTenants + true + diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/pom.xml b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/pom.xml index 3f46c57a47..6cccfe9f48 100644 --- a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/pom.xml +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/pom.xml @@ -21,13 +21,13 @@ org.wso2.carbon.devicemgt certificate-mgt - 2.0.18-SNAPSHOT + 2.0.37-SNAPSHOT ../pom.xml 4.0.0 org.wso2.carbon.certificate.mgt.core - 2.0.18-SNAPSHOT + 2.0.37-SNAPSHOT bundle WSO2 Carbon - Certificate Management Core WSO2 Carbon - Certificate Management Core @@ -61,7 +61,7 @@ javax.security.auth.x500, javax.xml.*, javax.xml.parsers;version="${javax.xml.parsers.import.pkg.version}";resolution:=optional, - org.apache.commons.codec.binary, + org.apache.commons.codec.binary;version="${commons-codec.wso2.osgi.version.range}", org.bouncycastle.asn1, org.bouncycastle.asn1.x500, org.bouncycastle.asn1.x509, diff --git a/components/certificate-mgt/pom.xml b/components/certificate-mgt/pom.xml index d5a58eb8b1..996b9cf1d0 100644 --- a/components/certificate-mgt/pom.xml +++ b/components/certificate-mgt/pom.xml @@ -22,14 +22,14 @@ org.wso2.carbon.devicemgt carbon-devicemgt - 2.0.18-SNAPSHOT + 2.0.37-SNAPSHOT ../../pom.xml 4.0.0 org.wso2.carbon.devicemgt certificate-mgt - 2.0.18-SNAPSHOT + 2.0.37-SNAPSHOT pom WSO2 Carbon - Certificate Management Component http://wso2.org diff --git a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/pom.xml b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/pom.xml index 05acbf9226..ffaa79ca49 100644 --- a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/pom.xml +++ b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/pom.xml @@ -22,7 +22,7 @@ device-mgt-extensions org.wso2.carbon.devicemgt - 2.0.18-SNAPSHOT + 2.0.37-SNAPSHOT ../pom.xml diff --git a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/deployer/config/Claimable.java b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/deployer/config/Claimable.java new file mode 100644 index 0000000000..661778e62d --- /dev/null +++ b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/deployer/config/Claimable.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2017, 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. + * + */ +package org.wso2.carbon.device.mgt.extensions.device.type.deployer.config; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.XmlValue; + + +/** + *

Java class for DeviceDetails complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="DeviceDetails">
+ *   <simpleContent>
+ *     <extension base="<http://www.w3.org/2001/XMLSchema>string">
+ *       <attribute name="table-id" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *     </extension>
+ *   </simpleContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "Claimable", propOrder = { + "value" +}) +public class Claimable { + + @XmlValue + protected String value; + @XmlAttribute(name = "enabled") + protected boolean enabled; + + /** + * Gets the value of the value property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getValue() { + return value; + } + + /** + * Sets the value of the value property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setValue(String value) { + this.value = value; + } + + /** + * Gets the value of the enabled property. + * + * @return + * possible object is + * {@link String } + * + */ + public boolean isEnabled() { + return enabled; + } + + /** + * Sets the value of the enabled property. + * + * @param enabled + * allowed object is + * {@link String } + * + */ + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + +} diff --git a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/deployer/config/DeviceTypeConfiguration.java b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/deployer/config/DeviceTypeConfiguration.java index 2a43797e9d..00d20b4ebe 100644 --- a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/deployer/config/DeviceTypeConfiguration.java +++ b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/deployer/config/DeviceTypeConfiguration.java @@ -18,11 +18,8 @@ */ package org.wso2.carbon.device.mgt.extensions.device.type.deployer.config; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.*; +import java.util.List; /** @@ -56,6 +53,8 @@ public class DeviceTypeConfiguration { @XmlElement(name = "DeviceDetails", required = true) protected DeviceDetails deviceDetails; + @XmlElement(name = "Claimable", required = true) + protected Claimable claimable; @XmlElement(name = "Features", required = true) protected Features features; @XmlElement(name = "ProvisioningConfig", required = true) @@ -74,6 +73,21 @@ public class DeviceTypeConfiguration { protected String name; @XmlElement(name = "PolicyMonitoring", required = true) protected PolicyMonitoring policyMonitoring; + @XmlElementWrapper(name = "InitialOperationConfig") + @XmlElement(name = "Operation", required = true) + protected List operations; + + public List getOperations() { + return operations; + } + + public void setOperations(List operations) { + this.operations = operations; + } + + + + /** * Gets the value of the taskConfiguration property. @@ -119,6 +133,27 @@ public class DeviceTypeConfiguration { this.deviceDetails = value; } + /** + * Gets the value of the Claimable property. + * + * @return possible object is + * {@link DeviceDetails } + */ + public Claimable getClaimable() { + return claimable; + } + + /** + * Sets the value of the deviceDetails property. + * + * @param value allowed object is + * {@link DeviceDetails } + */ + public void setClaimable(Claimable value) { + this.claimable = value; + } + + /** * Gets the value of the policyMonitoring property. * diff --git a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/deployer/config/InitialOperationConfig.java b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/deployer/config/InitialOperationConfig.java new file mode 100644 index 0000000000..e172d7b009 --- /dev/null +++ b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/deployer/config/InitialOperationConfig.java @@ -0,0 +1,39 @@ +package org.wso2.carbon.device.mgt.extensions.device.type.deployer.config; + +import javax.xml.bind.annotation.*; +import java.util.List; + +/** + *

Java class for InitialOperationConfig complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="InitialOperationConfig">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Operations" type="{http://www.w3.org/2001/XMLSchema}list"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlRootElement(name = "InitialOperationConfig") +public class InitialOperationConfig { + + private List operations; + + @XmlElementWrapper(name = "Operations", required = true) + @XmlElement(name = "Operation", required = true) + public List getOperations() { + return operations; + } + + public void setOperationsll(List operations) { + this.operations = operations; + } +} diff --git a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/deployer/template/DeviceTypeManager.java b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/deployer/template/DeviceTypeManager.java index eba2f18721..98c5ef2870 100644 --- a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/deployer/template/DeviceTypeManager.java +++ b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/deployer/template/DeviceTypeManager.java @@ -65,6 +65,7 @@ public class DeviceTypeManager implements DeviceManager { private LicenseManager licenseManager; private boolean propertiesExist; private boolean requiredDeviceTypeAuthorization; + private boolean claimable; private FeatureManager featureManager; @@ -101,8 +102,13 @@ public class DeviceTypeManager implements DeviceManager { String msg = "Error occurred while adding default license for " + deviceType + " devices"; throw new DeviceTypeDeployerFileException(msg, e); } + claimable = false; + if (deviceTypeConfiguration.getClaimable() != null ) { + claimable = deviceTypeConfiguration.getClaimable().isEnabled(); + } DeviceDetails deviceDetails = deviceTypeConfiguration.getDeviceDetails(); + if (deviceDetails != null) { //Check whether device dao definition exist. @@ -341,7 +347,7 @@ public class DeviceTypeManager implements DeviceManager { @Override public boolean isClaimable(DeviceIdentifier deviceIdentifier) throws DeviceManagementException { - return false; + return claimable; } @Override diff --git a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/deployer/template/DeviceTypeManagerService.java b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/deployer/template/DeviceTypeManagerService.java index c7720093a6..64398d3715 100644 --- a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/deployer/template/DeviceTypeManagerService.java +++ b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/deployer/template/DeviceTypeManagerService.java @@ -20,11 +20,7 @@ package org.wso2.carbon.device.mgt.extensions.device.type.deployer.template; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.wso2.carbon.device.mgt.common.DeviceManagementException; -import org.wso2.carbon.device.mgt.common.DeviceManager; -import org.wso2.carbon.device.mgt.common.MonitoringOperation; -import org.wso2.carbon.device.mgt.common.OperationMonitoringTaskConfig; -import org.wso2.carbon.device.mgt.common.ProvisioningConfig; +import org.wso2.carbon.device.mgt.common.*; import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManager; import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationEntry; import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration; @@ -57,6 +53,8 @@ public class DeviceTypeManagerService implements DeviceManagementService { private OperationMonitoringTaskConfig operationMonitoringConfigs; private List monitoringOperations; private PolicyMonitoringManager policyMonitoringManager; + private InitialOperationConfig initialOperationConfig; + private List operations; public DeviceTypeManagerService(DeviceTypeConfigIdentifier deviceTypeConfigIdentifier, DeviceTypeConfiguration deviceTypeConfiguration) { @@ -66,6 +64,7 @@ public class DeviceTypeManagerService implements DeviceManagementService { this.populatePushNotificationConfig(deviceTypeConfiguration.getPushNotificationProvider()); this.operationMonitoringConfigs = new OperationMonitoringTaskConfig(); this.setOperationMonitoringConfig(deviceTypeConfiguration); + this.setInitialOperationConfig(deviceTypeConfiguration); if (deviceTypeConfiguration.getPolicyMonitoring() != null && deviceTypeConfiguration.getPolicyMonitoring() .isEnabled()) { this.policyMonitoringManager = new DefaultPolicyMonitoringManager(); @@ -157,6 +156,11 @@ public class DeviceTypeManagerService implements DeviceManagementService { return policyMonitoringManager; } + @Override + public InitialOperationConfig getInitialOperationConfig() { + return initialOperationConfig; + } + private void setProvisioningConfig(String tenantDomain, DeviceTypeConfiguration deviceTypeConfiguration) { if (deviceTypeConfiguration.getProvisioningConfig() != null) { boolean sharedWithAllTenants = deviceTypeConfiguration.getProvisioningConfig().isSharedWithAllTenants(); @@ -166,6 +170,15 @@ public class DeviceTypeManagerService implements DeviceManagementService { } } + protected void setInitialOperationConfig(DeviceTypeConfiguration deviceTypeConfiguration) { + if (deviceTypeConfiguration.getOperations() != null) { + List ops = deviceTypeConfiguration.getOperations(); + if (ops != null && !ops.isEmpty()) { + initialOperationConfig.setOperations(ops); + } + } + } + private void setType(String type) { this.type = type; } diff --git a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/src/test/resources/sample.xml b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/src/test/resources/sample.xml index aa18e5d03b..414bcaa8dd 100644 --- a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/src/test/resources/sample.xml +++ b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.device.type.deployer/src/test/resources/sample.xml @@ -36,10 +36,12 @@ - + false diff --git a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.gcm/pom.xml b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm/pom.xml similarity index 94% rename from components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.gcm/pom.xml rename to components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm/pom.xml index 014435e721..10f89f5d1b 100644 --- a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.gcm/pom.xml +++ b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm/pom.xml @@ -22,15 +22,15 @@ device-mgt-extensions org.wso2.carbon.devicemgt - 2.0.18-SNAPSHOT + 2.0.37-SNAPSHOT ../pom.xml 4.0.0 - org.wso2.carbon.device.mgt.extensions.push.notification.provider.gcm + org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm bundle - WSO2 Carbon - GCM Based Push Notification Provider Implementation - WSO2 Carbon - GCM Based Push Notification Provider Implementation + WSO2 Carbon - FCM Based Push Notification Provider Implementation + WSO2 Carbon - FCM Based Push Notification Provider Implementation http://wso2.org @@ -128,10 +128,10 @@ ${project.artifactId} ${project.artifactId} ${carbon.device.mgt.version} - GCM Based Push Notification Provider Bundle + FCM Based Push Notification Provider Bundle - !org.wso2.carbon.device.mgt.extensions.push.notification.provider.gcm.internal, - org.wso2.carbon.device.mgt.extensions.push.notification.provider.gcm.* + !org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm.internal, + org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm.* com.google.gson, diff --git a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.gcm/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/gcm/GCMBasedPushNotificationProvider.java b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/fcm/FCMBasedPushNotificationProvider.java similarity index 84% rename from components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.gcm/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/gcm/GCMBasedPushNotificationProvider.java rename to components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/fcm/FCMBasedPushNotificationProvider.java index 5168e25e25..30affceb27 100644 --- a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.gcm/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/gcm/GCMBasedPushNotificationProvider.java +++ b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/fcm/FCMBasedPushNotificationProvider.java @@ -16,24 +16,24 @@ * under the License. * */ -package org.wso2.carbon.device.mgt.extensions.push.notification.provider.gcm; +package org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm; import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy; import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationConfig; import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationProvider; -public class GCMBasedPushNotificationProvider implements PushNotificationProvider { +public class FCMBasedPushNotificationProvider implements PushNotificationProvider { - private static final String PS_PROVIDER_GCM = "GCM"; + private static final String PS_PROVIDER_FCM = "FCM"; @Override public String getType() { - return PS_PROVIDER_GCM; + return PS_PROVIDER_FCM; } @Override public NotificationStrategy getNotificationStrategy(PushNotificationConfig config) { - return new GCMNotificationStrategy(config); + return new FCMNotificationStrategy(config); } } diff --git a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.gcm/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/gcm/GCMNotificationStrategy.java b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/fcm/FCMNotificationStrategy.java similarity index 76% rename from components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.gcm/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/gcm/GCMNotificationStrategy.java rename to components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/fcm/FCMNotificationStrategy.java index af93b692a4..6dd66f0836 100644 --- a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.gcm/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/gcm/GCMNotificationStrategy.java +++ b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/fcm/FCMNotificationStrategy.java @@ -16,7 +16,7 @@ * under the License. * */ -package org.wso2.carbon.device.mgt.extensions.push.notification.provider.gcm; +package org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm; import com.google.gson.JsonArray; import com.google.gson.JsonObject; @@ -27,7 +27,7 @@ import org.wso2.carbon.device.mgt.common.push.notification.NotificationContext; import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy; import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationConfig; import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationExecutionFailedException; -import org.wso2.carbon.device.mgt.extensions.push.notification.provider.gcm.internal.GCMDataHolder; +import org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm.internal.FCMDataHolder; import java.io.IOException; import java.io.OutputStream; @@ -35,16 +35,16 @@ import java.net.HttpURLConnection; import java.net.URL; import java.util.List; -public class GCMNotificationStrategy implements NotificationStrategy { +public class FCMNotificationStrategy implements NotificationStrategy { - private static final String GCM_TOKEN = "GCM_TOKEN"; - private final static String GCM_ENDPOINT = "https://fcm.googleapis.com/fcm/send"; - private static final String GCM_API_KEY = "gcmAPIKey"; + private static final String FCM_TOKEN = "FCM_TOKEN"; + private static final String FCM_ENDPOINT = "https://fcm.googleapis.com/fcm/send"; + private static final String FCM_API_KEY = "fcmAPIKey"; private static final int TIME_TO_LIVE = 60; private static final int HTTP_STATUS_CODE_OK = 200; private PushNotificationConfig config; - public GCMNotificationStrategy(PushNotificationConfig config) { + public FCMNotificationStrategy(PushNotificationConfig config) { this.config = config; } @@ -57,7 +57,7 @@ public class GCMNotificationStrategy implements NotificationStrategy { public void execute(NotificationContext ctx) throws PushNotificationExecutionFailedException { try { Device device = - GCMDataHolder.getInstance().getDeviceManagementProviderService().getDevice(ctx.getDeviceId()); + FCMDataHolder.getInstance().getDeviceManagementProviderService().getDevice(ctx.getDeviceId()); this.sendWakeUpCall(ctx.getOperation().getCode(), device); } catch (DeviceManagementException e) { throw new PushNotificationExecutionFailedException("Error occurred while retrieving device information", e); @@ -79,13 +79,13 @@ public class GCMNotificationStrategy implements NotificationStrategy { private void sendWakeUpCall(String message, Device device) throws IOException, PushNotificationExecutionFailedException { OutputStream os = null; - byte[] bytes = getGCMRequest(message, getGCMToken(device.getProperties())).getBytes(); + byte[] bytes = getFCMRequest(message, getFCMToken(device.getProperties())).getBytes(); HttpURLConnection conn = null; try { - conn = (HttpURLConnection) new URL(GCM_ENDPOINT).openConnection(); + conn = (HttpURLConnection) new URL(FCM_ENDPOINT).openConnection(); conn.setRequestProperty("Content-Type", "application/json"); - conn.setRequestProperty("Authorization", "key=" + config.getProperty(GCM_API_KEY)); + conn.setRequestProperty("Authorization", "key=" + config.getProperty(FCM_API_KEY)); conn.setRequestMethod("POST"); conn.setDoOutput(true); os = conn.getOutputStream(); @@ -102,35 +102,35 @@ public class GCMNotificationStrategy implements NotificationStrategy { } } - private static String getGCMRequest(String message, String registrationId) { - JsonObject gcmRequest = new JsonObject(); - gcmRequest.addProperty("delay_while_idle", false); - gcmRequest.addProperty("time_to_live", TIME_TO_LIVE); + private static String getFCMRequest(String message, String registrationId) { + JsonObject fcmRequest = new JsonObject(); + fcmRequest.addProperty("delay_while_idle", false); + fcmRequest.addProperty("time_to_live", TIME_TO_LIVE); - //Add message to GCM request + //Add message to FCM request JsonObject data = new JsonObject(); if (message != null && !message.isEmpty()) { data.addProperty("data", message); - gcmRequest.add("data", data); + fcmRequest.add("data", data); } //Set device reg-id JsonArray regIds = new JsonArray(); regIds.add(new JsonPrimitive(registrationId)); - gcmRequest.add("registration_ids", regIds); - return gcmRequest.toString(); + fcmRequest.add("registration_ids", regIds); + return fcmRequest.toString(); } - private static String getGCMToken(List properties) { - String gcmToken = null; + private static String getFCMToken(List properties) { + String fcmToken = null; for (Device.Property property : properties) { - if (GCM_TOKEN.equals(property.getName())) { - gcmToken = property.getValue(); + if (FCM_TOKEN.equals(property.getName())) { + fcmToken = property.getValue(); break; } } - return gcmToken; + return fcmToken; } } diff --git a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.gcm/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/gcm/internal/GCMDataHolder.java b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/fcm/internal/FCMDataHolder.java similarity index 88% rename from components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.gcm/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/gcm/internal/GCMDataHolder.java rename to components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/fcm/internal/FCMDataHolder.java index 67b44109af..64569d7fb6 100644 --- a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.gcm/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/gcm/internal/GCMDataHolder.java +++ b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/fcm/internal/FCMDataHolder.java @@ -16,16 +16,16 @@ * under the License. * */ -package org.wso2.carbon.device.mgt.extensions.push.notification.provider.gcm.internal; +package org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm.internal; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; -public class GCMDataHolder { +public class FCMDataHolder { private DeviceManagementProviderService deviceManagementProviderService; - private static GCMDataHolder thisInstance = new GCMDataHolder(); + private static FCMDataHolder thisInstance = new FCMDataHolder(); - public static GCMDataHolder getInstance() { + public static FCMDataHolder getInstance() { return thisInstance; } diff --git a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.gcm/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/gcm/internal/GCMPushNotificationServiceComponent.java b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/fcm/internal/FCMPushNotificationServiceComponent.java similarity index 78% rename from components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.gcm/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/gcm/internal/GCMPushNotificationServiceComponent.java rename to components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/fcm/internal/FCMPushNotificationServiceComponent.java index 6e5171ec4b..8993e6928a 100644 --- a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.gcm/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/gcm/internal/GCMPushNotificationServiceComponent.java +++ b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/fcm/internal/FCMPushNotificationServiceComponent.java @@ -16,7 +16,7 @@ * under the License. * */ -package org.wso2.carbon.device.mgt.extensions.push.notification.provider.gcm.internal; +package org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm.internal; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -24,7 +24,7 @@ import org.osgi.service.component.ComponentContext; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; /** - * @scr.component name="org.wso2.carbon.device.mgt.extensions.push.notification.provider.gcm.internal.GCMPushNotificationServiceComponent" immediate="true" + * @scr.component name="org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm.internal.FCMPushNotificationServiceComponent" immediate="true" * @scr.reference name="carbon.device.mgt.provider" * interface="org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService" * cardinality="1..1" @@ -32,23 +32,20 @@ import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; * bind="setDeviceManagementProviderService" * unbind="unsetDeviceManagementProviderService" */ -public class GCMPushNotificationServiceComponent { +public class FCMPushNotificationServiceComponent { - private static final Log log = LogFactory.getLog(GCMPushNotificationServiceComponent.class); + private static final Log log = LogFactory.getLog(FCMPushNotificationServiceComponent.class); @SuppressWarnings("unused") protected void activate(ComponentContext componentContext) { try { - if (log.isDebugEnabled()) { - log.debug("Initializing GCM based push notification provider implementation bundle"); - } //Do nothing if (log.isDebugEnabled()) { - log.debug("GCM based push notification provider implementation bundle has been successfully " + + log.debug("FCM based push notification provider implementation bundle has been successfully " + "initialized"); } } catch (Throwable e) { - log.error("Error occurred while initializing GCM based push notification provider " + + log.error("Error occurred while initializing FCM based push notification provider " + "implementation bundle", e); } } @@ -59,12 +56,12 @@ public class GCMPushNotificationServiceComponent { protected void setDeviceManagementProviderService( DeviceManagementProviderService deviceManagementProviderService) { - GCMDataHolder.getInstance().setDeviceManagementProviderService(deviceManagementProviderService); + FCMDataHolder.getInstance().setDeviceManagementProviderService(deviceManagementProviderService); } protected void unsetDeviceManagementProviderService( DeviceManagementProviderService deviceManagementProviderService) { - GCMDataHolder.getInstance().setDeviceManagementProviderService(deviceManagementProviderService); + FCMDataHolder.getInstance().setDeviceManagementProviderService(deviceManagementProviderService); } } diff --git a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.mqtt/pom.xml b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.mqtt/pom.xml index 9a747bf07c..b4753e7ea5 100644 --- a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.mqtt/pom.xml +++ b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.mqtt/pom.xml @@ -22,7 +22,7 @@ device-mgt-extensions org.wso2.carbon.devicemgt - 2.0.18-SNAPSHOT + 2.0.37-SNAPSHOT ../pom.xml diff --git a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.xmpp/pom.xml b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.xmpp/pom.xml index 29678ac31f..0e20bfd521 100644 --- a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.xmpp/pom.xml +++ b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.xmpp/pom.xml @@ -22,7 +22,7 @@ device-mgt-extensions org.wso2.carbon.devicemgt - 2.0.18-SNAPSHOT + 2.0.37-SNAPSHOT ../pom.xml diff --git a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.xmpp/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/xmpp/internal/XMPPPushNotificationServiceComponent.java b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.xmpp/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/xmpp/internal/XMPPPushNotificationServiceComponent.java index 7085191dc8..71dada3b66 100644 --- a/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.xmpp/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/xmpp/internal/XMPPPushNotificationServiceComponent.java +++ b/components/device-mgt-extensions/org.wso2.carbon.device.mgt.extensions.push.notification.provider.xmpp/src/main/java/org/wso2/carbon/device/mgt/extensions/push/notification/provider/xmpp/internal/XMPPPushNotificationServiceComponent.java @@ -25,7 +25,7 @@ import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterService; /** - * @scr.component name="org.wso2.carbon.device.mgt.extensions.push.notification.provider.gcm.internal.XMPPPushNotificationServiceComponent" immediate="true" + * @scr.component name="org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm.internal.XMPPPushNotificationServiceComponent" immediate="true" * @scr.reference name="carbon.device.mgt.provider" * interface="org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService" * cardinality="1..1" diff --git a/components/device-mgt-extensions/pom.xml b/components/device-mgt-extensions/pom.xml index 418369abfd..08bd64adb0 100644 --- a/components/device-mgt-extensions/pom.xml +++ b/components/device-mgt-extensions/pom.xml @@ -22,7 +22,7 @@ carbon-devicemgt org.wso2.carbon.devicemgt - 2.0.18-SNAPSHOT + 2.0.37-SNAPSHOT ../../pom.xml @@ -34,7 +34,7 @@ http://wso2.org - org.wso2.carbon.device.mgt.extensions.push.notification.provider.gcm + org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm org.wso2.carbon.device.mgt.extensions.push.notification.provider.mqtt org.wso2.carbon.device.mgt.extensions.push.notification.provider.xmpp org.wso2.carbon.device.mgt.extensions.device.type.deployer diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.analytics.dashboard/pom.xml b/components/device-mgt/org.wso2.carbon.device.mgt.analytics.dashboard/pom.xml index bc4290bd74..739046f85b 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.analytics.dashboard/pom.xml +++ b/components/device-mgt/org.wso2.carbon.device.mgt.analytics.dashboard/pom.xml @@ -3,7 +3,7 @@ org.wso2.carbon.devicemgt device-mgt - 2.0.18-SNAPSHOT + 2.0.37-SNAPSHOT ../pom.xml diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.analytics.data.publisher/pom.xml b/components/device-mgt/org.wso2.carbon.device.mgt.analytics.data.publisher/pom.xml index c93ba47588..0dd15957ef 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.analytics.data.publisher/pom.xml +++ b/components/device-mgt/org.wso2.carbon.device.mgt.analytics.data.publisher/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.devicemgt device-mgt - 2.0.18-SNAPSHOT + 2.0.37-SNAPSHOT ../pom.xml diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/pom.xml b/components/device-mgt/org.wso2.carbon.device.mgt.api/pom.xml index 8ac9e1b58f..1470d02951 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/pom.xml +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/pom.xml @@ -22,7 +22,7 @@ device-mgt org.wso2.carbon.devicemgt - 2.0.18-SNAPSHOT + 2.0.37-SNAPSHOT ../pom.xml @@ -281,6 +281,23 @@ javax.ws.rs javax.ws.rs-api + + org.wso2.carbon.commons + org.wso2.carbon.application.mgt.stub + provided + + + org.wso2.carbon.devicemgt + org.wso2.carbon.identity.jwt.client.extension + provided + + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.user.store.count + ${carbon.identity.framework.version} + provided + + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/BasePaginatedResult.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/BasePaginatedResult.java index 8d1c82d8d7..5c2936a1a3 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/BasePaginatedResult.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/BasePaginatedResult.java @@ -30,13 +30,13 @@ public class BasePaginatedResult { value = "Number of total resources.", example = "1") @JsonProperty("count") - private int count; + private long count; - public int getCount() { + public long getCount() { return count; } - public void setCount(int count) { + public void setCount(long count) { this.count = count; } } \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/DeviceManagementService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/DeviceManagementService.java index 46ffac27e3..ddbdfcdc08 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/DeviceManagementService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/DeviceManagementService.java @@ -423,6 +423,83 @@ public interface DeviceManagementService { @HeaderParam("If-Modified-Since") String ifModifiedSince); + + @GET + @Path("/{type}/{id}/location") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "GET", + value = "Getting Location Details of a Device", + notes = "Get the location details of a device by specifying the device type and device identifier.", + tags = "Device Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:devices:details") + }) + } + ) + @ApiResponses( + value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully fetched the location details of the device.", + response = Device.class, + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @ResponseHeader( + name = "ETag", + description = "Entity Tag of the response resource.\n" + + "Used by caches, or in conditional requests."), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource was last modified.\n" + + "Used by caches, or in conditional requests."), + }), + @ApiResponse( + code = 304, + message = "Not Modified. Empty body because the client already has the latest version" + + " of the requested resource.\n"), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid request or validation error.", + response = ErrorResponse.class), + @ApiResponse( + code = 404, + message = "Not Found. \n Location data for the specified device was not found.", + response = ErrorResponse.class), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n " + + "Server error occurred while retrieving the device details.", + response = ErrorResponse.class) + }) + Response getDeviceLocation( + @ApiParam( + name = "type", + value = "The device type name, such as ios, android, windows or fire-alarm.", + required = true) + @PathParam("type") + @Size(max = 45) + String type, + @ApiParam( + name = "id", + value = "The device identifier of the device you want ot get details.", + required = true) + @PathParam("id") + @Size(max = 45) + String id, + @ApiParam( + name = "If-Modified-Since", + value = "Checks if the requested variant was modified, since the specified date-time. \n" + + "Provide the value in the following format: EEE, d MMM yyyy HH:mm:ss Z. \n" + + "Example: Mon, 05 Jan 2014 15:10:00 +0200", + required = false) + @HeaderParam("If-Modified-Since") + String ifModifiedSince); + + //device rename request would looks like follows //POST devices/type/virtual_firealarm/id/us06ww93auzp/rename @POST @@ -575,7 +652,7 @@ public interface DeviceManagementService { produces = MediaType.APPLICATION_JSON, httpMethod = "GET", value = "Getting Feature Details of a Device", - notes = "WSO2 EMM features enable you to carry out many operations based on the device platform. " + + notes = "WSO2 IoTS features enable you to carry out many operations based on the device platform. " + "Using this REST API you can get the features that can be carried out on a preferred device type," + " such as iOS, Android or Windows.", tags = "Device Management", @@ -644,7 +721,7 @@ public interface DeviceManagementService { @ApiParam( name = "id", value = "The device identifier of the device.\n" + - "INFO: Make sure to add the ID of a device that is already registered with WSO2 EMM.", + "INFO: Make sure to add the ID of a device that is already registered with WSO2 IoTS.", required = true) @PathParam("id") @Size(max = 45) @@ -911,7 +988,7 @@ public interface DeviceManagementService { @ApiParam( name = "id", value = "The device identifier of the device you wish to get details.\n" + - "INFO: Make sure to add the ID of a device that is already registered with WSO2 EMM.", + "INFO: Make sure to add the ID of a device that is already registered with WSO2 IoTS.", required = true) @PathParam("id") @Size(max = 45) @@ -952,8 +1029,8 @@ public interface DeviceManagementService { produces = MediaType.APPLICATION_JSON, httpMethod = "GET", value = "Get the details of the policy that is enforced on a device.", - notes = "A policy is enforced on all the devices that register with WSO2 EMM." + - "WSO2 EMM filters the policies based on the device platform (device type)," + + notes = "A policy is enforced on all the devices that register with WSO2 IoTS." + + "WSO2 IoTS filters the policies based on the device platform (device type)," + "the device ownership type, the user role or name and finally, the policy that matches these filters will be enforced on the device.", tags = "Device Management", extensions = { @@ -1041,7 +1118,7 @@ public interface DeviceManagementService { produces = MediaType.APPLICATION_JSON, httpMethod = "GET", value = "Getting Policy Compliance Details of a Device", - notes = "A policy is enforced on the devices that register with WSO2 EMM. " + + notes = "A policy is enforced on the devices that register with WSO2 IoTS. " + "The server checks if the settings in the device comply with the policy that is enforced on the device using this REST API.", tags = "Device Management", extensions = { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/RoleManagementService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/RoleManagementService.java index e330d7d3d3..295fb47555 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/RoleManagementService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/RoleManagementService.java @@ -18,17 +18,7 @@ */ package org.wso2.carbon.device.mgt.jaxrs.service.api; -import io.swagger.annotations.SwaggerDefinition; -import io.swagger.annotations.Info; -import io.swagger.annotations.ExtensionProperty; -import io.swagger.annotations.Extension; -import io.swagger.annotations.Tag; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import io.swagger.annotations.ResponseHeader; +import io.swagger.annotations.*; import org.wso2.carbon.apimgt.annotations.api.Scope; import org.wso2.carbon.apimgt.annotations.api.Scopes; import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse; @@ -120,20 +110,20 @@ public interface RoleManagementService { produces = MediaType.APPLICATION_JSON, httpMethod = "GET", value = "Getting the List of Roles", - notes = "WSO2 EMM supports role-based access control (RBAC) and role management. Using this API you can the list of roles that are in WSO2 EMM.\n" + + notes = "WSO2 IoTS supports role-based access control (RBAC) and role management. Using this API you can the list of roles that are in WSO2 IoTS.\n" + "Note: Internal roles, roles created for service-providers, and application related roles will not be given in the output.", tags = "Role Management", extensions = { - @Extension(properties = { - @ExtensionProperty(name = Constants.SCOPE, value = "perm:roles:view") - }) + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:roles:view") + }) } ) @ApiResponses( value = { @ApiResponse( code = 200, - message = "OK. \n Successfully fetched the list of roles in WSO2 EMM.", + message = "OK. \n Successfully fetched the list of roles in WSO2 IoTS.", response = RoleList.class, responseHeaders = { @ResponseHeader( @@ -190,467 +180,549 @@ public interface RoleManagementService { defaultValue = "5") @QueryParam("limit") int limit); - @GET - @Path("/{roleName}/permissions") - @ApiOperation( - produces = MediaType.APPLICATION_JSON, - httpMethod = "GET", - value = "Getting Permission Details of a Role", - notes = "An individual is associated a with set of responsibilities based on their " + - "role. In WSO2 EMM you are able to configure permissions based on the responsibilities carried " + - "out by various roles. Therefore, if you wish to retrieve the permission details of a role, you can do " + - "so using this REST API.", - response = UIPermissionNode.class, - responseContainer = "List", - tags = "Role Management", - extensions = { - @Extension(properties = { - @ExtensionProperty(name = Constants.SCOPE, value = "perm:roles:permissions") + @GET + @Path("/filter/{prefix}") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "GET", + value = "Getting the List of Roles filtered by the given prefix", + notes = "WSO2 IoTS supports role-based access control (RBAC) and role management. Using this API you can the list of roles that are in WSO2 IoTS.\n" + + "Note: Internal roles, roles created for service-providers, and application related roles will not be given in the output.", + tags = "Role Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:roles:view") + }) + } + ) + @ApiResponses( + value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully fetched the list of roles in WSO2 IoTS.", + response = RoleList.class, + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @ResponseHeader( + name = "ETag", + description = "Entity Tag of the response resource.\n" + + "Used by caches, or in conditional requests."), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource has been modified the last time.\n" + + "Used by caches, or in conditional requests."), + }), + @ApiResponse( + code = 304, + message = "Not Modified. \n Empty body because the client already has the latest version of the requested resource."), + @ApiResponse( + code = 406, + message = "Not Acceptable.\n The requested media type is not supported"), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Server error occurred while fetching list of roles.", + response = ErrorResponse.class) }) - } - ) - @ApiResponses( - value = { - @ApiResponse( - code = 200, - message = "OK. \n Successfully fetched the permissions details for the specified role.", - response = UIPermissionNode.class, - responseContainer = "List", - responseHeaders = { - @ResponseHeader( - name = "Content-Type", - description = "The content type of the body"), - @ResponseHeader( - name = "ETag", - description = "Entity Tag of the response resource.\n" + - "Used by caches, or in conditional requests."), - @ResponseHeader( - name = "Last-Modified", - description = "Date and time the resource has been modified the last time.\n" + - "Used by caches, or in conditional requests."), - }), - @ApiResponse( - code = 304, - message = "Not Modified. \n Empty body because the client already has the latest version of the requested resource.\n"), - @ApiResponse( - code = 400, - message = "Bad Request. \n Invalid request or validation error.", - response = ErrorResponse.class), - @ApiResponse( - code = 404, - message = "Not Found. \n The specified role does not exist.", - response = ErrorResponse.class), - @ApiResponse( - code = 406, - message = "Not Acceptable.\n The requested media type is not supported", - response = ErrorResponse.class), - @ApiResponse( - code = 500, - message = "Internal Server ErrorResponse. \n Server error occurred while fetching the permission list for the requested role.", - response = ErrorResponse.class) - }) - Response getPermissionsOfRole( - @ApiParam( - name = "roleName", - value = "The name of the role.", - required = true, - defaultValue = "Engineer") - @PathParam("roleName") String roleName, - @ApiParam( - name = "user-store", - value = "The name of the user store from which you wish to get the permission of role.", - required = false) - @QueryParam("user-store") String userStoreName, - @ApiParam( - name = "If-Modified-Since", - value = "Checks if the requested variant was modified, since the specified date-time." + - "Provide the value in the following format: EEE, d MMM yyyy HH:mm:ss Z.\n" + - "Example: Mon, 05 Jan 2014 15:10:00 +0200", - required = false) - @HeaderParam("If-Modified-Since") String ifModifiedSince); + Response getFilteredRoles( + @ApiParam( + name = "prefix", + value = "Filtering prefix of the role.", + required = true, + defaultValue = "") + @PathParam("prefix") String prefix, + @ApiParam( + name = "filter", + value = "Provide a character or a few characters in the role name.", + required = false) + @QueryParam("filter") String filter, + @ApiParam( + name = "user-store", + value = "The name of the UserStore you wish to get the list of roles.", + required = false) + @QueryParam("user-store") String userStoreName, + @ApiParam( + name = "If-Modified-Since", + value = "Checks if the requested variant was modified, since the specified date-time." + + "Provide the value in the following format: EEE, d MMM yyyy HH:mm:ss Z.\n" + + "Example: Mon, 05 Jan 2014 15:10:00 +0200", + required = false) + @HeaderParam("If-Modified-Since") String ifModifiedSince, + @ApiParam( + name = "offset", + value = "The starting pagination index for the complete list of qualified items.", + required = false, + defaultValue = "0") + @QueryParam("offset") int offset, + @ApiParam( + name = "limit", + value = "Provide how many role details you require from the starting pagination index/offset.", + required = false, + defaultValue = "5") + @QueryParam("limit") int limit); - @GET - @Path("/{roleName}") - @ApiOperation( - produces = MediaType.APPLICATION_JSON, - httpMethod = "GET", - value = "Getting Details of a Role", - notes = "Get the permissions associated with a role and role specific details using this REST API.", - response = RoleInfo.class, - tags = "Role Management", - extensions = { - @Extension(properties = { - @ExtensionProperty(name = Constants.SCOPE, value = "perm:roles:details") + @GET + @Path("/{roleName}/permissions") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "GET", + value = "Getting Permission Details of a Role", + notes = "An individual is associated a with set of responsibilities based on their " + + "role. In WSO2 IoTS you are able to configure permissions based on the responsibilities carried " + + "out by various roles. Therefore, if you wish to retrieve the permission details of a role, you can do " + + "so using this REST API.", + response = UIPermissionNode.class, + responseContainer = "List", + tags = "Role Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:roles:permissions") + }) + } + ) + @ApiResponses( + value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully fetched the permissions details for the specified role.", + response = UIPermissionNode.class, + responseContainer = "List", + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @ResponseHeader( + name = "ETag", + description = "Entity Tag of the response resource.\n" + + "Used by caches, or in conditional requests."), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource has been modified the last time.\n" + + "Used by caches, or in conditional requests."), + }), + @ApiResponse( + code = 304, + message = "Not Modified. \n Empty body because the client already has the latest version of the requested resource.\n"), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid request or validation error.", + response = ErrorResponse.class), + @ApiResponse( + code = 404, + message = "Not Found. \n The specified role does not exist.", + response = ErrorResponse.class), + @ApiResponse( + code = 406, + message = "Not Acceptable.\n The requested media type is not supported", + response = ErrorResponse.class), + @ApiResponse( + code = 500, + message = "Internal Server ErrorResponse. \n Server error occurred while fetching the permission list for the requested role.", + response = ErrorResponse.class) }) - } - ) - @ApiResponses( - value = { - @ApiResponse( - code = 200, - message = "OK. \n Successfully fetched the details of the role.", - response = RoleInfo.class, - responseHeaders = { - @ResponseHeader( - name = "Content-Type", - description = "The content type of the body"), - @ResponseHeader( - name = "ETag", - description = "Entity Tag of the response resource.\n" + - "Used by caches, or in conditional requests."), - @ResponseHeader( - name = "Last-Modified", - description = "Date and time the resource has been modified the last time.\n" + - "Used by caches, or in conditional requests."), - }), - @ApiResponse( - code = 304, - message = "Not Modified. \n Empty body because the client already has the latest version of the requested resource."), - @ApiResponse( - code = 400, - message = "Bad Request. \n Invalid request or validation error.", - response = ErrorResponse.class), - @ApiResponse( - code = 404, - message = "Not Found. \n The specified role does not exist.", - response = ErrorResponse.class), - @ApiResponse( - code = 406, - message = "Not Acceptable.\n The requested media type is not supported", - response = ErrorResponse.class), - @ApiResponse( - code = 500, - message = "Internal Server Error. \n Server error occurred while fetching the details of" + - "requested role.", - response = ErrorResponse.class) - }) - Response getRole( - @ApiParam( - name = "roleName", - value = "The name of the role.", - required = true, - defaultValue = "admin") - @PathParam("roleName") String roleName, - @ApiParam( - name = "user-store", - value = "The name of the user store which the particular of role resides in", - required = false) - @QueryParam("user-store") String userStoreName, - @ApiParam( - name = "If-Modified-Since", - value = "Checks if the requested variant was modified, since the specified date-time." + - "Provide the value in the following format: EEE, d MMM yyyy HH:mm:ss Z.\n" + - "Example: Mon, 05 Jan 2014 15:10:00 +0200", - required = false) - @HeaderParam("If-Modified-Since") String ifModifiedSince); + Response getPermissionsOfRole( + @ApiParam( + name = "roleName", + value = "The name of the role.", + required = true, + defaultValue = "Engineer") + @PathParam("roleName") String roleName, + @ApiParam( + name = "user-store", + value = "The name of the user store from which you wish to get the permission of role.", + required = false) + @QueryParam("user-store") String userStoreName, + @ApiParam( + name = "If-Modified-Since", + value = "Checks if the requested variant was modified, since the specified date-time." + + "Provide the value in the following format: EEE, d MMM yyyy HH:mm:ss Z.\n" + + "Example: Mon, 05 Jan 2014 15:10:00 +0200", + required = false) + @HeaderParam("If-Modified-Since") String ifModifiedSince); - @POST - @ApiOperation( - consumes = MediaType.APPLICATION_JSON, - produces = MediaType.APPLICATION_JSON, - httpMethod = "POST", - value = "Adding a Role", - notes = "WSO2 EMM supports role-based access control (RBAC) and role management. Add a new role to WSO2 EMM using this REST API.", - tags = "Role Management", - extensions = { - @Extension(properties = { - @ExtensionProperty(name = Constants.SCOPE, value = "perm:roles:add") + @GET + @Path("/{roleName}") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "GET", + value = "Getting Details of a Role", + notes = "Get the permissions associated with a role and role specific details using this REST API.", + response = RoleInfo.class, + tags = "Role Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:roles:details") + }) + } + ) + @ApiResponses( + value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully fetched the details of the role.", + response = RoleInfo.class, + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @ResponseHeader( + name = "ETag", + description = "Entity Tag of the response resource.\n" + + "Used by caches, or in conditional requests."), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource has been modified the last time.\n" + + "Used by caches, or in conditional requests."), + }), + @ApiResponse( + code = 304, + message = "Not Modified. \n Empty body because the client already has the latest version of the requested resource."), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid request or validation error.", + response = ErrorResponse.class), + @ApiResponse( + code = 404, + message = "Not Found. \n The specified role does not exist.", + response = ErrorResponse.class), + @ApiResponse( + code = 406, + message = "Not Acceptable.\n The requested media type is not supported", + response = ErrorResponse.class), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Server error occurred while fetching the details of" + + "requested role.", + response = ErrorResponse.class) }) - } - ) - @ApiResponses(value = { - @ApiResponse( - code = 201, - message = "Created. \n Successfully created the role.", - responseHeaders = { - @ResponseHeader( - name = "Content-Location", - description = "The URL to the newly added role."), - @ResponseHeader( - name = "Content-Type", - description = "The content type of the body"), - @ResponseHeader( - name = "ETag", - description = "Entity Tag of the response resource.\n" + - "Used by caches, or in conditional requests."), - @ResponseHeader( - name = "Last-Modified", - description = "Date and time the resource has been modified the last time.\n" + - "Used by caches, or in conditional requests.")}), - @ApiResponse( - code = 303, - message = "See Other. \n The source can be retrieved from the URL specified in the location header.", - responseHeaders = { - @ResponseHeader( - name = "Content-Location", - description = "The Source URL of the document.")}), - @ApiResponse( - code = 400, - message = "Bad Request. \n Invalid request or validation error.", - response = ErrorResponse.class), - @ApiResponse( - code = 415, - message = "Unsupported media type. \n The format of the requested entity was not supported.", - response = ErrorResponse.class), - @ApiResponse( - code = 500, - message = "Internal Server Error. \n Server error occurred while adding a new role.", - response = ErrorResponse.class) - }) - Response addRole( - @ApiParam( - name = "role", - value = "The properties required to add a new role.", - required = true) RoleInfo role); + Response getRole( + @ApiParam( + name = "roleName", + value = "The name of the role.", + required = true, + defaultValue = "admin") + @PathParam("roleName") String roleName, + @ApiParam( + name = "user-store", + value = "The name of the user store which the particular of role resides in", + required = false) + @QueryParam("user-store") String userStoreName, + @ApiParam( + name = "If-Modified-Since", + value = "Checks if the requested variant was modified, since the specified date-time." + + "Provide the value in the following format: EEE, d MMM yyyy HH:mm:ss Z.\n" + + "Example: Mon, 05 Jan 2014 15:10:00 +0200", + required = false) + @HeaderParam("If-Modified-Since") String ifModifiedSince); - @POST - @Path("/create-combined-role/{roleName}") - @ApiOperation( - consumes = MediaType.APPLICATION_JSON, - produces = MediaType.APPLICATION_JSON, - httpMethod = "POST", - value = "Adding a combined Role", - notes = "WSO2 EMM supports role-based access control (RBAC) and role management. Add a new combined role to WSO2 EMM using this REST API.", - tags = "Role Management", - extensions = { - @Extension(properties = { - @ExtensionProperty(name = Constants.SCOPE, value = "perm:roles:create-combined-role") - }) - } - ) - @ApiResponses(value = { - @ApiResponse( - code = 201, - message = "Created. \n Successfully created the role.", - responseHeaders = { - @ResponseHeader( - name = "Content-Location", - description = "The URL to the newly added role."), - @ResponseHeader( - name = "Content-Type", - description = "The content type of the body"), - @ResponseHeader( - name = "ETag", - description = "Entity Tag of the response resource.\n" + - "Used by caches, or in conditional requests."), - @ResponseHeader( - name = "Last-Modified", - description = "Date and time the resource has been modified the last time.\n" + - "Used by caches, or in conditional requests.")}), - @ApiResponse( - code = 303, - message = "See Other. \n The source can be retrieved from the URL specified in the location header.", - responseHeaders = { - @ResponseHeader( - name = "Content-Location", - description = "The Source URL of the document.")}), - @ApiResponse( - code = 400, - message = "Bad Request. \n Invalid request or validation error.", - response = ErrorResponse.class), - @ApiResponse( - code = 415, - message = "Unsupported media type. \n The format of the requested entity was not supported.", - response = ErrorResponse.class), - @ApiResponse( - code = 500, - message = "Internal Server Error. \n Server error occurred while adding a new role.", - response = ErrorResponse.class) - }) - Response addCombinedRole( - @ApiParam( - name = "roles", - value = "List of roles names required to add a new combined role.", - required = true) List roles, - @PathParam("roleName") String roleName, - @QueryParam("user-store") String userStoreName); + @POST + @ApiOperation( + consumes = MediaType.APPLICATION_JSON, + produces = MediaType.APPLICATION_JSON, + httpMethod = "POST", + value = "Adding a Role", + notes = "WSO2 IoTS supports role-based access control (RBAC) and role management. Add a new role to WSO2 IoTS using this REST API.", + tags = "Role Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:roles:add") + }) + } + ) + @ApiResponses(value = { + @ApiResponse( + code = 201, + message = "Created. \n Successfully created the role.", + responseHeaders = { + @ResponseHeader( + name = "Content-Location", + description = "The URL to the newly added role."), + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @ResponseHeader( + name = "ETag", + description = "Entity Tag of the response resource.\n" + + "Used by caches, or in conditional requests."), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource has been modified the last time.\n" + + "Used by caches, or in conditional requests.")}), + @ApiResponse( + code = 303, + message = "See Other. \n The source can be retrieved from the URL specified in the location header.", + responseHeaders = { + @ResponseHeader( + name = "Content-Location", + description = "The Source URL of the document.")}), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid request or validation error.", + response = ErrorResponse.class), + @ApiResponse( + code = 415, + message = "Unsupported media type. \n The format of the requested entity was not supported.", + response = ErrorResponse.class), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Server error occurred while adding a new role.", + response = ErrorResponse.class) + }) + Response addRole( + @ApiParam( + name = "role", + value = "The properties required to add a new role.", + required = true) RoleInfo role); - @PUT - @Path("/{roleName}") - @ApiOperation( - consumes = MediaType.APPLICATION_JSON, - produces = MediaType.APPLICATION_JSON, - httpMethod = "PUT", - value = "Updating Role Details", - notes = "There will be situations where you need to update the role details, such as the permissions" + - " or the role name. Update the role details using this REST API.", - tags = "Role Management", - extensions = { - @Extension(properties = { - @ExtensionProperty(name = Constants.SCOPE, value = "perm:roles:update") - }) - } - ) - @ApiResponses(value = { - @ApiResponse( - code = 200, - message = "OK. \n Successfully updated the specified role.", - responseHeaders = { - @ResponseHeader( - name = "Content-Type", - description = "Content type of the body"), - @ResponseHeader( - name = "ETag", - description = "Entity Tag of the response resource.\n" + - "Used by caches, or in conditional requests."), - @ResponseHeader( - name = "Last-Modified", - description = "Date and time the resource was last modified.\n" + - "Used by caches, or in conditional requests.")}), - @ApiResponse( - code = 400, - message = "Bad Request. \n Invalid request or validation error.", - response = ErrorResponse.class), - @ApiResponse( - code = 404, - message = "Not Found. \n The specified role does not exist.", - response = ErrorResponse.class), - @ApiResponse( - code = 415, - message = "Unsupported media type. \n The format of the requested entity was not supported.\n", - response = ErrorResponse.class), - @ApiResponse( - code = 500, - message = "Internal Server Error. \n Server error occurred while updating the role.", - response = ErrorResponse.class) - }) - Response updateRole( - @ApiParam( - name = "roleName", - value = "The name of the role.", - required = true, - defaultValue = "admin") - @PathParam("roleName") String roleName, - @ApiParam( - name = "role", - value = "The properties required to update a role.\n" + - "NOTE: Don't change the role and the permissions of the admin user. " + - "If you want to try out this API by updating all the properties, create a new role and update the properties accordingly.", - required = true) RoleInfo role, - @ApiParam( - name = "user-store", - value = "The name of the user store which the particular role resides in.", - required = false) - @QueryParam("user-store") String userStoreName); + @POST + @Path("/create-combined-role/{roleName}") + @ApiOperation( + consumes = MediaType.APPLICATION_JSON, + produces = MediaType.APPLICATION_JSON, + httpMethod = "POST", + value = "Adding a combined Role", + notes = "WSO2 IoTS supports role-based access control (RBAC) and role management. Add a new combined role to WSO2 IoTS using this REST API.", + tags = "Role Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:roles:create-combined-role") + }) + } + ) + @ApiResponses(value = { + @ApiResponse( + code = 201, + message = "Created. \n Successfully created the role.", + responseHeaders = { + @ResponseHeader( + name = "Content-Location", + description = "The URL to the newly added role."), + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @ResponseHeader( + name = "ETag", + description = "Entity Tag of the response resource.\n" + + "Used by caches, or in conditional requests."), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource has been modified the last time.\n" + + "Used by caches, or in conditional requests.")}), + @ApiResponse( + code = 303, + message = "See Other. \n The source can be retrieved from the URL specified in the location header.", + responseHeaders = { + @ResponseHeader( + name = "Content-Location", + description = "The Source URL of the document.")}), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid request or validation error.", + response = ErrorResponse.class), + @ApiResponse( + code = 415, + message = "Unsupported media type. \n The format of the requested entity was not supported.", + response = ErrorResponse.class), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Server error occurred while adding a new role.", + response = ErrorResponse.class) + }) + Response addCombinedRole( + @ApiParam( + name = "roles", + value = "List of roles names required to add a new combined role.", + required = true) List roles, + @PathParam("roleName") String roleName, + @QueryParam("user-store") String userStoreName); - @DELETE - @Path("/{roleName}") - @ApiOperation( - httpMethod = "DELETE", - value = "Deleting a Role", - notes = "Roles become obsolete over time due to various reasons. In a situation where your Organization identifies that a specific role is no longer required, you " + - "can delete a role using this REST API.", - tags = "Role Management", - extensions = { - @Extension(properties = { - @ExtensionProperty(name = Constants.SCOPE, value = "perm:roles:delete") - }) - } - ) - @ApiResponses(value = { - @ApiResponse( - code = 200, - message = "OK. \n Successfully removed the specified role."), - @ApiResponse( - code = 400, - message = "Bad Request. \n Invalid request or validation error.", - response = ErrorResponse.class), - @ApiResponse( - code = 404, - message = "Not Found. \n The specified role does not exist.", - response = ErrorResponse.class), - @ApiResponse( - code = 500, - message = "Internal Server Error. \n Server error occurred while removing the role.", - response = ErrorResponse.class) - }) - Response deleteRole( - @ApiParam( - name = "roleName", - value = "The name of the role that needs to de deleted.\n" + - "NOTE: Don't delete the admin role", - required = true) - @PathParam("roleName") String roleName, - @ApiParam( - name = "user-store", - value = "The name of the user store which the particular role resides in.", - required = false) - @QueryParam("user-store") String userStoreName); + @PUT + @Path("/{roleName}") + @ApiOperation( + consumes = MediaType.APPLICATION_JSON, + produces = MediaType.APPLICATION_JSON, + httpMethod = "PUT", + value = "Updating Role Details", + notes = "There will be situations where you need to update the role details, such as the permissions" + + " or the role name. Update the role details using this REST API.", + tags = "Role Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:roles:update") + }) + } + ) + @ApiResponses(value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully updated the specified role.", + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "Content type of the body"), + @ResponseHeader( + name = "ETag", + description = "Entity Tag of the response resource.\n" + + "Used by caches, or in conditional requests."), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource was last modified.\n" + + "Used by caches, or in conditional requests.")}), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid request or validation error.", + response = ErrorResponse.class), + @ApiResponse( + code = 404, + message = "Not Found. \n The specified role does not exist.", + response = ErrorResponse.class), + @ApiResponse( + code = 415, + message = "Unsupported media type. \n The format of the requested entity was not supported.\n", + response = ErrorResponse.class), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Server error occurred while updating the role.", + response = ErrorResponse.class) + }) + Response updateRole( + @ApiParam( + name = "roleName", + value = "The name of the role.", + required = true, + defaultValue = "admin") + @PathParam("roleName") String roleName, + @ApiParam( + name = "role", + value = "The properties required to update a role.\n" + + "NOTE: Don't change the role and the permissions of the admin user. " + + "If you want to try out this API by updating all the properties, create a new role and update the properties accordingly.", + required = true) RoleInfo role, + @ApiParam( + name = "user-store", + value = "The name of the user store which the particular role resides in.", + required = false) + @QueryParam("user-store") String userStoreName); - @PUT - @Path("/{roleName}/users") - @ApiOperation( - consumes = MediaType.APPLICATION_JSON, - produces = MediaType.APPLICATION_JSON, - httpMethod = "PUT", - value = "Adding Users to a Role", - notes = "Defining users to a role at the point of creating a new role is optional. " + - "You can update the users that belong to a given role after you have created " + - "a role using this REST API.\n" + - "Example: Your Organization hires 30 new engineers. Updating the role details for each user can " + - "be cumbersome. Therefore, you can define all the new employees that belong to the engineering " + - "role using this API.", - tags = "Role Management", - extensions = { - @Extension(properties = { - @ExtensionProperty(name = Constants.SCOPE, value = "perm:roles:add-users") + @DELETE + @Path("/{roleName}") + @ApiOperation( + httpMethod = "DELETE", + value = "Deleting a Role", + notes = "Roles become obsolete over time due to various reasons. In a situation where your Organization identifies that a specific role is no longer required, you " + + "can delete a role using this REST API.", + tags = "Role Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:roles:delete") + }) + } + ) + @ApiResponses(value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully removed the specified role."), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid request or validation error.", + response = ErrorResponse.class), + @ApiResponse( + code = 404, + message = "Not Found. \n The specified role does not exist.", + response = ErrorResponse.class), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Server error occurred while removing the role.", + response = ErrorResponse.class) + }) + Response deleteRole( + @ApiParam( + name = "roleName", + value = "The name of the role that needs to de deleted.\n" + + "NOTE: Don't delete the admin role", + required = true) + @PathParam("roleName") String roleName, + @ApiParam( + name = "user-store", + value = "The name of the user store which the particular role resides in.", + required = false) + @QueryParam("user-store") String userStoreName); + + @PUT + @Path("/{roleName}/users") + @ApiOperation( + consumes = MediaType.APPLICATION_JSON, + produces = MediaType.APPLICATION_JSON, + httpMethod = "PUT", + value = "Adding Users to a Role", + notes = "Defining users to a role at the point of creating a new role is optional. " + + "You can update the users that belong to a given role after you have created " + + "a role using this REST API.\n" + + "Example: Your Organization hires 30 new engineers. Updating the role details for each user can " + + "be cumbersome. Therefore, you can define all the new employees that belong to the engineering " + + "role using this API.", + tags = "Role Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:roles:add-users") + }) + } + ) + @ApiResponses( + value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully added the users to the specified role.", + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "Content type of the body"), + @ResponseHeader( + name = "ETag", + description = "Entity Tag of the response resource.\n" + + "Used by caches, or in conditional requests."), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource has been modified the last time.\n" + + "Used by caches, or in conditional requests.")}), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid request or validation error.", + response = ErrorResponse.class), + @ApiResponse( + code = 404, + message = "Not Found. \n The specified role does not exist.", + response = ErrorResponse.class), + @ApiResponse( + code = 415, + message = "Unsupported media type. \n The format of the requested entity was not supported.\n" + + "supported format.", + response = ErrorResponse.class), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n " + + "Server error occurred while adding the user to the specified role.", + response = ErrorResponse.class) }) - } - ) - @ApiResponses( - value = { - @ApiResponse( - code = 200, - message = "OK. \n Successfully added the users to the specified role.", - responseHeaders = { - @ResponseHeader( - name = "Content-Type", - description = "Content type of the body"), - @ResponseHeader( - name = "ETag", - description = "Entity Tag of the response resource.\n" + - "Used by caches, or in conditional requests."), - @ResponseHeader( - name = "Last-Modified", - description = "Date and time the resource has been modified the last time.\n" + - "Used by caches, or in conditional requests.")}), - @ApiResponse( - code = 400, - message = "Bad Request. \n Invalid request or validation error.", - response = ErrorResponse.class), - @ApiResponse( - code = 404, - message = "Not Found. \n The specified role does not exist.", - response = ErrorResponse.class), - @ApiResponse( - code = 415, - message = "Unsupported media type. \n The format of the requested entity was not supported.\n" + - "supported format.", - response = ErrorResponse.class), - @ApiResponse( - code = 500, - message = "Internal Server Error. \n " + - "Server error occurred while adding the user to the specified role.", - response = ErrorResponse.class) - }) - Response updateUsersOfRole( - @ApiParam( - name = "roleName", - value = "The name of the role.", - required = true, - defaultValue = "admin") - @PathParam("roleName") String roleName, - @ApiParam( - name = "user-store", - value = "The name of the user store which the particular role resides in.", - required = false) - @QueryParam("user-store") String userStoreName, - @ApiParam( - name = "users", - value = "Define the users that belong to the role.\n" + - "Multiple users can be added to a role by using comma separated values. ", - required = true, - defaultValue = "[admin]" - ) List users); + Response updateUsersOfRole( + @ApiParam( + name = "roleName", + value = "The name of the role.", + required = true, + defaultValue = "admin") + @PathParam("roleName") String roleName, + @ApiParam( + name = "user-store", + value = "The name of the user store which the particular role resides in.", + required = false) + @QueryParam("user-store") String userStoreName, + @ApiParam( + name = "users", + value = "Define the users that belong to the role.\n" + + "Multiple users can be added to a role by using comma separated values. ", + required = true, + defaultValue = "[admin]" + ) List users); -} + } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/admin/DeviceTypePublisherAdminService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/admin/DeviceTypePublisherAdminService.java new file mode 100644 index 0000000000..7914f9d071 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/admin/DeviceTypePublisherAdminService.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2017, 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. + * + */ +package org.wso2.carbon.device.mgt.jaxrs.service.api.admin; + + +import io.swagger.annotations.*; +import org.wso2.carbon.apimgt.annotations.api.Scope; +import org.wso2.carbon.apimgt.annotations.api.Scopes; +import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse; +import org.wso2.carbon.device.mgt.jaxrs.util.Constants; + +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Response; + +@SwaggerDefinition( + info = @Info( + version = "1.0.0", + title = "", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = "name", value = "DeviceTypePublisherAdminService"), + @ExtensionProperty(name = "context", value = "/api/device-mgt/v1.0/admin/devicetype"), + }) + } + ), + tags = { + @Tag(name = "device_management", description = "") + } +) +@Path("/admin/devicetype") +@Api(value = "Devicetype deployment Administrative Service", description = "This an API intended to be used to " + + "deploy device type components" + + "Further, this is strictly restricted to admin users only ") +@Scopes( + scopes = { + @Scope( + name = "Devicetype deployment", + description = "Deploy devicetype", + key = "perm:devicetype:deployment", + permissions = {"/device-mgt/devicetype/deploy"} + ) + } +) + +public interface DeviceTypePublisherAdminService { + + @POST + @Path("/deploy/{type}") + @ApiOperation( + httpMethod = "POST", + value = "Deploy device type\n", + notes = "This is an API that can be used to deploy existing device type artifact for tenant", + response = Response.class, + tags = "Devicetype Deployment Service", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:devicetype:deployment") + }) + }) + + @ApiResponses(value = { + @ApiResponse( + code = 201, + message = "OK. \n Successfully deployed the artifacts.", + response = Response.class), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid request or validation error.", + response = ErrorResponse.class), + @ApiResponse( + code = 404, + message = "Not Found. \n The specified resource does not exist."), + @ApiResponse( + code = 415, + message = "Unsupported media type. \n The entity of the request was in a not supported format."), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Server error occurred while checking the authorization" + + " for a specified set of devices.", + response = ErrorResponse.class) + }) + + Response doPublish( + @ApiParam(name = "type", + value = "The type of deployment." + + "INFO: Deploy artifact with given type.", + required = true) + @PathParam("type") String type); + + @GET + @Path("/deploy/{type}/status") + @ApiOperation( + httpMethod = "GET", + value = "Check the status of device type artifact\n", + notes = "This is an API that can be used to check the status of the artifact", + response = Response.class, + tags = "Devicetype Status Service", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:devicetype:deployment") + }) + }) + + @ApiResponses(value = { + @ApiResponse( + code = 201, + message = "OK. \n Successfully deployed the artifacts.", + response = Response.class), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid request or validation error.", + response = ErrorResponse.class), + @ApiResponse( + code = 404, + message = "Not Found. \n The specified resource does not exist."), + @ApiResponse( + code = 415, + message = "Unsupported media type. \n The entity of the request was in a not supported format."), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Server error occurred while checking the authorization" + + " for a specified set of devices.", + response = ErrorResponse.class) + }) + + Response getStatus(@PathParam("type") String deviceType); + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceManagementServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceManagementServiceImpl.java index 9b56130540..3f3185a30d 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceManagementServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceManagementServiceImpl.java @@ -18,6 +18,7 @@ */ package org.wso2.carbon.device.mgt.jaxrs.service.impl; +import io.swagger.annotations.ApiParam; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -34,6 +35,7 @@ import org.wso2.carbon.device.mgt.common.app.mgt.Application; import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManagementException; import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationException; import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService; +import org.wso2.carbon.device.mgt.common.device.details.DeviceLocation; import org.wso2.carbon.device.mgt.common.operation.mgt.Operation; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException; import org.wso2.carbon.device.mgt.common.policy.mgt.Policy; @@ -41,6 +43,8 @@ import org.wso2.carbon.device.mgt.common.policy.mgt.monitor.NonComplianceData; import org.wso2.carbon.device.mgt.common.policy.mgt.monitor.PolicyComplianceException; import org.wso2.carbon.device.mgt.common.search.SearchContext; import org.wso2.carbon.device.mgt.core.app.mgt.ApplicationManagementProviderService; +import org.wso2.carbon.device.mgt.core.device.details.mgt.DeviceDetailsMgtException; +import org.wso2.carbon.device.mgt.core.device.details.mgt.DeviceInformationManager; import org.wso2.carbon.device.mgt.core.search.mgt.SearchManagerService; import org.wso2.carbon.device.mgt.core.search.mgt.SearchMgtException; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; @@ -99,8 +103,8 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { if (!StringUtils.isEmpty(name) && !StringUtils.isEmpty(role)) { return Response.status(Response.Status.BAD_REQUEST).entity( new ErrorResponse.ErrorResponseBuilder().setMessage("Request contains both name and role " + - "parameters. Only one is allowed " + - "at once.").build()).build(); + "parameters. Only one is allowed " + + "at once.").build()).build(); } // RequestValidationUtil.validateSelectionCriteria(type, user, roleName, ownership, status); RequestValidationUtil.validatePaginationParameters(offset, limit); @@ -110,7 +114,7 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { if (deviceAccessAuthorizationService == null) { return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity( new ErrorResponse.ErrorResponseBuilder().setMessage("Device access authorization service is " + - "failed").build()).build(); + "failed").build()).build(); } PaginationRequest request = new PaginationRequest(offset, limit); PaginationResult result; @@ -133,7 +137,7 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { RequestValidationUtil.validateStatus(status); request.setStatus(status); } - if (groupId != 0 ) { + if (groupId != 0) { request.setGroupId(groupId); } if (role != null && !role.isEmpty()) { @@ -155,7 +159,7 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { request.setOwner(user); } else { String msg = "User '" + authorizedUser + "' is not authorized to retrieve devices of '" + user - + "' user"; + + "' user"; log.error(msg); return Response.status(Response.Status.UNAUTHORIZED).entity( new ErrorResponse.ErrorResponseBuilder().setCode(401l).setMessage(msg).build()).build(); @@ -330,12 +334,12 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { } catch (ParseException e) { return Response.status(Response.Status.BAD_REQUEST).entity( new ErrorResponse.ErrorResponseBuilder().setMessage("Invalid date " + - "string is provided in 'If-Modified-Since' header").build()).build(); + "string is provided in 'If-Modified-Since' header").build()).build(); } device = dms.getDevice(new DeviceIdentifier(id, type), sinceDate); if (device == null) { return Response.status(Response.Status.NOT_MODIFIED).entity("No device is modified " + - "after the timestamp provided in 'If-Modified-Since' header").build(); + "after the timestamp provided in 'If-Modified-Since' header").build(); } } else { device = dms.getDevice(new DeviceIdentifier(id, type)); @@ -359,6 +363,32 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { return Response.status(Response.Status.OK).entity(device).build(); } + @GET + @Path("/{type}/{id}/location") + @Override + public Response getDeviceLocation( + @PathParam("type") @Size(max = 45) String type, + @PathParam("id") @Size(max = 45) String id, + @HeaderParam("If-Modified-Since") String ifModifiedSince) { + DeviceInformationManager informationManager; + DeviceLocation deviceLocation; + try { + DeviceIdentifier deviceIdentifier = new DeviceIdentifier(); + deviceIdentifier.setId(id); + deviceIdentifier.setType(type); + informationManager = DeviceMgtAPIUtils.getDeviceInformationManagerService(); + deviceLocation = informationManager.getDeviceLocation(deviceIdentifier); + + } catch (DeviceDetailsMgtException e) { + String msg = "Error occurred while getting the device location."; + log.error(msg, e); + return Response.serverError().entity( + new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build(); + } + return Response.status(Response.Status.OK).entity(deviceLocation).build(); + + } + @GET @Path("/{type}/{id}/features") @Override diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/RoleManagementServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/RoleManagementServiceImpl.java index dd6932981f..e947c258c0 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/RoleManagementServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/RoleManagementServiceImpl.java @@ -30,37 +30,20 @@ import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.FilteringUtil; import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.RequestValidationUtil; import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtAPIUtils; import org.wso2.carbon.device.mgt.jaxrs.util.SetReferenceTransformer; -import org.wso2.carbon.user.api.AuthorizationManager; -import org.wso2.carbon.user.api.Permission; -import org.wso2.carbon.user.api.UserRealm; -import org.wso2.carbon.user.api.UserStoreException; -import org.wso2.carbon.user.api.UserStoreManager; +import org.wso2.carbon.user.api.*; import org.wso2.carbon.user.core.common.AbstractUserStoreManager; import org.wso2.carbon.user.mgt.UserRealmProxy; import org.wso2.carbon.user.mgt.common.UIPermissionNode; import org.wso2.carbon.user.mgt.common.UserAdminException; -import javax.ws.rs.Consumes; -import javax.ws.rs.DELETE; -import javax.ws.rs.GET; -import javax.ws.rs.HeaderParam; -import javax.ws.rs.POST; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; +import javax.ws.rs.*; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; import static org.wso2.carbon.device.mgt.jaxrs.util.Constants.PRIMARY_USER_STORE; @@ -105,6 +88,48 @@ public class RoleManagementServiceImpl implements RoleManagementService { } } + @GET + @Path("/filter/{prefix}") + @Override + public Response getFilteredRoles( + @PathParam("prefix") String prefix, + @QueryParam("filter") String filter, + @QueryParam("user-store") String userStore, + @HeaderParam("If-Modified-Since") String ifModifiedSince, + @QueryParam("offset") int offset, @QueryParam("limit") int limit) { + RequestValidationUtil.validatePaginationParameters(offset, limit); + List finalRoleList; + RoleList targetRoles = new RoleList(); + + //if user store is null set it to primary + if (userStore == null || "".equals(userStore)) { + userStore = PRIMARY_USER_STORE; + } + + try { + + //Get the total role count that matches the given filter + List filteredRoles = getRolesFromUserStore(filter, userStore); + finalRoleList = new ArrayList(); + + filteredRoles = FilteringUtil.getFilteredList(getRolesFromUserStore(filter, userStore), offset, limit); + for (String rolename : filteredRoles){ + if (rolename.startsWith(prefix)){ + finalRoleList.add(rolename); + } + } + targetRoles.setCount(finalRoleList.size()); + targetRoles.setList(finalRoleList); + + return Response.ok().entity(targetRoles).build(); + } catch (UserStoreException e) { + String msg = "Error occurred while retrieving roles from the underlying user stores"; + log.error(msg, e); + return Response.serverError().entity( + new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build(); + } + } + @GET @Path("/{roleName}/permissions") @Override @@ -208,7 +233,7 @@ public class RoleManagementServiceImpl implements RoleManagementService { if (!userStoreManager.isExistingRole(roleName)) { return Response.status(404).entity( new ErrorResponse.ErrorResponseBuilder().setMessage("No role exists with the name '" + - roleName + "'").build()).build(); + roleName + "'").build()).build(); } roleInfo.setRoleName(roleName); roleInfo.setUsers(userStoreManager.getUserListOfRole(roleName)); @@ -275,7 +300,7 @@ public class RoleManagementServiceImpl implements RoleManagementService { //TODO fix what's returned in the entity return Response.created(new URI(API_BASE_PATH + "/" + URLEncoder.encode(roleInfo.getRoleName(), "UTF-8"))). entity("Role '" + roleInfo.getRoleName() + "' has " + "successfully been" - + " added").build(); + + " added").build(); } catch (UserStoreException e) { String msg = "Error occurred while adding role '" + roleInfo.getRoleName() + "'"; log.error(msg, e); @@ -335,7 +360,7 @@ public class RoleManagementServiceImpl implements RoleManagementService { //TODO fix what's returned in the entity return Response.created(new URI(API_BASE_PATH + "/" + URLEncoder.encode(roleName, "UTF-8"))). entity("Role '" + roleName + "' has " + "successfully been" - + " added").build(); + + " added").build(); } catch (UserAdminException e) { String msg = "Error occurred while retrieving the permissions of role '" + roleName + "'"; log.error(msg, e); @@ -376,7 +401,7 @@ public class RoleManagementServiceImpl implements RoleManagementService { if (!userStoreManager.isExistingRole(roleName)) { return Response.status(404).entity( new ErrorResponse.ErrorResponseBuilder().setMessage("No role exists with the name '" + - roleName + "'").build()).build(); + roleName + "'").build()).build(); } final AuthorizationManager authorizationManager = userRealm.getAuthorizationManager(); @@ -392,7 +417,7 @@ public class RoleManagementServiceImpl implements RoleManagementService { if (roleInfo.getUsers() != null) { SetReferenceTransformer transformer = new SetReferenceTransformer<>(); transformer.transform(Arrays.asList(userStoreManager.getUserListOfRole(newRoleName)), - Arrays.asList(roleInfo.getUsers())); + Arrays.asList(roleInfo.getUsers())); final String[] usersToAdd = transformer.getObjectsToAdd().toArray(new String[transformer .getObjectsToAdd().size()]); final String[] usersToDelete = transformer.getObjectsToRemove().toArray(new String[transformer @@ -404,7 +429,7 @@ public class RoleManagementServiceImpl implements RoleManagementService { // Get all role permissions final UIPermissionNode rolePermissions = this.getAllRolePermissions(roleName, userRealm); List permissions = new ArrayList(); - final UIPermissionNode emmRolePermissions = (UIPermissionNode)this.getRolePermissions(roleName); + final UIPermissionNode emmRolePermissions = (UIPermissionNode) this.getRolePermissions(roleName); List emmConsolePermissions = new ArrayList(); this.getAuthorizedPermissions(emmRolePermissions, emmConsolePermissions); emmConsolePermissions.removeAll(new ArrayList(Arrays.asList(roleInfo.getPermissions()))); @@ -413,7 +438,7 @@ public class RoleManagementServiceImpl implements RoleManagementService { permissions.add(permission); } permissions.removeAll(emmConsolePermissions); - String [] allApplicablePerms = new String[permissions.size()]; + String[] allApplicablePerms = new String[permissions.size()]; allApplicablePerms = permissions.toArray(allApplicablePerms); roleInfo.setPermissions(allApplicablePerms); @@ -428,7 +453,7 @@ public class RoleManagementServiceImpl implements RoleManagementService { } //TODO: Need to send the updated role information in the entity back to the client return Response.status(Response.Status.OK).entity("Role '" + roleInfo.getRoleName() + "' has " + - "successfully been updated").build(); + "successfully been updated").build(); } catch (UserStoreException e) { String msg = "Error occurred while updating role '" + roleName + "'"; log.error(msg, e); @@ -456,7 +481,7 @@ public class RoleManagementServiceImpl implements RoleManagementService { if (!userStoreManager.isExistingRole(roleName)) { return Response.status(404).entity( new ErrorResponse.ErrorResponseBuilder().setMessage("No role exists with the name '" + - roleName + "'").build()).build(); + roleName + "'").build()).build(); } final AuthorizationManager authorizationManager = userRealm.getAuthorizationManager(); @@ -493,7 +518,7 @@ public class RoleManagementServiceImpl implements RoleManagementService { } SetReferenceTransformer transformer = new SetReferenceTransformer<>(); transformer.transform(Arrays.asList(userStoreManager.getUserListOfRole(roleName)), - users); + users); final String[] usersToAdd = transformer.getObjectsToAdd().toArray(new String[transformer .getObjectsToAdd().size()]); final String[] usersToDelete = transformer.getObjectsToRemove().toArray(new String[transformer @@ -502,7 +527,7 @@ public class RoleManagementServiceImpl implements RoleManagementService { userStoreManager.updateUserListOfRole(roleName, usersToDelete, usersToAdd); return Response.status(Response.Status.OK).entity("Role '" + roleName + "' has " + - "successfully been updated with the user list") + "successfully been updated with the user list") .build(); } catch (UserStoreException e) { String msg = "Error occurred while updating the users of the role '" + roleName + "'"; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/UserManagementServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/UserManagementServiceImpl.java index 2b5a2e8d45..ca1ad45d1d 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/UserManagementServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/UserManagementServiceImpl.java @@ -38,6 +38,8 @@ import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.RequestValidationUtil; import org.wso2.carbon.device.mgt.jaxrs.util.Constants; import org.wso2.carbon.device.mgt.jaxrs.util.CredentialManagementResponseBuilder; import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtAPIUtils; +import org.wso2.carbon.identity.user.store.count.UserStoreCountRetriever; +import org.wso2.carbon.identity.user.store.count.exception.UserStoreCounterException; import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.api.UserStoreManager; import org.wso2.carbon.utils.CarbonUtils; @@ -395,6 +397,30 @@ public class UserManagementServiceImpl implements UserManagementService { @Path("/count") @Override public Response getUserCount() { + try { + UserStoreCountRetriever userStoreCountRetrieverService = DeviceMgtAPIUtils.getUserStoreCountRetrieverService(); + if (userStoreCountRetrieverService != null) { + long count = userStoreCountRetrieverService.countUsers(""); + if (count != -1) { + BasicUserInfoList result = new BasicUserInfoList(); + result.setCount(count); + return Response.status(Response.Status.OK).entity(result).build(); + } + } + } catch (UserStoreCounterException e) { + String msg = + "Error occurred while retrieving the count of users that exist within the current tenant"; + log.error(msg, e); + } + return getUserCountViaUserStoreManager(); + } + + /** + * This method returns the count of users using UserStoreManager. + * + * @return user count + */ + private Response getUserCountViaUserStoreManager() { if (log.isDebugEnabled()) { log.debug("Getting the user count"); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/admin/DeviceTypePublisherAdminServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/admin/DeviceTypePublisherAdminServiceImpl.java new file mode 100644 index 0000000000..0efa036da0 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/admin/DeviceTypePublisherAdminServiceImpl.java @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2017, 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. + * + */ +package org.wso2.carbon.device.mgt.jaxrs.service.impl.admin; + +import org.apache.axis2.client.Options; +import org.apache.axis2.java.security.SSLProtocolSocketFactory; +import org.apache.axis2.transport.http.HTTPConstants; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.httpclient.Header; +import org.apache.commons.httpclient.protocol.Protocol; +import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.application.mgt.stub.upload.CarbonAppUploaderStub; +import org.wso2.carbon.application.mgt.stub.upload.types.carbon.UploadedFileItem; +import org.wso2.carbon.base.ServerConfiguration; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.core.util.Utils; +import org.wso2.carbon.device.mgt.jaxrs.service.api.admin.DeviceTypePublisherAdminService; +import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtAPIUtils; +import org.wso2.carbon.identity.jwt.client.extension.JWTClient; +import org.wso2.carbon.registry.core.Registry; +import org.wso2.carbon.registry.core.Resource; +import org.wso2.carbon.registry.core.ResourceImpl; +import org.wso2.carbon.registry.core.exceptions.RegistryException; +import org.wso2.carbon.utils.CarbonUtils; + +import javax.activation.DataHandler; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.core.Response; +import java.io.*; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import java.util.ArrayList; +import java.util.List; + +@Path("/admin/devicetype") +public class DeviceTypePublisherAdminServiceImpl implements DeviceTypePublisherAdminService { + + /** + * required soap header for authorization + */ + private static final String AUTHORIZATION_HEADER = "Authorization"; + + /** + * required soap header value for mutualSSL + */ + private static final String AUTHORIZATION_HEADER_VALUE = "Bearer"; + + private static final String KEY_STORE_TYPE = "JKS"; + /** + * Default truststore type of the client + */ + private static final String TRUST_STORE_TYPE = "JKS"; + /** + * Default keymanager type of the client + */ + private static final String KEY_MANAGER_TYPE = "SunX509"; //Default Key Manager Type + /** + * Default trustmanager type of the client + */ + private static final String TRUST_MANAGER_TYPE = "SunX509"; //Default Trust Manager Type + + private static final String SSLV3 = "SSLv3"; + + private KeyStore keyStore; + private KeyStore trustStore; + private char[] keyStorePassword; + private SSLContext sslContext; + + private static final Log log = LogFactory.getLog(DeviceTypePublisherAdminServiceImpl.class); + private static final String DEFAULT_RESOURCE_LOCATION = "/resources/devicetypes"; + private static final String CAR_FILE_LOCATION = CarbonUtils.getCarbonHome() + File.separator + "repository" + + File.separator + "resources" + File.separator + "devicetypes"; + private static final String DAS_PORT = "${iot.analytics.https.port}"; + private static final String DAS_HOST_NAME = "${iot.analytics.host}"; + private static final String DEFAULT_HTTP_PROTOCOL = "https"; + private static final String IOT_MGT_PORT = "${iot.manager.https.port}"; + private static final String IOT_MGT_HOST_NAME = "${iot.manager.host}"; + private static final String DAS_URL = DEFAULT_HTTP_PROTOCOL + "://" + DAS_HOST_NAME + + ":" + DAS_PORT + "/services/CarbonAppUploader" + "/"; + private static final String IOT_MGT_URL = DEFAULT_HTTP_PROTOCOL + "://" + IOT_MGT_HOST_NAME + + ":" + IOT_MGT_PORT + "/services/CarbonAppUploader" + "/"; + private static final String MEDIA_TYPE_XML = "application/xml"; + private static final String DEVICE_MANAGEMENT_TYPE = "device_management"; + + @Override + @POST + @Path("/deploy/{type}") + public Response doPublish(@PathParam("type") String type) { + + try { + //Getting the tenant Domain + String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); + String username = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); + String tenantAdminUser = username + "@" + tenantDomain; + + String keyStorePassword = ServerConfiguration.getInstance().getFirstProperty("Security.KeyStore.Password"); + String trustStorePassword = ServerConfiguration.getInstance().getFirstProperty( + "Security.TrustStore.Password"); + String keyStoreLocation = ServerConfiguration.getInstance().getFirstProperty("Security.KeyStore.Location"); + String trustStoreLocation = ServerConfiguration.getInstance().getFirstProperty( + "Security.TrustStore.Location"); + + //Call to load the keystore. + loadKeyStore(keyStoreLocation, keyStorePassword); + //Call to load the TrustStore. + loadTrustStore(trustStoreLocation, trustStorePassword); + //Create the SSL context with the loaded TrustStore/keystore. + initSSLConnection(); + JWTClient jwtClient = DeviceMgtAPIUtils.getJWTClientManagerService().getJWTClient(); + + String authValue = AUTHORIZATION_HEADER_VALUE + " " + new String(Base64.encodeBase64( + jwtClient.getJwtToken(tenantAdminUser).getBytes())); + + List
list = new ArrayList
(); + Header httpHeader = new Header(); + httpHeader.setName(AUTHORIZATION_HEADER); + httpHeader.setValue(authValue); + list.add(httpHeader);//"https" + + File directory = new File(CAR_FILE_LOCATION + File.separator + type); + if (directory.isDirectory() && directory.exists()) { + UploadedFileItem[] uploadedFileItems = loadCappFromFileSystem(type); + if (uploadedFileItems.length > 0) { + CarbonAppUploaderStub carbonAppUploaderStub = new CarbonAppUploaderStub(Utils.replaceSystemProperty( + IOT_MGT_URL)); + Options appUploaderOptions = carbonAppUploaderStub._getServiceClient().getOptions(); + if (appUploaderOptions == null) { + appUploaderOptions = new Options(); + } + appUploaderOptions.setProperty(HTTPConstants.HTTP_HEADERS, list); + appUploaderOptions.setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER + , new Protocol(DEFAULT_HTTP_PROTOCOL, (ProtocolSocketFactory) new SSLProtocolSocketFactory + (sslContext), Integer.parseInt(Utils.replaceSystemProperty(IOT_MGT_PORT)))); + + carbonAppUploaderStub._getServiceClient().setOptions(appUploaderOptions); + carbonAppUploaderStub.uploadApp(uploadedFileItems); + + if (!DEVICE_MANAGEMENT_TYPE.equals(type.toLowerCase())) { + carbonAppUploaderStub = new CarbonAppUploaderStub(Utils.replaceSystemProperty(DAS_URL)); + appUploaderOptions = carbonAppUploaderStub._getServiceClient().getOptions(); + if (appUploaderOptions == null) { + appUploaderOptions = new Options(); + } + appUploaderOptions.setProperty(HTTPConstants.HTTP_HEADERS, list); + appUploaderOptions.setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER + , new Protocol(DEFAULT_HTTP_PROTOCOL + , (ProtocolSocketFactory) new SSLProtocolSocketFactory(sslContext) + , Integer.parseInt(Utils.replaceSystemProperty(DAS_PORT)))); + + carbonAppUploaderStub._getServiceClient().setOptions(appUploaderOptions); + carbonAppUploaderStub.uploadApp(uploadedFileItems); + } + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); + Registry registry = DeviceMgtAPIUtils.getRegistryService().getConfigSystemRegistry(tenantId); + if (!registry.resourceExists(DEFAULT_RESOURCE_LOCATION + type + ".exist")) { + Resource resource = new ResourceImpl(); + resource.setContent(""); + resource.setMediaType(MEDIA_TYPE_XML); + registry.put(DEFAULT_RESOURCE_LOCATION + type + ".exist", resource); + } + } + } else { + return Response.status(Response.Status.BAD_REQUEST) + .entity("\"Error, Artifact does not exist.\"").build(); + } + + } catch (Exception e) { + log.error("Capp deployment failed due to " + e.getMessage(), e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity( + "\"Error, Artifact deployment has failed\"").build(); + } + + return Response.status(Response.Status.CREATED).entity("\"OK. \\n Successfully uploaded the artifacts.\"") + .build(); + } + + @GET + @Path("/deploy/{type}/status") + @Override + public Response getStatus(@PathParam("type") String deviceType) { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); + Registry registry = null; + try { + registry = DeviceMgtAPIUtils.getRegistryService().getConfigSystemRegistry(tenantId); + if (registry.resourceExists(DEFAULT_RESOURCE_LOCATION + deviceType + ".exist")) { + return Response.status(Response.Status.OK).entity("Exist").build(); + } else { + return Response.status(Response.Status.NO_CONTENT).entity("Does not Exist").build(); + } + } catch (RegistryException e) { + log.error("Registry failed to load." + e.getMessage(), e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity( + "\"Error, Artifact status check has failed\"").build(); + } + } + + private UploadedFileItem[] loadCappFromFileSystem(String deviceType) throws IOException { + + File directory = new File(CAR_FILE_LOCATION + File.separator + deviceType); + File[] carFiles = directory.listFiles(new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + return name.toLowerCase().endsWith(".car"); + } + }); + List uploadedFileItemLis = new ArrayList<>(); + if (carFiles != null) { + + for (File carFile : carFiles) { + UploadedFileItem uploadedFileItem = new UploadedFileItem(); + DataHandler param = new DataHandler(carFile.toURI().toURL()); + uploadedFileItem.setDataHandler(param); + uploadedFileItem.setFileName(carFile.getName()); + uploadedFileItem.setFileType("jar"); + uploadedFileItemLis.add(uploadedFileItem); + } + } + UploadedFileItem[] fileItems = new UploadedFileItem[uploadedFileItemLis.size()]; + fileItems = uploadedFileItemLis.toArray(fileItems); + return fileItems; + } + + /** + * Loads the keystore. + * + * @param keyStorePath - the path of the keystore + * @param ksPassword - the keystore password + */ + private void loadKeyStore(String keyStorePath, String ksPassword) + throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException { + InputStream fis = null; + try { + keyStorePassword = ksPassword.toCharArray(); + keyStore = KeyStore.getInstance(KEY_STORE_TYPE); + fis = new FileInputStream(keyStorePath); + keyStore.load(fis, keyStorePassword); + } finally { + if (fis != null) { + fis.close(); + } + } + } + + /** + * Loads the trustore + * + * @param trustStorePath - the trustore path in the filesystem. + * @param tsPassword - the truststore password + */ + private void loadTrustStore(String trustStorePath, String tsPassword) + throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException { + + InputStream fis = null; + try { + trustStore = KeyStore.getInstance(TRUST_STORE_TYPE); + fis = new FileInputStream(trustStorePath); + trustStore.load(fis, tsPassword.toCharArray()); + } finally { + if (fis != null) { + fis.close(); + } + } + } + + /** + * Initializes the SSL Context + */ + private void initSSLConnection() throws NoSuchAlgorithmException, UnrecoverableKeyException, + KeyStoreException, KeyManagementException { + KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KEY_MANAGER_TYPE); + keyManagerFactory.init(keyStore, keyStorePassword); + TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TRUST_MANAGER_TYPE); + trustManagerFactory.init(trustStore); + + // Create and initialize SSLContext for HTTPS communication + sslContext = SSLContext.getInstance(SSLV3); + sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); + SSLContext.setDefault(sslContext); + } + + +} + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/DeviceMgtAPIUtils.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/DeviceMgtAPIUtils.java index afc03336d5..888b1c42ee 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/DeviceMgtAPIUtils.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/DeviceMgtAPIUtils.java @@ -29,7 +29,6 @@ import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationEntry; import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration; import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfigurationManagementService; import org.wso2.carbon.device.mgt.common.notification.mgt.NotificationManagementService; -import org.wso2.carbon.device.mgt.common.scope.mgt.ScopeManagementService; import org.wso2.carbon.device.mgt.core.app.mgt.ApplicationManagementProviderService; import org.wso2.carbon.device.mgt.core.device.details.mgt.DeviceInformationManager; import org.wso2.carbon.device.mgt.core.search.mgt.SearchManagerService; @@ -37,13 +36,22 @@ import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.core.service.GroupManagementProviderService; import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse; import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.InputValidationException; +import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService; +import org.wso2.carbon.identity.user.store.count.AbstractCountRetrieverFactory; +import org.wso2.carbon.identity.user.store.count.UserStoreCountRetriever; +import org.wso2.carbon.identity.user.store.count.exception.UserStoreCounterException; +import org.wso2.carbon.identity.user.store.count.jdbc.JDBCCountRetrieverFactory; +import org.wso2.carbon.identity.user.store.count.jdbc.internal.InternalCountRetrieverFactory; import org.wso2.carbon.policy.mgt.common.PolicyMonitoringTaskException; import org.wso2.carbon.policy.mgt.core.PolicyManagerService; import org.wso2.carbon.policy.mgt.core.task.TaskScheduleService; +import org.wso2.carbon.registry.core.service.RegistryService; import org.wso2.carbon.user.api.AuthorizationManager; +import org.wso2.carbon.user.api.RealmConfiguration; import org.wso2.carbon.user.api.UserRealm; import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.api.UserStoreManager; +import org.wso2.carbon.user.core.jdbc.JDBCUserStoreManager; import org.wso2.carbon.user.core.service.RealmService; import javax.ws.rs.core.MediaType; @@ -105,6 +113,32 @@ public class DeviceMgtAPIUtils { return deviceManagementProviderService; } + public static UserStoreCountRetriever getUserStoreCountRetrieverService() + throws UserStoreCounterException { + PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + List countRetrieverFactories = ctx.getOSGiServices(AbstractCountRetrieverFactory.class, null); + RealmService realmService = (RealmService) ctx.getOSGiService(RealmService.class, null); + RealmConfiguration realmConfiguration = realmService.getBootstrapRealmConfiguration(); + String userStoreType; + //Ignoring Sonar warning as getUserStoreClass() returning string name of the class. So cannot use 'instanceof'. + if (JDBCUserStoreManager.class.getName().equals(realmConfiguration.getUserStoreClass())) { + userStoreType = JDBCCountRetrieverFactory.JDBC; + } else { + userStoreType = InternalCountRetrieverFactory.INTERNAL; + } + AbstractCountRetrieverFactory countRetrieverFactory = null; + for (Object countRetrieverFactoryObj : countRetrieverFactories) { + countRetrieverFactory = (AbstractCountRetrieverFactory) countRetrieverFactoryObj; + if (userStoreType.equals(countRetrieverFactory.getCounterType())) { + break; + } + } + if (countRetrieverFactory == null) { + return null; + } + return countRetrieverFactory.buildCountRetriever(realmConfiguration); + } + public static DeviceAccessAuthorizationService getDeviceAccessAuthorizationService() { PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); DeviceAccessAuthorizationService deviceAccessAuthorizationService = @@ -156,6 +190,30 @@ public class DeviceMgtAPIUtils { return realmService; } + public static RegistryService getRegistryService() { + RegistryService registryService; + PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + registryService = (RegistryService) ctx.getOSGiService(RegistryService.class, null); + if (registryService == null) { + String msg = "registry service has not initialized."; + log.error(msg); + throw new IllegalStateException(msg); + } + return registryService; + } + + public static JWTClientManagerService getJWTClientManagerService() { + JWTClientManagerService jwtClientManagerService; + PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + jwtClientManagerService = (JWTClientManagerService) ctx.getOSGiService(JWTClientManagerService.class, null); + if (jwtClientManagerService == null) { + String msg = "jwtClientManagerServicehas not initialized."; + log.error(msg); + throw new IllegalStateException(msg); + } + return jwtClientManagerService; + } + /** * Getting the current tenant's user realm */ @@ -262,16 +320,6 @@ public class DeviceMgtAPIUtils { return gadgetDataService; } - public static ScopeManagementService getScopeManagementService() { - PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); - ScopeManagementService scopeManagementService = - (ScopeManagementService) ctx.getOSGiService(ScopeManagementService.class, null); - if (scopeManagementService == null) { - throw new IllegalStateException("Scope Management Service has not been initialized."); - } - return scopeManagementService; - } - public static int getTenantId(String tenantDomain) throws DeviceManagementException { RealmService realmService = (RealmService) PrivilegedCarbonContext.getThreadLocalCarbonContext().getOSGiService(RealmService.class, null); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/DeviceMgtUtil.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/DeviceMgtUtil.java index 0ffb728f0c..c11fd758c9 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/DeviceMgtUtil.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/DeviceMgtUtil.java @@ -18,7 +18,7 @@ package org.wso2.carbon.device.mgt.jaxrs.util; -import org.wso2.carbon.apimgt.api.model.Scope; +import org.wso2.carbon.device.mgt.core.config.permission.Scope; import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorListItem; import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse; import org.wso2.carbon.device.mgt.jaxrs.beans.ProfileFeature; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/cxf-servlet.xml b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/cxf-servlet.xml index 7948186893..fd6c5e0309 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/cxf-servlet.xml +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/cxf-servlet.xml @@ -39,6 +39,8 @@ + + @@ -80,7 +82,9 @@ - + + + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/pom.xml b/components/device-mgt/org.wso2.carbon.device.mgt.common/pom.xml index e31513e6a2..45157c840e 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/pom.xml +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/pom.xml @@ -21,7 +21,7 @@ device-mgt org.wso2.carbon.devicemgt - 2.0.18-SNAPSHOT + 2.0.37-SNAPSHOT ../pom.xml @@ -50,7 +50,6 @@ javax.xml.bind.annotation; version="${javax.xml.bind.imp.pkg.version}", com.fasterxml.jackson.annotation;version="${jackson-annotations.version}", - org.wso2.carbon.apimgt.api.model.*;version="${carbon.api.mgt.version.range}", io.swagger.annotations; version="${swagger.annotations.version}"; resolution:=optional @@ -69,10 +68,6 @@ org.wso2.orbit.com.fasterxml.jackson.core jackson-annotations - - org.wso2.carbon.apimgt - org.wso2.carbon.apimgt.api - diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/InitialOperationConfig.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/InitialOperationConfig.java new file mode 100644 index 0000000000..758ba549f2 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/InitialOperationConfig.java @@ -0,0 +1,36 @@ +/* + * 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. + * + */ + +package org.wso2.carbon.device.mgt.common; + +import java.util.List; + +public class InitialOperationConfig { + private List operations; + + public List getOperations() { + return operations; + } + + public void setOperations(List operations) { + this.operations = operations; + } + + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/scope/mgt/ScopeManagementException.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/scope/mgt/ScopeManagementException.java deleted file mode 100644 index ed5082a72c..0000000000 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/scope/mgt/ScopeManagementException.java +++ /dev/null @@ -1,57 +0,0 @@ -/* -* Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. -* -* Licensed 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. -*/ -package org.wso2.carbon.device.mgt.common.scope.mgt; - -/** - * This exception is used to throw when there is an issue in scope management service. - */ -public class ScopeManagementException extends Exception { - - private static final long serialVersionUID = -315127931137779899L; - - private String errorMessage; - - public String getErrorMessage() { - return errorMessage; - } - - public void setErrorMessage(String errorMessage) { - this.errorMessage = errorMessage; - } - - public ScopeManagementException(String msg, Exception nestedEx) { - super(msg, nestedEx); - setErrorMessage(msg); - } - - public ScopeManagementException(String message, Throwable cause) { - super(message, cause); - setErrorMessage(message); - } - - public ScopeManagementException(String msg) { - super(msg); - setErrorMessage(msg); - } - - public ScopeManagementException() { - super(); - } - - public ScopeManagementException(Throwable cause) { - super(cause); - } -} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/scope/mgt/ScopeManagementService.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/scope/mgt/ScopeManagementService.java deleted file mode 100644 index 2d60dbd1f0..0000000000 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/scope/mgt/ScopeManagementService.java +++ /dev/null @@ -1,78 +0,0 @@ -/* -* 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. -*/ - -package org.wso2.carbon.device.mgt.common.scope.mgt; - -import java.util.List; -import org.wso2.carbon.apimgt.api.model.Scope; - -/** - * This interface contains the basic operations related to scope management. - */ -public interface ScopeManagementService { - - /** - * This method is used to update the given list of scopes. - * - * @param scopes List of scopes to be updated. - * @throws ScopeManagementException - */ - void updateScopes(List scopes) throws ScopeManagementException; - - /** - * This method is used to update the given list of scopes keys with the role name. - * - * @param scopeKeys List of scopes to be updated. - * @param roleName Role name - * @throws ScopeManagementException - */ - void updateScopes(List scopeKeys, String roleName) throws ScopeManagementException; - - /** - * This method is used to retrieve all the scopes. - * - * @return List of scopes. - * @throws ScopeManagementException - */ - List getAllScopes() throws ScopeManagementException; - - /** - * This method is to retrieve the roles of the given scope - * @param scopeKey key of the scope - * @return List of roles - * @throws ScopeManagementException - */ - String getRolesOfScope(String scopeKey) throws ScopeManagementException; - - /** - * This method is to retrieve the scopes of the given role - * @param roleName key of the scope - * @return List of scopes - * @throws ScopeManagementException - */ - List getScopesOfRole(String roleName) throws ScopeManagementException; - - /** - * This method is used to remove the scopes of a given user role. - * - * @param roleName Role name - * @throws ScopeManagementException - */ - void removeScopes(String roleName) throws ScopeManagementException; - -} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/search/Condition.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/search/Condition.java index 2007a3f121..8483788e9d 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/search/Condition.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/search/Condition.java @@ -25,7 +25,7 @@ import io.swagger.annotations.ApiModelProperty; @ApiModel(value = "Condition", description = "Contains the advance search parameters.") public class Condition { - @ApiModelProperty(name = "conditions", value = "Provide the operation code. You can assign the following operation " + + @ApiModelProperty(name = "key", value = "Provide the operation code. You can assign the following operation " + "codes:\n" + "DEVICE_MODEL : The model of the device.\n" + "VENDOR : The name of the device vendor.\n" + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/spi/DeviceManagementService.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/spi/DeviceManagementService.java index 197275600e..7e6f730337 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/spi/DeviceManagementService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/spi/DeviceManagementService.java @@ -18,10 +18,7 @@ */ package org.wso2.carbon.device.mgt.common.spi; -import org.wso2.carbon.device.mgt.common.DeviceManagementException; -import org.wso2.carbon.device.mgt.common.DeviceManager; -import org.wso2.carbon.device.mgt.common.OperationMonitoringTaskConfig; -import org.wso2.carbon.device.mgt.common.ProvisioningConfig; +import org.wso2.carbon.device.mgt.common.*; import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManager; import org.wso2.carbon.device.mgt.common.policy.mgt.PolicyMonitoringManager; import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationConfig; @@ -48,4 +45,8 @@ public interface DeviceManagementService { PolicyMonitoringManager getPolicyMonitoringManager(); + InitialOperationConfig getInitialOperationConfig(); + + + } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/pom.xml b/components/device-mgt/org.wso2.carbon.device.mgt.core/pom.xml index a27d1bf143..e3155cd475 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/pom.xml +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.devicemgt device-mgt - 2.0.18-SNAPSHOT + 2.0.37-SNAPSHOT ../pom.xml @@ -77,7 +77,6 @@ org.wso2.carbon.identity.oauth.stub, org.wso2.carbon.identity.oauth.stub.dto, org.wso2.carbon.ndatasource.core, - org.wso2.carbon.apimgt.impl, org.wso2.carbon.ntask.core.*, org.wso2.carbon.ntask.common, org.apache.catalina, @@ -86,7 +85,8 @@ org.wso2.carbon.email.sender.*, io.swagger.annotations.*;resolution:=optional, org.wso2.carbon, - org.wso2.carbon.base + org.wso2.carbon.base, + org.scannotation.* !org.wso2.carbon.device.mgt.core.internal, @@ -94,7 +94,8 @@ javax.ws.rs-api, - scribe;scope=compile|runtime;inline=false; + scribe;scope=compile|runtime;inline=false, + javassist;inline=false * @@ -124,6 +125,10 @@ org.eclipse.osgi org.eclipse.osgi.services + + org.wso2.orbit.org.scannotation + scannotation + org.wso2.carbon.devicemgt org.wso2.carbon.device.mgt.common @@ -203,34 +208,6 @@ org.apache.ws.commons.axiom.wso2 axiom - - org.wso2.carbon.apimgt - org.wso2.carbon.apimgt.api - - - org.wso2.carbon.identity - org.wso2.carbon.user.mgt.stub - - - org.wso2.carbon.identity - org.wso2.carbon.user.mgt - - - - - org.wso2.carbon.apimgt - org.wso2.carbon.apimgt.impl - - - org.wso2.carbon.identity - org.wso2.carbon.user.mgt.stub - - - org.wso2.carbon.identity - org.wso2.carbon.user.mgt - - - org.apache.axis2.wso2 axis2 @@ -281,12 +258,6 @@ swagger-annotations provided - - - org.wso2.orbit.org.scannotation - scannotation - - org.wso2.carbon.devicemgt org.wso2.carbon.apimgt.annotations @@ -296,12 +267,14 @@ javax.ws.rs javax.ws.rs-api - javax.ws.rs jsr311-api - + + javassist + javassist + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/permission/AnnotationProcessor.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/permission/AnnotationProcessor.java index 52c59d753f..d6a6a84118 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/permission/AnnotationProcessor.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/permission/AnnotationProcessor.java @@ -19,11 +19,9 @@ package org.wso2.carbon.device.mgt.core.config.permission; import io.swagger.annotations.SwaggerDefinition; -import io.swagger.models.Swagger; import org.apache.catalina.core.StandardContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.wso2.carbon.apimgt.api.model.Scope; import org.wso2.carbon.device.mgt.common.permission.mgt.Permission; import javax.servlet.ServletContext; @@ -80,7 +78,6 @@ public class AnnotationProcessor { private Class pathClazz; private ClassLoader classLoader; private ServletContext servletContext; - private Swagger swagger; private Class apiClazz; private Class consumesClass; private Class producesClass; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/permission/ExtendedAnnotationDB.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/permission/ExtendedAnnotationDB.java index dbbd97e3a6..c4ba51d1f4 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/permission/ExtendedAnnotationDB.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/permission/ExtendedAnnotationDB.java @@ -30,11 +30,11 @@ public class ExtendedAnnotationDB extends AnnotationDB { } public void scanArchives(URL... urls) throws IOException { - URL[] arr$ = urls; - int len$ = urls.length; + URL[] arr = urls; + int len = urls.length; - for(int i$ = 0; i$ < len$; ++i$) { - URL url = arr$[i$]; + for(int i = 0; i < len; ++i) { + URL url = arr[i]; Filter filter = new Filter() { public boolean accepts(String filename) { if(filename.endsWith(".class")) { @@ -60,16 +60,16 @@ public class ExtendedAnnotationDB extends AnnotationDB { } private boolean ignoreScan(String intf) { - String[] arr$; - int len$; - int i$; + String[] arr; + int len; + int i; String ignored; if(this.scanPackages != null) { - arr$ = this.scanPackages; - len$ = arr$.length; + arr = this.scanPackages; + len = arr.length; - for(i$ = 0; i$ < len$; ++i$) { - ignored = arr$[i$]; + for(i = 0; i < len; ++i) { + ignored = arr[i]; if(intf.startsWith(ignored + ".")) { return false; } @@ -77,11 +77,11 @@ public class ExtendedAnnotationDB extends AnnotationDB { return true; } else { - arr$ = this.ignoredPackages; - len$ = arr$.length; + arr = this.ignoredPackages; + len = arr.length; - for(i$ = 0; i$ < len$; ++i$) { - ignored = arr$[i$]; + for(i = 0; i < len; ++i) { + ignored = arr[i]; if(intf.startsWith(ignored + ".")) { return true; } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/permission/Scope.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/permission/Scope.java new file mode 100644 index 0000000000..aab33dcccd --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/permission/Scope.java @@ -0,0 +1,70 @@ +/* +* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +* +* Licensed 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. +*/ +package org.wso2.carbon.device.mgt.core.config.permission; + +import java.io.Serializable; + +public class Scope implements Serializable { + String key; + String name; + String roles; + String description; + int id; + + public Scope() { + } + + public String getKey() { + return this.key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public String getRoles() { + return this.roles; + } + + public void setRoles(String roles) { + this.roles = roles; + } + + public String getDescription() { + return this.description; + } + + public void setDescription(String description) { + this.description = description; + } + + public int getId() { + return this.id; + } + + public void setId(int id) { + this.id = id; + } +} + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java index ffb9aacc1f..4e37aca000 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java @@ -83,7 +83,7 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO { try { conn = this.getConnection(); String sql = "UPDATE DM_DEVICE SET NAME = ?, DESCRIPTION = ?, LAST_UPDATED_TIMESTAMP = ? " + - "WHERE DEVICE_TYPE_ID = (SELECT ID FROM DM_DEVICE_TYPE WHERE NAME = ? AND PROVIDER_TENANT_ID = ?) " + + "WHERE DEVICE_TYPE_ID = (SELECT ID FROM DM_DEVICE_TYPE WHERE NAME = ? AND (PROVIDER_TENANT_ID = ? OR SHARED_WITH_ALL_TENANTS = ?)) " + "AND DEVICE_IDENTIFICATION = ? AND TENANT_ID = ?"; stmt = conn.prepareStatement(sql, new String[] {"id"}); stmt.setString(1, device.getName()); @@ -91,8 +91,9 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO { stmt.setTimestamp(3, new Timestamp(new Date().getTime())); stmt.setString(4, device.getType()); stmt.setInt(5, tenantId); - stmt.setString(6, device.getDeviceIdentifier()); - stmt.setInt(7, tenantId); + stmt.setBoolean(6, true); + stmt.setString(7, device.getDeviceIdentifier()); + stmt.setInt(8, tenantId); rows = stmt.executeUpdate(); return (rows > 0); } catch (SQLException e) { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementDataHolder.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementDataHolder.java index 0ca96ec4d2..f7e8e0a177 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementDataHolder.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementDataHolder.java @@ -18,7 +18,6 @@ package org.wso2.carbon.device.mgt.core.internal; -import org.wso2.carbon.apimgt.impl.APIManagerConfiguration; import org.wso2.carbon.device.mgt.common.OperationMonitoringTaskConfig; import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManager; import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService; @@ -63,17 +62,10 @@ public class DeviceManagementDataHolder { private Map map = new HashMap<>(); - - public void addToMap(OperationMonitoringTaskConfig taskConfig) { - this.map.put("aa", taskConfig); - } - public Map getMap(){ return this.map; } - private APIManagerConfiguration apiManagerConfiguration; - private DeviceManagementDataHolder() {} public static DeviceManagementDataHolder getInstance() { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementServiceComponent.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementServiceComponent.java index adbf6cda43..7930aab2b3 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementServiceComponent.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementServiceComponent.java @@ -21,7 +21,6 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.osgi.framework.BundleContext; import org.osgi.service.component.ComponentContext; -import org.wso2.carbon.apimgt.impl.APIManagerConfigurationService; import org.wso2.carbon.device.mgt.common.DeviceManagementException; import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManagementException; import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService; @@ -84,12 +83,6 @@ import java.util.List; * policy="dynamic" * bind="setRegistryService" * unbind="unsetRegistryService" - * @scr.reference name="api.manager.config.service" - * interface="org.wso2.carbon.apimgt.impl.APIManagerConfigurationService" - * cardinality="1..1" - * policy="dynamic" - * bind="setAPIManagerConfigurationService" - * unbind="unsetAPIManagerConfigurationService" * @scr.reference name="org.wso2.carbon.ndatasource" * interface="org.wso2.carbon.ndatasource.core.DataSourceService" * cardinality="1..1" @@ -355,14 +348,6 @@ public class DeviceManagementServiceComponent { DeviceManagementDataHolder.getInstance().setRegistryService(null); } - protected void setAPIManagerConfigurationService(APIManagerConfigurationService service) { - //do nothing - } - - protected void unsetAPIManagerConfigurationService(APIManagerConfigurationService service) { - //do nothing - } - protected void setDataSourceService(DataSourceService dataSourceService) { /* This is to avoid mobile device management component getting initialized before the underlying datasources are registered */ @@ -404,13 +389,13 @@ public class DeviceManagementServiceComponent { } - protected void setDeviceTaskManagerService(DeviceTaskManagerService emailSenderService) { + protected void setDeviceTaskManagerService(DeviceTaskManagerService deviceTaskManagerService) { if (log.isDebugEnabled()) { } - DeviceManagementDataHolder.getInstance().setDeviceTaskManagerService(emailSenderService); + DeviceManagementDataHolder.getInstance().setDeviceTaskManagerService(deviceTaskManagerService); } - protected void unsetDeviceTaskManagerService(DeviceTaskManagerService emailSenderService) { + protected void unsetDeviceTaskManagerService(DeviceTaskManagerService deviceTaskManagerService) { if (log.isDebugEnabled()) { } DeviceManagementDataHolder.getInstance().setDeviceTaskManagerService(null); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java index acf07ec207..a48cb423c8 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java @@ -317,5 +317,4 @@ public interface DeviceManagementProviderService { */ boolean changeDeviceStatus(DeviceIdentifier deviceIdentifier, EnrolmentInfo.Status newStatus) throws DeviceManagementException; - } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java index 3457a7227a..f89fe627c3 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java @@ -23,20 +23,7 @@ import org.apache.commons.logging.LogFactory; import org.wso2.carbon.CarbonConstants; import org.wso2.carbon.context.CarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext; -import org.wso2.carbon.device.mgt.common.Device; -import org.wso2.carbon.device.mgt.common.DeviceIdentifier; -import org.wso2.carbon.device.mgt.common.DeviceManagementException; -import org.wso2.carbon.device.mgt.common.DeviceManager; -import org.wso2.carbon.device.mgt.common.DeviceNotFoundException; -import org.wso2.carbon.device.mgt.common.DeviceTypeIdentifier; -import org.wso2.carbon.device.mgt.common.EnrolmentInfo; -import org.wso2.carbon.device.mgt.common.FeatureManager; -import org.wso2.carbon.device.mgt.common.InvalidDeviceException; -import org.wso2.carbon.device.mgt.common.MonitoringOperation; -import org.wso2.carbon.device.mgt.common.OperationMonitoringTaskConfig; -import org.wso2.carbon.device.mgt.common.PaginationRequest; -import org.wso2.carbon.device.mgt.common.PaginationResult; -import org.wso2.carbon.device.mgt.common.TransactionManagementException; +import org.wso2.carbon.device.mgt.common.*; import org.wso2.carbon.device.mgt.common.app.mgt.Application; import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration; import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo; @@ -66,6 +53,7 @@ import org.wso2.carbon.device.mgt.core.dto.DeviceType; import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder; import org.wso2.carbon.device.mgt.core.internal.DeviceManagementServiceComponent; import org.wso2.carbon.device.mgt.core.internal.PluginInitializationListener; +import org.wso2.carbon.device.mgt.core.operation.mgt.CommandOperation; import org.wso2.carbon.device.mgt.core.util.DeviceManagerUtil; import org.wso2.carbon.email.sender.core.ContentProviderInfo; import org.wso2.carbon.email.sender.core.EmailContext; @@ -257,6 +245,8 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv if (status) { addDeviceToGroups(deviceIdentifier, device.getEnrolmentInfo().getOwnership()); + addInitialOperations(deviceIdentifier, device.getType()); + } return status; } @@ -279,7 +269,9 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv DeviceManagementDAOFactory.beginTransaction(); Device currentDevice = deviceDAO.getDevice(deviceIdentifier, tenantId); device.setId(currentDevice.getId()); - device.getEnrolmentInfo().setId(currentDevice.getEnrolmentInfo().getId()); + if (device.getEnrolmentInfo().getId() == 0) { + device.getEnrolmentInfo().setId(currentDevice.getEnrolmentInfo().getId()); + } if (device.getName() == null) { device.setName(currentDevice.getName()); } @@ -315,7 +307,7 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv return enrolmentInfos; } - @Override + @Override public boolean disenrollDevice(DeviceIdentifier deviceId) throws DeviceManagementException { DeviceManager deviceManager = this.getDeviceManager(deviceId.getType()); if (deviceManager == null) { @@ -2084,6 +2076,37 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv } } + private void addInitialOperations(DeviceIdentifier deviceIdentifier, String deviceType) throws DeviceManagementException { + DeviceManagementProviderService deviceManagementProviderService = DeviceManagementDataHolder.getInstance(). + getDeviceManagementProvider(); + DeviceManagementService deviceManagementService = + pluginRepository.getDeviceManagementService(deviceType, this.getTenantId()); + InitialOperationConfig init = deviceManagementService.getInitialOperationConfig(); + List deviceIdentifiers = new ArrayList<>(); + deviceIdentifiers.add(deviceIdentifier); + if (init != null) { + List initialOperations = init.getOperations(); + + for (String str : initialOperations) { + CommandOperation operation = new CommandOperation(); + operation.setEnabled(true); + operation.setType(Operation.Type.COMMAND); + operation.setCode(str); + try { + deviceManagementProviderService. + addOperation(deviceType, + operation, deviceIdentifiers); + } catch (OperationManagementException e) { + throw new DeviceManagementException("Unable to find the device with the id: '" + deviceIdentifier.getId(), + e); + } catch (InvalidDeviceException e) { + throw new DeviceManagementException("Unable to find the device with the id: '" + deviceIdentifier.getId(), + e); + } + } + } + } + /** * Checks for the default group existence and create group based on device ownership * diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/task/impl/DeviceDetailsRetrieverTask.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/task/impl/DeviceDetailsRetrieverTask.java index 69e49b7874..6d1228563c 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/task/impl/DeviceDetailsRetrieverTask.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/task/impl/DeviceDetailsRetrieverTask.java @@ -54,7 +54,6 @@ public class DeviceDetailsRetrieverTask implements Task { @Override public void execute() { - if (log.isDebugEnabled()) { log.debug("Device details retrieving task started to run."); } @@ -73,4 +72,3 @@ public class DeviceDetailsRetrieverTask implements Task { } } - diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/TestDeviceManagementService.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/TestDeviceManagementService.java index e30cdf4389..d425133ce5 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/TestDeviceManagementService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/TestDeviceManagementService.java @@ -17,10 +17,7 @@ */ package org.wso2.carbon.device.mgt.core; -import org.wso2.carbon.device.mgt.common.DeviceManagementException; -import org.wso2.carbon.device.mgt.common.DeviceManager; -import org.wso2.carbon.device.mgt.common.OperationMonitoringTaskConfig; -import org.wso2.carbon.device.mgt.common.ProvisioningConfig; +import org.wso2.carbon.device.mgt.common.*; import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManager; import org.wso2.carbon.device.mgt.common.policy.mgt.PolicyMonitoringManager; import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationConfig; @@ -75,4 +72,9 @@ public class TestDeviceManagementService implements DeviceManagementService { return null; } + @Override + public InitialOperationConfig getInitialOperationConfig() { + return null; + } + } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.extensions/pom.xml b/components/device-mgt/org.wso2.carbon.device.mgt.extensions/pom.xml index 50387f2e8d..794c88e926 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.extensions/pom.xml +++ b/components/device-mgt/org.wso2.carbon.device.mgt.extensions/pom.xml @@ -22,7 +22,7 @@ device-mgt org.wso2.carbon.devicemgt - 2.0.18-SNAPSHOT + 2.0.37-SNAPSHOT ../pom.xml diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/pom.xml b/components/device-mgt/org.wso2.carbon.device.mgt.ui/pom.xml index 23a6b4e157..e1b634191b 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/pom.xml +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/pom.xml @@ -22,7 +22,7 @@ device-mgt org.wso2.carbon.devicemgt - 2.0.18-SNAPSHOT + 2.0.37-SNAPSHOT ../pom.xml 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 7087cdb976..d2beaa71a7 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 @@ -1,5 +1,5 @@ { - "appName": "CDMF", + "appName": "WSO2 Device Cloud", "cachingEnabled": false, "debuggingEnabled": false, "permissionRoot": "/", @@ -31,7 +31,7 @@ "issuer" : "devicemgt", "appName" : "devicemgt", "identityProviderUrl" : "https://%iot.keymanager.host%:%iot.keymanager.https.port%/samlsso", - "acs": "https://%iot.keymanager.host%:%iot.keymanager.https.port%/devicemgt/uuf/sso/acs", + "acs": "https://%iot.manager.host%:%iot.manager.https.port%/devicemgt/uuf/sso/acs", "identityAlias": "wso2carbon", "responseSigningEnabled" : true, "validateAssertionValidityPeriod": true, @@ -40,7 +40,6 @@ } }, "errorPages": { - "404": "cdmf.page.error-404", "default": "uuf.page.error" } } \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/config.json b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/config.json index 858aff57fe..5caf20f31f 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/config.json +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/config.json @@ -1,184 +1,185 @@ { - "appContext": "/devicemgt/", - "isCloud": false, - "httpsURL" : "https://%iot.gateway.host%:%iot.gateway.https.port%", - "httpURL" : "http://%iot.gateway.host%:%iot.gateway.http.port", - "wssURL" : "https://%iot.analytics.host%:%iot.analytics.https.port%", - "portalURL": "https://%iot.analytics.host%:%iot.analytics.https.port%", - "dashboardServerURL" : "%https.ip%", - "androidEnrollmentDir": "/android-web-agent/enrollment", - "windowsEnrollmentDir": "/windows-web-agent/enrollment", - "iOSEnrollmentDir": "/ios-web-agent/enrollment", - "iOSConfigRoot" : "%https.ip%/ios-enrollment/", - "iOSAPIRoot" : "%https.ip%/ios/", - "adminService": "%https.ip%", - "gatewayEnabled": true, - "oauthProvider": { - "appRegistration": { - "appType": "webapp", - "clientName": "emm", - "owner": "admin@carbon.super", - "dynamicClientAppRegistrationServiceURL": "%https.ip%/dynamic-client-web/register", - "apiManagerClientAppRegistrationServiceURL": "https://%iot.gateway.host%:%iot.gateway.https.port%/api-application-registration/register/tenants", - "grantType": "password refresh_token urn:ietf:params:oauth:grant-type:saml2-bearer urn:ietf:params:oauth:grant-type:jwt-bearer", - "tokenScope": "admin", - "callbackUrl": "%https.ip%/api/device-mgt/v1.0" - }, - "tokenServiceURL": "https://%iot.gateway.host%:%iot.gateway.https.port%/token" + "appContext": "/devicemgt/", + "isCloud": false, + "httpsURL": "https://%iot.gateway.host%:%iot.gateway.https.port%", + "httpURL": "http://%iot.gateway.host%:%iot.gateway.http.port", + "wssURL": "https://%iot.analytics.host%:%iot.analytics.https.port%", + "portalURL": "https://%iot.analytics.host%:%iot.analytics.https.port%", + "dashboardServerURL": "%https.ip%", + "androidEnrollmentDir": "/android-web-agent/enrollment", + "windowsEnrollmentDir": "/windows-web-agent/enrollment", + "iOSEnrollmentDir": "/ios-web-agent/enrollment", + "iOSConfigRoot": "%https.ip%/ios-enrollment/", + "iOSAPIRoot": "%https.ip%/ios/", + "adminService": "%https.ip%", + "gatewayEnabled": true, + "oauthProvider": { + "appRegistration": { + "appType": "webapp", + "clientName": "iot_ui", + "owner": "admin@carbon.super", + "dynamicClientAppRegistrationServiceURL": "%https.ip%/dynamic-client-web/register", + "apiManagerClientAppRegistrationServiceURL": "https://%iot.gateway.host%:%iot.gateway.https.port%/api-application-registration/register/tenants", + "grantType": "password refresh_token urn:ietf:params:oauth:grant-type:saml2-bearer urn:ietf:params:oauth:grant-type:jwt-bearer", + "tokenScope": "admin", + "callbackUrl": "%https.ip%/api/device-mgt/v1.0", + "samlGrantTypeName": "urn:ietf:params:oauth:grant-type:saml2-bearer" }, - "adminUser":"admin@carbon.super", - "adminUserTenantId":"-1234", - "adminRole":"admin", - "userValidationConfig" : { - "usernameLength":30, - "usernameJSRegEx" : "^[\\S]{3,30}$", - "usernameRegExViolationErrorMsg" : "Provided username is invalid.", - "usernameHelpMsg" : "Should be in minimum 3 characters long and do not include any whitespaces.", - "firstnameJSRegEx" : "^.{3,30}$", - "firstnameRegExViolationErrorMsg" : "Provided first name is invalid.", - "lastnameJSRegEx" : "^.{3,30}$", - "lastnameRegExViolationErrorMsg" : "Provided last name is invalid.", - "emailJSRegEx" : "/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/", - "emailRegExViolationErrorMsg" : "Provided email is invalid." - }, - "groupValidationConfig": { - "groupNameJSRegEx": "^[\\S]{3,30}$", - "groupNameRegExViolationErrorMsg": "Provided group name is invalid.", - "groupNameHelpMsg": "Should be in minimum 3 characters long and should not include any whitespaces." - }, - "roleValidationConfig" : { - "roleNameJSRegEx" : "^[\\S]{3,30}$", - "roleNameRegExViolationErrorMsg" : "Provided role name is invalid.", - "roleNameHelpMsg" : "should be in minimum 3 characters long and do not include any whitespaces." - }, - "generalConfig" : { - "host" : "%http.ip%", - "companyName" : "WSO2 Carbon Device Manager", - "browserTitle" : "WSO2 Device Manager", - "copyrightPrefix" : "\u00A9 %date-year%, ", - "copyrightOwner" : "WSO2 Inc.", - "copyrightOwnersSite" : "http://www.wso2.org", - "copyrightSuffix" : " All Rights Reserved." - }, - "scopes" : [ - "perm:sign-csr", - "perm:admin:devices:view", - "perm:roles:add", - "perm:roles:add-users", - "perm:roles:update", - "perm:roles:permissions", - "perm:roles:details", - "perm:roles:view", - "perm:roles:create-combined-role", - "perm:roles:delete", - "perm:dashboard:vulnerabilities", - "perm:dashboard:non-compliant-count", - "perm:dashboard:non-compliant", - "perm:dashboard:by-groups", - "perm:dashboard:device-counts", - "perm:dashboard:feature-non-compliant", - "perm:dashboard:count-overview", - "perm:dashboard:filtered-count", - "perm:dashboard:details", - "perm:get-activity", - "perm:devices:delete", - "perm:devices:applications", - "perm:devices:change-status", - "perm:devices:effective-policy", - "perm:devices:compliance-data", - "perm:devices:features", - "perm:devices:operations", - "perm:devices:search", - "perm:devices:details", - "perm:devices:update", - "perm:devices:view", - "perm:view-configuration", - "perm:manage-configuration", - "perm:policies:remove", - "perm:policies:priorities", - "perm:policies:deactivate", - "perm:policies:get-policy-details", - "perm:policies:manage", - "perm:policies:activate", - "perm:policies:update", - "perm:policies:changes", - "perm:policies:get-details", - "perm:users:add", - "perm:users:details", - "perm:users:count", - "perm:users:delete", - "perm:users:roles", - "perm:users:user-details", - "perm:users:credentials", - "perm:users:search", - "perm:users:is-exist", - "perm:users:update", - "perm:users:send-invitation", - "perm:admin-users:view", - "perm:groups:devices", - "perm:groups:update", - "perm:groups:add", - "perm:groups:device", - "perm:groups:devices-count", - "perm:groups:remove", - "perm:groups:groups", - "perm:groups:groups-view", - "perm:groups:share", - "perm:groups:count", - "perm:groups:roles", - "perm:groups:devices-remove", - "perm:groups:devices-add", - "perm:groups:assign", - "perm:device-types:features", - "perm:device-types:types", - "perm:applications:install", - "perm:applications:uninstall", - "perm:admin-groups:count", - "perm:admin-groups:view", - "perm:notifications:mark-checked", - "perm:notifications:view", - "perm:admin:certificates:delete", - "perm:admin:certificates:details", - "perm:admin:certificates:view", - "perm:admin:certificates:add", - "perm:admin:certificates:verify", - "perm:ios:enroll", - "perm:ios:view-device", - "perm:ios:apn", - "perm:ios:ldap", - "perm:ios:enterprise-app", - "perm:ios:store-application", - "perm:ios:remove-application", - "perm:ios:app-list", - "perm:ios:profile-list", - "perm:ios:lock", - "perm:ios:enterprise-wipe", - "perm:ios:device-info", - "perm:ios:restriction", - "perm:ios:email", - "perm:ios:cellular", - "perm:ios:applications", - "perm:ios:wifi", - "perm:ios:ring", - "perm:ios:location", - "perm:ios:notification", - "perm:ios:airplay", - "perm:ios:caldav", - "perm:ios:cal-subscription", - "perm:ios:passcode-policy", - "perm:ios:webclip", - "perm:ios:vpn", - "perm:ios:per-app-vpn", - "perm:ios:app-to-per-app-vpn", - "perm:ios:app-lock", - "perm:ios:clear-passcode", - "perm:ios:remove-profile", - "perm:ios:get-restrictions", - "perm:ios:wipe-data", - "perm:admin" - ], - "isOAuthEnabled" : true, - "backendRestEndpoints" : { - "deviceMgt" : "/api/device-mgt/v1.0" - } -} \ No newline at end of file + "tokenServiceURL": "https://%iot.gateway.host%:%iot.gateway.https.port%/token" + }, + "adminUser": "admin@carbon.super", + "adminUserTenantId": "-1234", + "adminRole": "admin", + "userValidationConfig": { + "usernameLength": 30, + "usernameJSRegEx": "^[\\S]{3,30}$", + "usernameRegExViolationErrorMsg": "Provided username is invalid.", + "usernameHelpMsg": "Should be in minimum 3 characters long and do not include any whitespaces.", + "firstnameJSRegEx": "^.{3,30}$", + "firstnameRegExViolationErrorMsg": "Provided first name is invalid.", + "lastnameJSRegEx": "^.{3,30}$", + "lastnameRegExViolationErrorMsg": "Provided last name is invalid.", + "emailJSRegEx": "/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/", + "emailRegExViolationErrorMsg": "Provided email is invalid." + }, + "groupValidationConfig": { + "groupNameJSRegEx": "^[\\S]{3,30}$", + "groupNameRegExViolationErrorMsg": "Provided group name is invalid.", + "groupNameHelpMsg": "Should be in minimum 3 characters long and should not include any whitespaces." + }, + "roleValidationConfig": { + "roleNameJSRegEx": "^[\\S]{3,30}$", + "roleNameRegExViolationErrorMsg": "Provided role name is invalid.", + "roleNameHelpMsg": "should be in minimum 3 characters long and do not include any whitespaces." + }, + "generalConfig": { + "host": "%http.ip%", + "companyName": "WSO2 Carbon Device Manager", + "browserTitle": "WSO2 Device Manager", + "copyrightPrefix": "\u00A9 %date-year%, ", + "copyrightOwner": "WSO2 Inc.", + "copyrightOwnersSite": "http://www.wso2.org", + "copyrightSuffix": " All Rights Reserved." + }, + "scopes": [ + "perm:sign-csr", + "perm:admin:devices:view", + "perm:roles:add", + "perm:roles:add-users", + "perm:roles:update", + "perm:roles:permissions", + "perm:roles:details", + "perm:roles:view", + "perm:roles:create-combined-role", + "perm:roles:delete", + "perm:dashboard:vulnerabilities", + "perm:dashboard:non-compliant-count", + "perm:dashboard:non-compliant", + "perm:dashboard:by-groups", + "perm:dashboard:device-counts", + "perm:dashboard:feature-non-compliant", + "perm:dashboard:count-overview", + "perm:dashboard:filtered-count", + "perm:dashboard:details", + "perm:get-activity", + "perm:devices:delete", + "perm:devices:applications", + "perm:devices:effective-policy", + "perm:devices:compliance-data", + "perm:devices:features", + "perm:devices:operations", + "perm:devices:search", + "perm:devices:details", + "perm:devices:update", + "perm:devices:view", + "perm:view-configuration", + "perm:manage-configuration", + "perm:policies:remove", + "perm:policies:priorities", + "perm:policies:deactivate", + "perm:policies:get-policy-details", + "perm:policies:manage", + "perm:policies:activate", + "perm:policies:update", + "perm:policies:changes", + "perm:policies:get-details", + "perm:users:add", + "perm:users:details", + "perm:users:count", + "perm:users:delete", + "perm:users:roles", + "perm:users:user-details", + "perm:users:credentials", + "perm:users:search", + "perm:users:is-exist", + "perm:users:update", + "perm:users:send-invitation", + "perm:admin-users:view", + "perm:groups:devices", + "perm:groups:update", + "perm:groups:add", + "perm:groups:device", + "perm:groups:devices-count", + "perm:groups:remove", + "perm:groups:groups", + "perm:groups:groups-view", + "perm:groups:share", + "perm:groups:count", + "perm:groups:roles", + "perm:groups:devices-remove", + "perm:groups:devices-add", + "perm:groups:assign", + "perm:device-types:features", + "perm:device-types:types", + "perm:applications:install", + "perm:applications:uninstall", + "perm:admin-groups:count", + "perm:admin-groups:view", + "perm:notifications:mark-checked", + "perm:notifications:view", + "perm:admin:certificates:delete", + "perm:admin:certificates:details", + "perm:admin:certificates:view", + "perm:admin:certificates:add", + "perm:admin:certificates:verify", + "perm:ios:enroll", + "perm:ios:view-device", + "perm:ios:apn", + "perm:ios:ldap", + "perm:ios:enterprise-app", + "perm:ios:store-application", + "perm:ios:remove-application", + "perm:ios:app-list", + "perm:ios:profile-list", + "perm:ios:lock", + "perm:ios:enterprise-wipe", + "perm:ios:device-info", + "perm:ios:restriction", + "perm:ios:email", + "perm:ios:cellular", + "perm:ios:applications", + "perm:ios:wifi", + "perm:ios:ring", + "perm:ios:location", + "perm:ios:notification", + "perm:ios:airplay", + "perm:ios:caldav", + "perm:ios:cal-subscription", + "perm:ios:passcode-policy", + "perm:ios:webclip", + "perm:ios:vpn", + "perm:ios:per-app-vpn", + "perm:ios:app-to-per-app-vpn", + "perm:ios:app-lock", + "perm:ios:clear-passcode", + "perm:ios:remove-profile", + "perm:ios:get-restrictions", + "perm:ios:wipe-data", + "perm:admin", + "perm:devicetype:deployment" + ], + "isOAuthEnabled": true, + "backendRestEndpoints": { + "deviceMgt": "/api/device-mgt/v1.0" + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/toplink-menu.json b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/toplink-menu.json new file mode 100644 index 0000000000..ae866dd37c --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/toplink-menu.json @@ -0,0 +1,198 @@ +{ + "Logo": { + "name": "Cloud", + "url": "https://<%= @cloudmgt_host %>/cloudmgt", + "target": "_parent" + }, + "Main": { + "Domain": { + "url": "#", + "icon": "fw fw-organization", + "isAdminOnly": false, + "target": "_parent", + "dropDown": { + "Organization": { + "url": "https://<%= @cloudmgt_host %>/cloudmgt/site/pages/organization.jag", + "icon": "fw fw-organization", + "dropDown": "false", + "target": "_self" + }, + "Members": { + "url": "https://<%= @cloudmgt_host %>/cloudmgt/site/pages/user.jag", + "icon": "fa fa-users", + "dropDown": "false", + "target": "_self" + } + } + }, + "Account": { + "url": "https://<%= @cloudmgt_host %>/cloudmgt/site/pages/account-summary.jag", + "icon": "fw fw-resource", + "isAdminOnly": true, + "target": "_blank", + "dropDown": { + "Upgrade Now": { + "url": "https://<%= @cloudmgt_host %>/cloudmgt/site/pages/payment-plans.jag?cloud-type=api_cloud", + "icon": "fw fw-export", + "target": "_self" + }, + "Monetization": { + "url": "https://<%= @cloudmgt_host %>/cloudmgt/site/pages/monetization-dashboard.jag", + "icon": "fa fa-money fa-lg", + "dropDown": "false", + "target": "_self" + }, + "Request Extension": { + "url": "https://<%= @cloudmgt_host %>/cloudmgt/site/pages/contact-us.jag?cloud-type=api_cloud&request-extension=true", + "icon": "fw fw-mail", + "target": "_blank" + }, + "Usage data": { + "url": "https://<%= @cloudmgt_host %>/cloudmgt/site/pages/tenant-usage.jag?cloud-type=api_cloud", + "icon": "fw fw-bar-chart", + "target": "_self" + } + } + }, + "Configure": { + "url": "none", + "icon": "fw fw-settings", + "isAdminOnly": true, + "dropDown": { + "Admin Dashboard": { + "id": "admin-dashboard", + "url": "https://<%= @apimpublisher_host %>/admin-dashboard/", + "icon": "fw fw-user", + "target": "_self" + }, + "Custom URL": { + "id": "custom-url", + "url": "https://<%= @cloudmgt_host %>/cloudmgt/site/pages/custom_url.jag", + "icon": "fw fw-uri", + "target": "_self" + }, + "API Store Access": { + "id": "custom-url", + "url": "https://<%= @cloudmgt_host %>/cloudmgt/site/pages/selfSignup.jag", + "icon": "fw fw-store", + "target": "_self" + } + } + }, + "Support": { + "url": "https://<%= @cloudmgt_host %>/cloudmgt/site/pages/contact-us.jag", + "icon": "fw fw-mail", + "isAdminOnly": false, + "target": "_self", + "dropDown": "false" + }, + "Documentation": { + "url": "#", + "icon": "fw fw-document", + "isAdminOnly": false, + "dropDown": { + "API Cloud": { + "id": "api_cloud", + "url": "https://docs.wso2.com/display/APICloud/WSO2+API+Cloud+Documentation", + "icon": "fw fw-api", + "target": "_blank" + }, + "Integration Cloud": { + "id": "integration_cloud", + "url": "https://docs.wso2.com/display/IntegrationCloud/WSO2+Integration+Cloud+Documentation", + "icon": "fw fw-application", + "target": "_blank" + }, + "Device Cloud": { + "id": "device_cloud", + "url": "https://docs.wso2.com/display/DeviceCloud/WSO2+Device+Cloud+Documentation", + "icon": "fw fw-mobile", + "target": "_self" + }, + "API Cloud Walkthrough": { + "id": "api_cloud_walkthrough", + "url": "https://<%= @apimpublisher_host %>/publisher?interactiveTutorial=true", + "icon": "fw fw-document", + "target": "_self" + } + } + } + }, + "User": { + "url": "#", + "icon": "fw fw-user", + "dropDown": { + "Profile": { + "url": "https://<%= @cloudmgt_host %>/cloudmgt/site/pages/user-profile.jag", + "icon": "fw fw-user", + "dropDown": "true", + "target": "_self" + }, + "Change Password": { + "url": "https://<%= @cloudmgt_host %>/cloudmgt/site/pages/change-password.jag", + "icon": "fw fw-lock", + "dropDown": "true", + "target": "_self" + }, + "Logout": { + "url": "https://<%= @apimpublisher_host %>/publisher/site/pages/logout.jag", + "icon": "fw fw-sign-out", + "dropDown": "true", + "target": "_self" + } + } + }, + "Expand": { + "Clouds": { + "API Cloud": { + "id": "api_cloud", + "url": "https://<%= @apimpublisher_host %>/publisher", + "icon": "fw fw-api fw-3x", + "dropDown": "true", + "target": "_self" + }, + "Integration Cloud": { + "id": "integration_cloud", + "url": "https://milestones.appfactory.wso2.com:9443/appmgt", + "icon": "fa fa-cubes fw-3x", + "dropDown": "true", + "target": "_self" + }, + "Identity Cloud": { + "id": "integration_cloud", + "url": "https://identity.cloudlocal.wso2.com:9443/admin", + "icon": "fw fw-security fw-3x", + "dropDown": "true", + "target": "_self" + }, + "App Cloud": { + "id": "app_cloud", + "url": "https://<%= @appcloud_host %>/appmgt", + "icon": "fw fw-application fw-3x", + "dropDown": "true", + "target": "_self" + }, + "Device Cloud": { + "id": "device_cloud", + "url": "https://<%= @mgt_hostname %>/devicemgt", + "icon": "fw fw-mobile fw-3x", + "dropDown": "true", + "target": "_self" + } + }, + "Actions": { + "Organization": { + "url": "https://<%= @cloudmgt_host %>/cloudmgt/site/pages/organization.jag", + "icon": "fw fw-organization fw-3x", + "dropDown": "true", + "target": "_self" + }, + "Members": { + "url": "https://<%= @cloudmgt_host %>/cloudmgt/site/pages/user.jag", + "icon": "fa fa-users fw-3x", + "dropDown": "true", + "target": "_self" + } + } + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/layouts/cdmf.layout.error.hbs b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/layouts/cdmf.layout.error.hbs new file mode 100644 index 0000000000..d14f195c32 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/layouts/cdmf.layout.error.hbs @@ -0,0 +1,48 @@ +{{!-- 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 "title"}} + + + +
+
+
+ +
+
+

{{#defineZone "messageTitle"}}Oops something went wrong{{/defineZone}}

+

{{defineZone "messageDescription"}}

+
+ +
+
+ +
+
+
+
+ + \ 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/business-controllers/device.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/business-controllers/device.js index 68fa4630d7..0138c57897 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/business-controllers/device.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/business-controllers/device.js @@ -98,6 +98,26 @@ deviceModule = function () { locationTimeData.push(gpsReadingTimes); } } + var locationInfo = {}; + try { + var url = devicemgtProps["httpsURL"] + "/api/device-mgt/v1.0/devices/" + deviceType + "/" + deviceId + "/location"; + serviceInvokers.XMLHttp.get( + url, + function (backendResponse) { + + if (backendResponse.status == 200 && backendResponse.responseText) { + var device = parse(backendResponse.responseText); + locationInfo.latitude = device.latitude; + locationInfo.longitude = device.longitude; + locationInfo.updatedOn = device.updatedTime; + + } + }); + } catch (e) { + log.error(e.message, e); + } + + var utility = require('/app/modules/utility.js')["utility"]; try { utility.startTenantFlow(carbonUser); @@ -174,11 +194,26 @@ deviceModule = function () { } if (device["deviceInfo"]) { filteredDeviceData["latestDeviceInfo"] = device["deviceInfo"]; + + //location related verification and modifications + // adding the location histry for the movement path. + var locationHistory = {}; + locationHistory.locations = locationData; + locationHistory.times = locationTimeData; + filteredDeviceData["locationHistory"] = locationHistory; + + //checking for the latest location information. + if (filteredDeviceData.latestDeviceInfo.location && locationInfo) { + var infoDate = new Date(filteredDeviceData.latestDeviceInfo.location.updatedTime); + var locationDate = new Date(locationInfo.updatedOn); + if (infoDate < locationDate) { + filteredDeviceData.latestDeviceInfo.location.longitude = locationInfo.longitude; + filteredDeviceData.latestDeviceInfo.location.latitude = locationInfo.latitude; + } + } } - var locationHistory = {}; - locationHistory.locations = locationData; - locationHistory.times = locationTimeData; - filteredDeviceData["locationHistory"] = locationHistory; + + response["content"] = filteredDeviceData; response["status"] = "success"; return response; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/business-controllers/group.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/business-controllers/group.js index a7727ccea5..82ecb1ae3d 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/business-controllers/group.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/business-controllers/group.js @@ -48,7 +48,7 @@ var groupModule = {}; } return serviceInvokers.XMLHttp.get( endPoint, function (responsePayload) { - return responsePayload["responseText"]; + return parse(responsePayload["responseText"]); }, function (responsePayload) { log.error(responsePayload["responseText"]); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/business-controllers/operation.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/business-controllers/operation.js index 127a0df064..dd200cdfbe 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/business-controllers/operation.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/business-controllers/operation.js @@ -51,6 +51,16 @@ var operationModule = function () { feature["contentType"] = features[i].contentType; feature["deviceType"] = deviceType; feature["params"] = []; + var featuresEntry = utility.getDeviceTypeConfig(deviceType)["deviceType"]["features"]; + if (featuresEntry) { + var featureEntry = featuresEntry[features[i].code]; + if (featureEntry) { + var permissionEntry = featureEntry["permission"]; + if (permissionEntry) { + feature["permission"] = permissionEntry + } + } + } var metaData = features[i].metadataEntries; if (metaData) { for (var j = 0; j < metaData.length; j++) { @@ -71,21 +81,11 @@ var operationModule = function () { publicMethods.getControlOperations = function (deviceType) { var operations = privateMethods.getOperationsFromFeatures(deviceType, "operation"); - var features = utility.getDeviceTypeConfig(deviceType).deviceType.features; for (var op in operations) { var iconIdentifier = operations[op].operation; - if (features && features[iconIdentifier]) { - var icon = features[iconIdentifier].icon; - if (icon) { - operations[op]["iconFont"] = icon; - } else if (iconPath) { - var iconPath = utility.getOperationIcon(deviceType, iconIdentifier); - operations[op]["icon"] = iconPath; - } - var formParams = features[iconIdentifier].formParams; - if (formParams) { - operations[op]["uiParams"] = formParams; - } + var icon = utility.getOperationIcon(deviceType, iconIdentifier); + if (icon) { + operations[op]["icon"] = icon; } } return operations; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/business-controllers/user.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/business-controllers/user.js index 931625def3..e85f46c347 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/business-controllers/user.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/business-controllers/user.js @@ -174,7 +174,7 @@ var userModule = function () { } try { utility.startTenantFlow(carbonUser); - var url = devicemgtProps["httpsURL"] + devicemgtProps["backendRestEndpoints"]["deviceMgt"] + "/users?offset=0&limit=1"; + var url = devicemgtProps["httpsURL"] + devicemgtProps["backendRestEndpoints"]["deviceMgt"] + "/users/count"; return serviceInvokers.XMLHttp.get( url, function (responsePayload) { return parse(responsePayload["responseText"])["count"]; @@ -302,6 +302,32 @@ var userModule = function () { } }; + /** + * Get User Roles from user store (Internal roles not included). + */ + publicMethods.getFilteredRoles = function (prefix) { + var carbonUser = session.get(constants["USER_SESSION_KEY"]); + var utility = require("/app/modules/utility.js")["utility"]; + if (!carbonUser) { + log.error("User object was not found in the session"); + throw constants["ERRORS"]["USER_NOT_FOUND"]; + } + try { + utility.startTenantFlow(carbonUser); + var url = devicemgtProps["httpsURL"] + devicemgtProps["backendRestEndpoints"]["deviceMgt"] + + "/roles/filter/" + prefix + "?offset=0&limit=100&user-store=all"; + var response = privateMethods.callBackend(url, constants["HTTP_GET"]); + if (response.status == "success") { + response.content = parse(response.content); + } + return response; + } catch (e) { + throw e; + } finally { + utility.endTenantFlow(); + } + }; + /** * Get User Roles count from user store (Internal roles not included). */ @@ -463,7 +489,13 @@ var userModule = function () { publicMethods.isAuthorized = function (permission) { var carbon = require("carbon"); var carbonServer = application.get("carbonServer"); - var carbonUser = session.get(constants.USER_SESSION_KEY); + var carbonUser; + try { + carbonUser = session.get(constants.USER_SESSION_KEY); + } catch (e) { + log.error("User object was not found in the session"); + carbonUser = null; + } var utility = require('/app/modules/utility.js').utility; if (!carbonUser) { log.error("User object was not found in the session"); @@ -505,7 +537,7 @@ var userModule = function () { permissions["LIST_DEVICES"] = true; permissions["LIST_OWN_DEVICES"] = true; } - if (publicMethods.isAuthorized("/permission/admin/device-mgt/devices/owning-device")) { + if (publicMethods.isAuthorized("/permission/admin/device-mgt/devices/owning-device/view")) { permissions["LIST_OWN_DEVICES"] = true; } if (publicMethods.isAuthorized("/permission/admin/device-mgt/admin/groups/view")) { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/conf-reader/cloud.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/conf-reader/cloud.js new file mode 100644 index 0000000000..ec1487a685 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/conf-reader/cloud.js @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2017, 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. + */ + +var conf = function () { + var cloudConf = application.get("CLOUD_CONF"); + if (!cloudConf) { + cloudConf = require("/app/conf/toplink-menu.json"); + var pinch = require("/app/modules/conf-reader/pinch.min.js")["pinch"]; + var server = require("carbon")["server"]; + var process = require("process"); + pinch(cloudConf, /^/, + function (path, key, value) { + if ((typeof value === "string") && value.indexOf("%https.ip%") > -1) { + //noinspection JSUnresolvedFunction + return value.replace("%https.ip%", server.address("https")); + } else if ((typeof value === "string") && value.indexOf("%http.ip%") > -1) { + //noinspection JSUnresolvedFunction + return value.replace("%http.ip%", server.address("http")); + } else if ((typeof value === "string") && value.indexOf("%date-year%") > -1) { + var year = new Date().getFullYear(); + return value.replace("%date-year%", year); + } else if ((typeof value === "string") && value.indexOf("%server.ip%") > -1) { + var getProperty = require("process").getProperty; + return value.replace("%server.ip%", getProperty("carbon.local.ip")); + } else { + var paramPattern = new RegExp("%(.*?)%", "g"); + var out = value; + while ((matches = paramPattern.exec(value)) !== null) { + // This is necessary to avoid infinite loops with zero-width matches + if (matches.index === paramPattern.lastIndex) { + paramPattern.lastIndex++; + } + if (matches.length == 2) { + var property = process.getProperty(matches[1]); + if (property) { + out = out.replace(new RegExp("%" + matches[1] + "%", "g"), property); + } + } + } + return out; + } + } + ); + application.put("CLOUD_CONF", cloudConf); + } + return cloudConf; +}(); \ 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/init.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/init.js index 50cbba4dca..f6ee8587ec 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/init.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/init.js @@ -30,11 +30,17 @@ application.put("carbonServer", carbonServer); var permissions = { "/permission/admin/Login": ["ui.execute"], - "/permission/admin/manage/api/subscribe": ["ui.execute"] + "/permission/admin/device-mgt/device/api/subscribe": ["ui.execute"], + "/permission/admin/device-mgt/devices/enroll": ["ui.execute"], + "/permission/admin/device-mgt/devices/disenroll": ["ui.execute"], + "/permission/admin/device-mgt/devices/owning-device/view": ["ui.execute"], + "/permission/admin/manage/portal": ["ui.execute"] }; var adminPermissions = { - "/permission/admin": ["ui.execute"] + "/permission/admin/device-mgt": ["ui.execute"], + "/permission/admin/manage/api": ["ui.execute"], + "/permission/admin/manage/portal": ["ui.execute"] }; //On Startup, admin user will get both roles: devicemgt-admin and devicemgt-user 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 d36e7af0ab..166859f89b 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 @@ -26,7 +26,11 @@ var onFail; var utility = require("/app/modules/utility.js").utility; var apiWrapperUtil = require("/app/modules/oauth/token-handlers.js")["handlers"]; 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); + /** + * Since the user can be verified using the sso.client.js we can use JWT grant type to issue the token for the user. + */ + apiWrapperUtil.setupTokenPairByJWTGrantType(context.user.username + '@' + context.user.domain, context.input.samlToken); } else { apiWrapperUtil.setupTokenPairByPasswordGrantType(context.input.username, context.input.password); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/oauth/token-handler-utils.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/oauth/token-handler-utils.js index 81cdc1729b..109e67f7ac 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/oauth/token-handler-utils.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/oauth/token-handler-utils.js @@ -22,6 +22,7 @@ var utils = function () { var deviceMgtProps = require("/app/modules/conf-reader/main.js")["conf"]; var constants = require("/app/modules/constants.js"); var carbon = require("carbon"); + var authModule = require("/lib/modules/auth/auth.js").module; //noinspection JSUnresolvedVariable var Base64 = Packages.org.apache.commons.codec.binary.Base64; @@ -108,7 +109,8 @@ var utils = function () { var jwtToken = publicMethods.getJwtToken(adminUsername, claims); // register a tenant based client app at API Manager - var applicationName = "webapp_" + tenantDomain; + var applicationName = deviceMgtProps["oauthProvider"]["appRegistration"] + ["clientName"] + "_" + tenantDomain; var requestURL = deviceMgtProps["oauthProvider"]["appRegistration"] ["apiManagerClientAppRegistrationServiceURL"] + "?tenantDomain=" + tenantDomain + "&applicationName=" + applicationName; @@ -274,59 +276,34 @@ var utils = function () { } }; - publicMethods["getTokenPairAndScopesBySAMLGrantType"] = function (assertion, encodedClientAppCredentials, scopes) { - if (!assertion || !encodedClientAppCredentials || !scopes) { - log.error("{/app/modules/oauth/token-handler-utils.js} Error in retrieving access token by saml " + - "grant type. No assertion, encoded client app credentials or scopes are " + - "found - getTokenPairAndScopesBySAMLGrantType(x, y, z)"); - return null; - } else { - var assertionXML = publicMethods.decode(assertion); - /* - TODO: make assertion extraction with proper parsing. - Since Jaggery XML parser seem to add formatting which causes signature verification to fail. - */ - var assertionStartMarker = "/g, ">") - .replace(/\\u0027/g, "'") - .replace(/'/g, "'") - .replace(/\\"/g, """) - .replace(/\\u0022/g, """) + if (text) { + return text + .replace(/\\u003c/g, "<") + .replace(//g, ">") + .replace(/\\u0027/g, "'") + .replace(/'/g, "'") + .replace(/\\"/g, """) + .replace(/\\u0022/g, """); + } else { + return ""; + } }; return publicMethods; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.dashboard/dashboard.hbs b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.dashboard/dashboard.hbs index 1ed9f22d3e..f526cc03a3 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.dashboard/dashboard.hbs +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.dashboard/dashboard.hbs @@ -35,18 +35,18 @@
@@ -97,7 +99,7 @@
{{userCount}} - + {{#if userCount}} @@ -108,14 +110,16 @@ View {{/if}} - - + + {{#unless isCloud}} + Add + {{/unless}}
@@ -128,7 +132,7 @@
{{policyCount}} - + {{#if policyCount}} @@ -139,14 +143,16 @@ View {{/if}} - - + + + Add +
@@ -171,13 +177,15 @@ {{/if}} - + {{#unless isCloud}} + Add + {{/unless}} @@ -189,4 +197,4 @@ {{/if}} -{{/zone}} \ No newline at end of file +{{/zone}} 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 35a4eb0c05..1d2d7c8607 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 @@ -39,7 +39,11 @@ function onRequest() { viewModel.groupCount = groupModule.getGroupCount(); viewModel.userCount = userModule.getUsersCount(); viewModel.policyCount = policyModule.getPoliciesCount(); - viewModel.roleCount = userModule.getRolesCount(); - + viewModel.isCloud = devicemgtProps.isCloud; + if (devicemgtProps.isCloud) { + viewModel.roleCount = userModule.getFilteredRoles("devicemgt").content.count; + } else { + viewModel.roleCount = userModule.getRolesCount(); + } return viewModel; } \ 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.device.search/public/js/bottomJs.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.device.search/public/js/bottomJs.js index 68a4292ea8..66c1719052 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.device.search/public/js/bottomJs.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.device.search/public/js/bottomJs.js @@ -44,7 +44,7 @@ var dynamicForm = ' @@ -149,7 +151,6 @@ - diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.devices/devices.hbs b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.devices/devices.hbs index b5f0f93954..bdd2e9d39b 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.devices/devices.hbs +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.devices/devices.hbs @@ -57,7 +57,7 @@ Assign from My Devices -
  • + {{else}} {{#if permissions.enroll}}
  • @@ -91,7 +91,8 @@
    - +
    @@ -139,7 +140,7 @@ {{unit "cdmf.unit.device.operation-mod"}} {{#if deviceCount}}
    - + Loading devices . . .
    @@ -214,11 +215,11 @@ -
    +
    -
    +
  • {{/if}} + + {{#unless isCloud}} {{#if permissions.VIEW_DASHBOARD}}
  • - + Device Statistics +
  • {{/if}} + {{/unless}} + + {{#if permissions.LIST_GROUPS}}
  • @@ -61,6 +86,8 @@ {{#if permissions.LIST_POLICIES}}
  • Policy Management
  • {{/if}} + + {{#unless isCloud}} {{#if permissions.TENANT_CONFIGURATION}}
  • Configuration Management
      @@ -72,6 +99,10 @@
  • {{/if}} + {{/unless}} + + + {{/zone}} {{#zone "navbarCollapsableRightItems"}} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.navbar.nav-menu/nav-menu.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.navbar.nav-menu/nav-menu.js index 471a152402..69e306f590 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.navbar.nav-menu/nav-menu.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.navbar.nav-menu/nav-menu.js @@ -52,6 +52,7 @@ function onRequest(context) { context["isAuthorizedForNotifications"] = isAuthorizedForNotifications; context["currentUser"] = currentUser; context["appContext"] = mdmProps["appContext"]; + context["isCloud"] = mdmProps["isCloud"]; return context; } \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.navbar.nav-menu/public/js/nav-menu.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.navbar.nav-menu/public/js/nav-menu.js index 2b7d3cf2d4..07ddd59f2a 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.navbar.nav-menu/public/js/nav-menu.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.navbar.nav-menu/public/js/nav-menu.js @@ -20,7 +20,7 @@ var modalPopup = ".modal"; var modalPopupContainer = modalPopup + " .modal-content"; var modalPopupContent = modalPopup + " .modal-content"; -var emmAdminBasePath = "/api/device-mgt/v1.0"; +var backendEndBasePath = "/api/device-mgt/v1.0"; /* * set popup maximum height function. @@ -66,7 +66,7 @@ var updateNotificationCount = function (data, textStatus, jqXHR) { function loadNotificationsPanel() { if ("true" == $("#right-sidebar").attr("is-authorized")) { - var serviceURL = emmAdminBasePath + "/notifications?status=NEW"; + var serviceURL = backendEndBasePath + "/notifications?status=NEW"; invokerUtil.get(serviceURL, updateNotificationCount, hideNotificationCount); loadNewNotifications(); } else { @@ -90,7 +90,7 @@ function loadNewNotifications() { var currentUser = notifications.data("currentUser"); $.template("notification-listing", notifications.attr("src"), function (template) { - var serviceURL = emmAdminBasePath + "/notifications?status=NEW"; + var serviceURL = backendEndBasePath + "/notifications?status=NEW"; var successCallback = function (data, textStatus, jqXHR) { if (jqXHR.status == 200 && data) { @@ -453,3 +453,44 @@ $(document).ready(function () { }); } }); + +function statisticLoad(redirectUrl) { + var contentType = "application/json"; + + var uri = backendEndBasePath + "/admin/devicetype/deploy/device_management/status"; + var defaultStatusClasses = "fw fw-stack-1x"; + var content = $("#statistic-response-template").find(".content"); + var title = content.find("#title"); + var statusIcon = content.find("#status-icon"); + + invokerUtil.get(uri, function (data, textStatus, jqXHR) { + if (jqXHR.status == 204) { + var urix = backendEndBasePath + "/admin/devicetype/deploy/device_management"; + var device = {}; + invokerUtil.post(urix, device, function (data) { + title.html("Deploying statistic artifacts. Please wait..."); + statusIcon.attr("class", defaultStatusClasses + " fw-check"); + $(modalPopupContent).html(content.html()); + showPopup(); + setTimeout(function () { + hidePopup(); + // location.reload(true); + location.href = redirectUrl; + }, 20000); + + }, function (jqXHR) { + title.html("Failed to deploy artifacts, Please contact administrator."); + statusIcon.attr("class", defaultStatusClasses + " fw-error"); + $(modalPopupContent).html(content.html()); + showPopup(); + }, contentType); + } else { + location.href = redirectUrl; + } + }, function (jqXHR) { + title.html("Failed to connect with server, Please contact administrator."); + statusIcon.attr("class", defaultStatusClasses + " fw-error"); + $(modalPopupContent).html(content.html()); + showPopup(); + }, contentType); +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.theme/public/css/custom-common.css b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.theme/public/css/custom-common.css index a0e5807636..1fa92bf549 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.theme/public/css/custom-common.css +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.theme/public/css/custom-common.css @@ -16,12 +16,10 @@ * under the License. */ - .wr-input-control .helper { font-weight: 100; } - .wr-input-control .cus-col-25 { float: left; width: 25%; @@ -53,6 +51,12 @@ /*padding-left:20px;*/ /*}*/ +.user-icon-black { + color: black !important; +} + +/**/ + /* wizard */ .wr-wizard { @@ -99,6 +103,9 @@ } @media only screen and (min-width: 768px) { + header .username { + max-width: calc(100% - 100px); + } body > .page-content-wrapper > .container, body > .page-content-wrapper > .container-fluid { margin: 1% 1% 1%; @@ -109,3 +116,153 @@ header .brand h1 { text-transform: none !important; } + +header .username { + display: inline-block; + max-width: 180px; + white-space: nowrap; + overflow: hidden !important; + text-overflow: ellipsis; + vertical-align: middle; +} + +.visible-inline-block { + display: inline-block !important; +} + +.cloud-menu .popover { + border-radius: 0px; + width: 24em; + left: -21.1em !important; + max-width: 32em; + background-color: #006690 +} + +.cloud-menu .popover-title, .navbar-header .popover-title { + background-color: #006690; + font-size: 16px; + border-bottom: none; + font-weight: 400; +} + +.cloud-menu .popover.bottom > .arrow { + margin-left: -2px; +} + +.cloud-menu .popover.bottom > .arrow:after, .navbar-header .popover.bottom > .arrow:after { + border-bottom-color: #006690; +} + +.cloud-block { + float: left; + width: 8.2em; + height: 8.2em; + background-color: #fff; + margin: 0.5em 0em 0.5em 0.5em; + text-align: center; + vertical-align: middle; +} + +.cloud-name { + font-size: 14px; + margin-top: .5em; + font-weight: 400; +} + +.cloud-menu-popover { + position: relative; + float: right; + padding: 0px 8px; + background-color: transparent; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; + color: #fff; + cursor: pointer; +} + +#cloud-menu-popover-xs { + color: #fff; + line-height: 24px; + border: none; + margin-right: 15px !important; +} + +.navbar-toggle { + border: none; + border-radius: 0px; +} + +.navbar-header .popover { + border-radius: 0px; + width: 21em; + max-width: 32em; + background-color: #006690; +} + +.navbar-header .popover .popover-content { + padding: 0px; +} + +.cloud-menu .popover-content { + padding: 0px; +} + +.cloud-actions { + background-color: #005578; + float: left; + position: absolute; + width: 100%; + left: 0px; + overflow: hidden; +} + +.cloud-actions h3 { + font-size: 16px; + font-weight: 400; + padding-left: 14px; + margin-top: 10px; +} + +.cloud-block-invert { + color: #fff; + float: left; + width: 8.2em; + height: 8.2em; + background-color: #1f1f1f; + margin: 0.5em 0em 0.5em 0.5em; + text-align: center; + cursor: pointer; +} + +.cloud-block-default { + color: #006690; + background-color: #fff; + cursor: pointer; +} + +.cloud-actions a:hover { + color: #d7d5d5; + background-color: #3d3d3d; + text-decoration: none +} + +.cloud-apps a { + text-decoration: none; + color: #006690 !important; + cursor: pointer +} + +.cloud-apps a:hover { + text-decoration: none; + color: #006690; + background-color: #c5c5c5; +} + +.cloud-apps .cloud-actions a { + color: #fff +} + +.add-padding-top-3x { + padding-top: 15px !important; +} \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.theme/public/css/custom-desktop.css b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.theme/public/css/custom-desktop.css index f85ad9c35e..e38dc27929 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.theme/public/css/custom-desktop.css +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.theme/public/css/custom-desktop.css @@ -2028,6 +2028,11 @@ input[type=number].form-control { .thumbnail.icon img { width: 100%; + padding: 10px; +} + +.table .icon-only{ + cursor: pointer; } /* ======================================================================== @@ -6355,6 +6360,7 @@ ul.tiles .icon { #device-location{ height:450px; + width: 100%; margin-bottom:0px; } #device-location .leaflet-popup-content-wrapper{ @@ -6549,6 +6555,27 @@ select > option:hover { color : #C7C7C7; } +/** + * + * Temporary navigation color fix for IoT cloud release + * + */ + +header.header-default { + background: #181e22 !important; + height: 50px; +} + +.navbar-collapse { + background: #37474F; +} + +.dropdown-menu > li { + width: 100%; +} + +/** End **/ + /** * * Temporary responsive fix for table listing action button width issue @@ -6581,6 +6608,9 @@ select > option:hover { /** End **/ +.tooltip-overflow-fix{ + overflow: visible !important; + .editable-input select{ height: 35px !important; } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/error-pages/error400-cloud.html b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/error-pages/error400-cloud.html new file mode 100644 index 0000000000..3007e7d0be --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/error-pages/error400-cloud.html @@ -0,0 +1,30 @@ + + + + + + + + +
    +
    +
    + +
    +
    +

    Oops something went wrong

    +

    400 - Bad request

    +
    + +
    +
    + +
    +
    +
    +
    + + \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/error-pages/error401-cloud.html b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/error-pages/error401-cloud.html new file mode 100644 index 0000000000..8c195bd0f0 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/error-pages/error401-cloud.html @@ -0,0 +1,30 @@ + + + + + + + + +
    +
    +
    + +
    +
    +

    Oops something went wrong

    +

    401 - Unauthorized

    +
    + +
    +
    + +
    +
    +
    +
    + + \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/error-pages/error403-cloud.html b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/error-pages/error403-cloud.html new file mode 100644 index 0000000000..d9d7d00b0c --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/error-pages/error403-cloud.html @@ -0,0 +1,30 @@ + + + + + + + + +
    +
    +
    + +
    +
    +

    Oops something went wrong

    +

    403 - Forbidden

    +
    + +
    +
    + +
    +
    +
    +
    + + \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/error-pages/error404-cloud.html b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/error-pages/error404-cloud.html new file mode 100644 index 0000000000..897eeb4821 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/error-pages/error404-cloud.html @@ -0,0 +1,30 @@ + + + + + + + + +
    +
    +
    + +
    +
    +

    Oops something went wrong

    +

    404 - Page Not Found

    +
    + +
    +
    + +
    +
    +
    +
    + + \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/error-pages/error405-cloud.html b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/error-pages/error405-cloud.html new file mode 100644 index 0000000000..bc3d5bdd57 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/error-pages/error405-cloud.html @@ -0,0 +1,30 @@ + + + + + + + + +
    +
    +
    + +
    +
    +

    Oops something went wrong

    +

    405 - Method Not Allowed

    +
    + +
    +
    + +
    +
    +
    +
    + + \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/error-pages/error500-cloud.html b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/error-pages/error500-cloud.html new file mode 100644 index 0000000000..1ece4cc29d --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/error-pages/error500-cloud.html @@ -0,0 +1,30 @@ + + + + + + + + +
    +
    +
    + +
    +
    +

    Oops something went wrong

    +

    500 - Internal Server Error

    +
    + +
    +
    + +
    +
    +
    +
    + + \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/uuf-template-app/app/units/uuf.unit.navbar/navbar.hbs b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/uuf-template-app/app/units/uuf.unit.navbar/navbar.hbs index db9488ed02..4d8a513c58 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/uuf-template-app/app/units/uuf.unit.navbar/navbar.hbs +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/uuf-template-app/app/units/uuf.unit.navbar/navbar.hbs @@ -17,7 +17,7 @@ }} {{#zone "navbars"}} -