From ffc7542d4d634fa92ecb4207a22c9fdd2f075968 Mon Sep 17 00:00:00 2001 From: mharindu Date: Thu, 28 Apr 2016 11:36:34 +0530 Subject: [PATCH] Modified authorization to support API gateway --- .../apimgt/annotations/api/Permission.java | 36 ++ .../publisher/APIPublisherServiceImpl.java | 204 +++++----- .../webapp/publisher/APIPublisherUtil.java | 82 ++-- .../webapp/publisher/config/APIResource.java | 133 +++---- .../config/PermissionConfiguration.java | 45 +++ .../config/PermissionManagementException.java | 60 +++ .../APIPublisherLifecycleListener.java | 370 +++++++++--------- .../lifecycle/util/AnnotationUtil.java | 104 +++-- .../lifecycle/util/PermissionUtils.java | 91 +++++ .../WebAppDeploymentLifecycleListener.java | 44 +-- .../pom.xml | 9 +- 11 files changed, 734 insertions(+), 444 deletions(-) create mode 100644 components/apimgt-extensions/org.wso2.carbon.apimgt.annotations/src/main/java/org/wso2/carbon/apimgt/annotations/api/Permission.java create mode 100644 components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/config/PermissionConfiguration.java create mode 100644 components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/config/PermissionManagementException.java create mode 100644 components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/lifecycle/util/PermissionUtils.java diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.annotations/src/main/java/org/wso2/carbon/apimgt/annotations/api/Permission.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.annotations/src/main/java/org/wso2/carbon/apimgt/annotations/api/Permission.java new file mode 100644 index 00000000000..5cb590d3a59 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.annotations/src/main/java/org/wso2/carbon/apimgt/annotations/api/Permission.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.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(); + +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherServiceImpl.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherServiceImpl.java index 3ce653c6c87..1d29863f864 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherServiceImpl.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherServiceImpl.java @@ -18,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 @@ -50,96 +48,122 @@ import java.util.Map; public class APIPublisherServiceImpl implements APIPublisherService { private static final Log log = LogFactory.getLog(APIPublisherServiceImpl.class); - private static final String PUBLISH_ACTION = "Publish"; + private static final String PUBLISH_ACTION = "Publish"; - @Override - public void publishAPI(final API api) throws APIManagementException, FaultGatewaysException { - String tenantDomain = MultitenantUtils.getTenantDomain(api.getApiOwner()); - PrivilegedCarbonContext.startTenantFlow(); - PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true); - try { - int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); - // Below code snippet is added to load API Lifecycle in tenant mode. - RegistryService registryService = APIPublisherDataHolder.getInstance().getRegistryService(); - CommonUtil.addDefaultLifecyclesIfNotAvailable(registryService.getConfigSystemRegistry(tenantId), - CommonUtil.getRootSystemRegistry(tenantId)); - APIProvider provider = APIManagerFactory.getInstance().getAPIProvider(api.getApiOwner()); - MultitenantUtils.getTenantDomain(api.getApiOwner()); - if (provider != null) { - if (provider.isDuplicateContextTemplate(api.getContext())) { - throw new APIManagementException( - "Error occurred while adding the API. A duplicate API" + - " context already exists for " + api.getContext()); - } - if (!provider.isAPIAvailable(api.getId())) { - provider.addAPI(api); - provider.changeLifeCycleStatus(api.getId(), PUBLISH_ACTION); - if (log.isDebugEnabled()) { - log.debug("Successfully published API '" + api.getId().getApiName() + - "' with context '" + api.getContext() + "' and version '" - + api.getId().getVersion() + "'"); - } - } else { - api.setStatus(APIStatus.PUBLISHED); - provider.updateAPI(api); - if (log.isDebugEnabled()) { - log.debug("An API already exists with the name '" + api.getId().getApiName() + - "', context '" + api.getContext() + "' and version '" - + api.getId().getVersion() + "'. Thus, the API config is updated"); - } - } - provider.saveSwagger20Definition(api.getId(), createSwaggerDefinition(api)); - } else { - throw new APIManagementException("API provider configured for the given API configuration " + - "is null. Thus, the API is not published"); - } - } catch (FileNotFoundException e) { - throw new APIManagementException("Failed to retrieve life cycle file ", e); - } catch (RegistryException e) { - throw new APIManagementException("Failed to access the registry ", e); - } catch (XMLStreamException e) { - throw new APIManagementException("Failed parsing the lifecycle xml.", e); - } finally { - PrivilegedCarbonContext.endTenantFlow(); - } - } + @Override + public void publishAPI(final API api) throws APIManagementException, FaultGatewaysException { + String tenantDomain = MultitenantUtils.getTenantDomain(api.getApiOwner()); + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true); + try { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); + // Below code snippet is added to load API Lifecycle in tenant mode. + RegistryService registryService = APIPublisherDataHolder.getInstance().getRegistryService(); + CommonUtil.addDefaultLifecyclesIfNotAvailable(registryService.getConfigSystemRegistry(tenantId), + CommonUtil.getRootSystemRegistry(tenantId)); + APIProvider provider = APIManagerFactory.getInstance().getAPIProvider(api.getApiOwner()); + MultitenantUtils.getTenantDomain(api.getApiOwner()); + if (provider != null) { + if (provider.isDuplicateContextTemplate(api.getContext())) { + throw new APIManagementException( + "Error occurred while adding the API. A duplicate API" + + " context already exists for " + api.getContext()); + } + if (!provider.isAPIAvailable(api.getId())) { + provider.addAPI(api); + provider.changeLifeCycleStatus(api.getId(), PUBLISH_ACTION); + if (log.isDebugEnabled()) { + log.debug("Successfully published API '" + api.getId().getApiName() + + "' with context '" + api.getContext() + "' and version '" + + api.getId().getVersion() + "'"); + } + } else { + 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() + + "', context '" + api.getContext() + "' and version '" + + api.getId().getVersion() + "'. Thus, the API config is updated"); + } + } + provider.saveSwagger20Definition(api.getId(), createSwaggerDefinition(api)); + } else { + throw new APIManagementException("API provider configured for the given API configuration " + + "is null. Thus, the API is not published"); + } + } catch (FileNotFoundException e) { + throw new APIManagementException("Failed to retrieve life cycle file ", e); + } catch (RegistryException e) { + throw new APIManagementException("Failed to access the registry ", e); + } catch (XMLStreamException e) { + throw new APIManagementException("Failed parsing the lifecycle xml.", e); + } finally { + PrivilegedCarbonContext.endTenantFlow(); + } + } + + private String createSwaggerDefinition(API api) { + Map httpVerbsMap = new HashMap<>(); + List scopes = new ArrayList<>(); - private String createSwaggerDefinition(API api) { - Map httpVerbsMap = new HashMap<>(); + 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", ""); - for (URITemplate uriTemplate : api.getUriTemplates()) { - JsonObject response = new JsonObject(); - response.addProperty("200", ""); + JsonObject responses = new JsonObject(); + responses.add("responses", response); + JsonObject httpVerbs = httpVerbsMap.get(uriTemplate.getUriTemplate()); + if (httpVerbs == null) { + httpVerbs = new JsonObject(); + } + JsonObject httpVerb = new JsonObject(); + httpVerb.add("responses", response); - JsonObject responses = new JsonObject(); - responses.add("responses", response); - JsonObject httpVerbs = httpVerbsMap.get(uriTemplate.getUriTemplate()); - if (httpVerbs == null) { - httpVerbs = new JsonObject(); - } - httpVerbs.add(uriTemplate.getHTTPVerb().toLowerCase(), responses); - httpVerbsMap.put(uriTemplate.getUriTemplate(), httpVerbs); - } + httpVerb.addProperty("x-auth-type", "Application%20%26%20Application%20User"); + httpVerb.addProperty("x-throttling-tier", "Unlimited"); + if (uriTemplate.getScope() != null) { + httpVerb.addProperty("x-scope", uriTemplate.getScope().getName()); + scopes.add(uriTemplate.getScope()); + } + httpVerbs.add(uriTemplate.getHTTPVerb().toLowerCase(), httpVerb); + httpVerbsMap.put(uriTemplate.getUriTemplate(), httpVerbs); + } - Iterator it = httpVerbsMap.entrySet().iterator(); - JsonObject paths = new JsonObject(); - while (it.hasNext()) { - Map.Entry pair = (Map.Entry) it.next(); - paths.add(pair.getKey(), pair.getValue()); - it.remove(); - } + Iterator it = httpVerbsMap.entrySet().iterator(); + JsonObject paths = new JsonObject(); + while (it.hasNext()) { + Map.Entry pair = (Map.Entry) it.next(); + paths.add(pair.getKey(), pair.getValue()); + it.remove(); + } - JsonObject info = new JsonObject(); - info.addProperty("title", api.getId().getApiName()); - info.addProperty("version", api.getId().getVersion()); + JsonObject info = new JsonObject(); + info.addProperty("title", api.getId().getApiName()); + info.addProperty("version", api.getId().getVersion()); - JsonObject swaggerDefinition = new JsonObject(); - swaggerDefinition.add("paths", paths); - swaggerDefinition.addProperty("swagger", "2.0"); - swaggerDefinition.add("info", info); + JsonObject swaggerDefinition = new JsonObject(); + swaggerDefinition.add("paths", paths); + swaggerDefinition.addProperty("swagger", "2.0"); + swaggerDefinition.add("info", info); - return swaggerDefinition.toString(); - } + // adding scopes to definition + if (!api.getScopes().isEmpty()) { + Gson gson = new Gson(); + JsonElement element = gson.toJsonTree(api.getScopes(), new TypeToken>() { + }.getType()); + if (element != null) { + JsonArray apiScopes = element.getAsJsonArray(); + JsonObject apim = new JsonObject(); + apim.add("x-wso2-scopes", apiScopes); + JsonObject wso2Security = new JsonObject(); + wso2Security.add("apim", apim); + swaggerDefinition.add("x-wso2-security", wso2Security); + } + } + return swaggerDefinition.toString(); + } @Override public void removeAPI(APIIdentifier id) throws APIManagementException { diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherUtil.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherUtil.java index 9ae9340513f..42644a67669 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherUtil.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherUtil.java @@ -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 httpMethods; - - static { - httpMethods = new ArrayList(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 environements = new HashSet<>(); - environements.add(API_PUBLISH_ENVIRONEMENT); - api.setEnvironments(environements); - Set tiers = new HashSet(); + Set environments = new HashSet<>(); + environments.add(API_PUBLISH_ENVIRONMENT); + api.setEnvironments(environments); + Set tiers = new HashSet<>(); tiers.add(new Tier(APIConstants.UNLIMITED_TIER)); api.addAvailableTiers(tiers); if (config.isSharedWithAllTenants()) { @@ -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 tags = new HashSet<>(Arrays.asList(config.getTags())); api.addTags(tags); } - return api; - } - private static Set getURITemplates(String endpoint, String authType) { - Set uriTemplates = new LinkedHashSet(); - 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); - } else { - template.setAuthType(APIConstants.AUTH_APPLICATION_OR_USER_LEVEL_TOKEN); + // adding scopes to the api + Set uriTemplates = config.getUriTemplates(); + Map apiScopes = new HashMap<>(); + + if (uriTemplates != null) { + // this creates distinct scopes list + for (URITemplate template : uriTemplates) { + Scope scope = template.getScope(); + if (scope != null) { + if (apiScopes.get(scope.getKey()) == null) { + apiScopes.put(scope.getKey(), scope); + } else { + // 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); } + Set scopes = new HashSet<>(apiScopes.values()); + api.setScopes(scopes); + api.setUriTemplates(uriTemplates); } - return 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 */ diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/config/APIResource.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/config/APIResource.java index 2f28fbe6a53..577f4efecb9 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/config/APIResource.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/config/APIResource.java @@ -18,70 +18,71 @@ package org.wso2.carbon.apimgt.webapp.publisher.config; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; - -@XmlRootElement(name = "Resource") -public class APIResource{ - - private String AuthType; - private String HttpVerb; - private String Uri; - private String UriTemplate; - private String consumes; - private String produces; - - public String getAuthType() { - return AuthType; - } - - @XmlElement(name = "AuthType", required = true) - public void setAuthType(String authType) { - AuthType = authType; - } - - public String getHttpVerb() { - return HttpVerb; - } - - @XmlElement(name = "HttpVerb", required = true) - public void setHttpVerb(String httpVerb) { - HttpVerb = httpVerb; - } - - public String getUri() { - return Uri; - } - - @XmlElement(name = "Uri", required = true) - public void setUri(String uri) { - Uri = uri; - } - - public String getUriTemplate() { - return UriTemplate; - } - - @XmlElement(name = "UriTemplate", required = true) - public void setUriTemplate(String uriTemplate) { - UriTemplate = uriTemplate; - } - - public String getConsumes() { - return consumes; - } - - @XmlElement(name = "Consumes", required = true) - public void setConsumes(String consumes) { - this.consumes = consumes; - } - - public String getProduces() { - return produces; - } - - @XmlElement(name = "Produces", required = true) - public void setProduces(String produces) { - this.produces = produces; - } +import org.wso2.carbon.apimgt.api.model.Scope; + +public class APIResource { + + private String AuthType; + private String HttpVerb; + private String Uri; + private String UriTemplate; + private String consumes; + private String produces; + private Scope scope; + + public String getAuthType() { + return AuthType; + } + + public void setAuthType(String authType) { + AuthType = authType; + } + + public String getHttpVerb() { + return HttpVerb; + } + + public void setHttpVerb(String httpVerb) { + HttpVerb = httpVerb; + } + + public String getUri() { + return Uri; + } + + public void setUri(String uri) { + Uri = uri; + } + + public String getUriTemplate() { + return UriTemplate; + } + + public void setUriTemplate(String uriTemplate) { + UriTemplate = uriTemplate; + } + + public String getConsumes() { + return consumes; + } + + public void setConsumes(String consumes) { + this.consumes = consumes; + } + + public String getProduces() { + return produces; + } + + public void setProduces(String produces) { + this.produces = produces; + } + + public Scope getScope() { + return scope; + } + + public void setScope(Scope scope) { + this.scope = scope; + } } diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/config/PermissionConfiguration.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/config/PermissionConfiguration.java new file mode 100644 index 00000000000..7d16d198b94 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/config/PermissionConfiguration.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.apimgt.webapp.publisher.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; + } + +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/config/PermissionManagementException.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/config/PermissionManagementException.java new file mode 100644 index 00000000000..651c2857231 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/config/PermissionManagementException.java @@ -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); + } + +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/lifecycle/listener/APIPublisherLifecycleListener.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/lifecycle/listener/APIPublisherLifecycleListener.java index 0b4a3cff914..f9fbad7c48d 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/lifecycle/listener/APIPublisherLifecycleListener.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/lifecycle/listener/APIPublisherLifecycleListener.java @@ -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; @@ -41,189 +42,190 @@ import java.util.Set; @SuppressWarnings("unused") public class APIPublisherLifecycleListener implements LifecycleListener { - private static final String API_CONFIG_DEFAULT_VERSION = "1.0.0"; - - private static final String PARAM_MANAGED_API_ENABLED = "managed-api-enabled"; - private static final String PARAM_MANAGED_API_NAME = "managed-api-name"; - private static final String PARAM_MANAGED_API_VERSION = "managed-api-version"; - private static final String PARAM_MANAGED_API_CONTEXT = "managed-api-context"; - private static final String PARAM_MANAGED_API_ENDPOINT = "managed-api-endpoint"; - private static final String PARAM_MANAGED_API_OWNER = "managed-api-owner"; - private static final String PARAM_MANAGED_API_TRANSPORTS = "managed-api-transports"; - private static final String PARAM_MANAGED_API_IS_SECURED = "managed-api-isSecured"; - private static final String PARAM_MANAGED_API_APPLICATION = "managed-api-application"; - private static final String PARAM_SHARED_WITH_ALL_TENANTS = "isSharedWithAllTenants"; - private static final String PARAM_PROVIDER_TENANT_DOMAIN = "providerTenantDomain"; - private static final Log log = LogFactory.getLog(APIPublisherLifecycleListener.class); - - @Override - public void lifecycleEvent(LifecycleEvent lifecycleEvent) { - if (Lifecycle.AFTER_START_EVENT.equals(lifecycleEvent.getType())) { - StandardContext context = (StandardContext) lifecycleEvent.getLifecycle(); - ServletContext servletContext = context.getServletContext(); - String param = servletContext.getInitParameter(PARAM_MANAGED_API_ENABLED); - boolean isManagedApi = (param != null && !param.isEmpty()) && Boolean.parseBoolean(param); - - if (isManagedApi) { - try { - AnnotationUtil annotationUtil = new AnnotationUtil(context); - Set annotatedAPIClasses = annotationUtil. - scanStandardContext(org.wso2.carbon.apimgt.annotations.api.API.class.getName()); - List apiDefinitions = annotationUtil.extractAPIInfo(servletContext, annotatedAPIClasses); - - for (APIResourceConfiguration apiDefinition : apiDefinitions) { - APIConfig apiConfig = this.buildApiConfig(servletContext, apiDefinition); - try { - int tenantId = APIPublisherDataHolder.getInstance().getTenantManager().getTenantId(apiConfig.getTenantDomain()); - boolean isTenantActive = APIPublisherDataHolder.getInstance().getTenantManager().isTenantActive(tenantId); - 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"); - } - apiPublisherService.publishAPI(api); - } else { - log.error("No tenant [" + apiConfig.getTenantDomain() + "] found when publishing the webapp"); - } - } catch (Throwable e) { - log.error("Error occurred while publishing API '" + apiConfig.getName() + - "' with the context '" + apiConfig.getContext() + - "' and version '" + apiConfig.getVersion() + "'", e); - } - } - } catch (IOException e) { - log.error("Error enconterd while discovering annotated classes", e); - } catch (ClassNotFoundException e) { - log.error("Error while scanning class for annotations", e); - } - } - } - } - - private List mergeAPIDefinitions(List inputList) { - //TODO : Need to implemented, to merge API Definitions in cases where implementation of an API Lies in two - // classes - return null; - } - - /** - * Build the API Configuration to be passed to APIM, from a given list of URL templates - * - * @param servletContext - * @return - */ - private APIConfig buildApiConfig(ServletContext servletContext, APIResourceConfiguration apidef) { - APIConfig apiConfig = new APIConfig(); - - String name = apidef.getName(); - if (name == null || name.isEmpty()) { - if (log.isDebugEnabled()) { - log.debug("API Name not set in @API Annotation"); - } - name = servletContext.getServletContextName(); - } - apiConfig.setName(name); - - String version = apidef.getVersion(); - if (version == null || version.isEmpty()) { - if (log.isDebugEnabled()) { - log.debug("'API Version not set in @API Annotation'"); - } - version = API_CONFIG_DEFAULT_VERSION; - } - apiConfig.setVersion(version); - - - String context = apidef.getContext(); - if (context == null || context.isEmpty()) { - if (log.isDebugEnabled()) { - log.debug("'API Context not set in @API Annotation'"); - } - context = servletContext.getContextPath(); - } - apiConfig.setContext(context); - - String[] tags = apidef.getTags(); - if (tags == null || tags.length == 0) { - if (log.isDebugEnabled()) { - log.debug("'API tag not set in @API Annotation'"); - } - } else { - apiConfig.setTags(tags); - } - - String tenantDomain = servletContext.getInitParameter(PARAM_PROVIDER_TENANT_DOMAIN); - tenantDomain = (tenantDomain != null && !tenantDomain.isEmpty()) ? tenantDomain : - MultitenantConstants.SUPER_TENANT_DOMAIN_NAME; - apiConfig.setTenantDomain(tenantDomain); - String contextTemplate = context + "/" + APIConstants.VERSION_PLACEHOLDER; - if (!tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) { - contextTemplate = context + "/t/" + tenantDomain + "/" + APIConstants.VERSION_PLACEHOLDER; - } - apiConfig.setContextTemplate(contextTemplate); - - String endpoint = servletContext.getInitParameter(PARAM_MANAGED_API_ENDPOINT); - if (endpoint == null || endpoint.isEmpty()) { - if (log.isDebugEnabled()) { - log.debug("'managed-api-endpoint' attribute is not configured"); - } - String endpointContext = servletContext.getContextPath(); - endpoint = APIPublisherUtil.getApiEndpointUrl(endpointContext); - } - apiConfig.setEndpoint(endpoint); - - String owner = servletContext.getInitParameter(PARAM_MANAGED_API_OWNER); - if (owner == null || owner.isEmpty()) { - if (log.isDebugEnabled()) { - log.debug("'managed-api-owner' attribute is not configured"); - } - } - apiConfig.setOwner(owner); - - String isSecuredParam = servletContext.getInitParameter(PARAM_MANAGED_API_IS_SECURED); - boolean isSecured; - if (isSecuredParam == null || isSecuredParam.isEmpty()) { - if (log.isDebugEnabled()) { - log.debug("'managed-api-isSecured' attribute is not configured. Therefore, using the default, " + - "which is 'true'"); - } - isSecured = false; - } else { - isSecured = Boolean.parseBoolean(isSecuredParam); - } - apiConfig.setSecured(isSecured); - - String transports = servletContext.getInitParameter(PARAM_MANAGED_API_TRANSPORTS); - if (transports == null || transports.isEmpty()) { - if (log.isDebugEnabled()) { - log.debug("'managed-api-transports' attribute is not configured. Therefore using the default, " + - "which is 'https'"); - } - transports = "https"; - } - apiConfig.setTransports(transports); - - String sharingValueParam = servletContext.getInitParameter(PARAM_SHARED_WITH_ALL_TENANTS); - boolean isSharedWithAllTenants = (sharingValueParam == null || (!sharingValueParam.isEmpty()) && Boolean.parseBoolean( - sharingValueParam)); - apiConfig.setSharedWithAllTenants(isSharedWithAllTenants); - - Set uriTemplates = new LinkedHashSet(); - 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()); - uriTemplates.add(template); - } - apiConfig.setUriTemplates(uriTemplates); - - return apiConfig; - } + private static final String API_CONFIG_DEFAULT_VERSION = "1.0.0"; + + private static final String PARAM_MANAGED_API_ENABLED = "managed-api-enabled"; + private static final String PARAM_MANAGED_API_NAME = "managed-api-name"; + private static final String PARAM_MANAGED_API_VERSION = "managed-api-version"; + private static final String PARAM_MANAGED_API_CONTEXT = "managed-api-context"; + private static final String PARAM_MANAGED_API_ENDPOINT = "managed-api-endpoint"; + private static final String PARAM_MANAGED_API_OWNER = "managed-api-owner"; + private static final String PARAM_MANAGED_API_TRANSPORTS = "managed-api-transports"; + private static final String PARAM_MANAGED_API_IS_SECURED = "managed-api-isSecured"; + private static final String PARAM_MANAGED_API_APPLICATION = "managed-api-application"; + private static final String PARAM_SHARED_WITH_ALL_TENANTS = "isSharedWithAllTenants"; + private static final String PARAM_PROVIDER_TENANT_DOMAIN = "providerTenantDomain"; + private static final Log log = LogFactory.getLog(APIPublisherLifecycleListener.class); + + @Override + public void lifecycleEvent(LifecycleEvent lifecycleEvent) { + if (Lifecycle.AFTER_START_EVENT.equals(lifecycleEvent.getType())) { + StandardContext context = (StandardContext) lifecycleEvent.getLifecycle(); + ServletContext servletContext = context.getServletContext(); + String param = servletContext.getInitParameter(PARAM_MANAGED_API_ENABLED); + boolean isManagedApi = (param != null && !param.isEmpty()) && Boolean.parseBoolean(param); + + if (isManagedApi) { + try { + AnnotationUtil annotationUtil = new AnnotationUtil(context); + Set annotatedAPIClasses = annotationUtil. + scanStandardContext(org.wso2.carbon.apimgt.annotations.api.API.class.getName()); + List apiDefinitions = annotationUtil.extractAPIInfo(servletContext, annotatedAPIClasses); + + for (APIResourceConfiguration apiDefinition : apiDefinitions) { + APIConfig apiConfig = this.buildApiConfig(servletContext, apiDefinition); + try { + int tenantId = APIPublisherDataHolder.getInstance().getTenantManager().getTenantId(apiConfig.getTenantDomain()); + boolean isTenantActive = APIPublisherDataHolder.getInstance().getTenantManager().isTenantActive(tenantId); + 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"); + } + apiPublisherService.publishAPI(api); + } else { + log.error("No tenant [" + apiConfig.getTenantDomain() + "] found when publishing the webapp"); + } + } catch (Throwable e) { + log.error("Error occurred while publishing API '" + apiConfig.getName() + + "' with the context '" + apiConfig.getContext() + + "' and version '" + apiConfig.getVersion() + "'", e); + } + } + } catch (IOException e) { + log.error("Error encountered while discovering annotated classes", e); + } catch (ClassNotFoundException e) { + log.error("Error while scanning class for annotations", e); + } + } + } + } + + private List mergeAPIDefinitions(List inputList) { + //TODO : Need to implemented, to merge API Definitions in cases where implementation of an API Lies in two + // classes + return null; + } + + /** + * Build the API Configuration to be passed to APIM, from a given list of URL templates + * + * @param servletContext + * @return + */ + private APIConfig buildApiConfig(ServletContext servletContext, APIResourceConfiguration apidef) { + APIConfig apiConfig = new APIConfig(); + + String name = apidef.getName(); + if (name == null || name.isEmpty()) { + if (log.isDebugEnabled()) { + log.debug("API Name not set in @API Annotation"); + } + name = servletContext.getServletContextName(); + } + apiConfig.setName(name); + + String version = apidef.getVersion(); + if (version == null || version.isEmpty()) { + if (log.isDebugEnabled()) { + log.debug("'API Version not set in @API Annotation'"); + } + version = API_CONFIG_DEFAULT_VERSION; + } + apiConfig.setVersion(version); + + + String context = apidef.getContext(); + if (context == null || context.isEmpty()) { + if (log.isDebugEnabled()) { + log.debug("'API Context not set in @API Annotation'"); + } + context = servletContext.getContextPath(); + } + apiConfig.setContext(context); + + String[] tags = apidef.getTags(); + if (tags == null || tags.length == 0) { + if (log.isDebugEnabled()) { + log.debug("'API tag not set in @API Annotation'"); + } + } else { + apiConfig.setTags(tags); + } + + String tenantDomain = servletContext.getInitParameter(PARAM_PROVIDER_TENANT_DOMAIN); + tenantDomain = (tenantDomain != null && !tenantDomain.isEmpty()) ? tenantDomain : + MultitenantConstants.SUPER_TENANT_DOMAIN_NAME; + apiConfig.setTenantDomain(tenantDomain); + String contextTemplate = context + "/" + APIConstants.VERSION_PLACEHOLDER; + if (!tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) { + contextTemplate = context + "/t/" + tenantDomain + "/" + APIConstants.VERSION_PLACEHOLDER; + } + apiConfig.setContextTemplate(contextTemplate); + + String endpoint = servletContext.getInitParameter(PARAM_MANAGED_API_ENDPOINT); + if (endpoint == null || endpoint.isEmpty()) { + if (log.isDebugEnabled()) { + log.debug("'managed-api-endpoint' attribute is not configured"); + } + String endpointContext = servletContext.getContextPath(); + endpoint = APIPublisherUtil.getApiEndpointUrl(endpointContext); + } + apiConfig.setEndpoint(endpoint); + + String owner = servletContext.getInitParameter(PARAM_MANAGED_API_OWNER); + if (owner == null || owner.isEmpty()) { + if (log.isDebugEnabled()) { + log.debug("'managed-api-owner' attribute is not configured"); + } + } + apiConfig.setOwner(owner); + + String isSecuredParam = servletContext.getInitParameter(PARAM_MANAGED_API_IS_SECURED); + boolean isSecured; + if (isSecuredParam == null || isSecuredParam.isEmpty()) { + if (log.isDebugEnabled()) { + log.debug("'managed-api-isSecured' attribute is not configured. Therefore, using the default, " + + "which is 'true'"); + } + isSecured = false; + } else { + isSecured = Boolean.parseBoolean(isSecuredParam); + } + apiConfig.setSecured(isSecured); + + String transports = servletContext.getInitParameter(PARAM_MANAGED_API_TRANSPORTS); + if (transports == null || transports.isEmpty()) { + if (log.isDebugEnabled()) { + log.debug("'managed-api-transports' attribute is not configured. Therefore using the default, " + + "which is 'https'"); + } + transports = "https"; + } + apiConfig.setTransports(transports); + + String sharingValueParam = servletContext.getInitParameter(PARAM_SHARED_WITH_ALL_TENANTS); + boolean isSharedWithAllTenants = (sharingValueParam == null || (!sharingValueParam.isEmpty()) && Boolean.parseBoolean( + sharingValueParam)); + apiConfig.setSharedWithAllTenants(isSharedWithAllTenants); + + Set uriTemplates = new LinkedHashSet(); + 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.setScope(apiResource.getScope()); + uriTemplates.add(template); + } + apiConfig.setUriTemplates(uriTemplates); + return apiConfig; + } } diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/lifecycle/util/AnnotationUtil.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/lifecycle/util/AnnotationUtil.java index a26c2042f1b..52db3720d3f 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/lifecycle/util/AnnotationUtil.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/lifecycle/util/AnnotationUtil.java @@ -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 apiClazz = (Class) - classLoader.loadClass(org.wso2.carbon.apimgt.annotations.api.API.class.getName()); + Class apiClazz = (Class) + classLoader.loadClass(API.class.getName()); Annotation apiAnno = clazz.getAnnotation(apiClazz); List resourceList; @@ -123,18 +134,18 @@ public class AnnotationUtil { } try { - for(int k=0;k consumesClass = (Class) classLoader.loadClass(Consumes.class.getName()); Method[] consumesClassMethods = consumesClass.getMethods(); Annotation consumesAnno = method.getAnnotation(consumesClass); resource.setConsumes(invokeMethod(consumesClassMethods[0], consumesAnno, STRING_ARR)); } - if(annotations[i].annotationType().getName().equals(Produces.class.getName())){ + if (annotations[i].annotationType().getName().equals(Produces.class.getName())) { Class producesClass = (Class) classLoader.loadClass(Produces.class.getName()); Method[] producesClassMethods = producesClass.getMethods(); 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); } @@ -231,12 +254,12 @@ public class AnnotationUtil { return resourceList; } - private String makeContextURLReady(String context){ - if(context != null && !context.equalsIgnoreCase("")){ - if(context.startsWith("/")){ + private String makeContextURLReady(String context) { + if (context != null && !context.equalsIgnoreCase("")) { + if (context.startsWith("/")) { return context; - }else{ - return "/"+context; + } else { + return "/" + context; } } return ""; @@ -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 @@ -252,11 +276,11 @@ public class AnnotationUtil { */ private String invokeMethod(Method method, Annotation annotation, String returnType) throws Throwable { InvocationHandler methodHandler = Proxy.getInvocationHandler(annotation); - switch (returnType){ + switch (returnType) { case STRING: return (String) methodHandler.invoke(annotation, method, null); case STRING_ARR: - return ((String[])methodHandler.invoke(annotation, method, null))[0]; + return ((String[]) methodHandler.invoke(annotation, method, null))[0]; default: return null; } @@ -267,6 +291,36 @@ public class AnnotationUtil { */ private String[] invokeMethod(Method method, Annotation annotation) throws Throwable { InvocationHandler methodHandler = Proxy.getInvocationHandler(annotation); - return ((String[])methodHandler.invoke(annotation, method, null)); + return ((String[]) methodHandler.invoke(annotation, method, null)); } + + private PermissionConfiguration getPermission(Method currentMethod) throws Throwable { + Class permissionClass = (Class) 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); + } + } + } diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/lifecycle/util/PermissionUtils.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/lifecycle/util/PermissionUtils.java new file mode 100644 index 00000000000..32c5bad8557 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/lifecycle/util/PermissionUtils.java @@ -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; + } + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/permission/lifecycle/WebAppDeploymentLifecycleListener.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/permission/lifecycle/WebAppDeploymentLifecycleListener.java index eacc7a84c84..f274eee8459 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/permission/lifecycle/WebAppDeploymentLifecycleListener.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/permission/lifecycle/WebAppDeploymentLifecycleListener.java @@ -45,23 +45,23 @@ import java.util.List; @SuppressWarnings("unused") public class WebAppDeploymentLifecycleListener implements LifecycleListener { - private static final String PERMISSION_CONFIG_PATH = "META-INF" + File.separator + "permissions.xml"; - private static final Log log = LogFactory.getLog(WebAppDeploymentLifecycleListener.class); + private static final String PERMISSION_CONFIG_PATH = "META-INF" + File.separator + "permissions.xml"; + private static final Log log = LogFactory.getLog(WebAppDeploymentLifecycleListener.class); - @Override - public void lifecycleEvent(LifecycleEvent lifecycleEvent) { - if (Lifecycle.AFTER_START_EVENT.equals(lifecycleEvent.getType())) { - StandardContext context = (StandardContext) lifecycleEvent.getLifecycle(); - ServletContext servletContext = context.getServletContext(); - String contextPath = context.getServletContext().getContextPath(); - try { - InputStream permissionStream = servletContext.getResourceAsStream(PERMISSION_CONFIG_PATH); - if (permissionStream != null) { + @Override + public void lifecycleEvent(LifecycleEvent lifecycleEvent) { + if (Lifecycle.AFTER_START_EVENT.equals(lifecycleEvent.getType())) { + StandardContext context = (StandardContext) lifecycleEvent.getLifecycle(); + ServletContext servletContext = context.getServletContext(); + String contextPath = context.getServletContext().getContextPath(); + try { + InputStream permissionStream = servletContext.getResourceAsStream(PERMISSION_CONFIG_PATH); + if (permissionStream != null) { /* Un-marshaling Device Management configuration */ - JAXBContext cdmContext = JAXBContext.newInstance(PermissionConfiguration.class); - Unmarshaller unmarshaller = cdmContext.createUnmarshaller(); - PermissionConfiguration permissionConfiguration = (PermissionConfiguration) - unmarshaller.unmarshal(permissionStream); + JAXBContext cdmContext = JAXBContext.newInstance(PermissionConfiguration.class); + Unmarshaller unmarshaller = cdmContext.createUnmarshaller(); + PermissionConfiguration permissionConfiguration = (PermissionConfiguration) + unmarshaller.unmarshal(permissionStream); List permissions = permissionConfiguration.getPermissions(); String apiVersion = permissionConfiguration.getApiVersion(); if (permissionConfiguration != null && permissions != null) { @@ -69,22 +69,22 @@ public class WebAppDeploymentLifecycleListener implements LifecycleListener { // update the permission path to absolute permission path permission.setPath(PermissionUtils.getAbsolutePermissionPath(permission.getPath())); permission.setUrl(PermissionUtils.getAbsoluteContextPathOfAPI(contextPath, apiVersion, - permission.getUrl()).toLowerCase()); + permission.getUrl()).toLowerCase()); permission.setMethod(permission.getMethod().toUpperCase()); PermissionManagerServiceImpl.getInstance().addPermission(permission); } - } - } - } catch (JAXBException e) { + } + } + } catch (JAXBException e) { log.error( "Exception occurred while parsing the permission configuration of webapp : " - + context.getServletContext().getContextPath(), e); + + context.getServletContext().getContextPath(), e); } catch (PermissionManagementException e) { log.error("Exception occurred while adding the permissions from webapp : " - + servletContext.getContextPath(), e); + + servletContext.getContextPath(), e); } } - } + } } diff --git a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/pom.xml b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/pom.xml index 5c343926c1d..e36f684f364 100644 --- a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/pom.xml +++ b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/pom.xml @@ -17,7 +17,8 @@ ~ under the License. --> - + org.wso2.carbon.devicemgt @@ -46,10 +47,6 @@ org.wso2.carbon org.wso2.carbon.user.core - - org.wso2.carbon - org.wso2.carbon.user.api - @@ -89,7 +86,7 @@ org.wso2.carbon.user.api, org.wso2.carbon.user.core.service, org.wso2.carbon.identity.application.common.model, - org.wso2.carbon.identity.application.authentication.framework.model, + org.wso2.carbon.identity.application.authentication.framework.model, org.wso2.carbon.user.core.tenant