Modified authorization to support API gateway

revert-70aa11f8
mharindu 9 years ago
parent 4c50d4842d
commit ffc7542d4d

@ -0,0 +1,36 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.apimgt.annotations.api;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* This class is the representation of custom developed Permission annotation.
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Permission {
String scope();
String[] permissions();
}

@ -18,16 +18,17 @@
*/
package org.wso2.carbon.apimgt.webapp.publisher;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.apimgt.api.APIManagementException;
import org.wso2.carbon.apimgt.api.APIProvider;
import org.wso2.carbon.apimgt.api.FaultGatewaysException;
import org.wso2.carbon.apimgt.api.model.API;
import org.wso2.carbon.apimgt.api.model.APIIdentifier;
import org.wso2.carbon.apimgt.api.model.APIStatus;
import org.wso2.carbon.apimgt.api.model.URITemplate;
import org.wso2.carbon.apimgt.api.model.*;
import org.wso2.carbon.apimgt.impl.APIManagerFactory;
import org.wso2.carbon.apimgt.webapp.publisher.internal.APIPublisherDataHolder;
import org.wso2.carbon.context.PrivilegedCarbonContext;
@ -38,10 +39,7 @@ import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import javax.xml.stream.XMLStreamException;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* This class represents the concrete implementation of the APIPublisherService that corresponds to providing all
@ -80,7 +78,7 @@ public class APIPublisherServiceImpl implements APIPublisherService {
+ api.getId().getVersion() + "'");
}
} else {
api.setStatus(APIStatus.PUBLISHED);
api.setStatus(provider.getAPI(api.getId()).getStatus());
provider.updateAPI(api);
if (log.isDebugEnabled()) {
log.debug("An API already exists with the name '" + api.getId().getApiName() +
@ -106,8 +104,11 @@ public class APIPublisherServiceImpl implements APIPublisherService {
private String createSwaggerDefinition(API api) {
Map<String, JsonObject> httpVerbsMap = new HashMap<>();
List<Scope> scopes = new ArrayList<>();
for (URITemplate uriTemplate : api.getUriTemplates()) {
JsonObject authType = new JsonObject();
authType.addProperty("x-auth-type", "Application%20%26%20Application%20User");
JsonObject response = new JsonObject();
response.addProperty("200", "");
@ -117,7 +118,16 @@ public class APIPublisherServiceImpl implements APIPublisherService {
if (httpVerbs == null) {
httpVerbs = new JsonObject();
}
httpVerbs.add(uriTemplate.getHTTPVerb().toLowerCase(), responses);
JsonObject httpVerb = new JsonObject();
httpVerb.add("responses", response);
httpVerb.addProperty("x-auth-type", "Application%20%26%20Application%20User");
httpVerb.addProperty("x-throttling-tier", "Unlimited");
if (uriTemplate.getScope() != null) {
httpVerb.addProperty("x-scope", uriTemplate.getScope().getName());
scopes.add(uriTemplate.getScope());
}
httpVerbs.add(uriTemplate.getHTTPVerb().toLowerCase(), httpVerb);
httpVerbsMap.put(uriTemplate.getUriTemplate(), httpVerbs);
}
@ -138,6 +148,20 @@ public class APIPublisherServiceImpl implements APIPublisherService {
swaggerDefinition.addProperty("swagger", "2.0");
swaggerDefinition.add("info", info);
// adding scopes to definition
if (!api.getScopes().isEmpty()) {
Gson gson = new Gson();
JsonElement element = gson.toJsonTree(api.getScopes(), new TypeToken<Set<Scope>>() {
}.getType());
if (element != null) {
JsonArray apiScopes = element.getAsJsonArray();
JsonObject apim = new JsonObject();
apim.add("x-wso2-scopes", apiScopes);
JsonObject wso2Security = new JsonObject();
wso2Security.add("apim", apim);
swaggerDefinition.add("x-wso2-security", wso2Security);
}
}
return swaggerDefinition.toString();
}

@ -24,35 +24,18 @@ import org.wso2.carbon.apimgt.api.model.*;
import org.wso2.carbon.apimgt.impl.APIConstants;
import org.wso2.carbon.apimgt.webapp.publisher.internal.APIPublisherDataHolder;
import org.wso2.carbon.base.MultitenantConstants;
import org.wso2.carbon.user.api.TenantManager;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.utils.CarbonUtils;
import org.wso2.carbon.utils.ConfigurationContextService;
import org.wso2.carbon.utils.NetworkUtils;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import java.util.*;
public class APIPublisherUtil {
private static final String DEFAULT_API_VERSION = "1.0.0";
public static final String API_VERSION_PARAM="{version}";
public static final String API_PUBLISH_ENVIRONEMENT = "Production and Sandbox";
private static final String API_VERSION_PARAM="{version}";
private static final String API_PUBLISH_ENVIRONMENT = "Production and Sandbox";
enum HTTPMethod {
GET, POST, DELETE, PUT, OPTIONS
}
private static List<HTTPMethod> httpMethods;
static {
httpMethods = new ArrayList<HTTPMethod>(5);
httpMethods.add(HTTPMethod.GET);
httpMethods.add(HTTPMethod.POST);
httpMethods.add(HTTPMethod.DELETE);
httpMethods.add(HTTPMethod.PUT);
httpMethods.add(HTTPMethod.OPTIONS);
}
public static API getAPI(APIConfig config) throws APIManagementException {
APIProvider provider = config.getProvider();
@ -79,11 +62,10 @@ public class APIPublisherUtil {
api.setStatus(APIStatus.CREATED);
api.setTransports(config.getTransports());
api.setContextTemplate(config.getContextTemplate());
api.setUriTemplates(config.getUriTemplates());
Set<String> environements = new HashSet<>();
environements.add(API_PUBLISH_ENVIRONEMENT);
api.setEnvironments(environements);
Set<Tier> tiers = new HashSet<Tier>();
Set<String> environments = new HashSet<>();
environments.add(API_PUBLISH_ENVIRONMENT);
api.setEnvironments(environments);
Set<Tier> tiers = new HashSet<>();
tiers.add(new Tier(APIConstants.UNLIMITED_TIER));
api.addAvailableTiers(tiers);
if (config.isSharedWithAllTenants()) {
@ -95,7 +77,8 @@ public class APIPublisherUtil {
}
api.setResponseCache(APIConstants.DISABLED);
String endpointConfig = "{\"production_endpoints\":{\"url\":\" " + config.getEndpoint() + "\",\"config\":null},\"implementation_status\":\"managed\",\"endpoint_type\":\"http\"}";
String endpointConfig = "{\"production_endpoints\":{\"url\":\" " + config.getEndpoint() +
"\",\"config\":null},\"implementation_status\":\"managed\",\"endpoint_type\":\"http\"}";
api.setEndpointConfig(endpointConfig);
if ("".equals(id.getVersion()) || (DEFAULT_API_VERSION.equals(id.getVersion()))) {
@ -106,35 +89,31 @@ public class APIPublisherUtil {
Set<String> tags = new HashSet<>(Arrays.asList(config.getTags()));
api.addTags(tags);
}
return api;
}
private static Set<URITemplate> getURITemplates(String endpoint, String authType) {
Set<URITemplate> uriTemplates = new LinkedHashSet<URITemplate>();
if (APIConstants.AUTH_NO_AUTHENTICATION.equals(authType)) {
for (HTTPMethod method : httpMethods) {
URITemplate template = new URITemplate();
template.setAuthType(APIConstants.AUTH_NO_AUTHENTICATION);
template.setHTTPVerb(method.toString());
template.setResourceURI(endpoint);
template.setUriTemplate("/*");
uriTemplates.add(template);
}
} else {
for (HTTPMethod method : httpMethods) {
URITemplate template = new URITemplate();
if (HTTPMethod.OPTIONS.equals(method)) {
template.setAuthType(APIConstants.AUTH_NO_AUTHENTICATION);
// adding scopes to the api
Set<URITemplate> uriTemplates = config.getUriTemplates();
Map<String, Scope> apiScopes = new HashMap<>();
if (uriTemplates != null) {
// this creates distinct scopes list
for (URITemplate template : uriTemplates) {
Scope scope = template.getScope();
if (scope != null) {
if (apiScopes.get(scope.getKey()) == null) {
apiScopes.put(scope.getKey(), scope);
} else {
template.setAuthType(APIConstants.AUTH_APPLICATION_OR_USER_LEVEL_TOKEN);
// this has to be done because of the use of pass by reference
// where same object reference of scope should be available for both
// api scope and uri template scope
template.setScope(apiScopes.get(scope.getKey()));
}
template.setHTTPVerb(method.toString());
template.setResourceURI(endpoint);
template.setUriTemplate("/*");
uriTemplates.add(template);
}
}
return uriTemplates;
Set<Scope> scopes = new HashSet<>(apiScopes.values());
api.setScopes(scopes);
api.setUriTemplates(uriTemplates);
}
return api;
}
public static String getServerBaseUrl() {
@ -163,7 +142,8 @@ public class APIPublisherUtil {
}
/**
* When an input is having '@',replace it with '-AT-' [This is required to persist API data in registry,as registry paths don't allow '@' sign.]
* When an input is having '@',replace it with '-AT-'
* [This is required to persist API data in registry,as registry paths don't allow '@' sign.]
* @param input inputString
* @return String modifiedString
*/

@ -18,10 +18,8 @@
package org.wso2.carbon.apimgt.webapp.publisher.config;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import org.wso2.carbon.apimgt.api.model.Scope;
@XmlRootElement(name = "Resource")
public class APIResource {
private String AuthType;
@ -30,12 +28,12 @@ public class APIResource{
private String UriTemplate;
private String consumes;
private String produces;
private Scope scope;
public String getAuthType() {
return AuthType;
}
@XmlElement(name = "AuthType", required = true)
public void setAuthType(String authType) {
AuthType = authType;
}
@ -44,7 +42,6 @@ public class APIResource{
return HttpVerb;
}
@XmlElement(name = "HttpVerb", required = true)
public void setHttpVerb(String httpVerb) {
HttpVerb = httpVerb;
}
@ -53,7 +50,6 @@ public class APIResource{
return Uri;
}
@XmlElement(name = "Uri", required = true)
public void setUri(String uri) {
Uri = uri;
}
@ -62,7 +58,6 @@ public class APIResource{
return UriTemplate;
}
@XmlElement(name = "UriTemplate", required = true)
public void setUriTemplate(String uriTemplate) {
UriTemplate = uriTemplate;
}
@ -71,7 +66,6 @@ public class APIResource{
return consumes;
}
@XmlElement(name = "Consumes", required = true)
public void setConsumes(String consumes) {
this.consumes = consumes;
}
@ -80,8 +74,15 @@ public class APIResource{
return produces;
}
@XmlElement(name = "Produces", required = true)
public void setProduces(String produces) {
this.produces = produces;
}
public Scope getScope() {
return scope;
}
public void setScope(Scope scope) {
this.scope = scope;
}
}

@ -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.config;
/**
* This class represents the information related to permissions.
*/
public class PermissionConfiguration {
private String scopeName;
private String[] permissions;
public String getScopeName() {
return scopeName;
}
public void setScopeName(String scope) {
this.scopeName = scope;
}
public String[] getPermissions() {
return permissions;
}
public void setPermissions(String[] permissions) {
this.permissions = permissions;
}
}

@ -0,0 +1,60 @@
/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* you may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.apimgt.webapp.publisher.config;
/**
* Custom exception class of Permission related operations.
*/
public class PermissionManagementException extends Exception {
private static final long serialVersionUID = -3151279311929070298L;
private String errorMessage;
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
public PermissionManagementException(String msg, Exception nestedEx) {
super(msg, nestedEx);
setErrorMessage(msg);
}
public PermissionManagementException(String message, Throwable cause) {
super(message, cause);
setErrorMessage(message);
}
public PermissionManagementException(String msg) {
super(msg);
setErrorMessage(msg);
}
public PermissionManagementException() {
super();
}
public PermissionManagementException(Throwable cause) {
super(cause);
}
}

@ -32,6 +32,7 @@ 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.AnnotationUtil;
import org.wso2.carbon.base.MultitenantConstants;
import javax.servlet.ServletContext;
import java.io.IOException;
import java.util.LinkedHashSet;
@ -96,7 +97,7 @@ public class APIPublisherLifecycleListener implements LifecycleListener {
}
}
} catch (IOException e) {
log.error("Error enconterd while discovering annotated classes", e);
log.error("Error encountered while discovering annotated classes", e);
} catch (ClassNotFoundException e) {
log.error("Error while scanning class for annotations", e);
}
@ -213,16 +214,17 @@ public class APIPublisherLifecycleListener implements LifecycleListener {
apiConfig.setSharedWithAllTenants(isSharedWithAllTenants);
Set<URITemplate> uriTemplates = new LinkedHashSet<URITemplate>();
Scope scope;
for (APIResource apiResource : apidef.getResources()) {
URITemplate template = new URITemplate();
template.setAuthType(apiResource.getAuthType());
template.setHTTPVerb(apiResource.getHttpVerb());
template.setResourceURI(apiResource.getUri());
template.setUriTemplate(apiResource.getUriTemplate());
template.setUriTemplate(apiResource.getUriTemplate());;
template.setScope(apiResource.getScope());
uriTemplates.add(template);
}
apiConfig.setUriTemplates(uriTemplates);
return apiConfig;
}

@ -20,12 +20,19 @@ package org.wso2.carbon.apimgt.webapp.publisher.lifecycle.util;
import org.apache.catalina.core.StandardContext;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.scannotation.AnnotationDB;
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.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 javax.servlet.ServletContext;
import javax.ws.rs.*;
import java.io.IOException;
@ -36,7 +43,9 @@ import java.lang.reflect.Proxy;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class AnnotationUtil {
@ -68,6 +77,7 @@ public class AnnotationUtil {
/**
* Scan the context for classes with annotations
*
* @return
* @throws IOException
*/
@ -89,6 +99,7 @@ public class AnnotationUtil {
/**
* Method identifies the URL templates and context by reading the annotations of a class
*
* @param entityClasses
* @return
*/
@ -107,8 +118,8 @@ public class AnnotationUtil {
APIResourceConfiguration apiResourceConfig = null;
try {
clazz = classLoader.loadClass(className);
Class<Path> apiClazz = (Class<Path>)
classLoader.loadClass(org.wso2.carbon.apimgt.annotations.api.API.class.getName());
Class<API> apiClazz = (Class<API>)
classLoader.loadClass(API.class.getName());
Annotation apiAnno = clazz.getAnnotation(apiClazz);
List<APIResource> resourceList;
@ -224,6 +235,18 @@ public class AnnotationUtil {
Annotation producesAnno = method.getAnnotation(producesClass);
resource.setProduces(invokeMethod(producesClassMethods[0], producesAnno, STRING_ARR));
}
if (annotations[i].annotationType().getName().equals(Permission.class.getName())) {
PermissionConfiguration permissionConf = this.getPermission(method);
if (permissionConf != null) {
Scope scope = new Scope();
scope.setKey(permissionConf.getScopeName());
scope.setDescription(permissionConf.getScopeName());
scope.setName(permissionConf.getScopeName());
String roles = StringUtils.join(permissionConf.getPermissions(), ",");
scope.setRoles(roles);
resource.setScope(scope);
}
}
}
resourceList.add(resource);
}
@ -244,6 +267,7 @@ public class AnnotationUtil {
/**
* When an annotation and method is passed, this method invokes that executes said method against the annotation
*
* @param method
* @param annotation
* @param returnType
@ -269,4 +293,34 @@ public class AnnotationUtil {
InvocationHandler methodHandler = Proxy.getInvocationHandler(annotation);
return ((String[]) methodHandler.invoke(annotation, method, null));
}
private PermissionConfiguration getPermission(Method currentMethod) throws Throwable {
Class<Permission> permissionClass = (Class<Permission>) classLoader.loadClass(Permission.class.getName());
Annotation permissionAnnotation = currentMethod.getAnnotation(permissionClass);
if (permissionClass != null) {
Method[] permissionClassMethods = permissionClass.getMethods();
PermissionConfiguration permissionConf = new PermissionConfiguration();
for (Method method : permissionClassMethods) {
switch (method.getName()) {
case "scope":
permissionConf.setScopeName(invokeMethod(method, permissionAnnotation, STRING));
break;
case "permissions":
String permissions[] = invokeMethod(method, permissionAnnotation);
this.addPermission(permissions);
permissionConf.setPermissions(permissions);
break;
}
}
return permissionConf;
}
return null;
}
private void addPermission(String[] permissions) throws PermissionManagementException {
for (String permission : permissions) {
PermissionUtils.addPermission(permission);
}
}
}

@ -0,0 +1,91 @@
/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* you may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.apimgt.webapp.publisher.lifecycle.util;
import org.wso2.carbon.apimgt.webapp.publisher.config.PermissionManagementException;
import org.wso2.carbon.apimgt.webapp.publisher.internal.APIPublisherDataHolder;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.registry.api.RegistryException;
import org.wso2.carbon.registry.api.Resource;
import org.wso2.carbon.registry.core.Registry;
import java.util.StringTokenizer;
/**
* Utility class which holds necessary utility methods required for persisting permissions in
* registry.
*/
public class PermissionUtils {
public static final String ADMIN_PERMISSION_REGISTRY_PATH = "/permission/admin";
public static final String PERMISSION_PROPERTY_NAME = "name";
public static Registry getGovernanceRegistry() throws PermissionManagementException {
try {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
return APIPublisherDataHolder.getInstance().getRegistryService()
.getGovernanceSystemRegistry(
tenantId);
} catch (RegistryException e) {
throw new PermissionManagementException(
"Error in retrieving governance registry instance: " +
e.getMessage(), e);
}
}
public static void addPermission(String permission) throws PermissionManagementException {
String resourcePermission = getAbsolutePermissionPath(permission);
try {
StringTokenizer tokenizer = new StringTokenizer(resourcePermission, "/");
String lastToken = "", currentToken, tempPath;
while (tokenizer.hasMoreTokens()) {
currentToken = tokenizer.nextToken();
tempPath = lastToken + "/" + currentToken;
if (!checkResourceExists(tempPath)) {
createRegistryCollection(tempPath, currentToken);
}
lastToken = tempPath;
}
} catch (RegistryException e) {
throw new PermissionManagementException("Error occurred while persisting permission : " +
resourcePermission, e);
}
}
public static void createRegistryCollection(String path, String resourceName)
throws PermissionManagementException,
RegistryException {
Resource resource = PermissionUtils.getGovernanceRegistry().newCollection();
resource.addProperty(PERMISSION_PROPERTY_NAME, resourceName);
PermissionUtils.getGovernanceRegistry().beginTransaction();
PermissionUtils.getGovernanceRegistry().put(path, resource);
PermissionUtils.getGovernanceRegistry().commitTransaction();
}
public static boolean checkResourceExists(String path)
throws PermissionManagementException,
org.wso2.carbon.registry.core.exceptions.RegistryException {
return PermissionUtils.getGovernanceRegistry().resourceExists(path);
}
private static String getAbsolutePermissionPath(String permissionPath) {
return PermissionUtils.ADMIN_PERMISSION_REGISTRY_PATH + permissionPath;
}
}

@ -17,7 +17,8 @@
~ under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
@ -46,10 +47,6 @@
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.user.core</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.user.api</artifactId>
</dependency>
</dependencies>
<build>

Loading…
Cancel
Save