forked from community/device-mgt-core
Merge pull request #426 from ayyoob/IoTS-1.0.0
exposed device access authorisation as a servicerevert-70aa11f8
commit
f3b3389a8a
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.wso2.carbon.device.mgt.jaxrs.beans;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@ApiModel(value = "AuthorizationRequest", description = "Authorization details together with deviceIdentifier and permission")
|
||||||
|
public class AuthorizationRequest {
|
||||||
|
|
||||||
|
@ApiModelProperty(name = "tenantDomain", value = "tenant domain.", required = false)
|
||||||
|
String tenantDomain;
|
||||||
|
@ApiModelProperty(name = "username", value = "username of the user, to whom the device identifiers needs to be verified", required = true)
|
||||||
|
String username;
|
||||||
|
@ApiModelProperty(name = "deviceIdentifiers", value = "list of devices that needs to be verified against the user", required = true)
|
||||||
|
List<DeviceIdentifier> deviceIdentifiers;
|
||||||
|
@ApiModelProperty(name = "permission", value = "if null then checks against the owner else it could be grouping permission", required = false)
|
||||||
|
List<String> permissions;
|
||||||
|
|
||||||
|
public String getTenantDomain() {
|
||||||
|
return tenantDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTenantDomain(String tenantDomain) {
|
||||||
|
this.tenantDomain = tenantDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DeviceIdentifier> getDeviceIdentifiers() {
|
||||||
|
return deviceIdentifiers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceIdentifiers(List<DeviceIdentifier> deviceIdentifiers) {
|
||||||
|
this.deviceIdentifiers = deviceIdentifiers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getPermissions() {
|
||||||
|
return permissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPermissions(List<String> permissions) {
|
||||||
|
this.permissions = permissions;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* 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.jaxrs.service.api.admin;
|
||||||
|
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import io.swagger.annotations.ApiResponse;
|
||||||
|
import io.swagger.annotations.ApiResponses;
|
||||||
|
import org.wso2.carbon.apimgt.annotations.api.Permission;
|
||||||
|
import org.wso2.carbon.device.mgt.common.authorization.DeviceAuthorizationResult;
|
||||||
|
import org.wso2.carbon.device.mgt.jaxrs.beans.AuthorizationRequest;
|
||||||
|
import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
@Path("/admin/authorization")
|
||||||
|
@Api(value = "Device Authorization Administrative Service", description = "This an API intended to be used by " +
|
||||||
|
"'internal' components to log in as an admin user and validate whether the user/device are trusted entity." +
|
||||||
|
"Further, this is strictly restricted to admin users only ")
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
/**
|
||||||
|
* This interface provided the definition of the device - user access verification service.
|
||||||
|
*/
|
||||||
|
public interface DeviceAccessAuthorizationAdminService {
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@ApiOperation(
|
||||||
|
consumes = MediaType.APPLICATION_JSON,
|
||||||
|
produces = MediaType.APPLICATION_JSON,
|
||||||
|
httpMethod = "POST",
|
||||||
|
value = "Check for device access authorization\n",
|
||||||
|
notes = "This is an internal API that can be used to check for authorization.",
|
||||||
|
response = DeviceAuthorizationResult.class,
|
||||||
|
tags = "Authorization Administrative Service")
|
||||||
|
@ApiResponses(value = {
|
||||||
|
@ApiResponse(
|
||||||
|
code = 200,
|
||||||
|
message = "OK. \n Authorized device list will be delivered to the requested services",
|
||||||
|
response = DeviceAuthorizationResult.class),
|
||||||
|
@ApiResponse(
|
||||||
|
code = 400,
|
||||||
|
message = "Bad Request. \n Invalid request or validation error.",
|
||||||
|
response = ErrorResponse.class),
|
||||||
|
@ApiResponse(
|
||||||
|
code = 404,
|
||||||
|
message = "Not Found. \n The specified resource does not exist."),
|
||||||
|
@ApiResponse(
|
||||||
|
code = 415,
|
||||||
|
message = "Unsupported media type. \n The entity of the request was in a not supported format."),
|
||||||
|
@ApiResponse(
|
||||||
|
code = 500,
|
||||||
|
message = "Internal Server Error. \n Server error occurred while checking the authorization" +
|
||||||
|
" for a specified set of devices.",
|
||||||
|
response = ErrorResponse.class)
|
||||||
|
})
|
||||||
|
Response isAuthorized(AuthorizationRequest authorizationRequest);
|
||||||
|
}
|
@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* 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.jaxrs.service.impl.admin;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.wso2.carbon.base.MultitenantConstants;
|
||||||
|
import org.wso2.carbon.context.CarbonContext;
|
||||||
|
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||||
|
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationException;
|
||||||
|
import org.wso2.carbon.device.mgt.common.authorization.DeviceAuthorizationResult;
|
||||||
|
import org.wso2.carbon.device.mgt.jaxrs.beans.AuthorizationRequest;
|
||||||
|
import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse;
|
||||||
|
import org.wso2.carbon.device.mgt.jaxrs.service.api.admin.DeviceAccessAuthorizationAdminService;
|
||||||
|
import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtAPIUtils;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
@Path("/admin/authorization")
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public class DeviceAccessAuthorizationAdminServiceImpl implements DeviceAccessAuthorizationAdminService {
|
||||||
|
|
||||||
|
private static final Log log = LogFactory.getLog(DeviceAccessAuthorizationAdminServiceImpl.class);
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Override
|
||||||
|
public Response isAuthorized(AuthorizationRequest authorizationRequest) {
|
||||||
|
int currentTenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
|
||||||
|
String loggedinUserTenantDomain = CarbonContext.getThreadLocalCarbonContext().getTenantDomain();
|
||||||
|
if (authorizationRequest.getTenantDomain() != null) {
|
||||||
|
if (!loggedinUserTenantDomain.equals(authorizationRequest.getTenantDomain())) {
|
||||||
|
if (MultitenantConstants.SUPER_TENANT_ID != currentTenantId) {
|
||||||
|
return Response.status(Response.Status.UNAUTHORIZED).entity(
|
||||||
|
new ErrorResponse.ErrorResponseBuilder().setMessage(
|
||||||
|
"Current logged in user is not authorized to perform this operation").build())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
authorizationRequest.setTenantDomain(loggedinUserTenantDomain);
|
||||||
|
}
|
||||||
|
if (authorizationRequest.getTenantDomain() == null || authorizationRequest.getTenantDomain().isEmpty()) {
|
||||||
|
authorizationRequest.setTenantDomain(
|
||||||
|
PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain());
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
PrivilegedCarbonContext.startTenantFlow();
|
||||||
|
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(
|
||||||
|
authorizationRequest.getTenantDomain(), true);
|
||||||
|
String[] permissionArr = null;
|
||||||
|
if (authorizationRequest.getPermissions() != null && authorizationRequest.getPermissions().size() > 0) {
|
||||||
|
permissionArr = new String[authorizationRequest.getPermissions().size()];
|
||||||
|
permissionArr = authorizationRequest.getPermissions().toArray(permissionArr);
|
||||||
|
}
|
||||||
|
DeviceAuthorizationResult deviceAuthorizationResult =
|
||||||
|
DeviceMgtAPIUtils.getDeviceAccessAuthorizationService().isUserAuthorized(
|
||||||
|
authorizationRequest.getDeviceIdentifiers(), authorizationRequest.getUsername()
|
||||||
|
, permissionArr);
|
||||||
|
|
||||||
|
return Response.status(Response.Status.OK).entity(deviceAuthorizationResult).build();
|
||||||
|
} catch (DeviceAccessAuthorizationException e) {
|
||||||
|
String msg = "Error occurred at server side while fetching authorization information.";
|
||||||
|
log.error(msg, e);
|
||||||
|
return Response.serverError().entity(
|
||||||
|
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
|
||||||
|
} finally {
|
||||||
|
PrivilegedCarbonContext.endTenantFlow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,77 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
|
||||||
* Version 2.0 (the "License"); you may not use this file except
|
|
||||||
* in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
package org.wso2.carbon.device.mgt.extensions.feature.mgt;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
import org.wso2.carbon.device.mgt.common.DeviceManagementException;
|
|
||||||
import org.wso2.carbon.device.mgt.common.DeviceTypeIdentifier;
|
|
||||||
import org.wso2.carbon.device.mgt.common.Feature;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This stores the features for device types that are mentioned through the annotations.
|
|
||||||
*/
|
|
||||||
public class GenericFeatureManager {
|
|
||||||
|
|
||||||
private static final Log log = LogFactory.getLog(GenericFeatureManager.class);
|
|
||||||
private static Map<DeviceTypeIdentifier, List<Feature>> featureSet = new HashMap<>();
|
|
||||||
private static GenericFeatureManager instance = new GenericFeatureManager();
|
|
||||||
|
|
||||||
private GenericFeatureManager() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public static GenericFeatureManager getInstance() {
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param deviceTypeFeatures feature list for each device type.
|
|
||||||
*/
|
|
||||||
public void addFeatures(Map<DeviceTypeIdentifier, List<Feature>> deviceTypeFeatures) {
|
|
||||||
this.featureSet.putAll(deviceTypeFeatures);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param deviceType
|
|
||||||
* @param featureName
|
|
||||||
* @return the extracted feature for the which matches the feature name and device type.
|
|
||||||
*/
|
|
||||||
public Feature getFeature(DeviceTypeIdentifier deviceType, String featureName) {
|
|
||||||
Feature extractedFeature = null;
|
|
||||||
List<Feature> deviceFeatureList = featureSet.get(deviceType);
|
|
||||||
for (Feature feature : deviceFeatureList) {
|
|
||||||
if (feature.getName().equalsIgnoreCase(featureName)) {
|
|
||||||
extractedFeature = feature;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return extractedFeature;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param deviceType returns the features for the device type.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public List<Feature> getFeatures(DeviceTypeIdentifier deviceType) {
|
|
||||||
return featureSet.get(deviceType);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
|
||||||
* Version 2.0 (the "License"); you may not use this file except
|
|
||||||
* in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
package org.wso2.carbon.device.mgt.extensions.feature.mgt.annotations;
|
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
@Target(ElementType.TYPE)
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
public @interface DeviceType {
|
|
||||||
String value();
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
|
||||||
* Version 2.0 (the "License"); you may not use this file except
|
|
||||||
* in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
package org.wso2.carbon.device.mgt.extensions.feature.mgt.annotations;
|
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
@Target(ElementType.METHOD)
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
public @interface Feature {
|
|
||||||
|
|
||||||
String code();
|
|
||||||
|
|
||||||
String name();
|
|
||||||
|
|
||||||
String description();
|
|
||||||
|
|
||||||
}
|
|
@ -1,90 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
|
||||||
* Version 2.0 (the "License"); you may not use this file except
|
|
||||||
* in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
package org.wso2.carbon.device.mgt.extensions.feature.mgt.lifecycle.listener;
|
|
||||||
|
|
||||||
import org.apache.catalina.Lifecycle;
|
|
||||||
import org.apache.catalina.LifecycleEvent;
|
|
||||||
import org.apache.catalina.LifecycleListener;
|
|
||||||
import org.apache.catalina.core.StandardContext;
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
import org.wso2.carbon.base.MultitenantConstants;
|
|
||||||
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
|
||||||
import org.wso2.carbon.device.mgt.common.DeviceTypeIdentifier;
|
|
||||||
import org.wso2.carbon.device.mgt.common.Feature;
|
|
||||||
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;
|
|
||||||
|
|
||||||
import javax.servlet.ServletContext;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public class FeatureManagementLifecycleListener 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_SHARED_WITH_ALL_TENANTS = "isSharedWithAllTenants";
|
|
||||||
private static final String PARAM_PROVIDER_TENANT_DOMAIN = "providerTenantDomain";
|
|
||||||
|
|
||||||
private static final Log log = LogFactory.getLog(FeatureManagementLifecycleListener.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 {
|
|
||||||
AnnotationProcessor annotationProcessor = new AnnotationProcessor(context);
|
|
||||||
Set<String> annotatedAPIClasses = annotationProcessor.scanStandardContext(DeviceType.class.getName());
|
|
||||||
String tenantDomain = servletContext.getInitParameter(PARAM_PROVIDER_TENANT_DOMAIN);
|
|
||||||
tenantDomain = (tenantDomain != null && !tenantDomain.isEmpty()) ? tenantDomain :
|
|
||||||
MultitenantConstants.SUPER_TENANT_DOMAIN_NAME;
|
|
||||||
try {
|
|
||||||
PrivilegedCarbonContext.startTenantFlow();
|
|
||||||
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true);
|
|
||||||
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
|
|
||||||
|
|
||||||
String sharingValueParam = servletContext.getInitParameter(PARAM_SHARED_WITH_ALL_TENANTS);
|
|
||||||
boolean isSharedWithAllTenants = Boolean.parseBoolean(sharingValueParam);
|
|
||||||
|
|
||||||
Map<DeviceTypeIdentifier, List<Feature>> features = annotationProcessor.extractFeatures(
|
|
||||||
annotatedAPIClasses, tenantId, isSharedWithAllTenants);
|
|
||||||
if (features != null && !features.isEmpty()) {
|
|
||||||
GenericFeatureManager.getInstance().addFeatures(features);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
PrivilegedCarbonContext.endTenantFlow();
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.error("Error enconterd while discovering annotated classes.", e);
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
log.error("Error while scanning class for annotations.", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,314 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
|
||||||
* Version 2.0 (the "License"); you may not use this file except
|
|
||||||
* in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.wso2.carbon.device.mgt.extensions.feature.mgt.util;
|
|
||||||
|
|
||||||
import org.apache.catalina.core.StandardContext;
|
|
||||||
import org.apache.commons.lang.ArrayUtils;
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
import org.scannotation.AnnotationDB;
|
|
||||||
import org.scannotation.WarUrlFinder;
|
|
||||||
import org.wso2.carbon.device.mgt.common.DeviceTypeIdentifier;
|
|
||||||
import org.wso2.carbon.device.mgt.common.Feature;
|
|
||||||
import org.wso2.carbon.device.mgt.extensions.feature.mgt.annotations.DeviceType;
|
|
||||||
|
|
||||||
import javax.servlet.ServletContext;
|
|
||||||
import javax.ws.rs.DELETE;
|
|
||||||
import javax.ws.rs.FormParam;
|
|
||||||
import javax.ws.rs.GET;
|
|
||||||
import javax.ws.rs.HttpMethod;
|
|
||||||
import javax.ws.rs.OPTIONS;
|
|
||||||
import javax.ws.rs.POST;
|
|
||||||
import javax.ws.rs.PUT;
|
|
||||||
import javax.ws.rs.Path;
|
|
||||||
import javax.ws.rs.PathParam;
|
|
||||||
import javax.ws.rs.QueryParam;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.annotation.Annotation;
|
|
||||||
import java.lang.reflect.InvocationHandler;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.lang.reflect.Proxy;
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.security.AccessController;
|
|
||||||
import java.security.PrivilegedAction;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This has the utility function to extract feature information.
|
|
||||||
*/
|
|
||||||
public class AnnotationProcessor {
|
|
||||||
|
|
||||||
private static final Log log = LogFactory.getLog(AnnotationProcessor.class);
|
|
||||||
|
|
||||||
private static final String PACKAGE_ORG_APACHE = "org.apache";
|
|
||||||
private static final String PACKAGE_ORG_CODEHAUS = "org.codehaus";
|
|
||||||
private static final String PACKAGE_ORG_SPRINGFRAMEWORK = "org.springframework";
|
|
||||||
private static final String STRING_ARR = "string_arr";
|
|
||||||
private static final String STRING = "string";
|
|
||||||
private static final String METHOD = "method";
|
|
||||||
private Class<org.wso2.carbon.device.mgt.extensions.feature.mgt.annotations.Feature>
|
|
||||||
featureAnnotationClazz;
|
|
||||||
private ClassLoader classLoader;
|
|
||||||
private ServletContext servletContext;
|
|
||||||
|
|
||||||
|
|
||||||
public AnnotationProcessor(final StandardContext context) {
|
|
||||||
servletContext = context.getServletContext();
|
|
||||||
classLoader = servletContext.getClassLoader();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Scan the context for classes with annotations
|
|
||||||
*/
|
|
||||||
public Set<String> scanStandardContext(String className) throws IOException {
|
|
||||||
ExtendedAnnotationDB db = new ExtendedAnnotationDB();
|
|
||||||
db.addIgnoredPackages(PACKAGE_ORG_APACHE);
|
|
||||||
db.addIgnoredPackages(PACKAGE_ORG_CODEHAUS);
|
|
||||||
db.addIgnoredPackages(PACKAGE_ORG_SPRINGFRAMEWORK);
|
|
||||||
|
|
||||||
URL classPath = findWebInfClassesPath(servletContext);
|
|
||||||
db.scanArchives(classPath);
|
|
||||||
|
|
||||||
//Returns a list of classes with given Annotation
|
|
||||||
return db.getAnnotationIndex().get(className);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method identifies the URL templates and context by reading the annotations of a class
|
|
||||||
*/
|
|
||||||
public Map<DeviceTypeIdentifier, List<Feature>> extractFeatures(Set<String> entityClasses, final int tenantId,
|
|
||||||
final boolean isSharedWithAllTenants)
|
|
||||||
throws ClassNotFoundException {
|
|
||||||
Map<DeviceTypeIdentifier, List<Feature>> features = null;
|
|
||||||
if (entityClasses != null && !entityClasses.isEmpty()) {
|
|
||||||
features = new HashMap<>();
|
|
||||||
for (final String className : entityClasses) {
|
|
||||||
final Map<DeviceTypeIdentifier, List<Feature>> featureMap =
|
|
||||||
AccessController.doPrivileged(new PrivilegedAction<Map<DeviceTypeIdentifier, List<Feature>>>() {
|
|
||||||
public Map<DeviceTypeIdentifier, List<Feature>> run() {
|
|
||||||
Map<DeviceTypeIdentifier, List<Feature>> featureMap = new HashMap<>();
|
|
||||||
try {
|
|
||||||
Class<?> clazz = classLoader.loadClass(className);
|
|
||||||
Class<DeviceType> deviceTypeClazz = (Class<DeviceType>) classLoader.loadClass(
|
|
||||||
DeviceType.class.getName());
|
|
||||||
Annotation deviceTypeAnno = clazz.getAnnotation(deviceTypeClazz);
|
|
||||||
if (deviceTypeAnno != null) {
|
|
||||||
Method[] deviceTypeMethod = deviceTypeClazz.getMethods();
|
|
||||||
String deviceType = invokeMethod(deviceTypeMethod[0], deviceTypeAnno, STRING);
|
|
||||||
featureAnnotationClazz =
|
|
||||||
(Class<org.wso2.carbon.device.mgt.extensions.feature.mgt.annotations
|
|
||||||
.Feature>) classLoader.loadClass(
|
|
||||||
org.wso2.carbon.device.mgt.extensions.feature.mgt
|
|
||||||
.annotations.Feature.class.getName());
|
|
||||||
List<Feature> featureList = getFeatures(clazz.getDeclaredMethods());
|
|
||||||
DeviceTypeIdentifier deviceTypeIdentifier;
|
|
||||||
if (isSharedWithAllTenants) {
|
|
||||||
deviceTypeIdentifier = new DeviceTypeIdentifier(deviceType);
|
|
||||||
} else {
|
|
||||||
deviceTypeIdentifier = new DeviceTypeIdentifier(deviceType, tenantId);
|
|
||||||
}
|
|
||||||
featureMap.put(deviceTypeIdentifier, featureList);
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
|
||||||
log.error("Failed to load the annotation from the features in the " +
|
|
||||||
"class " + className, e);
|
|
||||||
}
|
|
||||||
return featureMap;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
features.putAll(featureMap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return features;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Feature> getFeatures(Method[] methodsList) throws Throwable {
|
|
||||||
List<Feature> featureList = new ArrayList<>();
|
|
||||||
for (Method currentMethod : methodsList) {
|
|
||||||
Annotation featureAnnotation = currentMethod.getAnnotation(featureAnnotationClazz);
|
|
||||||
if (featureAnnotation != null) {
|
|
||||||
Feature feature = new Feature();
|
|
||||||
feature = processFeatureAnnotation(feature, currentMethod);
|
|
||||||
Annotation[] annotations = currentMethod.getDeclaredAnnotations();
|
|
||||||
Feature.MetadataEntry metadataEntry = new Feature.MetadataEntry();
|
|
||||||
metadataEntry.setId(-1);
|
|
||||||
Map<String, Object> apiParams = new HashMap<>();
|
|
||||||
for (int i = 0; i < annotations.length; i++) {
|
|
||||||
Annotation currentAnnotation = annotations[i];
|
|
||||||
processHttpMethodAnnotation(apiParams, currentAnnotation);
|
|
||||||
if (currentAnnotation.annotationType().getName().equals(Path.class.getName())) {
|
|
||||||
String uri = getPathAnnotationValue(currentMethod);
|
|
||||||
apiParams.put("uri", uri);
|
|
||||||
}
|
|
||||||
apiParams = processParamAnnotations(apiParams, currentMethod);
|
|
||||||
}
|
|
||||||
metadataEntry.setValue(apiParams);
|
|
||||||
List<Feature.MetadataEntry> metaInfoList = new ArrayList<>();
|
|
||||||
metaInfoList.add(metadataEntry);
|
|
||||||
feature.setMetadataEntries(metaInfoList);
|
|
||||||
featureList.add(feature);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return featureList;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<String, Object> processParamAnnotations(Map<String, Object> apiParams, Method currentMethod)
|
|
||||||
throws Throwable{
|
|
||||||
try {
|
|
||||||
apiParams.put("pathParams", processParamAnnotations(currentMethod, PathParam.class));
|
|
||||||
apiParams.put("queryParams", processParamAnnotations(currentMethod, QueryParam.class));
|
|
||||||
apiParams.put("formParams", processParamAnnotations(currentMethod, FormParam.class));
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
log.debug("No Form Param found for class " + featureAnnotationClazz.getName());
|
|
||||||
}
|
|
||||||
return apiParams;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> processParamAnnotations(Method currentMethod, Class<?> clazz) throws Throwable{
|
|
||||||
List<String> params = new ArrayList<>();
|
|
||||||
try {
|
|
||||||
Class<?> paramClazz = (Class<?>) classLoader.loadClass(clazz.getName());
|
|
||||||
Method[] formMethods = paramClazz.getMethods();
|
|
||||||
//Extract method parameter information and store same as feature meta info
|
|
||||||
Annotation[][] paramAnnotations = currentMethod.getParameterAnnotations();
|
|
||||||
Method valueMethod = formMethods[0];
|
|
||||||
for (int j = 0; j < paramAnnotations.length; j++) {
|
|
||||||
for (Annotation anno : paramAnnotations[j]) {
|
|
||||||
if (anno.annotationType().getName().equals(clazz.getName())) {
|
|
||||||
params.add(invokeMethod(valueMethod, anno, STRING));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
log.debug("No "+ clazz.getName() +" Param found for class " + featureAnnotationClazz.getName());
|
|
||||||
}
|
|
||||||
return params;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read Method annotations indicating HTTP Methods
|
|
||||||
*/
|
|
||||||
private void processHttpMethodAnnotation(Map<String, Object> apiParams, Annotation currentAnnotation) {
|
|
||||||
//Extracting method with which feature is exposed
|
|
||||||
if (currentAnnotation.annotationType().getName().equals(GET.class.getName())) {
|
|
||||||
apiParams.put(METHOD, HttpMethod.GET);
|
|
||||||
} else if (currentAnnotation.annotationType().getName().equals(POST.class.getName())) {
|
|
||||||
apiParams.put(METHOD, HttpMethod.POST);
|
|
||||||
} else if (currentAnnotation.annotationType().getName().equals(OPTIONS.class.getName())) {
|
|
||||||
apiParams.put(METHOD, HttpMethod.OPTIONS);
|
|
||||||
} else if (currentAnnotation.annotationType().getName().equals(DELETE.class.getName())) {
|
|
||||||
apiParams.put(METHOD, HttpMethod.DELETE);
|
|
||||||
} else if (currentAnnotation.annotationType().getName().equals(PUT.class.getName())) {
|
|
||||||
apiParams.put(METHOD, HttpMethod.PUT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read Feature annotation and Identify Features
|
|
||||||
* @param feature
|
|
||||||
* @param currentMethod
|
|
||||||
* @return
|
|
||||||
* @throws Throwable
|
|
||||||
*/
|
|
||||||
private Feature processFeatureAnnotation(Feature feature, Method currentMethod) throws Throwable{
|
|
||||||
Method[] featureAnnoMethods = featureAnnotationClazz.getMethods();
|
|
||||||
Annotation featureAnno = currentMethod.getAnnotation(featureAnnotationClazz);
|
|
||||||
for (int k = 0; k < featureAnnoMethods.length; k++) {
|
|
||||||
switch (featureAnnoMethods[k].getName()) {
|
|
||||||
case "name":
|
|
||||||
feature.setName(invokeMethod(featureAnnoMethods[k], featureAnno, STRING));
|
|
||||||
break;
|
|
||||||
case "code":
|
|
||||||
feature.setCode(invokeMethod(featureAnnoMethods[k], featureAnno, STRING));
|
|
||||||
break;
|
|
||||||
case "description":
|
|
||||||
feature.setDescription(invokeMethod(featureAnnoMethods[k], featureAnno, STRING));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return feature;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get value depicted by Path Annotation
|
|
||||||
* @param currentMethod
|
|
||||||
* @return
|
|
||||||
* @throws Throwable
|
|
||||||
*/
|
|
||||||
public String getPathAnnotationValue(Method currentMethod) throws Throwable{
|
|
||||||
String uri = "";
|
|
||||||
try {
|
|
||||||
Class<Path> pathClazz = (Class<Path>) classLoader.loadClass(Path.class.getName());
|
|
||||||
Annotation pathAnnno = currentMethod.getAnnotation(pathClazz);
|
|
||||||
Method[] pathMethods = pathClazz.getMethods();
|
|
||||||
Method valueMethod = pathMethods[0];
|
|
||||||
uri = invokeMethod(valueMethod, pathAnnno, STRING);
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
log.debug("No Path Param found for class " + featureAnnotationClazz.getName());
|
|
||||||
}
|
|
||||||
return uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When an annotation and method is passed, this method invokes that executes said method against the annotation
|
|
||||||
*/
|
|
||||||
private String invokeMethod(Method method, Annotation annotation, String returnType) throws Throwable {
|
|
||||||
InvocationHandler methodHandler = Proxy.getInvocationHandler(annotation);
|
|
||||||
switch (returnType) {
|
|
||||||
case STRING:
|
|
||||||
return (String) methodHandler.invoke(annotation, method, null);
|
|
||||||
case STRING_ARR:
|
|
||||||
return ((String[]) methodHandler.invoke(annotation, method, null))[0];
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find the URL pointing to "/WEB-INF/classes" This method may not work in conjunction with IteratorFactory
|
|
||||||
* if your servlet container does not extract the /WEB-INF/classes into a real file-based directory
|
|
||||||
*
|
|
||||||
* @param servletContext
|
|
||||||
* @return null if cannot determin /WEB-INF/classes
|
|
||||||
*/
|
|
||||||
public static URL findWebInfClassesPath(ServletContext servletContext)
|
|
||||||
{
|
|
||||||
String path = servletContext.getRealPath("/WEB-INF/classes");
|
|
||||||
if (path == null) return null;
|
|
||||||
File fp = new File(path);
|
|
||||||
if (fp.exists() == false) return null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
URI uri = fp.toURI();
|
|
||||||
return uri.toURL();
|
|
||||||
}
|
|
||||||
catch (MalformedURLException e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,92 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.wso2.carbon.device.mgt.extensions.feature.mgt.util;
|
|
||||||
|
|
||||||
import org.scannotation.AnnotationDB;
|
|
||||||
import org.scannotation.archiveiterator.Filter;
|
|
||||||
import org.scannotation.archiveiterator.StreamIterator;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.URL;
|
|
||||||
|
|
||||||
public class ExtendedAnnotationDB extends AnnotationDB {
|
|
||||||
|
|
||||||
public ExtendedAnnotationDB() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void scanArchives(URL... urls) throws IOException {
|
|
||||||
URL[] arr$ = urls;
|
|
||||||
int len$ = urls.length;
|
|
||||||
|
|
||||||
for(int i$ = 0; i$ < len$; ++i$) {
|
|
||||||
URL url = arr$[i$];
|
|
||||||
Filter filter = new Filter() {
|
|
||||||
public boolean accepts(String filename) {
|
|
||||||
if(filename.endsWith(".class")) {
|
|
||||||
if(filename.startsWith("/") || filename.startsWith("\\")) {
|
|
||||||
filename = filename.substring(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!ExtendedAnnotationDB.this.ignoreScan(filename.replace('/', '.'))) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
StreamIterator it = ExtendedIteratorFactory.create(url, filter);
|
|
||||||
|
|
||||||
InputStream stream;
|
|
||||||
while((stream = it.next()) != null) {
|
|
||||||
this.scanClass(stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean ignoreScan(String intf) {
|
|
||||||
String[] arr$;
|
|
||||||
int len$;
|
|
||||||
int i$;
|
|
||||||
String ignored;
|
|
||||||
if(this.scanPackages != null) {
|
|
||||||
arr$ = this.scanPackages;
|
|
||||||
len$ = arr$.length;
|
|
||||||
|
|
||||||
for(i$ = 0; i$ < len$; ++i$) {
|
|
||||||
ignored = arr$[i$];
|
|
||||||
if(intf.startsWith(ignored + ".")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
arr$ = this.ignoredPackages;
|
|
||||||
len$ = arr$.length;
|
|
||||||
|
|
||||||
for(i$ = 0; i$ < len$; ++i$) {
|
|
||||||
ignored = arr$[i$];
|
|
||||||
if(intf.startsWith(ignored + ".")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.wso2.carbon.device.mgt.extensions.feature.mgt.util;
|
|
||||||
|
|
||||||
import org.scannotation.archiveiterator.*;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URL;
|
|
||||||
|
|
||||||
public class ExtendedFileProtocolIteratorFactory implements DirectoryIteratorFactory {
|
|
||||||
|
|
||||||
private static final String ENCODING_SCHEME = "UTF-8";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public StreamIterator create(URL url, Filter filter) throws IOException {
|
|
||||||
File f = new File(java.net.URLDecoder.decode(url.getPath(), ENCODING_SCHEME));
|
|
||||||
return f.isDirectory()?new FileIterator(f, filter):new JarIterator(url.openStream(), filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.wso2.carbon.device.mgt.extensions.feature.mgt.util;
|
|
||||||
|
|
||||||
import org.scannotation.archiveiterator.DirectoryIteratorFactory;
|
|
||||||
import org.scannotation.archiveiterator.Filter;
|
|
||||||
import org.scannotation.archiveiterator.JarIterator;
|
|
||||||
import org.scannotation.archiveiterator.StreamIterator;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
public class ExtendedIteratorFactory {
|
|
||||||
|
|
||||||
private static final ConcurrentHashMap<String, DirectoryIteratorFactory> registry = new ConcurrentHashMap();
|
|
||||||
|
|
||||||
public static StreamIterator create(URL url, Filter filter) throws IOException {
|
|
||||||
String urlString = url.toString();
|
|
||||||
if(urlString.endsWith("!/")) {
|
|
||||||
urlString = urlString.substring(4);
|
|
||||||
urlString = urlString.substring(0, urlString.length() - 2);
|
|
||||||
url = new URL(urlString);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!urlString.endsWith("/")) {
|
|
||||||
return new JarIterator(url.openStream(), filter);
|
|
||||||
} else {
|
|
||||||
DirectoryIteratorFactory factory = registry.get(url.getProtocol());
|
|
||||||
if(factory == null) {
|
|
||||||
throw new IOException("Unable to scan directory of protocol: " + url.getProtocol());
|
|
||||||
} else {
|
|
||||||
return factory.create(url, filter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static {
|
|
||||||
registry.put("file", new ExtendedFileProtocolIteratorFactory());
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
package org.wso2.carbon.device.mgt.oauth.extensions;
|
|
||||||
|
|
||||||
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class holds the request format for device for grant type.
|
|
||||||
*/
|
|
||||||
public class DeviceRequestDTO {
|
|
||||||
|
|
||||||
private List<DeviceIdentifier> deviceIdentifiers;
|
|
||||||
private String scope;
|
|
||||||
|
|
||||||
public List<DeviceIdentifier> getDeviceIdentifiers() {
|
|
||||||
return deviceIdentifiers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDeviceIdentifiers(List<DeviceIdentifier> deviceIdentifiers) {
|
|
||||||
this.deviceIdentifiers = deviceIdentifiers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getScope() {
|
|
||||||
return scope;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setScope(String scope) {
|
|
||||||
this.scope = scope;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
package org.wso2.carbon.device.mgt.oauth.extensions;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This hold the OAuthConstants related oauth extensions.
|
|
||||||
*/
|
|
||||||
public class OAuthConstants {
|
|
||||||
|
|
||||||
public static final String DEFAULT_DEVICE_ASSERTION = "device";
|
|
||||||
public static final String DEFAULT_USERNAME_IDENTIFIER = "username";
|
|
||||||
public static final String DEFAULT_PASSWORD_IDENTIFIER = "password";
|
|
||||||
|
|
||||||
}
|
|
@ -1,90 +0,0 @@
|
|||||||
|
|
||||||
package org.wso2.carbon.device.mgt.oauth.extensions.config;
|
|
||||||
|
|
||||||
import javax.xml.bind.annotation.XmlAccessType;
|
|
||||||
import javax.xml.bind.annotation.XmlAccessorType;
|
|
||||||
import javax.xml.bind.annotation.XmlAttribute;
|
|
||||||
import javax.xml.bind.annotation.XmlElement;
|
|
||||||
import javax.xml.bind.annotation.XmlType;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Java class for Action complex type.
|
|
||||||
*
|
|
||||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* <complexType name="Action">
|
|
||||||
* <complexContent>
|
|
||||||
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
|
|
||||||
* <sequence>
|
|
||||||
* <element name="Permissions" type="{}Permissions"/>
|
|
||||||
* </sequence>
|
|
||||||
* <attribute name="name" type="{http://www.w3.org/2001/XMLSchema}string" />
|
|
||||||
* </restriction>
|
|
||||||
* </complexContent>
|
|
||||||
* </complexType>
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@XmlAccessorType(XmlAccessType.FIELD)
|
|
||||||
@XmlType(name = "Action", propOrder = {
|
|
||||||
"permissions"
|
|
||||||
})
|
|
||||||
public class Action {
|
|
||||||
|
|
||||||
@XmlElement(name = "Permissions", required = true)
|
|
||||||
protected Permissions permissions;
|
|
||||||
@XmlAttribute(name = "name")
|
|
||||||
protected String name;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the value of the permissions property.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* possible object is
|
|
||||||
* {@link Permissions }
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public Permissions getPermissions() {
|
|
||||||
return permissions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the value of the permissions property.
|
|
||||||
*
|
|
||||||
* @param value
|
|
||||||
* allowed object is
|
|
||||||
* {@link Permissions }
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public void setPermissions(Permissions value) {
|
|
||||||
this.permissions = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the value of the name property.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* possible object is
|
|
||||||
* {@link String }
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the value of the name property.
|
|
||||||
*
|
|
||||||
* @param value
|
|
||||||
* allowed object is
|
|
||||||
* {@link String }
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public void setName(String value) {
|
|
||||||
this.name = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,67 +0,0 @@
|
|||||||
|
|
||||||
package org.wso2.carbon.device.mgt.oauth.extensions.config;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import javax.xml.bind.annotation.XmlAccessType;
|
|
||||||
import javax.xml.bind.annotation.XmlAccessorType;
|
|
||||||
import javax.xml.bind.annotation.XmlElement;
|
|
||||||
import javax.xml.bind.annotation.XmlRootElement;
|
|
||||||
import javax.xml.bind.annotation.XmlType;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Java class for DeviceMgtScopes complex type.
|
|
||||||
*
|
|
||||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* <complexType name="DeviceMgtScopes">
|
|
||||||
* <complexContent>
|
|
||||||
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
|
|
||||||
* <sequence>
|
|
||||||
* <element name="Action" type="{}Action" maxOccurs="unbounded" minOccurs="0"/>
|
|
||||||
* </sequence>
|
|
||||||
* </restriction>
|
|
||||||
* </complexContent>
|
|
||||||
* </complexType>
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@XmlRootElement(name = "DeviceMgtScopes")
|
|
||||||
public class DeviceMgtScopes {
|
|
||||||
|
|
||||||
@XmlElement(name = "Action")
|
|
||||||
protected List<Action> action;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the value of the action property.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* This accessor method returns a reference to the live list,
|
|
||||||
* not a snapshot. Therefore any modification you make to the
|
|
||||||
* returned list will be present inside the JAXB object.
|
|
||||||
* This is why there is not a <CODE>set</CODE> method for the action property.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* For example, to add a new item, do as follows:
|
|
||||||
* <pre>
|
|
||||||
* getAction().add(newItem);
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Objects of the following type(s) are allowed in the list
|
|
||||||
* {@link Action }
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public List<Action> getAction() {
|
|
||||||
if (action == null) {
|
|
||||||
action = new ArrayList<Action>();
|
|
||||||
}
|
|
||||||
return this.action;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,67 +0,0 @@
|
|||||||
|
|
||||||
package org.wso2.carbon.device.mgt.oauth.extensions.config;
|
|
||||||
|
|
||||||
import org.w3c.dom.Document;
|
|
||||||
import org.wso2.carbon.device.mgt.oauth.extensions.OAuthExtUtils;
|
|
||||||
import org.wso2.carbon.utils.CarbonUtils;
|
|
||||||
|
|
||||||
import javax.xml.bind.JAXBContext;
|
|
||||||
import javax.xml.bind.JAXBException;
|
|
||||||
import javax.xml.bind.Unmarshaller;
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class represents the configuration that are needed for scopes to permission map.
|
|
||||||
*/
|
|
||||||
public class DeviceMgtScopesConfig {
|
|
||||||
|
|
||||||
private static DeviceMgtScopesConfig config = new DeviceMgtScopesConfig();
|
|
||||||
private static Map<String, String[]> actionPermissionMap = new HashMap<>();
|
|
||||||
|
|
||||||
private static final String DEVICE_MGT_SCOPES_CONFIG_PATH =
|
|
||||||
CarbonUtils.getEtcCarbonConfigDirPath() + File.separator + "device-mgt-scopes.xml";
|
|
||||||
|
|
||||||
private DeviceMgtScopesConfig() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DeviceMgtScopesConfig getInstance() {
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void init() throws DeviceMgtScopesConfigurationFailedException {
|
|
||||||
try {
|
|
||||||
File deviceMgtConfig = new File(DEVICE_MGT_SCOPES_CONFIG_PATH);
|
|
||||||
Document doc = OAuthExtUtils.convertToDocument(deviceMgtConfig);
|
|
||||||
|
|
||||||
/* Un-marshaling DeviceMGtScope configuration */
|
|
||||||
JAXBContext ctx = JAXBContext.newInstance(DeviceMgtScopes.class);
|
|
||||||
Unmarshaller unmarshaller = ctx.createUnmarshaller();
|
|
||||||
//unmarshaller.setSchema(getSchema());
|
|
||||||
DeviceMgtScopes deviceMgtScopes = (DeviceMgtScopes) unmarshaller.unmarshal(doc);
|
|
||||||
if (deviceMgtScopes != null) {
|
|
||||||
for (Action action : deviceMgtScopes.getAction()) {
|
|
||||||
Permissions permissions = action.getPermissions();
|
|
||||||
if (permissions != null) {
|
|
||||||
String permission[] = new String[permissions.getPermission().size()];
|
|
||||||
int i = 0;
|
|
||||||
for (String perm : permissions.getPermission()) {
|
|
||||||
permission[i] = perm;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
actionPermissionMap.put(action.getName(), permission);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (JAXBException e) {
|
|
||||||
throw new DeviceMgtScopesConfigurationFailedException("Error occurred while un-marshalling Device Scope" +
|
|
||||||
" Config", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, String[]> getDeviceMgtScopePermissionMap() {
|
|
||||||
return actionPermissionMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
|
||||||
* Version 2.0 (the "License"); you may not use this file except
|
|
||||||
* in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.wso2.carbon.device.mgt.oauth.extensions.config;
|
|
||||||
|
|
||||||
public class DeviceMgtScopesConfigurationFailedException extends Exception {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = -3151279312929070398L;
|
|
||||||
|
|
||||||
public DeviceMgtScopesConfigurationFailedException(String msg, Exception nestedEx) {
|
|
||||||
super(msg, nestedEx);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DeviceMgtScopesConfigurationFailedException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DeviceMgtScopesConfigurationFailedException(String msg) {
|
|
||||||
super(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DeviceMgtScopesConfigurationFailedException() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public DeviceMgtScopesConfigurationFailedException(Throwable cause) {
|
|
||||||
super(cause);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,78 +0,0 @@
|
|||||||
|
|
||||||
package org.wso2.carbon.device.mgt.oauth.extensions.config;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import javax.xml.bind.annotation.XmlAccessType;
|
|
||||||
import javax.xml.bind.annotation.XmlAccessorType;
|
|
||||||
import javax.xml.bind.annotation.XmlElement;
|
|
||||||
import javax.xml.bind.annotation.XmlType;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Java class for Permissions complex type.
|
|
||||||
*
|
|
||||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* <complexType name="Permissions">
|
|
||||||
* <complexContent>
|
|
||||||
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
|
|
||||||
* <sequence>
|
|
||||||
* <element name="Permission" maxOccurs="unbounded" minOccurs="0">
|
|
||||||
* <simpleType>
|
|
||||||
* <restriction base="{http://www.w3.org/2001/XMLSchema}string">
|
|
||||||
* <enumeration value="/permission/device-mgt/user/groups/device_operation"/>
|
|
||||||
* <enumeration value="/permission/device-mgt/groups"/>
|
|
||||||
* <enumeration value="/permission/device-mgt/user/groups"/>
|
|
||||||
* <enumeration value="/permission/device-mgt/user/groups/device_monitor"/>
|
|
||||||
* </restriction>
|
|
||||||
* </simpleType>
|
|
||||||
* </element>
|
|
||||||
* </sequence>
|
|
||||||
* </restriction>
|
|
||||||
* </complexContent>
|
|
||||||
* </complexType>
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@XmlAccessorType(XmlAccessType.FIELD)
|
|
||||||
@XmlType(name = "Permissions", propOrder = {
|
|
||||||
"permission"
|
|
||||||
})
|
|
||||||
public class Permissions {
|
|
||||||
|
|
||||||
@XmlElement(name = "Permission")
|
|
||||||
protected List<String> permission;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the value of the permission property.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* This accessor method returns a reference to the live list,
|
|
||||||
* not a snapshot. Therefore any modification you make to the
|
|
||||||
* returned list will be present inside the JAXB object.
|
|
||||||
* This is why there is not a <CODE>set</CODE> method for the permission property.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* For example, to add a new item, do as follows:
|
|
||||||
* <pre>
|
|
||||||
* getPermission().add(newItem);
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Objects of the following type(s) are allowed in the list
|
|
||||||
* {@link String }
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public List<String> getPermission() {
|
|
||||||
if (permission == null) {
|
|
||||||
permission = new ArrayList<String>();
|
|
||||||
}
|
|
||||||
return this.permission;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
|
||||||
* Version 2.0 (the "License"); you may not use this file except
|
|
||||||
* in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
package org.wso2.carbon.device.mgt.oauth.extensions.handlers.grant;
|
|
||||||
|
|
||||||
import org.wso2.carbon.device.mgt.oauth.extensions.OAuthExtUtils;
|
|
||||||
import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
|
|
||||||
import org.wso2.carbon.identity.oauth2.grant.jwt.JWTBearerGrantHandler;
|
|
||||||
import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
|
|
||||||
|
|
||||||
public class ExtendedDeviceMgtJWTBearerGrantHandler extends JWTBearerGrantHandler {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean validateScope(OAuthTokenReqMessageContext tokReqMsgCtx) throws IdentityOAuth2Exception {
|
|
||||||
return OAuthExtUtils.validateScope(tokReqMsgCtx);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,59 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
|
||||||
* Version 2.0 (the "License"); you may not use this file except
|
|
||||||
* in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.wso2.carbon.device.mgt.oauth.extensions.handlers.grant;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
import org.wso2.carbon.apimgt.keymgt.handlers.ExtendedPasswordGrantHandler;
|
|
||||||
import org.wso2.carbon.device.mgt.oauth.extensions.OAuthConstants;
|
|
||||||
import org.wso2.carbon.device.mgt.oauth.extensions.OAuthExtUtils;
|
|
||||||
import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
|
|
||||||
import org.wso2.carbon.identity.oauth2.model.RequestParameter;
|
|
||||||
import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public class ExtendedDeviceMgtPasswordGrantHandler extends ExtendedPasswordGrantHandler {
|
|
||||||
|
|
||||||
private static Log log = LogFactory.getLog(ExtendedDeviceMgtPasswordGrantHandler.class);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean validateGrant(OAuthTokenReqMessageContext tokReqMsgCtx) throws IdentityOAuth2Exception {
|
|
||||||
RequestParameter parameters[] = tokReqMsgCtx.getOauth2AccessTokenReqDTO().getRequestParameters();
|
|
||||||
for (RequestParameter parameter : parameters) {
|
|
||||||
switch (parameter.getKey()) {
|
|
||||||
case OAuthConstants.DEFAULT_USERNAME_IDENTIFIER:
|
|
||||||
String username = parameter.getValue()[0];
|
|
||||||
tokReqMsgCtx.getOauth2AccessTokenReqDTO().setResourceOwnerUsername(username);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OAuthConstants.DEFAULT_PASSWORD_IDENTIFIER:
|
|
||||||
String password = parameter.getValue()[0];
|
|
||||||
tokReqMsgCtx.getOauth2AccessTokenReqDTO().setResourceOwnerPassword(password);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return super.validateGrant(tokReqMsgCtx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean validateScope(OAuthTokenReqMessageContext tokReqMsgCtx) {
|
|
||||||
return OAuthExtUtils.validateScope(tokReqMsgCtx);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
|
||||||
* Version 2.0 (the "License"); you may not use this file except
|
|
||||||
* in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.wso2.carbon.device.mgt.oauth.extensions.validators;
|
|
||||||
|
|
||||||
import org.apache.oltu.oauth2.common.OAuth;
|
|
||||||
import org.apache.oltu.oauth2.common.validators.AbstractValidator;
|
|
||||||
import org.wso2.carbon.device.mgt.oauth.extensions.OAuthConstants;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Grant validator for JSON Web Tokens
|
|
||||||
* For JWT Grant to be valid the required parameters are
|
|
||||||
* grant_type and assertion
|
|
||||||
*/
|
|
||||||
public class ExtendedDeviceJWTGrantValidator extends AbstractValidator<HttpServletRequest> {
|
|
||||||
|
|
||||||
public ExtendedDeviceJWTGrantValidator() {
|
|
||||||
requiredParams.add(OAuth.OAUTH_GRANT_TYPE);
|
|
||||||
requiredParams.add(OAuth.OAUTH_ASSERTION);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
|
||||||
* Version 2.0 (the "License"); you may not use this file except
|
|
||||||
* in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.wso2.carbon.device.mgt.oauth.extensions.validators;
|
|
||||||
|
|
||||||
import org.apache.oltu.oauth2.common.OAuth;
|
|
||||||
import org.apache.oltu.oauth2.common.validators.AbstractValidator;
|
|
||||||
import org.wso2.carbon.device.mgt.oauth.extensions.OAuthConstants;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Grant validator for Device Object with Password Grant type
|
|
||||||
*/
|
|
||||||
public class ExtendedDevicePasswordGrantValidator extends AbstractValidator<HttpServletRequest> {
|
|
||||||
|
|
||||||
public ExtendedDevicePasswordGrantValidator() {
|
|
||||||
requiredParams.add(OAuth.OAUTH_USERNAME);
|
|
||||||
requiredParams.add(OAuth.OAUTH_PASSWORD);
|
|
||||||
requiredParams.add(OAuthConstants.DEFAULT_DEVICE_ASSERTION);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,112 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.device.mgt.oauth.extensions.validators;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
import org.wso2.carbon.device.mgt.common.permission.mgt.Permission;
|
|
||||||
import org.wso2.carbon.device.mgt.common.permission.mgt.PermissionManagementException;
|
|
||||||
import org.wso2.carbon.device.mgt.common.permission.mgt.PermissionManagerService;
|
|
||||||
import org.wso2.carbon.device.mgt.oauth.extensions.OAuthExtUtils;
|
|
||||||
import org.wso2.carbon.device.mgt.oauth.extensions.internal.OAuthExtensionsDataHolder;
|
|
||||||
import org.wso2.carbon.identity.application.common.model.User;
|
|
||||||
import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
|
|
||||||
import org.wso2.carbon.identity.oauth2.model.AccessTokenDO;
|
|
||||||
import org.wso2.carbon.identity.oauth2.validators.OAuth2ScopeValidator;
|
|
||||||
import org.wso2.carbon.user.api.UserRealm;
|
|
||||||
import org.wso2.carbon.user.api.UserStoreException;
|
|
||||||
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Custom OAuth2Token Scope validation implementation for DeviceManagement. This will validate the
|
|
||||||
* user permissions before dispatching the HTTP request to the actual endpoint.
|
|
||||||
*/
|
|
||||||
public class PermissionBasedScopeValidator extends OAuth2ScopeValidator {
|
|
||||||
|
|
||||||
private static final String URL_PROPERTY = "URL";
|
|
||||||
private static final String HTTP_METHOD_PROPERTY = "HTTP_METHOD";
|
|
||||||
|
|
||||||
public static final class PermissionMethod {
|
|
||||||
private PermissionMethod() {
|
|
||||||
throw new AssertionError();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final String READ = "read";
|
|
||||||
public static final String WRITE = "write";
|
|
||||||
public static final String DELETE = "delete";
|
|
||||||
public static final String ACTION = "action";
|
|
||||||
public static final String UI_EXECUTE = "ui.execute";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Log log = LogFactory.getLog(PermissionBasedScopeValidator.class);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean validateScope(AccessTokenDO accessTokenDO, String resource)
|
|
||||||
throws IdentityOAuth2Exception {
|
|
||||||
boolean status = true;
|
|
||||||
//Extract the url & http method
|
|
||||||
int idx = resource.lastIndexOf(':');
|
|
||||||
String url = resource.substring(0, idx);
|
|
||||||
String method = resource.substring(++idx, resource.length());
|
|
||||||
//This is to remove the url params for request path.
|
|
||||||
int urlParamIndex = url.indexOf('?');
|
|
||||||
if(urlParamIndex > 0) {
|
|
||||||
url = url.substring(0, urlParamIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
Properties properties = new Properties();
|
|
||||||
properties.put(PermissionBasedScopeValidator.URL_PROPERTY, url.toLowerCase());
|
|
||||||
properties.put(PermissionBasedScopeValidator.HTTP_METHOD_PROPERTY, method.toUpperCase());
|
|
||||||
PermissionManagerService permissionManagerService = OAuthExtensionsDataHolder.getInstance().
|
|
||||||
getPermissionManagerService();
|
|
||||||
try {
|
|
||||||
Permission permission = permissionManagerService.getPermission(properties);
|
|
||||||
User authzUser = accessTokenDO.getAuthzUser();
|
|
||||||
if ((permission != null) && (authzUser != null)) {
|
|
||||||
if (permission.getPath() == null) {
|
|
||||||
if (log.isDebugEnabled()) {
|
|
||||||
log.debug("Permission is not defined for the resource '" + resource + "'");
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
String username = authzUser.getUserName();
|
|
||||||
String userStore = authzUser.getUserStoreDomain();
|
|
||||||
int tenantId = OAuthExtUtils.getTenantId(authzUser.getTenantDomain());
|
|
||||||
UserRealm userRealm = OAuthExtensionsDataHolder.getInstance().getRealmService().getTenantUserRealm(tenantId);
|
|
||||||
if (userRealm != null && userRealm.getAuthorizationManager() != null) {
|
|
||||||
if (userStore != null) {
|
|
||||||
status = userRealm.getAuthorizationManager()
|
|
||||||
.isUserAuthorized(userStore + "/" + username, permission.getPath(),
|
|
||||||
PermissionMethod.UI_EXECUTE);
|
|
||||||
} else {
|
|
||||||
status = userRealm.getAuthorizationManager()
|
|
||||||
.isUserAuthorized(username, permission.getPath(), PermissionMethod.UI_EXECUTE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (PermissionManagementException e) {
|
|
||||||
log.error("Error occurred while validating the resource scope for : " + resource +
|
|
||||||
", Msg = " + e.getMessage(), e);
|
|
||||||
} catch (UserStoreException e) {
|
|
||||||
log.error("Error occurred while retrieving user store. " + e.getMessage());
|
|
||||||
}
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,51 +0,0 @@
|
|||||||
<?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 holds the scopes that are allowed by the device-mgt, The user require below permission to get the required scope-->
|
|
||||||
<!--These scopes are assigned after validating with device-mgt specific grant types-->
|
|
||||||
<DeviceMgtScopes>
|
|
||||||
<Action name="mqtt-publisher">
|
|
||||||
<Permissions>
|
|
||||||
<Permission>/permission/device-mgt/user/groups/device_operation</Permission>
|
|
||||||
<Permission>/permission/device-mgt/admin/groups</Permission>
|
|
||||||
<Permission>/permission/device-mgt/user/groups</Permission>
|
|
||||||
</Permissions>
|
|
||||||
</Action>
|
|
||||||
<Action name="mqtt-subscriber">
|
|
||||||
<Permissions>
|
|
||||||
<Permission>/permission/device-mgt/user/groups/device_monitor</Permission>
|
|
||||||
<Permission>/permission/device-mgt/admin/groups</Permission>
|
|
||||||
<Permission>/permission/device-mgt/user/groups</Permission>
|
|
||||||
</Permissions>
|
|
||||||
</Action>
|
|
||||||
<Action name="stats">
|
|
||||||
<Permissions>
|
|
||||||
<Permission>/permission/device-mgt/user/groups/device_monitor</Permission>
|
|
||||||
<Permission>/permission/device-mgt/admin/groups</Permission>
|
|
||||||
<Permission>/permission/device-mgt/user/groups</Permission>
|
|
||||||
</Permissions>
|
|
||||||
</Action>
|
|
||||||
<Action name="operation">
|
|
||||||
<Permissions>
|
|
||||||
<Permission>/permission/device-mgt/user/groups/device_operation</Permission>
|
|
||||||
<Permission>/permission/device-mgt/admin/groups</Permission>
|
|
||||||
<Permission>/permission/device-mgt/user/groups</Permission>
|
|
||||||
</Permissions>
|
|
||||||
</Action>
|
|
||||||
</DeviceMgtScopes>
|
|
@ -1,2 +1 @@
|
|||||||
instructions.configure = \
|
instructions.configure = \
|
||||||
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.oauth.extensions_${feature.version}/device-mgt-scopes.xml,target:${installFolder}/../../conf/etc/device-mgt-scopes.xml,overwrite:true);\
|
|
Loading…
Reference in new issue