From 08ee99f03433e878a1fb80ede3d44600fd57e6bd Mon Sep 17 00:00:00 2001 From: inoshperera Date: Wed, 29 Apr 2020 21:32:36 +0530 Subject: [PATCH] Add validation for policy Adding validation logic for policy APIs and added a new validate API to validate feature lists --- .../service/api/PolicyManagementService.java | 70 ++++++++++++++++++ .../impl/PolicyManagementServiceImpl.java | 27 ++++++- .../impl/util/RequestValidationUtil.java | 57 +++++++++++++- .../device/mgt/jaxrs/util/Constants.java | 6 ++ .../mgt/common/PolicyPayloadValidator.java | 8 ++ .../policy/mgt/common/ProfileFeature.java | 74 +++++++++++++++++++ 6 files changed, 236 insertions(+), 6 deletions(-) create mode 100644 components/policy-mgt/org.wso2.carbon.policy.mgt.common/src/main/java/org/wso2/carbon/policy/mgt/common/PolicyPayloadValidator.java create mode 100644 components/policy-mgt/org.wso2.carbon.policy.mgt.common/src/main/java/org/wso2/carbon/policy/mgt/common/ProfileFeature.java diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/PolicyManagementService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/PolicyManagementService.java index a438570798..607a4a8ef0 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/PolicyManagementService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/PolicyManagementService.java @@ -35,6 +35,7 @@ import org.wso2.carbon.device.mgt.common.policy.mgt.Policy; import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse; import org.wso2.carbon.device.mgt.jaxrs.beans.PolicyWrapper; import org.wso2.carbon.device.mgt.jaxrs.beans.PriorityUpdatedPolicyWrapper; +import org.wso2.carbon.device.mgt.jaxrs.beans.ProfileFeature; import org.wso2.carbon.device.mgt.jaxrs.util.Constants; import javax.validation.Valid; @@ -216,6 +217,75 @@ public interface PolicyManagementService { required = true) @Valid PolicyWrapper policy); + @POST + @Path("/validate") + @ApiOperation( + consumes = MediaType.APPLICATION_JSON, + produces = MediaType.APPLICATION_JSON, + httpMethod = "POST", + value = "Validate a policy", + notes = "Validate a policy", + tags = "Device Policy Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:policies:manage") + }) + } + ) + @ApiResponses( + value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully validated the policy.", + responseHeaders = { + @ResponseHeader( + name = "Content-Location", + description = "The URL of the added policy."), + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @ResponseHeader( + name = "ETag", + description = "Entity Tag of the response resource.\n" + + "Used by caches, or in conditional requests."), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource was last modified.\n" + + "Used by caches, or in conditional requests.") + } + ), + @ApiResponse( + code = 303, + message = "See Other. \n The source can be retrieved from the URL specified in the " + + "location header", + responseHeaders = { + @ResponseHeader( + name = "Content-Location", + description = "The Source URL of the document.")}), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid request or validation error.", + response = ErrorResponse.class), + @ApiResponse( + code = 401, + message = "Not Found. \n The user that is currently logged in is not " + + "authorized to validate policies.", + response = ErrorResponse.class), + @ApiResponse( + code = 415, + message = "Unsupported media type. \n The format of the requested entity was not " + + "supported."), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n " + + "Server error occurred while validating a policy.", + response = ErrorResponse.class) + }) + Response validatePolicy(@ApiParam( + name = "profileFeaturesList", + value = "The properties required to validate a policy.", + required = true) List profileFeaturesList); + @GET @ApiOperation( produces = MediaType.APPLICATION_JSON, diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/PolicyManagementServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/PolicyManagementServiceImpl.java index 415bda4f55..58f47a5f36 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/PolicyManagementServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/PolicyManagementServiceImpl.java @@ -48,6 +48,7 @@ import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse; import org.wso2.carbon.device.mgt.jaxrs.beans.PolicyList; import org.wso2.carbon.device.mgt.jaxrs.beans.PolicyWrapper; import org.wso2.carbon.device.mgt.jaxrs.beans.PriorityUpdatedPolicyWrapper; +import org.wso2.carbon.device.mgt.jaxrs.beans.ProfileFeature; import org.wso2.carbon.device.mgt.jaxrs.service.api.PolicyManagementService; import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.FilteringUtil; import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.RequestValidationUtil; @@ -78,7 +79,11 @@ public class PolicyManagementServiceImpl implements PolicyManagementService { @POST @Override public Response addPolicy(@Valid PolicyWrapper policyWrapper) { - RequestValidationUtil.validatePolicyDetails(policyWrapper); + List features = RequestValidationUtil + .validatePolicyDetails(policyWrapper); + if (features != null && features.size() > 0) { // validation failure results; + return Response.status(Response.Status.BAD_REQUEST).entity(features).build(); + } PolicyManagerService policyManagementService = DeviceMgtAPIUtils.getPolicyManagementService(); try { @@ -213,7 +218,11 @@ public class PolicyManagementServiceImpl implements PolicyManagementService { @Path("/{id}") @Override public Response updatePolicy(@PathParam("id") int id, @Valid PolicyWrapper policyWrapper) { - RequestValidationUtil.validatePolicyDetails(policyWrapper); + List features = RequestValidationUtil + .validatePolicyDetails(policyWrapper); + if (features != null && features.size() > 0) { // validation failure results; + return Response.status(Response.Status.BAD_REQUEST).entity(features).build(); + } PolicyManagerService policyManagementService = DeviceMgtAPIUtils.getPolicyManagementService(); try { Policy policy = this.getPolicyFromWrapper(policyWrapper); @@ -460,4 +469,18 @@ public class PolicyManagementServiceImpl implements PolicyManagementService { return Response.status(Response.Status.OK).entity(targetPolicies).build(); } + + @POST + @Path("/validate") + @Override + public Response validatePolicy(List profileFeaturesList) { + List features + = RequestValidationUtil.validateProfileFeatures(profileFeaturesList); + if (features != null && features.size() > 0) { // validation failure results; + return Response.status(Response.Status.BAD_REQUEST).entity(features).build(); + } + return Response.status(Response.Status.OK).entity("Valid request").build(); + + } + } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/util/RequestValidationUtil.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/util/RequestValidationUtil.java index aa0616fcf4..cc027fc5a8 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/util/RequestValidationUtil.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/util/RequestValidationUtil.java @@ -22,12 +22,18 @@ import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.HttpStatus; -import org.wso2.carbon.device.mgt.core.dao.impl.device.GenericDeviceDAOImpl; -import org.wso2.carbon.device.mgt.jaxrs.beans.Scope; import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration; import org.wso2.carbon.device.mgt.common.notification.mgt.Notification; -import org.wso2.carbon.device.mgt.jaxrs.beans.*; +import org.wso2.carbon.device.mgt.jaxrs.beans.ApplicationWrapper; +import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse; +import org.wso2.carbon.device.mgt.jaxrs.beans.OldPasswordResetWrapper; +import org.wso2.carbon.device.mgt.jaxrs.beans.PolicyWrapper; +import org.wso2.carbon.device.mgt.jaxrs.beans.ProfileFeature; +import org.wso2.carbon.device.mgt.jaxrs.beans.RoleInfo; +import org.wso2.carbon.device.mgt.jaxrs.beans.Scope; +import org.wso2.carbon.device.mgt.jaxrs.util.Constants; +import org.wso2.carbon.policy.mgt.common.PolicyPayloadValidator; import java.util.ArrayList; import java.util.List; @@ -273,13 +279,56 @@ public class RequestValidationUtil { } } - public static void validatePolicyDetails(PolicyWrapper policyWrapper) { + public static List validatePolicyDetails(PolicyWrapper policyWrapper) { if (policyWrapper == null) { throw new InputValidationException( new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage("Policy is empty.").build()); } + + return validateProfileFeatures(policyWrapper.getProfile().getProfileFeaturesList()); + } + + public static List validateProfileFeatures + (List profileFeatures) { + List features + = new ArrayList<>(); + String deviceType = null; + for (ProfileFeature profileFeature : profileFeatures) { + deviceType = profileFeature.getDeviceTypeId(); + org.wso2.carbon.policy.mgt.common.ProfileFeature feature = new org + .wso2.carbon.policy.mgt.common.ProfileFeature(); + feature.setContent(profileFeature.getContent()); + feature.setDeviceType(profileFeature.getDeviceTypeId()); + feature.setFeatureCode(profileFeature.getFeatureCode()); + feature.setPayLoad(profileFeature.getPayLoad()); + features.add(feature); + } + + try { + Class clz; + switch (deviceType) { + case Constants.ANDROID: + clz = Class.forName(Constants.ANDROID_POLICY_VALIDATOR); + PolicyPayloadValidator enrollmentNotifier = (PolicyPayloadValidator) clz.newInstance(); + return enrollmentNotifier.validate(features); + + default: + log.error("No policy validator found for device type " + deviceType); + } + } catch (InstantiationException e) { + log.error("Error when creating an instance of validator related to deviceType " + + deviceType); + } catch (IllegalAccessException e) { + log.error("Error when accessing an instance of validator related to deviceType " + + deviceType); + } catch (ClassNotFoundException e) { + log.error("Error when loading an instance of validator related to deviceType " + + deviceType); + } + return null; } + public static void validatePolicyIds(List policyIds) { if (policyIds == null || policyIds.size() == 0) { throw new InputValidationException( diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/Constants.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/Constants.java index 75f560ba68..e8efa58d19 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/Constants.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/Constants.java @@ -53,6 +53,12 @@ public class Constants { public static final String DEFAULT_SIMPLE_DATE_FORMAT = "EEE, d MMM yyyy HH:mm:ss Z"; public static final int DEFAULT_PAGE_LIMIT = 50; public static final String FORWARD_SLASH = "/"; + public static final String ANDROID = "android"; + public static final String ANDROID_POLICY_VALIDATOR = "io.entgra.proprietary.platform.android." + + "core.polcy.AndroidPolicyPayloadValidator"; + public static final String IOS = "ios"; + public static final String WINDOWS = "windows"; + public final class ErrorMessages { diff --git a/components/policy-mgt/org.wso2.carbon.policy.mgt.common/src/main/java/org/wso2/carbon/policy/mgt/common/PolicyPayloadValidator.java b/components/policy-mgt/org.wso2.carbon.policy.mgt.common/src/main/java/org/wso2/carbon/policy/mgt/common/PolicyPayloadValidator.java new file mode 100644 index 0000000000..45b91c9b05 --- /dev/null +++ b/components/policy-mgt/org.wso2.carbon.policy.mgt.common/src/main/java/org/wso2/carbon/policy/mgt/common/PolicyPayloadValidator.java @@ -0,0 +1,8 @@ +package org.wso2.carbon.policy.mgt.common; + +import java.util.List; + +public interface PolicyPayloadValidator { + + List validate(List features); +} diff --git a/components/policy-mgt/org.wso2.carbon.policy.mgt.common/src/main/java/org/wso2/carbon/policy/mgt/common/ProfileFeature.java b/components/policy-mgt/org.wso2.carbon.policy.mgt.common/src/main/java/org/wso2/carbon/policy/mgt/common/ProfileFeature.java new file mode 100644 index 0000000000..1040e8b771 --- /dev/null +++ b/components/policy-mgt/org.wso2.carbon.policy.mgt.common/src/main/java/org/wso2/carbon/policy/mgt/common/ProfileFeature.java @@ -0,0 +1,74 @@ +/* + * 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.policy.mgt.common; + +import java.io.Serializable; + +public class ProfileFeature implements Serializable { + + private boolean isValid; + private String featureCode; + private String deviceType; + private Object content; + private String payLoad; + + public boolean isValid() { + return isValid; + } + + public void setValid(boolean valid) { + isValid = valid; + } + + public String getDeviceType() { + return deviceType; + } + + public String getFeatureCode() { + return featureCode; + } + + public void setFeatureCode(String featureCode) { + this.featureCode = featureCode; + } + + public String getDeviceTypeId() { + return deviceType; + } + + public void setDeviceType(String deviceType) { + this.deviceType = deviceType; + } + + public String getPayLoad() { + return payLoad; + } + + public void setPayLoad(String payLoad) { + this.payLoad = payLoad; + } + + public Object getContent() { + return content; + } + + public void setContent(Object content) { + this.content = content; + } +}