Merge pull request #269 from milanperera/apim

Implemented API publishing to Synapse Gateway
revert-70aa11f8
Milan Perera 8 years ago
commit 073ed252e7

@ -105,10 +105,6 @@
<groupId>org.wso2.carbon.governance</groupId>
<artifactId>org.wso2.carbon.governance.lcm</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.core</artifactId>
</dependency>
</dependencies>

@ -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() +

@ -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();
}
}

@ -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<URITemplate> uriTemplates = config.getUriTemplates();
Map<String, Scope> 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<String>(Arrays.asList(permissions.split(","))).toArray(new String[0]);
return StringUtils.join(unique, ",");
}
}

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

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

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

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

@ -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<API> 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<API> getUnpublishedApis() {
return unpublishedApis;
}
public void setUnpublishedApis(Stack<API> unpublishedApis) {
this.unpublishedApis = unpublishedApis;
}
}

@ -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) {

@ -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<String> 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");

@ -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<Path>) 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<APIResource> getApiResources(String resourceRootContext, String apiRootContext,
Method[] annotatedMethods) throws Throwable {
List<APIResource> resourceList;
resourceList = new ArrayList<APIResource>();
private List<APIResource> getApiResources(String resourceRootContext, Method[] annotatedMethods) throws Throwable {
List<APIResource> 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
*

@ -143,9 +143,19 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.commons</groupId>
<groupId>org.wso2.carbon.identity</groupId>
<artifactId>org.wso2.carbon.user.mgt</artifactId>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
@ -227,6 +237,10 @@
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.apimgt.annotations</artifactId>
</dependency>
</dependencies>
</project>

@ -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)

@ -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 <JSON_PAYLOAD> 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 <JSON_PAYLOAD> value",
required = true) TenantConfiguration configuration);

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

@ -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<DeviceIdentifier> 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",

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

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

@ -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);

@ -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<String> 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);
}

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

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

@ -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<PriorityUpdatedPolicyWrapper> 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<Integer> 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<Integer> 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<Integer> 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,

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

@ -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();
}

@ -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 <JSON_PAYLOAD> 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 <JSON_PAYLOAD>", required = true)
List<String> 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<String> 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 <JSON_PAYLOAD> 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 <JSON_PAYLOAD> value",
required = true) UserCredentialWrapper credentials);

@ -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<DeviceGroup> 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

@ -943,13 +943,13 @@
</Permission>
<Permission>
<name>get certificate in the database</name>
<path>/device-mgt/android/certificate/Get</path>
<path>/device-mgt/android/certificate/view</path>
<url>/certificates/*</url>
<method>GET</method>
</Permission>
<Permission>
<name>get certificate in the database</name>
<path>/device-mgt/android/certificate/Get</path>
<name>Remove certificate in the database</name>
<path>/device-mgt/android/certificate/remove</path>
<url>/certificates/*</url>
<method>DELETE</method>
</Permission>
@ -986,7 +986,7 @@
<Permission>
<name>Group Delete</name>
<path>/device-mgt/user/groups/delete</path>
<path>/device-mgt/user/groups/remove</path>
<url>/groups/owner/*/name/*</url>
<method>DELETE</method>
</Permission>
@ -1091,7 +1091,7 @@
<Permission>
<name>Group Delete Permissions</name>
<path>/device-mgt/admin/groups/roles/permissions/delete</path>
<path>/device-mgt/admin/groups/roles/permissions/remove</path>
<url>/groups/owner/*/name/*/share/roles/*/permissions</url>
<method>DELETE</method>
</Permission>

@ -70,6 +70,16 @@
<param-value>true</param-value>
</context-param-->
<!--publish to apim-->
<context-param>
<param-name>managed-api-enabled</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>managed-api-owner</param-name>
<param-value>admin</param-value>
</context-param>
<!-- Below configuration is used to redirect http requests to https -->
<security-constraint>
<web-resource-collection>

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

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

@ -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<String> 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<String> getPushNotificationProviders() {

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

@ -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<String> annotatedAPIClasses = annotationProcessor.scanStandardContext(DeviceType.class.getName());

@ -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 */

@ -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
</Import-Package>
</instructions>
</configuration>

@ -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('@'));
}
}

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

@ -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}",
</Import-Package>
</instructions>
</configuration>
@ -214,6 +217,14 @@
<groupId>commons-pool.wso2</groupId>
<artifactId>commons-pool</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.registry</groupId>
<artifactId>org.wso2.carbon.registry.indexing</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.registry.core</artifactId>
</dependency>
</dependencies>
</project>

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

@ -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<String, PublicKey> 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);
}
}

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

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
~ 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 configuration file represents the configuration that are needed
when publishing APIs to API Manager
-->
<WebappPublisherConfigs>
<!-- This host is used to define the host address which is used to publish APIs -->
<Host>http://localhost:${carbon.http.port}</Host>
<!-- If it is true, the APIs of this instance will be published to the defined host -->
<PublishAPI>true</PublishAPI>
</WebappPublisherConfigs>

@ -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);\

@ -120,6 +120,7 @@
<bundleDef>
org.wso2.carbon.identity:org.wso2.carbon.identity.oauth.stub:${carbon.identity.version}
</bundleDef>
<!-- Below should be bundled with the email verification -->
</bundles>
<importFeatures>
<importFeatureDef>org.wso2.carbon.core.server:${carbon.kernel.version}</importFeatureDef>

@ -1378,16 +1378,16 @@
<artifactId>org.wso2.carbon.databridge.core</artifactId>
<version>${carbon.analytics.common.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.carbon.commons</groupId>
<artifactId>org.wso2.carbon.databridge.commons</artifactId>
<version>${carbon.commons.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.carbon.commons</groupId>
<artifactId>org.wso2.carbon.databridge.commons.thrift</artifactId>
<version>${carbon.commons.version}</version>
</dependency>
<!--<dependency>-->
<!--<groupId>org.wso2.carbon.commons</groupId>-->
<!--<artifactId>org.wso2.carbon.databridge.commons</artifactId>-->
<!--<version>${carbon.commons.version}</version>-->
<!--</dependency>-->
<!--<dependency>-->
<!--<groupId>org.wso2.carbon.commons</groupId>-->
<!--<artifactId>org.wso2.carbon.databridge.commons.thrift</artifactId>-->
<!--<version>${carbon.commons.version}</version>-->
<!--</dependency>-->
<dependency>
<groupId>org.wso2.carbon.analytics-common</groupId>
<artifactId>org.wso2.carbon.databridge.commons</artifactId>
@ -1448,9 +1448,9 @@
</dependency>
<dependency>
<groupId>org.wso2.carbon.commons</groupId>
<groupId>org.wso2.carbon.identity</groupId>
<artifactId>org.wso2.carbon.user.mgt</artifactId>
<version>${carbon.commons.version}</version>
<version>${carbon.identity.version}</version>
<scope>provided</scope>
</dependency>
@ -1721,7 +1721,7 @@
<properties>
<testng.version>6.1.1</testng.version>
<carbon.kernel.version>4.4.3</carbon.kernel.version>
<carbon.kernel.version.range>[4.4.0, 4.5.0)</carbon.kernel.version.range>
<carbon.kernel.version.range>[4.4.0, 5.0.0)</carbon.kernel.version.range>
<carbon.p2.plugin.version>1.5.4</carbon.p2.plugin.version>
<maven-buildnumber-plugin.version>1.3</maven-buildnumber-plugin.version>
@ -1768,9 +1768,6 @@
<!-- Carbon Multi-tenancy -->
<carbon.multitenancy.version>4.5.0</carbon.multitenancy.version>
<!-- Carbon Registry -->
<carbon.registry.version>4.4.8</carbon.registry.version>
<!-- Carbon Governance -->
<carbon.governance.version>4.5.8</carbon.governance.version>
@ -1789,7 +1786,7 @@
<version.commons.lang>2.6.0.wso2v1</version.commons.lang>
<!-- Carbon API Management -->
<carbon.api.mgt.version>5.0.3</carbon.api.mgt.version>
<carbon.api.mgt.version>5.0.4</carbon.api.mgt.version>
<carbon.api.mgt.version.range>(5.0.0,6.0.0]</carbon.api.mgt.version.range>
<!-- Carbon Analytics Commons -->

Loading…
Cancel
Save