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 63176b19db8..7da850e7a94 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 @@ -105,10 +105,6 @@ org.wso2.carbon.governance org.wso2.carbon.governance.lcm - - org.wso2.carbon.devicemgt - org.wso2.carbon.device.mgt.core - 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 fcb27541dbe..ca12f79a5b3 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 @@ -78,7 +78,10 @@ public class APIPublisherServiceImpl implements APIPublisherService { + api.getId().getVersion() + "'"); } } else { - api.setStatus(provider.getAPI(api.getId()).getStatus()); + 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() + 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 new file mode 100644 index 00000000000..30f79001535 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherStartupHandler.java @@ -0,0 +1,67 @@ +/* + * 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; + +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.internal.APIPublisherDataHolder; +import org.wso2.carbon.core.ServerStartupObserver; + +public class APIPublisherStartupHandler implements ServerStartupObserver { + + private static final Log log = LogFactory.getLog(APIPublisherStartupHandler.class); + + @Override + public void completingServerStartup() { + + } + + @Override + public void completedServerStartup() { + // adding temporary due to a bug in the platform + Thread t = new Thread(new Runnable() { + @Override + public void run() { + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + log.error("Error occurred while sleeping", e); + } + APIPublisherDataHolder.getInstance().setServerStarted(true); + log.info("Server has just started, hence started publishing unpublished APIs"); + if (log.isDebugEnabled()) { + log.debug("Total number of unpublished APIs: " + + APIPublisherDataHolder.getInstance().getUnpublishedApis().size()); + } + APIPublisherService publisher = APIPublisherDataHolder.getInstance().getApiPublisherService(); + while (!APIPublisherDataHolder.getInstance().getUnpublishedApis().isEmpty()) { + API api = APIPublisherDataHolder.getInstance().getUnpublishedApis().pop(); + try { + publisher.publishAPI(api); + } catch (java.lang.Exception e) { + log.error("Error occurred while publishing API '" + api.getId().getApiName(), e); + } + } + } + }); + t.start(); + } +} 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 2e7c8caac7c..1b4758a475b 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,6 +18,7 @@ package org.wso2.carbon.apimgt.webapp.publisher; +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.apimgt.api.APIManagementException; @@ -26,11 +27,9 @@ import org.wso2.carbon.apimgt.api.model.*; import org.wso2.carbon.apimgt.impl.APIConstants; 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.internal.APIPublisherDataHolder; +import org.wso2.carbon.apimgt.webapp.publisher.config.WebappPublisherConfig; import org.wso2.carbon.base.MultitenantConstants; -import org.wso2.carbon.utils.CarbonUtils; -import org.wso2.carbon.utils.ConfigurationContextService; -import org.wso2.carbon.utils.NetworkUtils; +import org.wso2.carbon.core.util.Utils; import javax.servlet.ServletContext; import java.util.*; @@ -96,7 +95,7 @@ public class APIPublisherUtil { } api.setResponseCache(APIConstants.DISABLED); - String endpointConfig = "{\"production_endpoints\":{\"url\":\" " + config.getEndpoint() + + String endpointConfig = "{\"production_endpoints\":{\"url\":\"" + config.getEndpoint() + "\",\"config\":null},\"implementation_status\":\"managed\",\"endpoint_type\":\"http\"}"; api.setEndpointConfig(endpointConfig); @@ -113,7 +112,8 @@ public class APIPublisherUtil { // adding scopes to the api Set uriTemplates = config.getUriTemplates(); Map apiScopes = new HashMap<>(); - + Scope existingScope; + String existingPermissions; if (uriTemplates != null) { // this creates distinct scopes list for (URITemplate template : uriTemplates) { @@ -121,6 +121,12 @@ public class APIPublisherUtil { if (scope != null) { if (apiScopes.get(scope.getKey()) == null) { apiScopes.put(scope.getKey(), scope); + } else { + existingScope = apiScopes.get(scope.getKey()); + existingPermissions = existingScope.getRoles(); + existingPermissions = getDistinctPermissions(existingPermissions + "," + scope.getRoles()); + existingScope.setRoles(existingPermissions); + apiScopes.put(scope.getKey(), existingScope); } } } @@ -132,7 +138,7 @@ public class APIPublisherUtil { // api scope and uri template scope for (Scope scope : scopes) { for (URITemplate template : uriTemplates) { - if (scope.getKey().equals(template.getScope().getKey())) { + if (template.getScope() != null && scope.getKey().equals(template.getScope().getKey())) { template.setScope(scope); } } @@ -143,24 +149,8 @@ public class APIPublisherUtil { } public static String getServerBaseUrl() { - // Hostname - String hostName = "localhost"; - try { - hostName = NetworkUtils.getMgtHostName(); - } catch (Exception ignored) { - } - // HTTPS port - String mgtConsoleTransport = CarbonUtils.getManagementTransport(); - ConfigurationContextService configContextService = - APIPublisherDataHolder.getInstance().getConfigurationContextService(); - int port = CarbonUtils.getTransportPort(configContextService, mgtConsoleTransport); - int httpsProxyPort = - CarbonUtils.getTransportProxyPort(configContextService.getServerConfigContext(), - mgtConsoleTransport); - if (httpsProxyPort > 0) { - port = httpsProxyPort; - } - return "https://" + hostName + ":" + port; + WebappPublisherConfig webappPublisherConfig = WebappPublisherConfig.getInstance(); + return Utils.replaceSystemProperty(webappPublisherConfig.getHost()); } public static String getApiEndpointUrl(String context) { @@ -262,7 +252,7 @@ public class APIPublisherUtil { if (log.isDebugEnabled()) { log.debug("'managed-api-endpoint' attribute is not configured"); } - String endpointContext = servletContext.getContextPath(); + String endpointContext = apiDef.getContext(); endpoint = APIPublisherUtil.getApiEndpointUrl(endpointContext); } apiConfig.setEndpoint(endpoint); @@ -318,4 +308,9 @@ public class APIPublisherUtil { return apiConfig; } + private static String getDistinctPermissions(String permissions) { + String[] unique = new HashSet(Arrays.asList(permissions.split(","))).toArray(new String[0]); + return StringUtils.join(unique, ","); + } + } diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/InvalidConfigurationStateException.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/InvalidConfigurationStateException.java new file mode 100644 index 00000000000..d3022f11d19 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/InvalidConfigurationStateException.java @@ -0,0 +1,75 @@ +/* + * 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; + +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.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/WebappPublisherConfigurationFailedException.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/WebappPublisherConfigurationFailedException.java new file mode 100644 index 00000000000..e5b3252f8eb --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/WebappPublisherConfigurationFailedException.java @@ -0,0 +1,44 @@ +/* + * 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; + +public class WebappPublisherConfigurationFailedException extends Exception { + + private static final long serialVersionUID = -3151279312929070398L; + + public WebappPublisherConfigurationFailedException(String msg, Exception nestedEx) { + super(msg, nestedEx); + } + + public WebappPublisherConfigurationFailedException(String message, Throwable cause) { + super(message, cause); + } + + public WebappPublisherConfigurationFailedException(String msg) { + super(msg); + } + + public WebappPublisherConfigurationFailedException() { + super(); + } + + public WebappPublisherConfigurationFailedException(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/WebappPublisherUtil.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/WebappPublisherUtil.java new file mode 100644 index 00000000000..9308910c065 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/WebappPublisherUtil.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.webapp.publisher; + +import org.w3c.dom.Document; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.File; + +/** + * This class contains the util methods which are needed + * to web app publisher related functions. + */ +public class WebappPublisherUtil { + + public static Document convertToDocument(File file) throws WebappPublisherConfigurationFailedException { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + try { + DocumentBuilder docBuilder = factory.newDocumentBuilder(); + return docBuilder.parse(file); + } catch (Exception e) { + throw new WebappPublisherConfigurationFailedException("Error occurred while parsing file, while converting " + + "to a org.w3c.dom.Document", e); + } + } + +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/config/WebappPublisherConfig.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/config/WebappPublisherConfig.java new file mode 100644 index 00000000000..192f91b9061 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/config/WebappPublisherConfig.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.webapp.publisher.config; + +import org.w3c.dom.Document; +import org.wso2.carbon.apimgt.webapp.publisher.InvalidConfigurationStateException; +import org.wso2.carbon.apimgt.webapp.publisher.WebappPublisherConfigurationFailedException; +import org.wso2.carbon.apimgt.webapp.publisher.WebappPublisherUtil; +import org.wso2.carbon.utils.CarbonUtils; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.File; + +/** + * This class represents the configuration that are needed + * when publishing APIs to API Manager. + */ +@XmlRootElement(name = "WebappPublisherConfigs") +public class WebappPublisherConfig { + + private String host; + private boolean isPublished; + + private static WebappPublisherConfig config; + + private static final String WEBAPP_PUBLISHER_CONFIG_PATH = + CarbonUtils.getEtcCarbonConfigDirPath() + File.separator + "webapp-publisher-config.xml"; + + private WebappPublisherConfig() { + } + + public static WebappPublisherConfig getInstance() { + if (config == null) { + throw new InvalidConfigurationStateException("Webapp Authenticator Configuration is not " + + "initialized properly"); + } + return config; + } + + @XmlElement(name = "Host", required = true) + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + @XmlElement(name = "PublishAPI", required = true) + public boolean isPublished() { + return isPublished; + } + + public void setPublished(boolean published) { + isPublished = published; + } + + public static void init() throws WebappPublisherConfigurationFailedException { + try { + File emailSenderConfig = new File(WEBAPP_PUBLISHER_CONFIG_PATH); + Document doc = WebappPublisherUtil.convertToDocument(emailSenderConfig); + + /* Un-marshaling Email Sender configuration */ + JAXBContext ctx = JAXBContext.newInstance(WebappPublisherConfig.class); + Unmarshaller unmarshaller = ctx.createUnmarshaller(); + //unmarshaller.setSchema(getSchema()); + config = (WebappPublisherConfig) unmarshaller.unmarshal(doc); + } catch (JAXBException e) { + throw new WebappPublisherConfigurationFailedException("Error occurred while un-marshalling Webapp " + + "Publisher Config", e); + } + } + +} 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 bd291ce3be2..b06bc1a4ca6 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 @@ -19,12 +19,15 @@ package org.wso2.carbon.apimgt.webapp.publisher.internal; +import org.wso2.carbon.apimgt.api.model.API; import org.wso2.carbon.apimgt.webapp.publisher.APIPublisherService; import org.wso2.carbon.registry.core.service.RegistryService; import org.wso2.carbon.user.core.service.RealmService; import org.wso2.carbon.user.core.tenant.TenantManager; import org.wso2.carbon.utils.ConfigurationContextService; +import java.util.Stack; + public class APIPublisherDataHolder { private APIPublisherService apiPublisherService; @@ -32,6 +35,8 @@ public class APIPublisherDataHolder { private RealmService realmService; private TenantManager tenantManager; private RegistryService registryService; + private boolean isServerStarted; + private Stack unpublishedApis = new Stack<>(); private static APIPublisherDataHolder thisInstance = new APIPublisherDataHolder(); @@ -94,4 +99,20 @@ public class APIPublisherDataHolder { public void setRegistryService(RegistryService registryService) { this.registryService = registryService; } + + public boolean isServerStarted() { + return isServerStarted; + } + + public void setServerStarted(boolean serverStarted) { + isServerStarted = serverStarted; + } + + public Stack getUnpublishedApis() { + return unpublishedApis; + } + + public void setUnpublishedApis(Stack unpublishedApis) { + this.unpublishedApis = unpublishedApis; + } } 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 2a67c78713d..44c2c6d7992 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 @@ -25,6 +25,9 @@ import org.osgi.service.component.ComponentContext; import org.wso2.carbon.apimgt.impl.APIManagerConfigurationService; import org.wso2.carbon.apimgt.webapp.publisher.APIPublisherService; import org.wso2.carbon.apimgt.webapp.publisher.APIPublisherServiceImpl; +import org.wso2.carbon.apimgt.webapp.publisher.APIPublisherStartupHandler; +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; @@ -57,16 +60,23 @@ public class APIPublisherServiceComponent { protected void activate(ComponentContext componentContext) { try { if (log.isDebugEnabled()) { - log.debug("Initializing device management core bundle"); + log.debug("Initializing webapp publisher bundle"); } + + if (log.isDebugEnabled()) { + log.debug("Loading webapp publisher configurations"); + } + /* Initializing webapp publisher configuration */ + WebappPublisherConfig.init(); + /* Registering declarative service instances exposed by DeviceManagementServiceComponent */ this.registerServices(componentContext); if (log.isDebugEnabled()) { - log.debug("Device management core bundle has been successfully initialized"); + log.debug("Webapp publisher bundle has been successfully initialized"); } } catch (Throwable e) { - log.error("Error occurred while initializing device management core bundle", e); + log.error("Error occurred while initializing webapp publisher bundle", e); } } @@ -84,6 +94,7 @@ public class APIPublisherServiceComponent { APIPublisherService publisher = new APIPublisherServiceImpl(); APIPublisherDataHolder.getInstance().setApiPublisherService(publisher); bundleContext.registerService(APIPublisherService.class, publisher, null); + bundleContext.registerService(ServerStartupObserver.class, new APIPublisherStartupHandler(), null); } protected void setAPIManagerConfigurationService(APIManagerConfigurationService service) { 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 6bd87907548..042da6b8c27 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 @@ -31,7 +31,6 @@ import org.wso2.carbon.apimgt.webapp.publisher.APIPublisherUtil; import org.wso2.carbon.apimgt.webapp.publisher.config.APIResourceConfiguration; import org.wso2.carbon.apimgt.webapp.publisher.internal.APIPublisherDataHolder; import org.wso2.carbon.apimgt.webapp.publisher.lifecycle.util.AnnotationProcessor; -import org.wso2.carbon.device.mgt.core.DeviceManagementConstants; import javax.servlet.ServletContext; import java.io.IOException; @@ -43,6 +42,9 @@ public class APIPublisherLifecycleListener implements LifecycleListener { private static final Log log = LogFactory.getLog(APIPublisherLifecycleListener.class); private static final String PARAM_MANAGED_API_ENABLED = "managed-api-enabled"; + public static final String PROPERTY_PROFILE = "profile"; + public static final String PROFILE_DT_WORKER = "dtWorker"; + public static final String PROFILE_DEFAULT = "default"; @Override public void lifecycleEvent(LifecycleEvent lifecycleEvent) { @@ -52,10 +54,10 @@ public class APIPublisherLifecycleListener implements LifecycleListener { String param = servletContext.getInitParameter(PARAM_MANAGED_API_ENABLED); boolean isManagedApi = (param != null && !param.isEmpty()) && Boolean.parseBoolean(param); - String profile = System.getProperty(DeviceManagementConstants.Common.PROPERTY_PROFILE); + String profile = System.getProperty(PROPERTY_PROFILE); - if ((profile.equalsIgnoreCase(DeviceManagementConstants.Common.PROFILE_DT_WORKER) || - profile.equalsIgnoreCase(DeviceManagementConstants.Common.PROFILE_DEFAULT)) && isManagedApi) { + if ((profile.equalsIgnoreCase(PROFILE_DT_WORKER) || + profile.equalsIgnoreCase(PROFILE_DEFAULT)) && isManagedApi) { try { AnnotationProcessor annotationProcessor = new AnnotationProcessor(context); Set annotatedAPIClasses = annotationProcessor. @@ -78,13 +80,22 @@ public class APIPublisherLifecycleListener implements LifecycleListener { if (isTenantActive) { apiConfig.init(); API api = APIPublisherUtil.getAPI(apiConfig); - APIPublisherService apiPublisherService = - APIPublisherDataHolder.getInstance().getApiPublisherService(); - if (apiPublisherService == null) { - throw new IllegalStateException( - "API Publisher service is not initialized properly"); + boolean isServerStarted = APIPublisherDataHolder.getInstance().isServerStarted(); + if (isServerStarted) { + APIPublisherService apiPublisherService = + APIPublisherDataHolder.getInstance().getApiPublisherService(); + if (apiPublisherService == null) { + throw new IllegalStateException( + "API Publisher service is not initialized properly"); + } + apiPublisherService.publishAPI(api); + } else { + if (log.isDebugEnabled()) { + log.debug("Server has not started yet. Hence adding API '" + + api.getId().getApiName() + "' to the queue"); + } + APIPublisherDataHolder.getInstance().getUnpublishedApis().push(api); } - apiPublisherService.publishAPI(api); } else { log.error("No tenant [" + apiConfig.getTenantDomain() + "] " + "found when publishing the Web app"); 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 730c8c82dca..af773d6df33 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 @@ -28,12 +28,11 @@ import org.scannotation.WarUrlFinder; import org.wso2.carbon.apimgt.annotations.api.API; import org.wso2.carbon.apimgt.annotations.api.Permission; 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.config.PermissionConfiguration; import org.wso2.carbon.apimgt.webapp.publisher.config.PermissionManagementException; -import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager; -import org.wso2.carbon.device.mgt.core.config.deviceType.DTConfiguration; import javax.servlet.ServletContext; import javax.ws.rs.*; @@ -137,7 +136,6 @@ public class AnnotationProcessor { try { apiResourceConfig = processAPIAnnotation(apiAnno); - // All the apis should map to same root "/" String rootContext = servletContext.getContextPath(); pathClazz = (Class) classLoader.loadClass(Path.class.getName()); pathClazzMethods = pathClazz.getMethods(); @@ -147,7 +145,11 @@ public class AnnotationProcessor { if (rootContectAnno != null) { subContext = invokeMethod(pathClazzMethods[0], rootContectAnno, STRING); if (subContext != null && !subContext.isEmpty()) { - rootContext = rootContext + "/" + subContext; + if (subContext.trim().startsWith("/")) { + rootContext = rootContext + subContext; + } else { + rootContext = rootContext + "/" + subContext; + } } else { subContext = ""; } @@ -157,7 +159,7 @@ public class AnnotationProcessor { } Method[] annotatedMethods = clazz.getDeclaredMethods(); - resourceList = getApiResources(rootContext, subContext, annotatedMethods); + resourceList = getApiResources(rootContext, annotatedMethods); apiResourceConfig.setResources(resourceList); } catch (Throwable throwable) { log.error("Error encountered while scanning for annotations", throwable); @@ -209,33 +211,30 @@ public class AnnotationProcessor { * Get Resources for each API * * @param resourceRootContext - * @param apiRootContext * @param annotatedMethods * @return * @throws Throwable */ - private List getApiResources(String resourceRootContext, String apiRootContext, - Method[] annotatedMethods) throws Throwable { - List resourceList; - resourceList = new ArrayList(); + private List getApiResources(String resourceRootContext, Method[] annotatedMethods) throws Throwable { + List resourceList = new ArrayList<>(); + String subCtx = null; for (Method method : annotatedMethods) { - Annotation methodContextAnno = method.getAnnotation(pathClazz); - if (methodContextAnno != null) { - String subCtx = invokeMethod(pathClazzMethods[0], methodContextAnno, STRING); - APIResource resource = new APIResource(); - resource.setUriTemplate(makeContextURLReady(apiRootContext + subCtx)); - - DTConfiguration deviceTypeConfig = DeviceConfigurationManager.getInstance(). - getDeviceManagementConfig().getDTDeploymentConfiguration(); - - String serverIP = deviceTypeConfig.getDtHostAddress(); - String httpServerPort = deviceTypeConfig.getDtHostPort(); + Annotation[] annotations = method.getDeclaredAnnotations(); + APIResource resource = new APIResource(); + + if (isHttpMethodAvailable(annotations)) { + Annotation methodContextAnno = method.getAnnotation(pathClazz); + if (methodContextAnno != null) { + subCtx = invokeMethod(pathClazzMethods[0], methodContextAnno, STRING); + } else { + subCtx = "/*"; + } + resource.setUriTemplate(makeContextURLReady(subCtx)); - resource.setUri(PROTOCOL_HTTP + "://" + serverIP + ":" + httpServerPort + makeContextURLReady( - resourceRootContext) + makeContextURLReady(subCtx)); + resource.setUri(APIPublisherUtil.getServerBaseUrl() + makeContextURLReady(resourceRootContext) + + makeContextURLReady(subCtx)); resource.setAuthType(AUTH_TYPE); - Annotation[] annotations = method.getDeclaredAnnotations(); for (int i = 0; i < annotations.length; i++) { processHTTPMethodAnnotation(resource, annotations[i]); if (annotations[i].annotationType().getName().equals(Consumes.class.getName())) { @@ -295,6 +294,23 @@ public class AnnotationProcessor { } } + private boolean isHttpMethodAvailable(Annotation[] annotations) { + for (Annotation annotation : annotations) { + if (annotation.annotationType().getName().equals(GET.class.getName())) { + return true; + } else if (annotation.annotationType().getName().equals(POST.class.getName())) { + return true; + } else if (annotation.annotationType().getName().equals(OPTIONS.class.getName())) { + return true; + } else if (annotation.annotationType().getName().equals(DELETE.class.getName())) { + return true; + } else if (annotation.annotationType().getName().equals(PUT.class.getName())) { + return true; + } + } + return false; + } + /** * Append '/' to the context and make it URL ready * 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 0d53ffbc058..ced2b64f42d 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 @@ -143,9 +143,19 @@ provided - org.wso2.carbon.commons + org.wso2.carbon.identity org.wso2.carbon.user.mgt provided + + + org.slf4j + slf4j-api + + + org.slf4j + jcl-over-slf4j + + org.wso2.carbon @@ -227,6 +237,10 @@ servlet-api provided + + org.wso2.carbon.devicemgt + org.wso2.carbon.apimgt.annotations + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Certificate.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Certificate.java index c7f1e4ff04c..56ec881e924 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Certificate.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Certificate.java @@ -19,6 +19,8 @@ package org.wso2.carbon.device.mgt.jaxrs.api; import io.swagger.annotations.*; +import org.wso2.carbon.apimgt.annotations.api.API; +import org.wso2.carbon.apimgt.annotations.api.Permission; import org.wso2.carbon.certificate.mgt.core.dto.CertificateResponse; import org.wso2.carbon.device.mgt.common.PaginationResult; import org.wso2.carbon.device.mgt.jaxrs.api.common.MDMAPIException; @@ -31,6 +33,9 @@ import javax.ws.rs.core.Response; /** * All the certificate related tasks such as saving certificates, can be done through this endpoint. */ +@API(name = "Certificate", version = "1.0.0", context = "/devicemgt_admin/certificates", tags = {"devicemgt_admin"}) + +// Below Api is for swagger annotations @Api(value = "Certificate", description = "Certificate related tasks such as saving certificates, " + "can be done through this API") @SuppressWarnings("NonJaxWsWebServices") @@ -58,6 +63,7 @@ public interface Certificate { @ApiResponse(code = 200, message = "Added successfully"), @ApiResponse(code = 500, message = "Error occurred while saving the certificate") }) + @Permission(scope = "certificate-modify", permissions = {"/permission/admin/device-mgt/certificate/save"}) Response saveCertificate(@HeaderParam("Accept") String acceptHeader, @ApiParam(name = "enrollmentCertificates", value = "certificate with serial, " + "pem and tenant id", required = true) EnrollmentCertificate[] @@ -83,6 +89,7 @@ public interface Certificate { @ApiResponse(code = 400, message = "Notification status updated successfully"), @ApiResponse(code = 500, message = "Error occurred while converting PEM file to X509Certificate") }) + @Permission(scope = "certificate-view", permissions = {"/permission/admin/device-mgt/certificate/view"}) Response getCertificate(@HeaderParam("Accept") String acceptHeader, @ApiParam(name = "serialNumber", value = "Provide the serial number of the " + "certificate that you wish to get the details of", required = true) @@ -113,6 +120,7 @@ public interface Certificate { @ApiResponse(code = 400, message = "Invalid length value"), @ApiResponse(code = 500, message = "Error occurred while fetching all certificates") }) + @Permission(scope = "certificate-view", permissions = {"/permission/admin/device-mgt/certificate/view"}) Response getAllCertificates(@HeaderParam("Accept") String acceptHeader, @ApiParam(name = "start", value = "Provide the starting pagination index as the value", required = true) @@ -135,6 +143,7 @@ public interface Certificate { @ApiResponse(code = 400, message = "Invalid start index"), @ApiResponse(code = 500, message = "Error when deleting the certificate" ) }) + @Permission(scope = "certificate-modify", permissions = {"/permission/admin/device-mgt/certificate/remove"}) Response removeCertificate(@HeaderParam("Accept") String acceptHeader, @ApiParam(name = "serialNumber", value = "Provide the serial number of the " + "certificate that you wish to delete", required = true) diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Configuration.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Configuration.java index 5ae44a51626..b15c4427866 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Configuration.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Configuration.java @@ -19,6 +19,7 @@ package org.wso2.carbon.device.mgt.jaxrs.api; import io.swagger.annotations.*; +import org.wso2.carbon.apimgt.annotations.api.*; import org.wso2.carbon.device.mgt.common.configuration.mgt.TenantConfiguration; import javax.ws.rs.*; @@ -29,6 +30,9 @@ import javax.ws.rs.core.Response; * General Tenant Configuration REST-API implementation. * All end points support JSON, XMl with content negotiation. */ +@API(name = "Configuration", version = "1.0.0", context = "/devicemgt_admin/configuration", tags = {"devicemgt_admin"}) + +// Below Api is for swagger annotations @Path("/configuration") @Api(value = "Configuration", description = "General Tenant Configuration management capabilities are exposed " + "through this API") @@ -48,6 +52,7 @@ public interface Configuration { @ApiResponse(code = 201, message = "Tenant configuration saved successfully"), @ApiResponse(code = 500, message = "Error occurred while saving the tenant configuration") }) + @Permission(scope = "configuration-modify", permissions = {"/permission/admin/device-mgt/admin/platform-configs/modify"}) Response saveTenantConfiguration(@ApiParam(name = "configuration", value = "The required properties to " + "update the platform configurations the as the value", required = true) TenantConfiguration configuration); @@ -64,6 +69,7 @@ public interface Configuration { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 500, message = "Error occurred while retrieving the tenant configuration") }) + @Permission(scope = "configuration-view", permissions = {"/permission/admin/device-mgt/admin/platform-configs/view"}) Response getConfiguration(); @PUT @@ -77,6 +83,7 @@ public interface Configuration { @ApiResponse(code = 201, message = "Tenant configuration updated successfully"), @ApiResponse(code = 500, message = "Error occurred while updating the tenant configuration") }) + @Permission(scope = "configuration-modify", permissions = {"/permission/admin/device-mgt/admin/platform-configs/modify"}) Response updateConfiguration(@ApiParam(name = "configuration", value = "The required properties to update" + " the platform configurations the as the value", required = true) TenantConfiguration configuration); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Device.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Device.java index 569df1cac1a..6756e863deb 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Device.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Device.java @@ -19,6 +19,7 @@ package org.wso2.carbon.device.mgt.jaxrs.api; import io.swagger.annotations.*; +import org.wso2.carbon.apimgt.annotations.api.*; import org.wso2.carbon.device.mgt.common.EnrolmentInfo; import org.wso2.carbon.device.mgt.core.dto.DeviceType; @@ -29,6 +30,9 @@ import javax.ws.rs.core.Response; /** * Device related operations such as get all the available devices, etc. */ +@API(name = "Device", version = "1.0.0", context = "/devicemgt_admin/devices", tags = {"devicemgt_admin"}) + +// Below Api is for swagger annotations @Path("/devices") @Api(value = "Device", description = "Device related operations such as get all the available devices, etc.") @SuppressWarnings("NonJaxWsWebServices") @@ -55,6 +59,7 @@ public interface Device { @ApiResponse(code = 200, message = "List of Devices"), @ApiResponse(code = 500, message = "Error occurred while fetching the device list") }) + @Permission(scope = "device-list", permissions = {"/permission/admin/device-mgt/admin/devices/list"}) Response getAllDevices(@ApiParam(name = "type", value = "Provide the device type, such as ios, android or" + " windows", required = true) @QueryParam("type") String type, @ApiParam(name = "user", value = "Get the details of the devices registered to a " @@ -86,6 +91,9 @@ public interface Device { @GET @Path("view") @Produces({ MediaType.APPLICATION_JSON }) + @Permission(scope = "device-view", permissions = { + "/permission/admin/device-mgt/admin/devices/view", + "/permission/admin/device-mgt/user/devices/view"}) Response getDevice(@QueryParam("type") String type, @QueryParam("id") String id); /** @@ -96,6 +104,9 @@ public interface Device { */ @GET @Path("user/{user}") + @Permission(scope = "device-view-own", permissions = { + "/permission/admin/device-mgt/user/devices/list", + "/permission/admin/device-mgt/admin/devices/list"}) Response getDeviceOfUser(@PathParam("user") String user); /** @@ -106,6 +117,9 @@ public interface Device { */ @GET @Path("user/{user}/count") + @Permission(scope = "device-count-own", permissions = { + "/permission/admin/device-mgt/user/devices/list", + "/permission/admin/device-mgt/admin/devices/list"}) Response getDeviceCountOfUser(@PathParam("user") String user); /** @@ -124,6 +138,7 @@ public interface Device { @ApiResponse(code = 200, message = "Device count"), @ApiResponse(code = 500, message = "Error occurred while fetching the device count") }) + @Permission(scope = "device-list", permissions = {"/permission/admin/device-mgt/admin/devices/list"}) Response getDeviceCount(); /** @@ -135,6 +150,7 @@ public interface Device { */ @GET @Path("name/{name}/{tenantDomain}") + @ApiOperation( httpMethod = "GET", value = "Get the device details of a specific device via the REST API", @@ -145,11 +161,12 @@ public interface Device { @ApiResponse(code = 200, message = "List of devices"), @ApiResponse(code = 500, message = "Error occurred while fetching the devices list of device name") }) - Response getDevicesByName(@ApiParam(name = "name", value = "The name of the device or windows", - required = true) @PathParam("name") String deviceName, + @Permission(scope = "device-list", permissions = {"/permission/admin/device-mgt/admin/devices/list"}) + Response getDevicesByName(@ApiParam(name = "name", value = "The name of the device or windows", required = true) + @PathParam("name") String deviceName, @ApiParam(name = "tenantDomain", value = "Tenant domain name. The default " + "tenant domain of WSO2 EMM is carbon.super", required = true) - @PathParam("tenantDomain") String tenantDomain); + @PathParam("tenantDomain") String tenantDomain); /** * Get the list of available device types. @@ -168,6 +185,7 @@ public interface Device { @ApiResponses(value = { @ApiResponse(code = 200, message = "List of devices based on the type"), @ApiResponse(code = 500, message = "Error occurred while fetching the list of device types") }) + @Permission(scope = "device-list", permissions = {"/permission/admin/device-mgt/admin/devices/list"}) Response getDeviceTypes(); /** @@ -177,6 +195,8 @@ public interface Device { */ @PUT @Path("type/{type}/id/{deviceId}") + @Permission(scope = "device-modify", permissions = { + "/permission/admin/device-mgt/user/devices/modify", "/permission/admin/device-mgt/admin/devices/modify"}) Response updateDevice(@PathParam("type") String deviceType, @PathParam("deviceId") String deviceId, org.wso2.carbon.device.mgt.common.Device updatedDevice); @@ -187,6 +207,8 @@ public interface Device { */ @DELETE @Path("type/{type}/id/{deviceId}") + @Permission(scope = "device-modify", permissions = { + "/permission/admin/device-mgt/user/devices/modify", "/permission/admin/device-mgt/admin/devices/modify"}) Response disenrollDevice(@PathParam("type") String deviceType, @PathParam("deviceId") String deviceId); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/DeviceInformation.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/DeviceInformation.java index 864eda023a4..b10412b516a 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/DeviceInformation.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/DeviceInformation.java @@ -19,6 +19,7 @@ package org.wso2.carbon.device.mgt.jaxrs.api; import io.swagger.annotations.*; +import org.wso2.carbon.apimgt.annotations.api.*; import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo; import org.wso2.carbon.device.mgt.common.device.details.DeviceLocation; @@ -34,6 +35,9 @@ import java.util.List; /** * Device information related operations. */ +@API(name = "Device Information", version = "1.0.0", context = "/devicemgt_admin/information", tags = {"devicemgt_admin"}) + +// Below Api is for swagger annotations @Path("/information") @Api(value = "DeviceInformation", description = "Device information related operations can be found here.") @SuppressWarnings("NonJaxWsWebServices") @@ -53,6 +57,7 @@ public interface DeviceInformation { @ApiResponse(code = 400, message = ""), @ApiResponse(code = 500, message = "Internal Server Error") }) + @Permission(scope = "device-info", permissions = {"/permission/admin/device-mgt/admin/devices/list"}) Response getDeviceInfo(@ApiParam(name = "type", value = "Provide the device type, such as ios, android " + "or windows", required = true) @PathParam("type") String type, @ApiParam(name = "id", value = "Provide the device identifier", required = true) @@ -60,7 +65,7 @@ public interface DeviceInformation { @POST - @Path("{list}") + @Path("list") @ApiOperation( produces = MediaType.APPLICATION_JSON, httpMethod = "POST", @@ -75,6 +80,7 @@ public interface DeviceInformation { @ApiResponse(code = 400, message = ""), @ApiResponse(code = 500, message = "Internal Server Error") }) + @Permission(scope = "device-info", permissions = {"/permission/admin/device-mgt/admin/devices/list"}) Response getDevicesInfo(@ApiParam(name = "deviceIdentifiers", value = "List of device identifiers", required = true) List deviceIdentifiers); @@ -93,6 +99,7 @@ public interface DeviceInformation { @ApiResponse(code = 400, message = ""), @ApiResponse(code = 500, message = "Internal Server Error") }) + @Permission(scope = "device-info", permissions = {"/permission/admin/device-mgt/admin/devices/list"}) Response getDeviceLocation(@ApiParam(name = "type", value = "Provide the device type, such as ios, " + "android or windows", required = true) @PathParam("type") String type, @ApiParam(name = "id", value = "Provide the device identifier", diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/DeviceNotification.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/DeviceNotification.java index 7941ac81c84..c2c5c99f81b 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/DeviceNotification.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/DeviceNotification.java @@ -18,21 +18,11 @@ package org.wso2.carbon.device.mgt.jaxrs.api; -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.*; +import org.wso2.carbon.apimgt.annotations.api.*; import org.wso2.carbon.device.mgt.common.notification.mgt.Notification; -import org.wso2.carbon.device.mgt.jaxrs.api.util.ResponsePayload; -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -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.*; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; @@ -40,6 +30,9 @@ import javax.ws.rs.core.Response; * DeviceNotification management REST-API implementation. * All end points support JSON, XMl with content negotiation. */ +@API(name = "Device Notification", version = "1.0.0", context = "/devicemgt_admin/notifications", tags = {"devicemgt_admin"}) + +// Below Api is for swagger annotations @Api(value = "DeviceNotification", description = "Device notification related operations can be found here.") @SuppressWarnings("NonJaxWsWebServices") @Path("/notifications") @@ -62,6 +55,9 @@ public interface DeviceNotification { responseContainer = "List"), @ApiResponse(code = 500, message = "Error occurred while retrieving the notification list") }) + @Permission(scope = "device-notification-view", permissions = { + "/permission/admin/device-mgt/admin/notifications/view", + "/permission/admin/device-mgt/user/notifications/view"}) Response getNotifications(); @GET @@ -80,6 +76,9 @@ public interface DeviceNotification { responseContainer = "List"), @ApiResponse(code = 500, message = "Error occurred while retrieving the notification list") }) + @Permission(scope = "device-notification-view", permissions = { + "/permission/admin/device-mgt/admin/notifications/view", + "/permission/admin/device-mgt/user/notifications/view"}) Response getNotificationsByStatus(@ApiParam(name = "status", value = "Provide the notification status as" + " the value for {status}", required = true) @PathParam("status") Notification.Status status); @@ -97,6 +96,8 @@ public interface DeviceNotification { @ApiResponse(code = 201, message = "Notification status updated successfully"), @ApiResponse(code = 500, message = "Error occurred while updating notification status") }) + @Permission(scope = "device-notification-modify", + permissions = {"/permission/admin/device-mgt/admin/notifications/modify"}) Response updateNotificationStatus(@ApiParam(name = "id", value = "Provide the ID of the notification" + " you wish you update", required = true) @PathParam("id") int id, @ApiParam(name = "status", value = "Provide the notification status as" @@ -114,6 +115,8 @@ public interface DeviceNotification { @ApiResponse(code = 201, message = "NNotification has added successfully"), @ApiResponse(code = 500, message = "Error occurred while updating notification status") }) + @Permission(scope = "device-notification-modify", + permissions = {"/permission/admin/device-mgt/admin/notifications/modify"}) Response addNotification(Notification notification); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/DeviceSearch.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/DeviceSearch.java index 38ea427db55..24a58f739cd 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/DeviceSearch.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/DeviceSearch.java @@ -19,6 +19,7 @@ package org.wso2.carbon.device.mgt.jaxrs.api; import io.swagger.annotations.*; +import org.wso2.carbon.apimgt.annotations.api.*; import org.wso2.carbon.device.mgt.common.device.details.DeviceWrapper; import org.wso2.carbon.device.mgt.common.search.SearchContext; @@ -30,6 +31,9 @@ import javax.ws.rs.core.Response; /** * Device search related operations such as getting device information. */ +@API(name = "Device Search", version = "1.0.0", context = "/devicemgt_admin/search", tags = {"devicemgt_admin"}) + +// Below Api is for swagger annotations @Path("/search") @Api(value = "DeviceSearch", description = "Device searching related operations can be found here.") @SuppressWarnings("NonJaxWsWebServices") @@ -47,6 +51,7 @@ public interface DeviceSearch { @ApiResponse(code = 200, message = "OK", response = DeviceWrapper.class, responseContainer = "List"), @ApiResponse(code = 500, message = "Error occurred while searching the device information") }) + @Permission(scope = "device-search", permissions = {"/permission/admin/device-mgt/admin/devices/list"}) Response getFilteredDeviceInfo(@ApiParam(name = "enrollmentCertificates", value = "List of search conditions", required = true) SearchContext searchContext); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Feature.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Feature.java index 5d85d40d4ea..64a2b243c57 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Feature.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Feature.java @@ -19,19 +19,18 @@ package org.wso2.carbon.device.mgt.jaxrs.api; import io.swagger.annotations.*; +import org.wso2.carbon.apimgt.annotations.api.*; -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; +import javax.ws.rs.*; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; /** * Features */ +@API(name = "Device Search", version = "1.0.0", context = "/devicemgt_admin/features", tags = {"devicemgt_admin"}) +// Below Api is for swagger annotations @Api(value = "Feature", description = "Feature management related operations can be found here.") @SuppressWarnings("NonJaxWsWebServices") @Path("/features") @@ -59,6 +58,8 @@ public interface Feature { @ApiResponses(value = { @ApiResponse(code = 200, message = "List of Features"), @ApiResponse(code = 500, message = "Error occurred while retrieving the list of features" + ".") }) + @Permission(scope = "device-search", permissions = {"/permission/admin/device-mgt/admin/devices/view", + "/permission/admin/device-mgt/user/devices/view"}) Response getFeatures(@ApiParam(name = "type", value = "Provide the device type, such as ios, android or windows", required = true) @PathParam("type") String type); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Group.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Group.java index 3f50b335964..20c5b2c9c89 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Group.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Group.java @@ -19,6 +19,8 @@ package org.wso2.carbon.device.mgt.jaxrs.api; import io.swagger.annotations.Api; +import org.wso2.carbon.apimgt.annotations.api.API; +import org.wso2.carbon.apimgt.annotations.api.Permission; import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup; @@ -35,80 +37,93 @@ import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; import java.util.List; +@API(name = "Group", version = "1.0.0", context = "/devicemgt_admin/groups", tags = {"devicemgt_admin"}) + +// Below Api is for swagger annotations @Path("/groups") @Api(value = "Group", description = "Group related operations such as get all the available groups, etc.") @SuppressWarnings("NonJaxWsWebServices") public interface Group { + @GET + @Produces("application/json") + @Permission(scope = "group-view", permissions = {"/permission/admin/device-mgt/user/groups/list"}) + Response getGroups(@QueryParam("start") int startIndex, @QueryParam("length") int length); + @POST @Consumes("application/json") + @Permission(scope = "group-add", permissions = {"/permission/admin/device-mgt/user/groups/add"}) Response createGroup(DeviceGroup group); + @Path("/owner/{owner}/name/{groupName}") + @GET + @Produces("application/json") + @Permission(scope = "group-view", permissions = {"/permission/admin/device-mgt/user/groups/view"}) + Response getGroup(@PathParam("groupName") String groupName, @PathParam("owner") String owner); + @Path("/owner/{owner}/name/{groupName}") @PUT @Consumes("application/json") @Produces("application/json") + @Permission(scope = "group-modify", permissions = {"/permission/admin/device-mgt/user/groups/update"}) Response updateGroup(@PathParam("groupName") String groupName, @PathParam("owner") String owner, DeviceGroup deviceGroup); @Path("/owner/{owner}/name/{groupName}") @DELETE + @Permission(scope = "group-remove", permissions = {"/permission/admin/device-mgt/user/groups/remove"}) Response deleteGroup(@PathParam("groupName") String groupName, @PathParam("owner") String owner); - @GET - @Produces("application/json") - Response getGroups(@QueryParam("start") int startIndex, @QueryParam("length") int length); + @Path("/all") @GET @Produces("application/json") + @Permission(scope = "group-view", permissions = {"/permission/admin/device-mgt/user/groups/list"}) Response getAllGroups(); @Path("/user/{user}") @GET @Produces("application/json") + @Permission(scope = "group-view", permissions = {"/permission/admin/device-mgt/user/groups/list"}) Response getGroups(@PathParam("user") String userName, @QueryParam("start") int startIndex, @QueryParam("length") int length); - @Path("/user/{user}/all") - @GET - @Produces("application/json") - Response getGroups(@PathParam("user") String userName); - - @Path("/owner/{owner}/name/{groupName}") - @GET - @Produces("application/json") - Response getGroup(@PathParam("groupName") String groupName, @PathParam("owner") String owner); - @Path("/user/{user}/search") @GET @Produces("application/json") + @Permission(scope = "group-view", permissions = {"/permission/admin/device-mgt/user/groups/list"}) Response findGroups(@QueryParam("groupName") String groupName, @PathParam("user") String user); @Path("/user/{user}/all") @GET @Produces("application/json") + @Permission(scope = "group-view", permissions = {"/permission/admin/device-mgt/user/groups/list"}) Response getGroups(@PathParam("user") String userName, @QueryParam("permission") String permission); @Path("/count") @GET @Produces("application/json") + @Permission(scope = "group-view", permissions = {"/permission/admin/device-mgt/user/groups/list"}) Response getAllGroupCount(); @Path("/user/{user}/count") @GET @Produces("application/json") + @Permission(scope = "group-view", permissions = {"/permission/admin/device-mgt/user/groups/list"}) Response getGroupCount(@PathParam("user") String userName); @Path("/owner/{owner}/name/{groupName}/share") @PUT @Produces("application/json") + @Permission(scope = "group-share", permissions = {"/permission/admin/device-mgt/user/groups/share"}) Response shareGroup(@PathParam("groupName") String groupName, @PathParam("owner") String owner, @FormParam("shareUser") String shareUser, @FormParam("roleName") String sharingRole); @Path("/owner/{owner}/name/{groupName}/unshare") @PUT @Produces("application/json") + @Permission(scope = "group-share", permissions = {"/permission/admin/device-mgt/user/groups/unshare"}) Response unShareGroup(@PathParam("groupName") String groupName, @PathParam("owner") String owner, @FormParam("unShareUser") String unShareUser, @FormParam("roleName") String sharingRole); @@ -116,58 +131,68 @@ public interface Group { @Path("/owner/{owner}/name/{groupName}/share/roles/{roleName}/permissions") @PUT @Produces("application/json") + @Permission(scope = "group-add", permissions = {"/permission/admin/device-mgt/admin/groups/roles/permissions/add"}) Response addSharing(@QueryParam("shareUser") String shareUser, @PathParam("groupName") String groupName, @PathParam("owner") String owner, @PathParam("roleName") String roleName, String[] permissions); @DELETE @Path("/owner/{owner}/name/{groupName}/share/roles/{roleName}/permissions") @Produces("application/json") + @Permission(scope = "group-remove", permissions = {"/permission/admin/device-mgt/admin/groups/roles/permissions/remove"}) Response removeSharing(@QueryParam("userName") String userName, @PathParam("groupName") String groupName, @PathParam("owner") String owner, @PathParam("roleName") String roleName); @GET @Path("/owner/{owner}/name/{groupName}/share/roles") @Produces("application/json") + @Permission(scope = "group-view", permissions = {"/permission/admin/device-mgt/admin/groups/roles"}) Response getRoles(@PathParam("groupName") String groupName, @PathParam("owner") String owner, @QueryParam("userName") String userName); @PUT @Path("/owner/{owner}/name/{groupName}/user/{userName}/share/roles") @Produces("application/json") + @Permission(scope = "group-modify", permissions = {"/permission/admin/device-mgt/admin/groups/roles"}) Response setRoles(@PathParam("groupName") String groupName, @PathParam("owner") String owner, @PathParam("userName") String userName, List selectedRoles); @GET @Path("/owner/{owner}/name/{groupName}/users") @Produces("application/json") + @Permission(scope = "group-view", permissions = {"/permission/admin/device-mgt/user/groups/list"}) Response getUsers(@PathParam("groupName") String groupName, @PathParam("owner") String owner); @GET @Path("/owner/{owner}/name/{groupName}/devices") @Produces("application/json") + @Permission(scope = "group-view", permissions = {"/permission/admin/device-mgt/admin/groups/roles"}) Response getDevices(@PathParam("groupName") String groupName, @PathParam("owner") String owner, @QueryParam("start") int startIdx, @QueryParam("length") int length); @GET @Path("/owner/{owner}/name/{groupName}/devices/count") @Produces("application/json") + @Permission(scope = "group-view", permissions = {"/permission/admin/device-mgt/user/groups/devices/count"}) Response getDeviceCount(@PathParam("groupName") String groupName, @PathParam("owner") String owner); @POST @Path("/owner/{owner}/name/{groupName}/devices") @Produces("application/json") + @Permission(scope = "group-add", permissions = {"/permission/admin/device-mgt/user/groups/devices/add"}) Response addDevice(@PathParam("groupName") String groupName, @PathParam("owner") String owner, DeviceIdentifier deviceIdentifier); @DELETE @Path("/owner/{owner}/name/{groupName}/devices/{deviceType}/{deviceId}") @Produces("application/json") + @Permission(scope = "group-remove", permissions = {"/permission/admin/device-mgt/user/groups/devices/remove"}) Response removeDevice(@PathParam("groupName") String groupName, @PathParam("owner") String owner, @PathParam("deviceId") String deviceId, @PathParam("deviceType") String deviceType); @GET @Path("/owner/{owner}/name/{groupName}/users/{userName}/permissions") @Produces("application/json") + @Permission(scope = "group-view", permissions = {"/permission/admin/device-mgt/user/groups/roles/permissions"}) Response getPermissions(@PathParam("userName") String userName, @PathParam("groupName") String groupName, @PathParam("owner") String owner); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/License.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/License.java index f8884e818c3..738a3d4588d 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/License.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/License.java @@ -19,6 +19,7 @@ package org.wso2.carbon.device.mgt.jaxrs.api; import io.swagger.annotations.Api; +import org.wso2.carbon.apimgt.annotations.api.*; import javax.ws.rs.*; import javax.ws.rs.core.MediaType; @@ -27,6 +28,9 @@ import javax.ws.rs.core.Response; /** * This class represents license related operations. */ +@API(name = "License", version = "1.0.0", context = "/devicemgt_admin/license", tags = {"devicemgt_admin"}) + +// Below Api is for swagger annotations @Api(value = "License") @Path("/license") @SuppressWarnings("NonJaxWsWebServices") @@ -42,6 +46,8 @@ public interface License { @GET @Path("{deviceType}/{languageCode}") @Produces({ MediaType.APPLICATION_JSON }) + @Permission(scope = "license-view", permissions = {"/permission/admin/device-mgt/admin/device/view", + "/permission/admin/device-mgt/user/devices/view"}) Response getLicense(@PathParam("deviceType") String deviceType, @PathParam("languageCode") String languageCode); @@ -54,6 +60,7 @@ public interface License { */ @POST @Path("{deviceType}") + @Permission(scope = "license-add", permissions = {"/permission/admin/device-mgt/admin/devices/view"}) Response addLicense(@PathParam("deviceType") String deviceType, org.wso2.carbon.device.mgt.common.license.mgt.License license); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Operation.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Operation.java index baefe958161..3004378df43 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Operation.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Operation.java @@ -19,6 +19,7 @@ package org.wso2.carbon.device.mgt.jaxrs.api; import io.swagger.annotations.*; +import org.wso2.carbon.apimgt.annotations.api.*; import org.wso2.carbon.device.mgt.common.app.mgt.Application; import org.wso2.carbon.device.mgt.jaxrs.api.common.MDMAPIException; import org.wso2.carbon.device.mgt.jaxrs.api.context.DeviceOperationContext; @@ -31,12 +32,18 @@ import javax.ws.rs.core.Response; /** * */ +@API(name = "Operation", version = "1.0.0", context = "/devicemgt_admin/operations", tags = {"devicemgt_admin"}) + +// Below Api is for swagger annotations @Path("/operations") @Api(value = "Operation", description = "Operation management related operations can be found here.") public interface Operation { /* @deprecated */ @GET + @Permission(scope = "operation-view", permissions = { + "/permission/admin/device-mgt/admin/devices/view", + "/permission/admin/device-mgt/user/devices/view"}) Response getAllOperations(); @GET @@ -56,6 +63,9 @@ public interface Operation { @ApiResponses(value = {@ApiResponse(code = 200, message = "List of Operations on a device."), @ApiResponse(code = 500, message = "Error occurred while fetching the operations for the " + "device.")}) + @Permission(scope = "operation-view", permissions = { + "/permission/admin/device-mgt/admin/devices/view", + "/permission/admin/device-mgt/user/devices/view"}) Response getDeviceOperations(@ApiParam(name = "type", value = "Define the device type as the value for {type}. " + "Example: ios, android or windows.", required = true) @PathParam("type") String type, @@ -85,6 +95,9 @@ public interface Operation { @ApiResponses(value = {@ApiResponse(code = 200, message = "List of Operations on a device."), @ApiResponse(code = 500, message = "Error occurred while fetching the operations for the " + "device.")}) + @Permission(scope = "operation-view", permissions = { + "/permission/admin/device-mgt/admin/devices/view", + "/permission/admin/device-mgt/user/devices/view"}) Response getAllDeviceOperations(@ApiParam(name = "type", value = "Define the device type as the value for {type}. " + "Example: ios, android or windows.", required = true) @PathParam("type") String type, @@ -93,6 +106,8 @@ public interface Operation { /* @deprecated */ @POST + @Permission(scope = "operation-modify", permissions = { + "/permission/admin/device-mgt/admin/devices/add"}) Response addOperation(DeviceOperationContext operationContext); @GET @@ -108,6 +123,9 @@ public interface Operation { @ApiResponses(value = {@ApiResponse(code = 200, message = "List of installed application details of a device.", response = Application.class, responseContainer = "List"), @ApiResponse(code = 500, message = "Error occurred while fetching the apps of the device" + ".")}) + @Permission(scope = "operation-view", permissions = { + "/permission/admin/device-mgt/admin/devices/view", + "/permission/admin/device-mgt/user/devices/view"}) Response getInstalledApps(@ApiParam(name = "type", value = "Define the device type as the value for {type}. " + "Example: ios, android or windows.", required = true) @PathParam("type") String type, @@ -116,6 +134,8 @@ public interface Operation { @POST @Path("installApp/{tenantDomain}") + @Permission(scope = "operation-install", + permissions = {"/permission/admin/device-mgt/admin/operations/applications/install-applications"}) @ApiOperation( consumes = MediaType.APPLICATION_JSON + ", " + MediaType.APPLICATION_XML, produces = MediaType.APPLICATION_JSON + ", " + MediaType.APPLICATION_XML, @@ -143,6 +163,8 @@ public interface Operation { notes = "Uninstall a selected application from a device.") @ApiResponses(value = {@ApiResponse(code = 200, message = "Operation was successfully added to the queue."), @ApiResponse(code = 500, message = "Error occurred while saving the operation.")}) + @Permission(scope = "operation-uninstall", + permissions = {"/permission/admin/device-mgt/admin/operations/applications/uninstall-applications"}) Response uninstallApplication(@ApiParam(name = "applicationWrapper", value = "Details about the application and" + " the users and roles it should be " + "uninstalled.", @@ -163,6 +185,7 @@ public interface Operation { notes = "This will return the operation details including the responses from the devices") @ApiResponses(value = {@ApiResponse(code = 200, message = "Activity details provided successfully.."), @ApiResponse(code = 500, message = "Error occurred while fetching the activity for the supplied id.")}) + @Permission(scope = "operation-view", permissions = {"/permission/admin/device-mgt/admin/devices/view"}) Response getActivity(@ApiParam(name = "id", value = "Provide activity id {id} as ACTIVITY_(number)", required = true) @PathParam("id") String id) throws MDMAPIException; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Policy.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Policy.java index 7189cff0e41..7067eb19f67 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Policy.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Policy.java @@ -19,6 +19,7 @@ package org.wso2.carbon.device.mgt.jaxrs.api; import io.swagger.annotations.*; +import org.wso2.carbon.apimgt.annotations.api.*; import org.wso2.carbon.device.mgt.jaxrs.api.common.MDMAPIException; import org.wso2.carbon.device.mgt.jaxrs.beans.PolicyWrapper; import org.wso2.carbon.device.mgt.jaxrs.beans.PriorityUpdatedPolicyWrapper; @@ -28,6 +29,9 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.util.List; +@API(name = "Policy", version = "1.0.0", context = "/devicemgt_admin/policies", tags = {"devicemgt_admin"}) + +// Below Api is for swagger annotations @Path("/policies") @Api(value = "Policy", description = "Policy management related operations can be found here.") public interface Policy { @@ -45,6 +49,7 @@ public interface Policy { @ApiResponses(value = {@ApiResponse(code = 201, message = "Created the policy."), @ApiResponse(code = 500, message = "Policy Management related error occurred when " + "adding the policy")}) + @Permission(scope = "policy-modify", permissions = {"/permission/admin/device-mgt/admin/policies/add"}) Response addPolicy(@ApiParam(name = "policyWrapper", value = "Policy details related to the operation.", required = true) PolicyWrapper policyWrapper); @@ -62,6 +67,7 @@ public interface Policy { @ApiResponses(value = {@ApiResponse(code = 201, message = "Created the policy."), @ApiResponse(code = 500, message = "Policy Management related error occurred when " + "adding the policy")}) + @Permission(scope = "policy-modify", permissions = {"/permission/admin/device-mgt/admin/policies/add"}) Response addActivePolicy(@ApiParam(name = "policyWrapper", value = "Policy details related to the operation.", required = true) PolicyWrapper policyWrapper); @@ -79,6 +85,7 @@ public interface Policy { response = org.wso2.carbon.policy.mgt.common.Policy.class, responseContainer = "List"), @ApiResponse(code = 500, message = "Policy Management related error occurred when " + "fetching the policies.")}) + @Permission(scope = "policy-view", permissions = {"/permission/admin/device-mgt/admin/policies/list"}) Response getAllPolicies(); @GET @@ -94,6 +101,7 @@ public interface Policy { @ApiResponses(value = {@ApiResponse(code = 200, message = "Fetched policy details."), @ApiResponse(code = 500, message = "Policy Management related error occurred when " + "fetching the policies.")}) + @Permission(scope = "policy-view", permissions = {"/permission/admin/device-mgt/admin/policies/list"}) Response getPolicy(@ApiParam(name = "id", value = "Policy ID value to identify a policy uniquely.", required = true) @PathParam("id") int policyId); @@ -108,6 +116,7 @@ public interface Policy { response = int.class) @ApiResponses(value = {@ApiResponse(code = 200, message = "Fetched the policy count."), @ApiResponse(code = 500, message = "Error while Fetching the policy count.")}) + @Permission(scope = "policy-view", permissions = {"/permission/admin/device-mgt/admin/policies/list"}) Response getPolicyCount(); @PUT @@ -122,6 +131,7 @@ public interface Policy { @ApiResponses(value = {@ApiResponse(code = 201, message = "Policy has been updated successfully."), @ApiResponse(code = 500, message = "Policy Management related exception in policy " + "update")}) + @Permission(scope = "policy-modify", permissions = {"/permission/admin/device-mgt/admin/policies/update"}) Response updatePolicy(@ApiParam(name = "policyWrapper", value = "Policy details related to the operation.", required = true) PolicyWrapper policyWrapper, @ApiParam(name = "id", value = "Policy ID value to identify a policy uniquely.", @@ -141,6 +151,7 @@ public interface Policy { @ApiResponses(value = {@ApiResponse(code = 200, message = "Policy Priorities successfully updated."), @ApiResponse(code = 400, message = "Policy priorities did not update."), @ApiResponse(code = 500, message = "Error in updating policy priorities.")}) + @Permission(scope = "policy-modify", permissions = {"/permission/admin/device-mgt/admin/policies/update"}) Response updatePolicyPriorities(@ApiParam(name = "priorityUpdatedPolicies", value = "List of policy update details..", required = true) List priorityUpdatedPolicies); @@ -158,6 +169,7 @@ public interface Policy { @ApiResponses(value = {@ApiResponse(code = 200, message = "Policies have been successfully deleted."), @ApiResponse(code = 400, message = "Policy does not exist."), @ApiResponse(code = 500, message = "Error in deleting policies.")}) + @Permission(scope = "policy-modify", permissions = {"/permission/admin/device-mgt/admin/policies/remove"}) Response bulkRemovePolicy(@ApiParam(name = "policyIds", value = "Policy ID list to be deleted.", required = true) List policyIds); @@ -173,6 +185,9 @@ public interface Policy { "in the inactive state to the active state.") @ApiResponses(value = {@ApiResponse(code = 200, message = "Policies have been successfully activated."), @ApiResponse(code = 500, message = "Error in activating policies.")}) + @Permission(scope = "policy-modify", permissions = { + "/permission/admin/device-mgt/admin/policies/update", + "/permission/admin/device-mgt/admin/policies/add"}) Response activatePolicy(@ApiParam(name = "policyIds", value = "Policy ID list to be activated.", required = true) List policyIds); @@ -188,6 +203,9 @@ public interface Policy { "is in the active state to the inactive state.") @ApiResponses(value = {@ApiResponse(code = 200, message = "Policies have been successfully deactivated."), @ApiResponse(code = 500, message = "Error in deactivating policies.")}) + @Permission(scope = "policy-modify", permissions = { + "/permission/admin/device-mgt/admin/policies/update", + "/permission/admin/device-mgt/admin/policies/add"}) Response inactivatePolicy(@ApiParam(name = "policyIds", value = "Policy ID list to be deactivated.", required = true) List policyIds) throws MDMAPIException; @@ -206,6 +224,7 @@ public interface Policy { " you need to apply the changes to push the policy changes to the existing devices.") @ApiResponses(value = {@ApiResponse(code = 200, message = "Changes have been successfully updated."), @ApiResponse(code = 500, message = "Error in updating policies.")}) + @Permission(scope = "policy-modify", permissions = {"/permission/admin/device-mgt/admin/policies/update"}) Response applyChanges(); @GET @@ -223,23 +242,28 @@ public interface Policy { @ApiResponses(value = {@ApiResponse(code = 200, message = "Policy monitoring service started successfully."), @ApiResponse(code = 500, message = "Policy Management related exception when starting " + "monitoring service.")}) + @Permission(scope = "policy-modify", permissions = {"/permission/admin/device-mgt/admin/policies/add"}) Response startTaskService(@ApiParam(name = "milliseconds", value = "Policy monitoring frequency in milliseconds.", required = true) @PathParam("milliseconds") int monitoringFrequency); @GET @Path("update-task/{milliseconds}") + @Permission(scope = "policy-modify", permissions = {"/permission/admin/device-mgt/admin/policies/add"}) Response updateTaskService(@PathParam("milliseconds") int monitoringFrequency); @GET @Path("stop-task") + @Permission(scope = "policy-modify", permissions = {"/permission/admin/device-mgt/admin/policies/add"}) Response stopTaskService(); @GET @Path("{type}/{id}") + @Permission(scope = "policy-view", permissions = {"/permission/admin/device-mgt/admin/policies/list"}) Response getComplianceDataOfDevice(@PathParam("type") String type, @PathParam("id") String id); @GET @Path("{type}/{id}/active-policy") + @Permission(scope = "policy-view", permissions = {"/permission/admin/device-mgt/admin/policies/list"}) @ApiOperation( consumes = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON, diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Profile.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Profile.java index 7762048499c..dcb2bf573d3 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Profile.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Profile.java @@ -19,6 +19,7 @@ package org.wso2.carbon.device.mgt.jaxrs.api; import io.swagger.annotations.Api; +import org.wso2.carbon.apimgt.annotations.api.*; import javax.ws.rs.DELETE; import javax.ws.rs.POST; @@ -29,20 +30,26 @@ import javax.ws.rs.core.Response; /** * These end points provide profile related operations. */ +@API(name = "Profile", version = "1.0.0", context = "/devicemgt_admin/profiles", tags = {"devicemgt_admin"}) + +// Below Api is for swagger annotations @Api(value = "Profile") @Path("/profiles") @SuppressWarnings("NonJaxWsWebServices") public interface Profile { @POST + @Permission(scope = "profile", permissions = {"/permission/admin/device-mgt/admin/policies/add"}) Response addProfile(org.wso2.carbon.policy.mgt.common.Profile profile); @POST @Path("{id}") + @Permission(scope = "profile", permissions = {"/permission/admin/device-mgt/admin/policies/update"}) Response updateProfile(org.wso2.carbon.policy.mgt.common.Profile profile, @PathParam("id") String profileId); @DELETE @Path("{id}") + @Permission(scope = "profile", permissions = {"/permission/admin/device-mgt/admin/policies/remove"}) Response deleteProfile(@PathParam("id") int profileId); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Role.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Role.java index a9cc10cf83b..735e4cfaf8c 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Role.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Role.java @@ -19,6 +19,7 @@ package org.wso2.carbon.device.mgt.jaxrs.api; import io.swagger.annotations.*; +import org.wso2.carbon.apimgt.annotations.api.*; import org.wso2.carbon.device.mgt.jaxrs.beans.RoleWrapper; import org.wso2.carbon.user.mgt.common.UIPermissionNode; @@ -27,6 +28,9 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.util.List; +@API(name = "Role", version = "1.0.0", context = "/devicemgt_admin/roles", tags = {"devicemgt_admin"}) + +// Below Api is for swagger annotations @Path("/roles") @Api(value = "Role", description = "Role management related operations can be found here.") public interface Role { @@ -43,6 +47,11 @@ public interface Role { response = String.class) @ApiResponses(value = { @ApiResponse(code = 200, message = "List of available roles"), @ApiResponse(code = 500, message = "Error occurred while fetching the role list.") }) + @Permission(scope = "roles-view", permissions = { + "/permission/admin/device-mgt/admin/roles/list", + "/permission/admin/device-mgt/admin/users/view", + "/permission/admin/device-mgt/admin/policies/add", + "/permission/admin/device-mgt/admin/policies/update"}) Response getAllRoles(); @GET @@ -58,6 +67,9 @@ public interface Role { response = String.class) @ApiResponses(value = { @ApiResponse(code = 200, message = "List of available roles"), @ApiResponse(code = 500, message = "Error occurred while fetching the role list.") }) + @Permission(scope = "roles-view", permissions = { + "/permission/admin/device-mgt/admin/users/add", + "/permission/admin/device-mgt/admin/roles/list"}) Response getRolesOfUserStore(@ApiParam(name = "userStore", value = "Provide the name of the UserStore you wish to get the" + " details from ", required = true) @PathParam("userStore") String userStore); @@ -79,6 +91,9 @@ public interface Role { @ApiResponses(value = { @ApiResponse(code = 200, message = "List of matching roles"), @ApiResponse(code = 500, message = "Error occurred while fetching the matching role list" + ".") }) + @Permission(scope = "roles-view", permissions = { + "/permission/admin/device-mgt/admin/users/add", + "/permission/admin/device-mgt/admin/roles/list"}) Response getMatchingRoles(@ApiParam(name = "filter", value = "Provide a character or a few characters in the" + " role name.", required = true) @QueryParam("filter") String filter); @@ -99,6 +114,7 @@ public interface Role { @ApiResponses(value = { @ApiResponse(code = 200, message = "Permission details of a role"), @ApiResponse(code = 500, message = "Error occurred while fetching the permission " + "details of a role.") }) + @Permission(scope = "roles-view", permissions = {"/permission/admin/device-mgt/admin/roles/list"}) Response getPermissions(@ApiParam(name = "rolename", value = "Provide the name of the role you wish to get the " + "permission details.", required = true) @QueryParam("rolename") String roleName); @@ -115,6 +131,7 @@ public interface Role { response = RoleWrapper.class) @ApiResponses(value = { @ApiResponse(code = 200, message = "Details of a role."), @ApiResponse(code = 500, message = "Error occurred while retrieving the user role.") }) + @Permission(scope = "roles-view", permissions = {"/permission/admin/device-mgt/admin/roles/list"}) Response getRole(@ApiParam(name = "rolename", value = "Provide the name of the role you wish to get the " + "details.", required = true) @QueryParam("rolename") String roleName); @@ -129,6 +146,7 @@ public interface Role { notes = "You are able to add a new role to WSO2 EMM using the REST API.") @ApiResponses(value = { @ApiResponse(code = 200, message = "Added the role."), @ApiResponse(code = 500, message = "Error occurred while adding the user role.") }) + @Permission(scope = "roles-modify", permissions = {"/permission/admin/device-mgt/admin/roles/add"}) Response addRole(@ApiParam(name = "roleWrapper", value = "Role and permission details.", required = true) RoleWrapper roleWrapper); @@ -144,6 +162,7 @@ public interface Role { @ApiResponses(value = { @ApiResponse(code = 200, message = "Updated the role."), @ApiResponse(code = 500, message = "Error occurred while updating the user role details" + ".") }) + @Permission(scope = "roles-modify", permissions = {"/permission/admin/device-mgt/admin/roles/update"}) Response updateRole(@ApiParam(name = "rolename", value = "Provide the name of the role you wish to update.", required = true) @QueryParam("rolename") String roleName, @ApiParam(name = "roleWrapper", value = "Role and permission details.", @@ -161,6 +180,7 @@ public interface Role { @ApiResponses(value = { @ApiResponse(code = 200, message = "Deleted the role."), @ApiResponse(code = 500, message = "Error occurred while deleting the user role details" + ".") }) + @Permission(scope = "roles-modify", permissions = {"/permission/admin/device-mgt/admin/roles/remove"}) Response deleteRole(@ApiParam(name = "rolename", value = "Provide the name of the role you wish to delete.", required = true) @QueryParam("rolename") String roleName); @@ -180,6 +200,7 @@ public interface Role { "role using this API.") @ApiResponses(value = { @ApiResponse(code = 200, message = "Added Users to a Role."), @ApiResponse(code = 500, message = "Error occurred while saving the users of the role.") }) + @Permission(scope = "roles-modify", permissions = {"/permission/admin/device-mgt/admin/roles/update"}) Response updateUsers(@ApiParam(name = "rolename", value = "Provide the name of the role you wish to update.", required = true) @QueryParam("rolename") String roleName, @ApiParam(name = "userList", value = "Provide the names of the users you will to update.", @@ -196,6 +217,7 @@ public interface Role { notes = "Get the number of roles in WSO2 EMM.") @ApiResponses(value = { @ApiResponse(code = 200, message = "Retrieved the role count."), @ApiResponse(code = 500, message = "Error occurred while retrieving the role count.") }) + @Permission(scope = "roles-modify", permissions = {"/permission/admin/device-mgt/admin/roles/list"}) Response getRoleCount(); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/User.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/User.java index 7ac2eeab7f1..eef95c6b6b0 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/User.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/User.java @@ -20,6 +20,7 @@ package org.wso2.carbon.device.mgt.jaxrs.api; import io.swagger.annotations.*; import org.apache.axis2.databinding.types.soapencoding.Integer; +import org.wso2.carbon.apimgt.annotations.api.*; import org.wso2.carbon.device.mgt.jaxrs.beans.UserCredentialWrapper; import org.wso2.carbon.device.mgt.jaxrs.beans.UserWrapper; @@ -31,6 +32,9 @@ import java.util.List; /** * This represents the JAX-RS services of User related functionality. */ +@API(name = "User", version = "1.0.0", context = "/devicemgt_admin/users", tags = {"devicemgt_admin"}) + +// Below Api is for swagger annotations @Path("/users") @Api(value = "User", description = "User management related operations can be found here.") public interface User { @@ -48,6 +52,7 @@ public interface User { @ApiResponse(code = 201, message = "Created"), @ApiResponse(code = 500, message = "Exception in trying to add user by username: 'username'") }) + @Permission(scope = "user-modify", permissions = {"/permission/admin/device-mgt/admin/user/add"}) Response addUser(@ApiParam(name = "userWrapper", value = "Includes the required properties to add a user" + " as the value", required = true) UserWrapper userWrapper); @@ -66,6 +71,7 @@ public interface User { @ApiResponse(code = 400, message = "User by username: 'username' does not exist"), @ApiResponse(code = 500, message = "Exception in trying to retrieve user by username: 'username'") }) + @Permission(scope = "user-view", permissions = {"/permission/admin/device-mgt/admin/user/view"}) Response getUser(@ApiParam(name = "username", value = "Provide the name of the user you wish to get the" + " details of as the value", required = true) @QueryParam("username") String username); @@ -86,6 +92,7 @@ public interface User { + "request made to update user was refused"), @ApiResponse(code = 500, message = "Exception in trying to update user by username: 'username'") }) + @Permission(scope = "user-modify", permissions = {"/permission/admin/device-mgt/admin/user/update"}) Response updateUser(@ApiParam(name = "userWrapper", value = "Provide the name of the user you wish to get" + " the details of as the value", required = true) UserWrapper userWrapper, @ApiParam(name = "username", value = "Provide the name of the user you wish to get " @@ -106,6 +113,7 @@ public interface User { @ApiResponse(code = 400, message = "User by username: 'username' does not exist for removal"), @ApiResponse(code = 500, message = "Exception in trying to remove user by username: 'username'") }) + @Permission(scope = "user-modify", permissions = {"/permission/admin/device-mgt/admin/user/remove"}) Response removeUser(@ApiParam(name = "username", value = "Provide the name of the user you wish to delete" + " as the value for {username}", required = true) @QueryParam("username") String username); @@ -126,6 +134,7 @@ public interface User { @ApiResponse(code = 400, message = "User by username: 'username' does not exist for role retrieval"), @ApiResponse(code = 500, message = "Exception in trying to retrieve roles for user by username: 'username'") }) + @Permission(scope = "user-view", permissions = {"/permission/admin/device-mgt/admin/user/view"}) Response getRolesOfUser(@ApiParam(name = "username", value = "Provide the user name of the user you wish to get" + " the role details", required = true) @QueryParam("username") String username); @@ -143,11 +152,13 @@ public interface User { @ApiResponse(code = 201, message = "All users were successfully retrieved"), @ApiResponse(code = 500, message = "Error occurred while retrieving the list of users") }) + @Permission(scope = "user-view", permissions = {"/permission/admin/device-mgt/admin/user/list"}) Response getAllUsers(); @GET @Path("{filter}") @Produces({MediaType.APPLICATION_JSON}) + @Permission(scope = "user-view", permissions = {"/permission/admin/device-mgt/admin/user/list"}) Response getMatchingUsers(@PathParam("filter") String filter); @GET @@ -167,6 +178,7 @@ public interface User { + " user count: 'count'"), @ApiResponse(code = 500, message = "Error occurred while retrieving the list of users") }) + @Permission(scope = "user-view", permissions = {"/permission/admin/device-mgt/admin/user/list"}) Response getAllUsersByUsername(@ApiParam(name = "username", value = "Provide any user detail of the user" + " as the value for {username} to retrieve the user details, such " + "as email address, first name or last name", required = true) @@ -190,6 +202,7 @@ public interface User { + " user count: 'count'"), @ApiResponse(code = 500, message = "Error occurred while retrieving the list of users") }) + @Permission(scope = "user-view", permissions = {"/permission/admin/device-mgt/admin/user/list"}) Response getAllUserNamesByUsername(@ApiParam(name = "username", value = "Provide a character or a few " + "character in the user name as the value for {username}", required = true) @QueryParam("username") String userName); @@ -207,6 +220,7 @@ public interface User { @ApiResponse(code = 200, message = "Email invitation was successfully sent to user"), @ApiResponse(code = 500, message = "Error occurred while retrieving the list of users") }) + @Permission(scope = "user-modify", permissions = {"/permission/admin/device-mgt/admin/users/invite"}) Response inviteExistingUsersToEnrollDevice(@ApiParam(name = "usernames", value = "List of the users to be" + " invited as the ", required = true) List usernames); @@ -226,6 +240,9 @@ public interface User { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 500, message = "Device management error") }) + @Permission(scope = "user-view", permissions = { + "/permission/admin/device-mgt/user/devices/list", + "/permission/admin/device-mgt/admin/devices/list"}) Response getAllDeviceOfUser(@ApiParam(name = "username", value = "Provide the name of the user you wish " + "to get the details", required = true) @QueryParam("username") String username, @@ -247,11 +264,13 @@ public interface User { @ApiResponse(code = 500, message = "Error occurred while retrieving the list of users that exist" + " within the current tenant") }) + @Permission(scope = "user-view", permissions = {"/permission/admin/device-mgt/admin/user/list"}) Response getUserCount(); @PUT @Path("{roleName}/users") @Produces({MediaType.APPLICATION_JSON}) + @Permission(scope = "user-modify", permissions = {"/permission/admin/device-mgt/admin/user/update"}) Response updateRoles(@PathParam("roleName") String roleName, List userList); @POST @@ -272,6 +291,7 @@ public interface User { + " Character Encoding is not supported"), @ApiResponse(code = 500, message = "Internal Server Error") }) + @Permission(scope = "user-modify", permissions = {"/permission/admin/login"}) Response resetPassword(@ApiParam(name = "credentials", value = "Include the required properties to change" + " the user password as value", required = true) UserCredentialWrapper credentials); @@ -297,6 +317,7 @@ public interface User { + " Character Encoding is not supported"), @ApiResponse(code = 500, message = "Internal Server Error") }) + @Permission(scope = "user-modify", permissions = {"/permission/admin/device-mgt/admin/users/password-reset"}) Response resetPasswordByAdmin(@ApiParam(name = "credentials", value = "Include the required properties " + "to change a user password as value", required = true) UserCredentialWrapper credentials); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/impl/GroupImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/impl/GroupImpl.java index ebe9228c31b..14c63238186 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/impl/GroupImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/impl/GroupImpl.java @@ -174,25 +174,6 @@ public class GroupImpl implements Group { } } - @Override - @Path("/user/{user}/all") - @GET - @Produces("application/json") - public Response getGroups(@PathParam("user") String userName) { - try { - List deviceGroups = DeviceMgtAPIUtils.getGroupManagementProviderService() - .getGroups(userName); - if (deviceGroups.size() > 0) { - return Response.status(Response.Status.OK).entity(deviceGroups).build(); - } else { - return Response.status(Response.Status.NOT_FOUND).build(); - } - } catch (GroupManagementException e) { - log.error(e.getMessage(), e); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build(); - } - } - @Override @Path("/owner/{owner}/name/{groupName}") @GET diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/META-INF/permissions.xml b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/META-INF/permissions.xml index 9b4e0862219..b06dc5fb4f4 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/META-INF/permissions.xml +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/META-INF/permissions.xml @@ -943,13 +943,13 @@ get certificate in the database - /device-mgt/android/certificate/Get + /device-mgt/android/certificate/view /certificates/* GET - get certificate in the database - /device-mgt/android/certificate/Get + Remove certificate in the database + /device-mgt/android/certificate/remove /certificates/* DELETE @@ -986,7 +986,7 @@ Group Delete - /device-mgt/user/groups/delete + /device-mgt/user/groups/remove /groups/owner/*/name/* DELETE @@ -1091,7 +1091,7 @@ Group Delete Permissions - /device-mgt/admin/groups/roles/permissions/delete + /device-mgt/admin/groups/roles/permissions/remove /groups/owner/*/name/*/share/roles/*/permissions DELETE diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/web.xml b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/web.xml index 6ee1d3216e3..406c03fac7b 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/web.xml +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/web.xml @@ -70,6 +70,16 @@ true + + + managed-api-enabled + true + + + managed-api-owner + admin + + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/DeviceManagementConstants.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/DeviceManagementConstants.java index b4d9dd3fbb7..379ca8c3d6c 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/DeviceManagementConstants.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/DeviceManagementConstants.java @@ -28,9 +28,6 @@ public final class DeviceManagementConstants { public static final String PROPERTY_SETUP = "setup"; public static final String DEFAULT_LICENSE_CONFIG_XML_NAME = "license-config.xml"; - public static final String PROPERTY_PROFILE = "profile"; - public static final String PROFILE_DT_WORKER = "dtWorker"; - public static final String PROFILE_DEFAULT = "default"; } public static final class AppManagement { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/authorization/DeviceAccessAuthorizationServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/authorization/DeviceAccessAuthorizationServiceImpl.java index 4707bcdd4c9..4c2e57d8bda 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/authorization/DeviceAccessAuthorizationServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/authorization/DeviceAccessAuthorizationServiceImpl.java @@ -47,7 +47,7 @@ import java.util.Map; */ public class DeviceAccessAuthorizationServiceImpl implements DeviceAccessAuthorizationService { - private final static String EMM_ADMIN_PERMISSION = "/device-mgt/admin-device-access"; + private final static String CDM_ADMIN_PERMISSION = "/device-mgt/admin"; private static Log log = LogFactory.getLog(DeviceAccessAuthorizationServiceImpl.class); public DeviceAccessAuthorizationServiceImpl() { @@ -221,7 +221,7 @@ public class DeviceAccessAuthorizationServiceImpl implements DeviceAccessAuthori if (userRealm != null && userRealm.getAuthorizationManager() != null) { return userRealm.getAuthorizationManager() .isUserAuthorized(removeTenantDomain(username), - PermissionUtils.getAbsolutePermissionPath(EMM_ADMIN_PERMISSION), + PermissionUtils.getAbsolutePermissionPath(CDM_ADMIN_PERMISSION), PermissionMethod.UI_EXECUTE); } return false; @@ -249,7 +249,7 @@ public class DeviceAccessAuthorizationServiceImpl implements DeviceAccessAuthori private boolean addAdminPermissionToRegistry() throws PermissionManagementException { Permission permission = new Permission(); - permission.setPath(PermissionUtils.getAbsolutePermissionPath(EMM_ADMIN_PERMISSION)); + permission.setPath(PermissionUtils.getAbsolutePermissionPath(CDM_ADMIN_PERMISSION)); return PermissionUtils.putPermission(permission); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/DeviceManagementConfig.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/DeviceManagementConfig.java index 30f7f7ea949..0891164cb06 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/DeviceManagementConfig.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/DeviceManagementConfig.java @@ -17,7 +17,6 @@ */ package org.wso2.carbon.device.mgt.core.config; -import org.wso2.carbon.device.mgt.core.config.deviceType.DTConfiguration; import org.wso2.carbon.device.mgt.core.config.identity.IdentityConfigurations; import org.wso2.carbon.device.mgt.core.config.policy.PolicyConfiguration; import org.wso2.carbon.device.mgt.core.config.task.TaskConfiguration; @@ -39,7 +38,7 @@ public final class DeviceManagementConfig { private IdentityConfigurations identityConfigurations; private PolicyConfiguration policyConfiguration; private List pushNotificationProviders; - private DTConfiguration dTDepyloymentConfiguration; + @XmlElement(name = "ManagementRepository", required = true) public DeviceManagementConfigRepository getDeviceManagementConfigRepository() { @@ -78,16 +77,6 @@ public final class DeviceManagementConfig { this.taskConfiguration = taskConfiguration; } - @XmlElement(name = "DTDeploymentConfiguration", required = true) - public DTConfiguration getDTDeploymentConfiguration() { - return dTDepyloymentConfiguration; - } - - public void setDTDeploymentConfiguration(DTConfiguration dTDeploymentConfiguration) { - this.dTDepyloymentConfiguration = dTDeploymentConfiguration; - } - - @XmlElementWrapper(name = "PushNotificationProviders", required = true) @XmlElement(name = "Provider", required = true) public List getPushNotificationProviders() { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/deviceType/DTConfiguration.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/deviceType/DTConfiguration.java deleted file mode 100644 index 14a3af12748..00000000000 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/deviceType/DTConfiguration.java +++ /dev/null @@ -1,53 +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. - */ - - -/** - * This class will read the configurations related to task. This task will be responsible for adding the operations. - */ -package org.wso2.carbon.device.mgt.core.config.deviceType; - -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; - -@XmlRootElement(name = "DTDepyloymentConfiguration") -public class DTConfiguration { - - private String dtHostAddress; - private String dtHostPort; - - @XmlElement(name = "DTHostAddress", required = true) - public String getDtHostAddress() { - return dtHostAddress; - } - - public void setDtHostAddress(String dtHostAddress) { - this.dtHostAddress = dtHostAddress; - } - - @XmlElement(name = "DTHostPort", required = true) - public String getDtHostPort() { - return dtHostPort; - } - - public void setDtHostPort(String dtHostPort) { - this.dtHostPort = dtHostPort; - } - - -} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/main/java/org/wso2/carbon/device/mgt/extensions/feature/mgt/lifecycle/listener/FeatureManagementLifecycleListener.java b/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/main/java/org/wso2/carbon/device/mgt/extensions/feature/mgt/lifecycle/listener/FeatureManagementLifecycleListener.java index 9753b4cfdd7..6fba635c3ef 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/main/java/org/wso2/carbon/device/mgt/extensions/feature/mgt/lifecycle/listener/FeatureManagementLifecycleListener.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/main/java/org/wso2/carbon/device/mgt/extensions/feature/mgt/lifecycle/listener/FeatureManagementLifecycleListener.java @@ -24,7 +24,6 @@ import org.apache.catalina.core.StandardContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.device.mgt.common.Feature; -import org.wso2.carbon.device.mgt.core.DeviceManagementConstants; import org.wso2.carbon.device.mgt.extensions.feature.mgt.GenericFeatureManager; import org.wso2.carbon.device.mgt.extensions.feature.mgt.annotations.DeviceType; import org.wso2.carbon.device.mgt.extensions.feature.mgt.util.AnnotationProcessor; @@ -44,6 +43,9 @@ public class FeatureManagementLifecycleListener implements LifecycleListener { private static final Log log = LogFactory.getLog(FeatureManagementLifecycleListener.class); private static final String UNLIMITED = "Unlimited"; + public static final String PROPERTY_PROFILE = "profile"; + public static final String PROFILE_DT_WORKER = "dtWorker"; + public static final String PROFILE_DEFAULT = "default"; @Override public void lifecycleEvent(LifecycleEvent lifecycleEvent) { @@ -53,10 +55,10 @@ public class FeatureManagementLifecycleListener implements LifecycleListener { String param = servletContext.getInitParameter(PARAM_MANAGED_API_ENABLED); boolean isManagedApi = (param != null && !param.isEmpty()) && Boolean.parseBoolean(param); - String profile = System.getProperty(DeviceManagementConstants.Common.PROPERTY_PROFILE); + String profile = System.getProperty(PROPERTY_PROFILE); - if ((profile.equalsIgnoreCase(DeviceManagementConstants.Common.PROFILE_DT_WORKER) || - profile.equalsIgnoreCase(DeviceManagementConstants.Common.PROFILE_DEFAULT)) && isManagedApi) { + if ((profile.equalsIgnoreCase(PROFILE_DT_WORKER) || + profile.equalsIgnoreCase(PROFILE_DEFAULT)) && isManagedApi) { try { AnnotationProcessor annotationProcessor = new AnnotationProcessor(context); Set annotatedAPIClasses = annotationProcessor.scanStandardContext(DeviceType.class.getName()); diff --git a/components/email-sender/org.wso2.carbon.email.sender.core/src/main/java/org/wso2/carbon/email/sender/core/internal/EmailSenderServiceComponent.java b/components/email-sender/org.wso2.carbon.email.sender.core/src/main/java/org/wso2/carbon/email/sender/core/internal/EmailSenderServiceComponent.java index 3d4e3933ed7..8747ca6e19f 100644 --- a/components/email-sender/org.wso2.carbon.email.sender.core/src/main/java/org/wso2/carbon/email/sender/core/internal/EmailSenderServiceComponent.java +++ b/components/email-sender/org.wso2.carbon.email.sender.core/src/main/java/org/wso2/carbon/email/sender/core/internal/EmailSenderServiceComponent.java @@ -52,7 +52,7 @@ public class EmailSenderServiceComponent { if (log.isDebugEnabled()) { log.debug("Initializing email sender core bundle"); } - /* Initializing email sende configuration */ + /* Initializing email sender configuration */ EmailSenderConfig.init(); /* Setting up default email templates */ diff --git a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/pom.xml b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/pom.xml index c08f1274042..2bd6852d061 100644 --- a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/pom.xml +++ b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/pom.xml @@ -113,7 +113,12 @@ org.wso2.carbon.user.core, org.wso2.carbon.user.core.config, org.wso2.carbon.user.core.util, - org.wso2.carbon.utils + org.wso2.carbon.utils, + org.wso2.carbon.context, + org.wso2.carbon.identity.oauth.cache, + org.wso2.carbon.identity.oauth.config, + org.wso2.carbon.identity.oauth2.dao, + org.wso2.carbon.utils.multitenancy diff --git a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/OAuthExtUtils.java b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/OAuthExtUtils.java index 32ad46ccd14..93a6db287c7 100644 --- a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/OAuthExtUtils.java +++ b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/OAuthExtUtils.java @@ -47,6 +47,7 @@ public class OAuthExtUtils { private static final String DEFAULT_SCOPE_NAME = "default"; private static final String UI_EXECUTE = "ui.execute"; private static final String REST_API_SCOPE_CACHE = "REST_API_SCOPE_CACHE"; + private static final int START_INDEX = 0; /** * This method is used to get the tenant id when given tenant domain. @@ -260,4 +261,12 @@ public class OAuthExtUtils { return authorizedScopes; } + public static String extractUserName(String username) { + if (username == null || username.isEmpty()) { + return null; + } + String trimmedName = username.trim(); + return trimmedName.substring(START_INDEX, trimmedName.lastIndexOf('@')); + } + } diff --git a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/validators/ExtendedJDBCScopeValidator.java b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/validators/ExtendedJDBCScopeValidator.java new file mode 100644 index 00000000000..8f5ffa25141 --- /dev/null +++ b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/validators/ExtendedJDBCScopeValidator.java @@ -0,0 +1,200 @@ +/* + * 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.oauth.extensions.validators; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.base.MultitenantConstants; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.device.mgt.oauth.extensions.internal.OAuthExtensionsDataHolder; +import org.wso2.carbon.identity.application.common.model.User; +import org.wso2.carbon.identity.core.util.IdentityTenantUtil; +import org.wso2.carbon.identity.oauth.cache.CacheEntry; +import org.wso2.carbon.identity.oauth.cache.OAuthCache; +import org.wso2.carbon.identity.oauth.cache.OAuthCacheKey; +import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration; +import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception; +import org.wso2.carbon.identity.oauth2.dao.TokenMgtDAO; +import org.wso2.carbon.identity.oauth2.model.AccessTokenDO; +import org.wso2.carbon.identity.oauth2.model.ResourceScopeCacheEntry; +import org.wso2.carbon.identity.oauth2.validators.OAuth2ScopeValidator; +import org.wso2.carbon.user.api.AuthorizationManager; +import org.wso2.carbon.user.api.UserStoreException; +import org.wso2.carbon.user.core.service.RealmService; +import org.wso2.carbon.utils.multitenancy.MultitenantUtils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +@SuppressWarnings("unused") +public class ExtendedJDBCScopeValidator extends OAuth2ScopeValidator{ + + private static final Log log = LogFactory.getLog(ExtendedJDBCScopeValidator.class); + private static final String UI_EXECUTE = "ui.execute"; + + + @Override + public boolean validateScope(AccessTokenDO accessTokenDO, String resource) throws IdentityOAuth2Exception { + //Get the list of scopes associated with the access token + String[] scopes = accessTokenDO.getScope(); + + //If no scopes are associated with the token + if (scopes == null || scopes.length == 0) { + return true; + } + + String resourceScope = null; + TokenMgtDAO tokenMgtDAO = new TokenMgtDAO(); + + boolean cacheHit = false; + // Check the cache, if caching is enabled. + if (OAuthServerConfiguration.getInstance().isCacheEnabled()) { + OAuthCache oauthCache = OAuthCache.getInstance(); + OAuthCacheKey cacheKey = new OAuthCacheKey(resource); + CacheEntry result = oauthCache.getValueFromCache(cacheKey); + + //Cache hit + if (result instanceof ResourceScopeCacheEntry) { + resourceScope = ((ResourceScopeCacheEntry) result).getScope(); + cacheHit = true; + } + } + + if (!cacheHit) { + resourceScope = tokenMgtDAO.findScopeOfResource(resource); + + if (OAuthServerConfiguration.getInstance().isCacheEnabled()) { + OAuthCache oauthCache = OAuthCache.getInstance(); + OAuthCacheKey cacheKey = new OAuthCacheKey(resource); + ResourceScopeCacheEntry cacheEntry = new ResourceScopeCacheEntry(resourceScope); + //Store resourceScope in cache even if it is null (to avoid database calls when accessing resources for + //which scopes haven't been defined). + oauthCache.addToCache(cacheKey, cacheEntry); + } + } + + //Return TRUE if - There does not exist a scope definition for the resource + if (resourceScope == null) { + if(log.isDebugEnabled()){ + log.debug("Resource '" + resource + "' is not protected with a scope"); + } + return true; + } + + List scopeList = new ArrayList<>(Arrays.asList(scopes)); + + //If the access token does not bear the scope required for accessing the Resource. + if(!scopeList.contains(resourceScope)){ + if(log.isDebugEnabled()){ + log.debug("Access token '" + accessTokenDO.getAccessToken() + "' does not bear the scope '" + + resourceScope + "'"); + } + return false; + } + + try { + //Get the permissions associated with the scope, if any + Set permissionsOfScope = tokenMgtDAO.getRolesOfScopeByScopeKey(resourceScope); + + //If the scope doesn't have any permissions associated with it. + if(permissionsOfScope == null || permissionsOfScope.isEmpty()){ + if(log.isDebugEnabled()){ + log.debug("Did not find any roles associated to the scope " + resourceScope); + } + return true; + } + + if(log.isDebugEnabled()){ + StringBuilder logMessage = new StringBuilder("Found permissions of scope '" + resourceScope + "' "); + for(String permission : permissionsOfScope){ + logMessage.append(permission); + logMessage.append(", "); + } + log.debug(logMessage.toString()); + } + + User authorizedUser = accessTokenDO.getAuthzUser(); + RealmService realmService = OAuthExtensionsDataHolder.getInstance().getRealmService(); + + int tenantId = realmService.getTenantManager().getTenantId(authorizedUser.getTenantDomain()); + + if (tenantId == 0 || tenantId == -1) { + tenantId = IdentityTenantUtil.getTenantIdOfUser(authorizedUser.getUserName()); + } + + AuthorizationManager authorizationManager; + String[] userRoles; + boolean tenantFlowStarted = false; + + try{ + //If this is a tenant user + if(tenantId != MultitenantConstants.SUPER_TENANT_ID){ + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain( + realmService.getTenantManager().getDomain(tenantId),true); + tenantFlowStarted = true; + } + + authorizationManager = realmService.getTenantUserRealm(tenantId).getAuthorizationManager(); + + } finally { + if (tenantFlowStarted) { + PrivilegedCarbonContext.endTenantFlow(); + } + } + boolean status = false; + String username = MultitenantUtils.getTenantAwareUsername(authorizedUser.getUserName()); + for (String permission : permissionsOfScope) { + if (authorizationManager != null) { + String userStore = authorizedUser.getUserStoreDomain(); + + if (userStore != null) { + status = authorizationManager + .isUserAuthorized(userStore + "/" + username, permission, UI_EXECUTE); + } else { + status = authorizationManager.isUserAuthorized(username , permission, UI_EXECUTE); + } + if (status) { + break; + } + } + } + + if (status) { + if(log.isDebugEnabled()){ + log.debug("User '" + authorizedUser.getUserName() + "' is authorized"); + } + return true; + } + + if(log.isDebugEnabled()){ + log.debug("No permissions associated for the user " + authorizedUser.getUserName()); + } + return false; + + } catch (UserStoreException e) { + //Log and return since we do not want to stop issuing the token in case of scope validation failures. + log.error("Error when getting the tenant's UserStoreManager or when getting roles of user ", e); + return false; + } + } + +} diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml index 08114db1909..eced0aba7da 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml @@ -117,7 +117,10 @@ org.apache.axiom.soap.impl.builder, org.apache.axiom.om, org.apache.axiom.om.impl.builder, - org.apache.axiom.om.util + org.apache.axiom.om.util, + org.wso2.carbon.registry.core.*, + org.wso2.carbon.registry.common.*;version="${carbon.registry.imp.pkg.version.range}", + org.wso2.carbon.registry.indexing.*; version="${carbon.registry.imp.pkg.version.range}", @@ -214,6 +217,14 @@ commons-pool.wso2 commons-pool + + org.wso2.carbon.registry + org.wso2.carbon.registry.indexing + + + org.wso2.carbon + org.wso2.carbon.registry.core + diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/AuthenticatorFrameworkDataHolder.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/AuthenticatorFrameworkDataHolder.java index 7b2813561be..ba6b1a2f6c9 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/AuthenticatorFrameworkDataHolder.java +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/AuthenticatorFrameworkDataHolder.java @@ -21,6 +21,8 @@ package org.wso2.carbon.webapp.authenticator.framework; import org.wso2.carbon.certificate.mgt.core.service.CertificateManagementService; import org.wso2.carbon.device.mgt.core.scep.SCEPManager; import org.wso2.carbon.identity.oauth2.OAuth2TokenValidationService; +import org.wso2.carbon.registry.core.service.TenantRegistryLoader; +import org.wso2.carbon.registry.indexing.service.TenantIndexingLoader; import org.wso2.carbon.user.core.service.RealmService; public class AuthenticatorFrameworkDataHolder { @@ -30,6 +32,8 @@ public class AuthenticatorFrameworkDataHolder { private CertificateManagementService certificateManagementService; private SCEPManager scepManager; private OAuth2TokenValidationService oAuth2TokenValidationService; + private TenantIndexingLoader tenantIndexingLoader; + private TenantRegistryLoader tenantRegistryLoader; private static AuthenticatorFrameworkDataHolder thisInstance = new AuthenticatorFrameworkDataHolder(); @@ -92,4 +96,21 @@ public class AuthenticatorFrameworkDataHolder { OAuth2TokenValidationService oAuth2TokenValidationService) { this.oAuth2TokenValidationService = oAuth2TokenValidationService; } + + public TenantIndexingLoader getTenantIndexingLoader() { + return tenantIndexingLoader; + } + + public void setTenantIndexingLoader( + TenantIndexingLoader tenantIndexingLoader) { + this.tenantIndexingLoader = tenantIndexingLoader; + } + + public void setTenantRegistryLoader(TenantRegistryLoader tenantRegistryLoader) { + this.tenantRegistryLoader = tenantRegistryLoader; + } + + public TenantRegistryLoader getTenantRegistryLoader() { + return tenantRegistryLoader; + } } diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/JWTAuthenticator.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/JWTAuthenticator.java index cb1d11d34fa..91c1b966f71 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/JWTAuthenticator.java +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/JWTAuthenticator.java @@ -22,23 +22,24 @@ import com.nimbusds.jose.JOSEException; import com.nimbusds.jose.JWSVerifier; import com.nimbusds.jose.crypto.RSASSAVerifier; import com.nimbusds.jwt.SignedJWT; -import org.apache.axiom.util.base64.Base64Utils; -import org.apache.axis2.transport.http.HTTPConstants; import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.core.util.KeyStoreManager; -import org.wso2.carbon.user.api.TenantManager; +import org.wso2.carbon.registry.core.exceptions.RegistryException; +import org.wso2.carbon.registry.core.service.TenantRegistryLoader; import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.api.UserStoreManager; -import org.wso2.carbon.utils.multitenancy.MultitenantConstants; import org.wso2.carbon.utils.multitenancy.MultitenantUtils; import org.wso2.carbon.webapp.authenticator.framework.AuthenticationInfo; import org.wso2.carbon.webapp.authenticator.framework.AuthenticatorFrameworkDataHolder; +import java.security.PublicKey; import java.security.interfaces.RSAPublicKey; import java.text.ParseException; +import java.util.HashMap; +import java.util.Map; import java.util.Properties; import java.util.StringTokenizer; @@ -47,11 +48,12 @@ import java.util.StringTokenizer; */ public class JWTAuthenticator implements WebappAuthenticator { - private static final Log log = LogFactory.getLog(JWTAuthenticator.class); - public static final String SIGNED_JWT_AUTH_USERNAME = "Username"; - private static final String JWT_AUTHENTICATOR = "JWT"; - private static final String JWT_ASSERTION_HEADER = "X-JWT-Assertion"; - + private static final Log log = LogFactory.getLog(JWTAuthenticator.class); + private static final String SIGNED_JWT_AUTH_USERNAME = "http://wso2.org/claims/enduser"; + private static final String SIGNED_JWT_AUTH_TENANT_ID = "http://wso2.org/claims/enduserTenantId"; + private static final String JWT_AUTHENTICATOR = "JWT"; + private static final String JWT_ASSERTION_HEADER = "X-JWT-Assertion"; + private static final Map publicKeyHolder = new HashMap<>(); @Override public void init() { @@ -59,46 +61,49 @@ public class JWTAuthenticator implements WebappAuthenticator { @Override public boolean canHandle(Request request) { - String authorizationHeader = request.getHeader(JWTAuthenticator.JWT_ASSERTION_HEADER); - if((authorizationHeader != null) && !authorizationHeader.isEmpty()){ - return true; - } - return false; + String authorizationHeader = request.getHeader(JWTAuthenticator.JWT_ASSERTION_HEADER); + if ((authorizationHeader != null) && !authorizationHeader.isEmpty()) { + return true; + } + return false; } @Override - public AuthenticationInfo authenticate(Request request, Response response) { - String requestUri = request.getRequestURI(); - AuthenticationInfo authenticationInfo = new AuthenticationInfo(); - if (requestUri == null || "".equals(requestUri)) { - authenticationInfo.setStatus(Status.CONTINUE); - } - StringTokenizer tokenizer = new StringTokenizer(requestUri, "/"); - String context = tokenizer.nextToken(); - if (context == null || "".equals(context)) { + public AuthenticationInfo authenticate(Request request, Response response) { + String requestUri = request.getRequestURI(); + AuthenticationInfo authenticationInfo = new AuthenticationInfo(); + if (requestUri == null || "".equals(requestUri)) { + authenticationInfo.setStatus(Status.CONTINUE); + } + StringTokenizer tokenizer = new StringTokenizer(requestUri, "/"); + String context = tokenizer.nextToken(); + if (context == null || "".equals(context)) { authenticationInfo.setStatus(Status.CONTINUE); - } - - //Get the filesystem keystore default primary certificate - KeyStoreManager keyStoreManager = KeyStoreManager.getInstance(MultitenantConstants.SUPER_TENANT_ID); - try { - keyStoreManager.getDefaultPrimaryCertificate(); - String authorizationHeader = request.getHeader(HTTPConstants.HEADER_AUTHORIZATION); - String headerData = decodeAuthorizationHeader(authorizationHeader); - JWSVerifier verifier = - new RSASSAVerifier((RSAPublicKey) keyStoreManager.getDefaultPublicKey()); - SignedJWT jwsObject = SignedJWT.parse(headerData); - if (jwsObject.verify(verifier)) { - String username = jwsObject.getJWTClaimsSet().getStringClaim(SIGNED_JWT_AUTH_USERNAME); - String tenantDomain = MultitenantUtils.getTenantDomain(username); - username = MultitenantUtils.getTenantAwareUsername(username); - TenantManager tenantManager = AuthenticatorFrameworkDataHolder.getInstance().getRealmService(). - getTenantManager(); - int tenantId = tenantManager.getTenantId(tenantDomain); - if (tenantId == -1) { - log.error("tenantDomain is not valid. username : " + username + ", tenantDomain " + - ": " + tenantDomain); - } else { + } + + try { + String authorizationHeader = request.getHeader(JWT_ASSERTION_HEADER); + + SignedJWT jwsObject = SignedJWT.parse(authorizationHeader); + String username = jwsObject.getJWTClaimsSet().getStringClaim(SIGNED_JWT_AUTH_USERNAME); + String tenantDomain = MultitenantUtils.getTenantDomain(username); + int tenantId = Integer.parseInt(jwsObject.getJWTClaimsSet().getStringClaim(SIGNED_JWT_AUTH_TENANT_ID)); + PublicKey publicKey = publicKeyHolder.get(tenantDomain); + if (publicKey == null) { + loadTenantRegistry(tenantId); + KeyStoreManager keyStoreManager = KeyStoreManager.getInstance(tenantId); + publicKey = keyStoreManager.getDefaultPublicKey(); + publicKeyHolder.put(tenantDomain, publicKey); + } + + //Get the filesystem keystore default primary certificate + JWSVerifier verifier = new RSASSAVerifier((RSAPublicKey) publicKey); + if (jwsObject.verify(verifier)) { + username = MultitenantUtils.getTenantAwareUsername(username); + if (tenantId == -1) { + log.error("tenantDomain is not valid. username : " + username + ", tenantDomain " + + ": " + tenantDomain); + } else { UserStoreManager userStore = AuthenticatorFrameworkDataHolder.getInstance().getRealmService(). getTenantUserRealm(tenantId).getUserStoreManager(); if (userStore.isExistingUser(username)) { @@ -108,41 +113,25 @@ public class JWTAuthenticator implements WebappAuthenticator { authenticationInfo.setStatus(Status.CONTINUE); } } - } - } catch (UserStoreException e) { - log.error("Error occurred while obtaining the user.", e); - } catch (ParseException e) { - log.error("Error occurred while parsing the JWT header.", e); - } catch (JOSEException e) { - log.error("Error occurred while verifying the JWT header.", e); - } catch (Exception e) { - log.error("Error occurred while verifying the JWT header.", e); - } - return authenticationInfo; - } - - private String decodeAuthorizationHeader(String authorizationHeader) { - - if(authorizationHeader == null) { - return null; - } - - String[] splitValues = authorizationHeader.trim().split(" "); - byte[] decodedBytes = Base64Utils.decode(splitValues[1].trim()); - if (decodedBytes != null) { - return new String(decodedBytes); - } else { - if (log.isDebugEnabled()) { - log.debug("Error decoding authorization header."); - } - return null; - } - } - - @Override - public String getName() { - return JWTAuthenticator.JWT_AUTHENTICATOR; - } + } else { + authenticationInfo.setStatus(Status.FAILURE); + } + } catch (UserStoreException e) { + log.error("Error occurred while obtaining the user.", e); + } catch (ParseException e) { + log.error("Error occurred while parsing the JWT header.", e); + } catch (JOSEException e) { + log.error("Error occurred while verifying the JWT header.", e); + } catch (Exception e) { + log.error("Error occurred while verifying the JWT header.", e); + } + return authenticationInfo; + } + + @Override + public String getName() { + return JWTAuthenticator.JWT_AUTHENTICATOR; + } @Override public void setProperties(Properties properties) { @@ -158,4 +147,11 @@ public class JWTAuthenticator implements WebappAuthenticator { public String getProperty(String name) { return null; } + + private static void loadTenantRegistry(int tenantId) throws RegistryException { + TenantRegistryLoader tenantRegistryLoader = AuthenticatorFrameworkDataHolder.getInstance(). + getTenantRegistryLoader(); + AuthenticatorFrameworkDataHolder.getInstance().getTenantIndexingLoader().loadTenantIndex(tenantId); + tenantRegistryLoader.loadTenantRegistry(tenantId); + } } diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/WebappAuthenticatorFrameworkServiceComponent.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/WebappAuthenticatorFrameworkServiceComponent.java index 4a342186a73..40769e0b3fb 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/WebappAuthenticatorFrameworkServiceComponent.java +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/WebappAuthenticatorFrameworkServiceComponent.java @@ -25,6 +25,8 @@ import org.osgi.service.component.ComponentContext; import org.wso2.carbon.certificate.mgt.core.service.CertificateManagementService; import org.wso2.carbon.device.mgt.core.scep.SCEPManager; import org.wso2.carbon.identity.oauth2.OAuth2TokenValidationService; +import org.wso2.carbon.registry.core.service.TenantRegistryLoader; +import org.wso2.carbon.registry.indexing.service.TenantIndexingLoader; import org.wso2.carbon.tomcat.ext.valves.CarbonTomcatValve; import org.wso2.carbon.tomcat.ext.valves.TomcatValveContainer; import org.wso2.carbon.user.core.service.RealmService; @@ -67,6 +69,17 @@ import java.util.Properties; * policy="dynamic" * bind="setOAuth2ValidationService" * unbind="unsetOAuth2ValidationService" + * @scr.reference name="tenant.indexloader" + * interface="org.wso2.carbon.registry.indexing.service.TenantIndexingLoader" + * cardinality="1..1" + * policy="dynamic" + * bind="setTenantIndexLoader" + * unbind="unsetTenantIndexLoader" + * @scr.reference name="tenant.registryloader" + * interface="org.wso2.carbon.registry.core.service.TenantRegistryLoader" + * cardinality="1..1" policy="dynamic" + * bind="setTenantRegistryLoader" + * unbind="unsetTenantRegistryLoader" */ public class WebappAuthenticatorFrameworkServiceComponent { @@ -183,4 +196,20 @@ public class WebappAuthenticatorFrameworkServiceComponent { } AuthenticatorFrameworkDataHolder.getInstance().setOAuth2TokenValidationService(null); } + + protected void setTenantIndexLoader(TenantIndexingLoader tenantIndexLoader) { + AuthenticatorFrameworkDataHolder.getInstance().setTenantIndexingLoader(tenantIndexLoader); + } + + protected void unsetTenantIndexLoader(TenantIndexingLoader tenantIndexLoader) { + AuthenticatorFrameworkDataHolder.getInstance().setTenantIndexingLoader(null); + } + + protected void setTenantRegistryLoader(TenantRegistryLoader tenantRegistryLoader) { + AuthenticatorFrameworkDataHolder.getInstance().setTenantRegistryLoader(tenantRegistryLoader); + } + + protected void unsetTenantRegistryLoader(TenantRegistryLoader tenantRegistryLoader) { + AuthenticatorFrameworkDataHolder.getInstance().setTenantRegistryLoader(null); + } } diff --git a/features/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher.feature/src/main/resources/build.properties b/features/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher.feature/src/main/resources/build.properties new file mode 100644 index 00000000000..9c86577d768 --- /dev/null +++ b/features/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher.feature/src/main/resources/build.properties @@ -0,0 +1 @@ +custom = true diff --git a/features/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher.feature/src/main/resources/conf/webapp-publisher-config.xml b/features/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher.feature/src/main/resources/conf/webapp-publisher-config.xml new file mode 100644 index 00000000000..013bcc3860a --- /dev/null +++ b/features/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher.feature/src/main/resources/conf/webapp-publisher-config.xml @@ -0,0 +1,32 @@ + + + + + + + + http://localhost:${carbon.http.port} + + + true + + \ No newline at end of file diff --git a/features/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher.feature/src/main/resources/p2.inf b/features/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher.feature/src/main/resources/p2.inf new file mode 100644 index 00000000000..3d6782a96ff --- /dev/null +++ b/features/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher.feature/src/main/resources/p2.inf @@ -0,0 +1,2 @@ +instructions.configure = \ +org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.apimgt.webapp.publisher_${feature.version}/conf/webapp-publisher-config.xml,target:${installFolder}/../../conf/etc/webapp-publisher-config.xml,overwrite:true);\ diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/pom.xml b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/pom.xml index ec7962494d4..78609ac5d0b 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/pom.xml +++ b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/pom.xml @@ -120,6 +120,7 @@ org.wso2.carbon.identity:org.wso2.carbon.identity.oauth.stub:${carbon.identity.version} + org.wso2.carbon.core.server:${carbon.kernel.version} diff --git a/pom.xml b/pom.xml index 772bcecc457..33ecf3817bd 100644 --- a/pom.xml +++ b/pom.xml @@ -1378,16 +1378,16 @@ org.wso2.carbon.databridge.core ${carbon.analytics.common.version} - - org.wso2.carbon.commons - org.wso2.carbon.databridge.commons - ${carbon.commons.version} - - - org.wso2.carbon.commons - org.wso2.carbon.databridge.commons.thrift - ${carbon.commons.version} - + + + + + + + + + + org.wso2.carbon.analytics-common org.wso2.carbon.databridge.commons @@ -1448,9 +1448,9 @@ - org.wso2.carbon.commons + org.wso2.carbon.identity org.wso2.carbon.user.mgt - ${carbon.commons.version} + ${carbon.identity.version} provided @@ -1721,7 +1721,7 @@ 6.1.1 4.4.3 - [4.4.0, 4.5.0) + [4.4.0, 5.0.0) 1.5.4 1.3 @@ -1768,9 +1768,6 @@ 4.5.0 - - 4.4.8 - 4.5.8 @@ -1789,7 +1786,7 @@ 2.6.0.wso2v1 - 5.0.3 + 5.0.4 (5.0.0,6.0.0]