Merge branch 'corrective-policy' into 'application-mgt-new'

Corrective Policy

See merge request entgra/carbon-device-mgt!328
feature/appm-store/pbac
Inosh Perara 5 years ago
commit 0539971f40

@ -14,6 +14,23 @@
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. 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.beans;
@ -21,6 +38,7 @@ 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 org.wso2.carbon.device.mgt.common.policy.mgt.CorrectiveAction;
import org.wso2.carbon.device.mgt.common.policy.mgt.DeviceGroupWrapper;
import javax.validation.constraints.NotNull;
@ -108,6 +126,12 @@ public class PolicyWrapper {
@NotNull
private String policyType;
@ApiModelProperty(
name = "correctiveActions",
value = "List of corrective actions to be applied when the policy is violated"
)
private List<CorrectiveAction> correctiveActions;
public String getPolicyType() {
return policyType;
}
@ -196,4 +220,11 @@ public class PolicyWrapper {
this.deviceGroups = deviceGroups;
}
public List<CorrectiveAction> getCorrectiveActions() {
return correctiveActions;
}
public void setCorrectiveActions(List<CorrectiveAction> correctiveActions) {
this.correctiveActions = correctiveActions;
}
}

@ -15,6 +15,23 @@
* specific language governing permissions and limitations
* under the License.
*
*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. 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;
@ -117,6 +134,7 @@ public class PolicyManagementServiceImpl implements PolicyManagementService {
policy.setPolicyName(policyWrapper.getPolicyName());
policy.setDescription(policyWrapper.getDescription());
policy.setProfile(DeviceMgtUtil.convertProfile(policyWrapper.getProfile()));
policy.setCorrectiveActions(policyWrapper.getCorrectiveActions());
policy.setOwnershipType(policyWrapper.getOwnershipType());
policy.setActive(policyWrapper.isActive());
policy.setRoles(policyWrapper.getRoles());

@ -0,0 +1,81 @@
/*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. 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.common.policy.mgt;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import java.util.List;
@ApiModel(
value = "CorrectiveAction",
description = "This bean carries all information related corrective action which is required " +
"when a policy is violated."
)
public class CorrectiveAction implements Serializable {
private static final long serialVersionUID = -3414709449056070148L;
@ApiModelProperty(
name = "action",
value = "Corrective action type (POLICY or OPERATION) to trigger when a policy is violated.",
example = "POLICY",
required = true
)
private String actionType;
@ApiModelProperty(
name = "policyId",
value = "When corrective action is POLICY, the corrective policy ID to be applied when a policy " +
"is violated.",
example = "1"
)
private int policyId;
@ApiModelProperty(
name = "operations",
value = "When corrective action is OPERATION, the list of operations in features to be applied " +
"when a policy is violated."
)
private List<ProfileFeature> operations;
public String getActionType() {
return actionType;
}
public void setActionType(String actionType) {
this.actionType = actionType;
}
public int getPolicyId() {
return policyId;
}
public void setPolicyId(int policyId) {
this.policyId = policyId;
}
public List<ProfileFeature> getOperations() {
return operations;
}
public void setOperations(List<ProfileFeature> operations) {
this.operations = operations;
}
}

@ -14,6 +14,23 @@
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. 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.common.policy.mgt;
@ -184,6 +201,13 @@ public class Policy implements Comparable<Policy>, Serializable {
example = "GENERAL")
private String policyType;
@ApiModelProperty(
name = "correctiveActions",
value = "List of corrective actions to be applied when the policy is violated",
example = "[{'actionType': 'POLICY', 'policyId': 1}]"
)
private List<CorrectiveAction> correctiveActions;
@XmlElement
public int getId() {
return id;
@ -355,6 +379,16 @@ public class Policy implements Comparable<Policy>, Serializable {
this.policyType = policyType;
}
@XmlElement
public List<CorrectiveAction> getCorrectiveActions() {
return correctiveActions;
}
public void setCorrectiveActions(
List<CorrectiveAction> correctiveActions) {
this.correctiveActions = correctiveActions;
}
@Override
public int compareTo(Policy o) {
if (this.priorityId == o.priorityId)

@ -62,6 +62,8 @@ policyModule = function () {
policyObjectToView["priorityId"] = policyObjectFromRestEndpoint["priorityId"];
policyObjectToView["name"] = policyObjectFromRestEndpoint["policyName"];
policyObjectToView["platform"] = policyObjectFromRestEndpoint["profile"]["deviceType"];
policyObjectFromRestEndpoint["policyType"] = policyListFromRestEndpoint["policyType"];
policyObjectFromRestEndpoint["correctiveActions"] = policyListFromRestEndpoint["correctiveActions"];
if (policyObjectToView["platform"] == "ios") {
policyObjectToView["deviceTypeIcon"] = "apple";
} else {
@ -168,6 +170,27 @@ policyModule = function () {
}
};
/**
* Retrieve all policies based on policy type
*/
publicMethods.getAllPoliciesByType = function (policyType) {
var carbonUser = session.get(constants["USER_SESSION_KEY"]);
if (!carbonUser) {
log.error("User object was not found in the session");
userModule.logout(function () {
response.sendRedirect(devicemgtProps["appContext"] + "login");
});
}
try {
var url = devicemgtProps["httpsURL"] + devicemgtProps["backendRestEndpoints"]["deviceMgt"] +
"/policies/type/" + policyType + "?offset=0&limit=100";
return serviceInvokers.XMLHttp.get(url, privateMethods.handleGetAllPoliciesResponse);
} catch (e) {
log.error("Error occurred while retrieving policies by policy type " + policyType);
throw e;
}
};
/*
Get policies count from backend services.
*/

@ -0,0 +1,25 @@
/*
*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. 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.
*/
$(document).ready(function () {
$("select.select2").select2();
});

@ -0,0 +1,35 @@
<!--Currently corrective action policy selection is supported only for android devices.
Once this is supported for other device type the below condition can be removed.-->
{{#equal deviceType "android"}}
<div id="corrective-policy-select-field" class="select-corrective-policy">
<div class="wr-input-control">
<div class="cus-col-50">
Select Corrective Policy
<span class="helper">
<i class="wr-help-tip glyphicon glyphicon-question-sign" title="Select the corrective policy to be applied when this general policy is violated"></i>
</span>
<!--suppress HtmlFormInputWithoutLabel -->
<select id="corrective-policy-input" class="form-control select2">
<option value="none">None</option>
{{#each correctivePolicies}}
{{#equal this.platform ../deviceType}}
<option value="{{this.id}}">{{this.name}}</option>
{{/equal}}
{{/each}}
</select>
</div>
<br class="c-both"/>
</div>
<div id="corrective-action-policy-id-missing-msg" class="hidden">
<br/>
<br/>
<span class="alert alert-info">
<strong>
<i class="icon fw fw-info"></i>
Corrective policy has been automatically changed to NONE since a previously selected corrective policy
has been updated to a GENERAL policy or it has been deleted.
</strong>
</span>
</div>
</div>
{{/equal}}

@ -2,36 +2,44 @@
{{#if isAuthorized}}
<span id="logged-in-user" class="hidden" data-username="{{@user.username}}" data-domain="{{@user.domain}}"
data-tenant-id="{{@user.tenantId}}" data-iscloud="{{isCloud}}"
data-isDeviceOwnerEnabled="{{isDeviceOwnerEnabled}}" data-storeapps="{{storeApps}}">
data-isDeviceOwnerEnabled="{{isDeviceOwnerEnabled}}" data-storeapps="{{storeApps}}"
data-corrective-policies="{{correctivePolicies}}">
</span>
<div class="row">
<div class="col-md-12">
<div class="wr-steps hidden">
<div class="col-md-3 col-xs-3">
<div class="col-md-2 col-xs-2 col-md-offset-1">
<div class="itm-wiz itm-wiz-current" data-step="policy-platform">
<div class="wiz-no">1</div>
<div class="wiz-lbl hidden-xs"><span>Select a platform</span></div>
</div>
<br class="c-both"/>
</div>
<div class="col-md-3 col-xs-3">
<div class="col-md-2 col-xs-2">
<div class="itm-wiz" data-step="policy-profile">
<div class="wiz-no">2</div>
<div class="wiz-lbl hidden-xs"><span>Configure profile</span></div>
</div>
<br class="c-both"/>
</div>
<div class="col-md-3 col-xs-3">
<div class="itm-wiz" data-step="policy-criteria">
<div class="col-md-2 col-xs-2">
<div class="itm-wiz" data-step="policy-type">
<div class="wiz-no">3</div>
<div class="wiz-lbl hidden-xs"><span>Select policy type</span></div>
</div>
<br class="c-both"/>
</div>
<div class="col-md-2 col-xs-2">
<div class="itm-wiz" data-step="policy-criteria">
<div class="wiz-no">4</div>
<div class="wiz-lbl hidden-xs"><span>Assign to groups</span></div>
</div>
<br class="c-both"/>
</div>
<div class="col-md-3 col-xs-3">
<div class="col-md-2 col-xs-2">
<div class="itm-wiz" data-step="policy-naming">
<div class="wiz-no">4</div>
<div class="wiz-no">5</div>
<div class="wiz-lbl hidden-xs"><span>Publish to devices</span></div>
</div>
<br class="c-both"/>
@ -55,7 +63,7 @@
<hr>
<div class="row">
<div class="col-lg-12">
<h4 class="hidden-xs">Step 4: Publish to devices</h4>
<h4 class="hidden-xs">Step 5: Publish to devices</h4>
<br>
<div id="policy-naming-main-error-msg" class="alert alert-danger hidden" role="alert">
<i class="icon fw fw-error"></i><span></span>
@ -110,7 +118,7 @@
<hr>
<div class="row">
<div class="col-lg-12">
<h4 class="hidden-xs">Step 3: Assign to groups</h4>
<h4 class="hidden-xs">Step 4: Assign to groups</h4>
<br>
<div id="policy-criteria-main-error-msg" class="alert alert-danger hidden" role="alert">
<i class="icon fw fw-error"></i><span></span>
@ -201,7 +209,7 @@
</div>
<div class="wr-input-control wr-btn-grp">
<a href="javascript:void(0)" class="wr-btn wizard-stepper" data-is-back-btn="true"
data-current="policy-criteria" data-next="policy-profile">Back</a>
data-current="policy-criteria" data-next="policy-type">Back</a>
<a href="javascript:void(0)" class="wr-btn wizard-stepper"
data-current="policy-criteria" data-next="policy-naming" data-validate="true">Continue</a>
</div>
@ -209,7 +217,45 @@
</div>
</div>
</div>
<div class="col-centered wr-content policy-type hidden">
<div class="wr-form">
<h1 id="policy-type-page-wizard-title" class="page-sub-title">ADD POLICY</h1>
<hr>
<div id="policy-type-wizard-steps" class="row wr-wizard"></div>
<hr>
<div class="row">
<div class="col-lg-12">
<h4 class="hidden-xs"> Step 3: Select policy type</h4>
<br>
<div id="policy-type-main-error-msg" class="alert alert-danger hidden" role="alert">
<i class="icon fw fw-error"></i><span></span>
</div>
<div>
<div class="wr-input-control">
<label class="wr-input-control radio light">
<input type="radio" id="policy-type-general" name="policy-type-radio-btn"
value="GENERAL" checked/>
<span class="helper">General Policy</span>
</label>
<label class="wr-input-control radio light">
<input type="radio" id="policy-type-corrective" name="policy-type-radio-btn"
value="CORRECTIVE"/>
<span class="helper">Corrective Policy</span>
</label>
</div>
</div>
<div id="select-general-policy-type"></div>
<div class="wr-input-control wr-btn-grp">
<a href="javascript:void(0)" class="wr-btn wizard-stepper" data-is-back-btn="true"
data-current="policy-type" data-next="policy-profile">Back</a>
<a href="javascript:void(0)" class="wr-btn wizard-stepper"
data-current="policy-type"
data-next="policy-criteria" data-validate="false">Continue</a>
</div>
</div>
</div>
</div>
</div>
<div class="col-centered wr-content policy-profile hidden">
<div class="wr-form">
<h1 id="policy-profile-page-wizard-title" class="page-sub-title">ADD POLICY</h1>
@ -242,7 +288,7 @@
data-current="policy-profile" data-next="policy-platform">Back</a>
<a href="javascript:void(0)" class="wr-btn wizard-stepper"
data-current="policy-profile"
data-next="policy-criteria" data-validate="true">Continue</a>
data-next="policy-type" data-validate="true">Continue</a>
</div>
</div>
</div>

@ -118,5 +118,7 @@ function onRequest(context) {
var enrollmentApps = policyModule.getStoreAppsForPolicy();
types["storeApps"] = JSON.stringify(enrollmentApps["content"]);
types["correctivePolicies"] = JSON.stringify(policyModule.getAllPoliciesByType("CORRECTIVE")["content"]);
return types;
}

@ -39,6 +39,7 @@ var validateInline = {};
var clearInline = {};
var validateStep = {};
var hasPolicyProfileScript = false;
var isCorrectiveActionProfileAdded = false;
var enableInlineError = function (inputField, errorMsg, errorSign) {
var fieldIdentifier = "#" + inputField;
@ -221,8 +222,36 @@ stepForwardFrom["policy-profile"] = function () {
*/
policy["profile"] = generatePolicyProfile();
}
// add policy correction action page
if (!isCorrectiveActionProfileAdded) {
var policyCorrectiveActionTemplateSrc =
"/public/cdmf.unit.policy.corrective-action/templates/policy-corrective-action.hbs";
var policyCorrectiveActionScriptSrc =
"/public/cdmf.unit.policy.corrective-action/js/policy-corrective-action.js";
var policyCorrectiveActionTemplateCacheKey = "policy-corrective-action";
$.template(policyCorrectiveActionTemplateCacheKey, context + policyCorrectiveActionTemplateSrc,
function (template) {
var content = template(
{
"deviceType": policy["platform"],
"correctivePolicies": $("#logged-in-user").data("corrective-policies")
}
);
$("#select-general-policy-type").html(content)
});
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = context + policyCorrectiveActionScriptSrc;
document.head.append(script);
isCorrectiveActionProfileAdded = true
}
// updating next-page wizard title with selected platform
$("#policy-criteria-page-wizard-title").text("ADD " + policy["platform"] + " POLICY");
$("#policy-type-page-wizard-title").text("ADD " + policy["platform"] + " POLICY");
};
/**
@ -238,6 +267,28 @@ stepBackFrom["policy-profile"] = function () {
}
};
/**
* Forward action of policy type page.
*/
stepForwardFrom["policy-type"] = function () {
policy["type"] = $("input[name=policy-type-radio-btn]:checked").val();
var correctiveActionList = [];
if (policy.type === "GENERAL") {
var selectedCorrectivePolicyId = $("#corrective-policy-input").val();
if (selectedCorrectivePolicyId && selectedCorrectivePolicyId !== "none") {
var correctiveAction = {
"actionType": "POLICY",
"policyId": selectedCorrectivePolicyId
};
correctiveActionList.push(correctiveAction);
}
}
policy["correctiveActionList"] = correctiveActionList;
//updating next-page wizard title with selected platform
$("#policy-criteria-page-wizard-title").text("ADD " + policy["platform"] + " POLICY");
};
/**
* Forward action of policy criteria page.
*/
@ -438,6 +489,8 @@ var savePolicy = function (policy, isActive, serviceURL) {
"compliance": policy["selectedNonCompliantAction"],
"ownershipType": null,
"active": isActive,
"policyType": policy["type"],
"correctiveActions": policy["correctiveActionList"],
"profile": {
"profileName": policy["policyName"],
"deviceType": policy["platform"],
@ -458,8 +511,6 @@ var savePolicy = function (policy, isActive, serviceURL) {
payload["deviceGroups"] = policy["selectedGroups"];
}
payload["policyType"] = "GENERAL";
invokerUtil.post(
serviceURL,
payload,
@ -594,6 +645,16 @@ $(document).ready(function () {
}
});
isCorrectiveActionProfileAdded = false;
$('input[type=radio][name=policy-type-radio-btn]').change(function() {
if ($(this).val() === "CORRECTIVE") {
$("#select-general-policy-type").addClass("hidden");
} else {
$("#select-general-policy-type").removeClass("hidden");
}
});
//Policy wizard stepper
$(".wizard-stepper").click(function () {
// button clicked here can be either a continue button or a back button.

@ -1,7 +1,8 @@
{{#zone "content"}}
{{#if isAuthorized }}
<span id="logged-in-user" class="hidden" data-username="{{@user.username}}" data-domain="{{@user.domain}}"
data-tenant-id="{{@user.tenantId}}" data-iscloud="{{isCloud}}" data-storeapps="{{storeApps}}"></span>
data-tenant-id="{{@user.tenantId}}" data-iscloud="{{isCloud}}" data-storeapps="{{storeApps}}"
data-corrective-policies="{{correctivePolicies}}"></span>
<span id="policy-operations" class="hidden" data-template="{{policyOperations.template}}"
data-script="{{policyOperations.script}}" data-style="{{policyOperations.style}}"></span>
<div class="row">
@ -16,15 +17,22 @@
<br class="c-both"/>
</div>
<div class="col-md-3 col-xs-3">
<div class="itm-wiz" data-step="policy-criteria">
<div class="itm-wiz itm-wiz" data-step="policy-type">
<div class="wiz-no">2</div>
<div class="wiz-lbl hidden-xs"><span>Edit policy type</span></div>
</div>
<br class="c-both"/>
</div>
<div class="col-md-3 col-xs-3">
<div class="itm-wiz" data-step="policy-criteria">
<div class="wiz-no">3</div>
<div class="wiz-lbl hidden-xs"><span>Edit assignment groups</span></div>
</div>
<br class="c-both"/>
</div>
<div class="col-md-3 col-xs-3">
<div class="itm-wiz" data-step="policy-naming">
<div class="wiz-no">3</div>
<div class="wiz-no">4</div>
<div class="wiz-lbl hidden-xs"><span>Republish to devices</span></div>
</div>
<br class="c-both"/>
@ -48,7 +56,7 @@
<hr>
<div class="row">
<div class="col-lg-12">
<h4 class="visible-xs">Step 3: Republish to devices</h4>
<h4 class="visible-xs">Step 4: Republish to devices</h4>
<br>
<div id="policy-naming-main-error-msg" class="alert alert-danger hidden" role="alert">
<i class="icon fw fw-error"></i><span></span>
@ -107,7 +115,7 @@
<hr>
<div class="row">
<div class="col-lg-12">
<h4 class="visible-xs">Step 2: Edit assignment groups</h4>
<h4 class="visible-xs">Step 3: Edit assignment groups</h4>
<br>
<div id="policy-criteria-main-error-msg" class="alert alert-danger hidden" role="alert">
<i class="icon fw fw-error"></i><span></span>
@ -196,7 +204,7 @@
</div>
<div class="wr-input-control wr-btn-grp">
<a href="#" class="wr-btn wizard-stepper" data-is-back-btn="true"
data-current="policy-criteria" data-next="policy-profile">
data-current="policy-criteria" data-next="policy-type">
Back
</a>
<a href="#" class="wr-btn wizard-stepper" data-current="policy-criteria"
@ -209,6 +217,53 @@
</div>
</div>
<div class="col-centered wr-content policy-type hidden">
<div class="wr-form">
<h1 id="policy-type-page-wizard-title" class="page-sub-title">EDIT POLICY</h1>
<hr>
<div id="policy-type-wizard-steps" class="row wr-wizard"></div>
<hr>
<div class="row">
<div class="col-lg-12">
<h4 class="visible-xs"> Step 2: Select policy type</h4>
<br>
<div id="policy-type-main-error-msg" class="alert alert-danger hidden" role="alert">
<i class="icon fw fw-error"></i><span></span>
</div>
<div>
<div class="wr-input-control">
<label class="wr-input-control radio light">
<input type="radio" id="policy-type-general" name="policy-type-radio-btn"
value="GENERAL"/>
<span class="helper">General Policy</span>
</label>
<label class="wr-input-control radio light">
<input type="radio" id="policy-type-corrective" name="policy-type-radio-btn"
value="CORRECTIVE"/>
<span class="helper">Corrective Policy</span>
</label>
</div>
</div>
<div class='policy-type-loading-corrective-actions'>
<br/>
<i class='fw fw-settings fw-spin fw-2x'></i>
Loading corrective actions . . .
<br/>
<br/>
</div>
<div id="select-general-policy-type"></div>
<div class="wr-input-control wr-btn-grp">
<a href="#" class="wr-btn wizard-stepper" data-is-back-btn="true"
data-current="policy-type" data-next="policy-profile">Back</a>
<a href="#" class="wr-btn wizard-stepper"
data-current="policy-type"
data-next="policy-criteria" data-validate="false">Continue</a>
</div>
</div>
</div>
</div>
</div>
<div class="col-centered wr-content policy-profile">
<div class="wr-form">
<h1 id="policy-profile-page-wizard-title" class="page-sub-title">EDIT POLICY</h1>
@ -238,7 +293,7 @@
</div>
<div class="wr-input-control wr-btn-grp">
<a href="#" class="wr-btn wizard-stepper" data-current="policy-profile"
data-next="policy-criteria" data-validate="true">
data-next="policy-type" data-validate="true">
Continue
</a>
</div>

@ -35,6 +35,7 @@
function onRequest(context) {
var deviceType = request.getParameter("deviceType");
var policyId = request.getParameter("id");
var utility = require("/app/modules/utility.js").utility;
var userModule = require("/app/modules/business-controllers/user.js")["userModule"];
var groupModule = require("/app/modules/business-controllers/group.js")["groupModule"];
@ -84,5 +85,18 @@ function onRequest(context) {
var enrollmentApps = policyModule.getStoreAppsForPolicy();
context["storeApps"] = JSON.stringify(enrollmentApps["content"]);
var correctivePolicies = policyModule.getAllPoliciesByType("CORRECTIVE")["content"];
if (correctivePolicies) {
var i;
for (i = 0; i < correctivePolicies.length; i++) {
if (correctivePolicies[i].id.toString() === policyId) {
correctivePolicies.splice(i, 1);
break;
}
}
}
context["correctivePolicies"] = JSON.stringify(correctivePolicies);
return context;
}

@ -42,6 +42,7 @@ var currentlyEffected = {};
var validateInline = {};
var clearInline = {};
var hasPolicyProfileScript = false;
var isCorrectiveActionProfileAdded = false;
var enableInlineError = function (inputField, errorMsg, errorSign) {
var fieldIdentifier = "#" + inputField;
@ -148,7 +149,6 @@ $("#policy-name-input").focus(function () {
skipStep["policy-platform"] = function (policyPayloadObj) {
policy["name"] = policyPayloadObj["policyName"];
policy["platform"] = policyPayloadObj["profile"]["deviceType"];
policy["policyType"] = policyPayloadObj["policyType"];
var userRoleInput = $("#user-roles-input");
var ownershipInput = $("#ownership-input");
@ -161,6 +161,8 @@ skipStep["policy-platform"] = function (policyPayloadObj) {
currentlyEffected["roles"] = policyPayloadObj.roles;
currentlyEffected["users"] = policyPayloadObj.users;
currentlyEffected["groups"] = [];
currentlyEffected["policyType"] = policyPayloadObj.policyType;
currentlyEffected["correctiveActions"] = policyPayloadObj.correctiveActions;
if (policyPayloadObj.deviceGroups) {
var deviceGroups = policyPayloadObj.deviceGroups;
@ -278,6 +280,75 @@ stepForwardFrom["policy-profile"] = function () {
*/
policy["profile"] = generatePolicyProfile();
}
var policyType = currentlyEffected.policyType;
$("input[name=policy-type-radio-btn][value=" + policyType + "]").prop("checked", true).trigger('change');
// add policy correction action page
if (!isCorrectiveActionProfileAdded) {
var policyCorrectiveActionTemplateSrc =
"/public/cdmf.unit.policy.corrective-action/templates/policy-corrective-action.hbs";
var policyCorrectiveActionScriptSrc =
"/public/cdmf.unit.policy.corrective-action/js/policy-corrective-action.js";
var policyCorrectiveActionTemplateCacheKey = "policy-corrective-action";
$.template(policyCorrectiveActionTemplateCacheKey, context + policyCorrectiveActionTemplateSrc,
function (template) {
var content = template(
{
"deviceType": policy["platform"],
"correctivePolicies": $("#logged-in-user").data("corrective-policies")
}
);
$("#select-general-policy-type").html(content);
if ("GENERAL" === policyType && currentlyEffected.correctiveActions &&
currentlyEffected.correctiveActions.length > 0) {
currentlyEffected.correctiveActions.forEach(function (correctiveAction) {
if ("POLICY" === correctiveAction.actionType) {
if ($("#corrective-policy-input option[value=" + correctiveAction.policyId + "]").length > 0) {
$("#corrective-policy-input").val(correctiveAction.policyId);
} else {
$("#corrective-action-policy-id-missing-msg").removeClass("hidden");
}
// returned from for each since currently only supported corrective action type is
// POLICY.
return true;
}
});
}
});
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = context + policyCorrectiveActionScriptSrc;
document.head.prepend(script);
isCorrectiveActionProfileAdded = true;
}
$(".policy-type-loading-corrective-actions").addClass("hidden");
// updating next-page wizard title with selected platform
$("#policy-type-page-wizard-title").text("EDIT " + policy["platform"] + " POLICY - " + policy["name"]);
};
/**
* Forward action of policy type page.
*/
stepForwardFrom["policy-type"] = function () {
policy["type"] = $("input[name=policy-type-radio-btn]:checked").val();
var correctiveActionList = [];
if (policy.type === "GENERAL") {
var selectedCorrectivePolicyId = $("#corrective-policy-input").val();
if (selectedCorrectivePolicyId && selectedCorrectivePolicyId !== "none") {
var correctiveAction = {
"actionType": "POLICY",
"policyId": selectedCorrectivePolicyId
};
correctiveActionList.push(correctiveAction);
}
}
policy["correctiveActionList"] = correctiveActionList;
// updating next-page wizard title with selected platform
$("#policy-criteria-page-wizard-title").text("EDIT " + policy["platform"] + " POLICY - " + policy["name"]);
};
@ -489,9 +560,10 @@ var updatePolicy = function (policy, state) {
var payload = {
"policyName": policy["policyName"],
"description": policy["description"],
"policyType": policy["policyType"],
"compliance": policy["selectedNonCompliantAction"],
"ownershipType": null,
"policyType": policy["type"],
"correctiveActions": policy["correctiveActionList"],
"profile": {
"profileName": policy["policyName"],
"deviceType": policy["platform"],
@ -696,6 +768,16 @@ $(document).ready(function () {
$("#policy-profile-wizard-steps").html($(".wr-steps").html());
isCorrectiveActionProfileAdded = false;
$('input[type=radio][name=policy-type-radio-btn]').change(function() {
if ($(this).val() === "CORRECTIVE") {
$("#select-general-policy-type").addClass("hidden");
} else {
$("#select-general-policy-type").removeClass("hidden");
}
});
$(".wizard-stepper").click(function () {
// button clicked here can be either a continue button or a back button.
var currentStep = $(this).data("current");

@ -28,6 +28,7 @@ var displayPolicy = function (policyPayloadObj) {
$("#policy-assignment").text(policyPayloadObj.deviceGroups);
$("#policy-action").text(policyPayloadObj.compliance.toUpperCase());
$("#policy-description").text(policyPayloadObj["description"]);
$("#policy-type").text(policyPayloadObj.policyType);
var policyStatus = "Active";
if (policyPayloadObj["active"] === true && policyPayloadObj["updated"] === true) {
policyStatus = '<i class="fw fw-warning icon-success"></i> Active/Updated</span>';
@ -68,6 +69,20 @@ var displayPolicy = function (policyPayloadObj) {
$("#policy-roles").text(policyPayloadObj.roles.toString().split(",").join(", "));
}
if ("GENERAL" === policyPayloadObj.policyType &&
policyPayloadObj.correctiveActions && policyPayloadObj.correctiveActions.length > 0) {
policyPayloadObj.correctiveActions.forEach(function (correctiveAction) {
if ("POLICY" === correctiveAction.actionType) {
$("#corrective-action-type-policy-id").html(correctiveAction.policyId);
return true;
}
});
$("#policy-corrective-actions-list").removeClass("hidden");
} else {
$("#policy-corrective-actions-list").addClass("hidden");
}
var policyId = policyPayloadObj["id"];
var deviceType = policy["platform"];
var policyOperations = $("#policy-operations");

@ -34,7 +34,7 @@
<td class="sorting_1" style="padding:10px 15px;">Action upon non-compliance</td>
<td id="policy-action" style="padding:10px 15px;"></td>
</tr>
<tr role="row" class="even">
<tr role="row" class="odd">
<td class="sorting_1" style="padding:10px 15px;">Status</td>
<td id="policy-status" style="padding:10px 15px;"></td>
</tr>
@ -46,9 +46,32 @@
<td class="sorting_1" style="padding:10px 15px;">Assigned Roles</td>
<td id="policy-roles" style="padding:10px 15px;"></td>
</tr>
<tr role="row" id="roles-row" class="even">
<td class="sorting_1" style="padding:10px 15px;">Policy Type</td>
<td id="policy-type" style="padding:10px 15px;"></td>
</tr>
</tbody>
</table>
{{/defineZone}}
<div id="policy-corrective-actions-list" class="hidden">
<div style="background: #008cc4; color: #fff; padding: 10px; margin-bottom: 5px">
Corrective Actions
</div>
<div class="add-margin-top-4x">
<div id="policy-corrective-actions">
<table class="table table-responsive table-striped">
<tbody>
<tr role="row">
<td class="sorting_1" style="padding:10px 15px; width: 14%;">Action Type</td>
<td style="padding:10px 15px;">POLICY</td>
<td class="sorting_1" style="padding:10px 15px; width: 14%;">Policy ID</td>
<td id="corrective-action-type-policy-id" style="padding:10px 15px;"></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div style="background: #008cc4; color: #fff; padding: 10px; margin-bottom: 5px">Description
</div>
<div class="add-margin-top-4x">

@ -0,0 +1,39 @@
/*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. 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;
public class PolicyTransformException extends Exception {
private static final long serialVersionUID = -4976670117832668628L;
public PolicyTransformException(String message, Throwable cause) {
super(message, cause);
}
public PolicyTransformException(Throwable cause) {
super(cause);
}
public PolicyTransformException(String msg) {
super(msg);
}
public PolicyTransformException() {
super();
}
}

@ -14,6 +14,23 @@
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. 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.core;
@ -134,6 +151,11 @@ public class PolicyManagerServiceImpl implements PolicyManagerService {
deviceIdentifier.getId() + " - " + deviceIdentifier.getType();
log.error(msg, e);
throw new PolicyManagementException(msg, e);
} catch (PolicyTransformException e) {
String msg = "Error occurred while transforming policy object to operation object type for device " +
deviceIdentifier.getId() + " - " + deviceIdentifier.getType();
log.error(msg, e);
throw new PolicyManagementException(msg, e);
}
}

@ -14,11 +14,29 @@
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. 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.core.dao;
import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.policy.mgt.CorrectiveAction;
import org.wso2.carbon.policy.mgt.common.Criterion;
import org.wso2.carbon.device.mgt.common.policy.mgt.DeviceGroupWrapper;
import org.wso2.carbon.device.mgt.common.policy.mgt.Policy;
@ -53,6 +71,41 @@ public interface PolicyDAO {
*/
Policy addPolicyToUser(List<String> usernameList, Policy policy) throws PolicyManagerDAOException;
/**
* This method is used to add corrective actions of policy in the database based on the policy ID
* @param correctiveActions list of corrective actions to be added to database
* @param policyId is used uniquely identify the policy to which corrective actions are to be added
* @throws PolicyManagerDAOException is thrown when there is an error in adding corrective actions to database
*/
void addCorrectiveActionsOfPolicy(List<CorrectiveAction> correctiveActions, int policyId)
throws PolicyManagerDAOException;
/**
* This method is used to retrieve corrective actions of policy from the database based on the policy ID
* @param policyId is used uniquely identify the policy from which corrective actions are retrieved
* @return list of retrieved {@link CorrectiveAction}
* @throws PolicyManagerDAOException is thrown when there is an error in retrieving corrective actions to database
*/
List<CorrectiveAction> getCorrectiveActionsOfPolicy(int policyId) throws PolicyManagerDAOException;
/**
* This method is used to update corrective actions of policy in the database based on the policy ID
* @param correctiveActions list of corrective actions to be updated in the database
* @param policyId is used uniquely identify the policy to which corrective actions are to be updated
* @throws PolicyManagerDAOException is thrown when there is an error in updating corrective actions to database
*/
void updateCorrectiveActionsOfPolicy(List<CorrectiveAction> correctiveActions, int policyId)
throws PolicyManagerDAOException;
/**
* This method is used to delete corrective actions of policy in the database based on the policy ID
* @param correctiveActions list of corrective actions to be deleted in the database
* @param policyId is used uniquely identify the policy to which corrective actions are to be deleted
* @throws PolicyManagerDAOException is thrown when there is an error in deleting corrective actions to database
*/
void deleteCorrectiveActionsOfPolicy(List<CorrectiveAction> correctiveActions, int policyId)
throws PolicyManagerDAOException;
Policy updateUserOfPolicy(List<String> usersToAdd, Policy policy) throws PolicyManagerDAOException;
Policy addPolicyToDevice(List<Device> devices, Policy policy) throws PolicyManagerDAOException;

@ -14,6 +14,23 @@
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. 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.core.dao.impl;
@ -22,6 +39,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.policy.mgt.CorrectiveAction;
import org.wso2.carbon.policy.mgt.common.Criterion;
import org.wso2.carbon.device.mgt.common.policy.mgt.DeviceGroupWrapper;
import org.wso2.carbon.device.mgt.common.policy.mgt.Policy;
@ -244,6 +262,108 @@ public class PolicyDAOImpl implements PolicyDAO {
return policy;
}
@Override
public void addCorrectiveActionsOfPolicy(List<CorrectiveAction> correctiveActions, int policyId)
throws PolicyManagerDAOException {
try {
Connection conn = this.getConnection();
String query = "INSERT INTO DM_POLICY_CORRECTIVE_ACTION " +
"(ACTION_TYPE, " +
"CORRECTIVE_POLICY_ID, " +
"POLICY_ID) VALUES (?, ?, ?)";
try (PreparedStatement insertStmt = conn.prepareStatement(query)) {
for (CorrectiveAction correctiveAction : correctiveActions) {
insertStmt.setString(1, correctiveAction.getActionType());
insertStmt.setInt(2, correctiveAction.getPolicyId());
insertStmt.setInt(3, policyId);
insertStmt.addBatch();
}
insertStmt.executeBatch();
}
} catch (SQLException e) {
String msg = "Error occurred while adding corrective actions of policy ID " + policyId;
log.error(msg, e);
throw new PolicyManagerDAOException(msg, e);
}
}
@Override
public List<CorrectiveAction> getCorrectiveActionsOfPolicy(int policyId) throws PolicyManagerDAOException {
try {
Connection conn = this.getConnection();
String query = "SELECT " +
"ACTION_TYPE, " +
"CORRECTIVE_POLICY_ID " +
"FROM DM_POLICY_CORRECTIVE_ACTION " +
"WHERE POLICY_ID = ?";
try (PreparedStatement selectStmt = conn.prepareStatement(query)) {
List<CorrectiveAction> correctiveActions = new ArrayList<>();
selectStmt.setInt(1, policyId);
try (ResultSet rs = selectStmt.executeQuery()) {
CorrectiveAction correctiveAction;
while (rs.next()) {
correctiveAction = new CorrectiveAction();
correctiveAction.setActionType(rs.getString("ACTION_TYPE"));
correctiveAction.setPolicyId(rs.getInt("CORRECTIVE_POLICY_ID"));
correctiveActions.add(correctiveAction);
}
}
return correctiveActions;
}
} catch (SQLException e) {
String msg = "Error occurred while retrieving corrective actions of policy ID " + policyId;
log.error(msg, e);
throw new PolicyManagerDAOException(msg, e);
}
}
@Override
public void updateCorrectiveActionsOfPolicy(List<CorrectiveAction> correctiveActions, int policyId)
throws PolicyManagerDAOException {
try {
Connection conn = this.getConnection();
String query = "UPDATE DM_POLICY_CORRECTIVE_ACTION " +
"SET CORRECTIVE_POLICY_ID = ? " +
"WHERE ACTION_TYPE = ? " +
"AND POLICY_ID = ?";
try (PreparedStatement updateStmt = conn.prepareStatement(query)) {
for (CorrectiveAction correctiveAction : correctiveActions) {
updateStmt.setInt(1, correctiveAction.getPolicyId());
updateStmt.setString(2, correctiveAction.getActionType());
updateStmt.setInt(3, policyId);
updateStmt.addBatch();
}
updateStmt.executeBatch();
}
} catch (SQLException e) {
String msg = "Error occurred while updating corrective actions of policy ID " + policyId;
log.error(msg, e);
throw new PolicyManagerDAOException(msg, e);
}
}
@Override
public void deleteCorrectiveActionsOfPolicy(List<CorrectiveAction> correctiveActions, int policyId)
throws PolicyManagerDAOException {
try {
Connection conn = this.getConnection();
String query = "DELETE FROM DM_POLICY_CORRECTIVE_ACTION " +
"WHERE ACTION_TYPE = ? " +
"AND POLICY_ID = ?";
try (PreparedStatement deleteStmt = conn.prepareStatement(query)) {
for (CorrectiveAction correctiveAction : correctiveActions) {
deleteStmt.setString(1, correctiveAction.getActionType());
deleteStmt.setInt(2, policyId);
deleteStmt.addBatch();
}
deleteStmt.executeBatch();
}
} catch (SQLException e) {
String msg = "Error occurred while deleting corrective actions of policy ID " + policyId;
log.error(msg, e);
throw new PolicyManagerDAOException(msg, e);
}
}
@Override
public Policy addPolicyToDevice(List<Device> devices, Policy policy) throws PolicyManagerDAOException {
@ -801,7 +921,7 @@ public class PolicyDAOImpl implements PolicyDAO {
try {
conn = this.getConnection();
String query = "UPDATE DM_POLICY SET NAME = ?, PROFILE_ID = ?, PRIORITY = ?, COMPLIANCE = ?," +
" UPDATED = ?, DESCRIPTION = ?, OWNERSHIP_TYPE = ? WHERE ID = ? AND TENANT_ID = ?";
" UPDATED = ?, DESCRIPTION = ?, OWNERSHIP_TYPE = ?, POLICY_TYPE = ? WHERE ID = ? AND TENANT_ID = ?";
stmt = conn.prepareStatement(query);
stmt.setString(1, policy.getPolicyName());
stmt.setInt(2, policy.getProfile().getProfileId());
@ -810,8 +930,9 @@ public class PolicyDAOImpl implements PolicyDAO {
stmt.setInt(5, 1);
stmt.setString(6, policy.getDescription());
stmt.setString(7, policy.getOwnershipType());
stmt.setInt(8, policy.getId());
stmt.setInt(9, tenantId);
stmt.setString(8, policy.getPolicyType());
stmt.setInt(9, policy.getId());
stmt.setInt(10, tenantId);
stmt.executeUpdate();
} catch (SQLException e) {
@ -1352,6 +1473,14 @@ public class PolicyDAOImpl implements PolicyDAO {
stmt.setInt(1, policyId);
stmt.executeUpdate();
if (log.isDebugEnabled()) {
log.debug("Deleting corrective actions of policy ID " + policyId);
}
String deleteCorrectiveActions = "DELETE FROM DM_POLICY_CORRECTIVE_ACTION WHERE POLICY_ID = ?";
stmt = conn.prepareStatement(deleteCorrectiveActions);
stmt.setInt(1, policyId);
stmt.executeUpdate();
if (log.isDebugEnabled()) {
log.debug("Policy (" + policyId + ") related configs deleted from database.");
}

@ -15,6 +15,22 @@
* specific language governing permissions and limitations
* under the License.
*
*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. 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.core.enforcement;
@ -31,6 +47,7 @@ import org.wso2.carbon.device.mgt.common.policy.mgt.Policy;
import org.wso2.carbon.policy.mgt.common.PolicyAdministratorPoint;
import org.wso2.carbon.policy.mgt.common.PolicyEvaluationException;
import org.wso2.carbon.policy.mgt.common.PolicyManagementException;
import org.wso2.carbon.policy.mgt.common.PolicyTransformException;
import org.wso2.carbon.policy.mgt.core.PolicyManagerService;
import org.wso2.carbon.policy.mgt.core.PolicyManagerServiceImpl;
import org.wso2.carbon.policy.mgt.core.internal.PolicyManagementDataHolder;
@ -136,6 +153,12 @@ public class PolicyEnforcementDelegatorImpl implements PolicyEnforcementDelegato
String msg = "Error occurred while adding the operation to device.";
log.error(msg, e);
throw new PolicyDelegationException(msg, e);
} catch (PolicyTransformException e) {
String msg = "Error occurred while transforming policy object to operation object type for policy " +
policy.getId() + " - " + policy.getPolicyName() + " for devices " +
deviceIdentifiers.toString();
log.error(msg, e);
throw new PolicyDelegationException(msg, e);
}
}

@ -14,6 +14,23 @@
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. 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.core.mgt.impl;
@ -28,6 +45,7 @@ import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup;
import org.wso2.carbon.device.mgt.common.group.mgt.GroupManagementException;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException;
import org.wso2.carbon.device.mgt.common.policy.mgt.CorrectiveAction;
import org.wso2.carbon.device.mgt.common.policy.mgt.DeviceGroupWrapper;
import org.wso2.carbon.device.mgt.common.policy.mgt.Policy;
import org.wso2.carbon.device.mgt.common.policy.mgt.PolicyCriterion;
@ -124,6 +142,14 @@ public class PolicyManagerImpl implements PolicyManager {
policyDAO.addPolicyCriteriaProperties(policy.getPolicyCriterias());
}
if (policy.getCorrectiveActions() != null && !policy.getCorrectiveActions().isEmpty()) {
if (log.isDebugEnabled()) {
log.debug("Adding corrective actions for policy " + policy.getPolicyName() +
" having policy id " + policy.getId());
}
policyDAO.addCorrectiveActionsOfPolicy(policy.getCorrectiveActions(), policy.getId());
}
if (policy.isActive()) {
policyDAO.activatePolicy(policy.getId());
}
@ -248,6 +274,55 @@ public class PolicyManagerImpl implements PolicyManager {
policyDAO.addPolicyCriteriaProperties(policy.getPolicyCriterias());
}
List<CorrectiveAction> updatedCorrectiveActions = policy.getCorrectiveActions();
List<CorrectiveAction> existingCorrectiveActions = previousPolicy.getCorrectiveActions();
List<CorrectiveAction> correctiveActionsToUpdate = new ArrayList<>();
List<CorrectiveAction> correctiveActionsToDelete = new ArrayList<>();
List<CorrectiveAction> correctiveActionsToAdd = new ArrayList<>();
List<String> correctiveActionTypesToUpdate = new ArrayList<>();
List<String> existingCorrectiveActionTypes = new ArrayList<>();
if (updatedCorrectiveActions != null) {
for (CorrectiveAction updatedCorrectiveAction : updatedCorrectiveActions) {
for (CorrectiveAction existingCorrectiveAction : existingCorrectiveActions) {
if (updatedCorrectiveAction.getActionType().equals(existingCorrectiveAction.getActionType())) {
correctiveActionsToUpdate.add(updatedCorrectiveAction);
existingCorrectiveActionTypes.add(updatedCorrectiveAction.getActionType());
}
}
correctiveActionTypesToUpdate.add(updatedCorrectiveAction.getActionType());
}
for (CorrectiveAction updatedCorrectiveAction : updatedCorrectiveActions) {
if (!existingCorrectiveActionTypes.contains(updatedCorrectiveAction.getActionType())) {
correctiveActionsToAdd.add(updatedCorrectiveAction);
}
}
}
for (CorrectiveAction existingCorrectiveAction : existingCorrectiveActions) {
if (!correctiveActionTypesToUpdate.contains(existingCorrectiveAction.getActionType())) {
correctiveActionsToDelete.add(existingCorrectiveAction);
}
}
if (log.isDebugEnabled()) {
log.debug("Updating corrective actions for policy " + policy.getPolicyName() +
" having policy id " + policy.getId());
}
if (!correctiveActionsToUpdate.isEmpty()) {
policyDAO.updateCorrectiveActionsOfPolicy(correctiveActionsToUpdate, previousPolicy.getId());
}
if (!correctiveActionsToAdd.isEmpty()) {
policyDAO.addCorrectiveActionsOfPolicy(correctiveActionsToAdd, previousPolicy.getId());
}
if (!correctiveActionsToDelete.isEmpty()) {
policyDAO.deleteCorrectiveActionsOfPolicy(correctiveActionsToDelete, previousPolicy.getId());
}
PolicyManagementDAOFactory.commitTransaction();
} catch (PolicyManagerDAOException e) {
PolicyManagementDAOFactory.rollbackTransaction();
@ -578,6 +653,12 @@ public class PolicyManagerImpl implements PolicyManager {
policy.setRoles(roleNames);
policy.setUsers(userNames);
if (log.isDebugEnabled()) {
log.debug("Retrieving corrective actions of policy " + policy.getPolicyName() +
" having policy id " + policy.getId());
}
policy.setCorrectiveActions(policyDAO.getCorrectiveActionsOfPolicy(policyId));
} catch (PolicyManagerDAOException e) {
throw new PolicyManagementException("Error occurred while getting the policy related to policy ID (" +
policyId + ")", e);
@ -1179,6 +1260,11 @@ public class PolicyManagerImpl implements PolicyManager {
deviceGroupWrappers = this.getDeviceGroupNames(deviceGroupWrappers);
}
policy.setDeviceGroups(deviceGroupWrappers);
if (log.isDebugEnabled()) {
log.debug("Retrieving corrective actions for policy " + policy.getPolicyName() +
" having policy id " + policy.getId());
}
policy.setCorrectiveActions(policyDAO.getCorrectiveActionsOfPolicy(policy.getId()));
}
Collections.sort(policyList);
}

@ -14,6 +14,23 @@
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. 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.core.util;
@ -45,6 +62,11 @@ public final class PolicyManagementConstants {
public static final String DELEGATION_TASK_NAME = "DELEGATION";
public static final String DELEGATION_TASK_CLAZZ = "org.wso2.carbon.policy.mgt.core.enforcement.DelegationTask";
public static final String GENERAL_POLICY_TYPE = "GENERAL";
public static final String CORRECTIVE_POLICY_TYPE = "CORRECTIVE";
public static final String POLICY_CORRECTIVE_ACTION_TYPE = "POLICY";
public static final String CORRECTIVE_POLICY_FEATURE_CODE = "CORRECTIVE_POLICY";
/**
Caller would reference the constants using PolicyManagementConstants.DEVICE_CONFIG_XML_NAME,
and so on. Any caller should be prevented from constructing objects of

@ -14,10 +14,28 @@
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. 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.core.util;
import com.google.gson.Gson;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
@ -28,17 +46,21 @@ import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration
import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfigurationManagementService;
import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
import org.wso2.carbon.device.mgt.common.policy.mgt.CorrectiveAction;
import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager;
import org.wso2.carbon.device.mgt.core.config.policy.PolicyConfiguration;
import org.wso2.carbon.device.mgt.core.config.tenant.PlatformConfigurationManagementServiceImpl;
import org.wso2.carbon.device.mgt.core.operation.mgt.PolicyOperation;
import org.wso2.carbon.device.mgt.core.operation.mgt.ProfileOperation;
import org.wso2.carbon.device.mgt.common.policy.mgt.Policy;
import org.wso2.carbon.policy.mgt.common.PolicyAdministratorPoint;
import org.wso2.carbon.policy.mgt.common.PolicyManagementException;
import org.wso2.carbon.device.mgt.common.policy.mgt.ProfileFeature;
import org.wso2.carbon.policy.mgt.common.PolicyTransformException;
import org.wso2.carbon.policy.mgt.core.config.datasource.DataSourceConfig;
import org.wso2.carbon.policy.mgt.core.config.datasource.JNDILookupDefinition;
import org.wso2.carbon.policy.mgt.core.dao.util.PolicyManagementDAOUtil;
import org.wso2.carbon.policy.mgt.core.impl.PolicyAdministratorPointImpl;
import javax.cache.Cache;
import javax.cache.CacheManager;
@ -116,28 +138,71 @@ public class PolicyManagerUtil {
return buff.toString();
}
public static Operation transformPolicy(Policy policy) {
public static Operation transformPolicy(Policy policy) throws PolicyTransformException {
List<ProfileFeature> effectiveFeatures = policy.getProfile().getProfileFeaturesList();
List<ProfileOperation> profileOperationList = new ArrayList<ProfileOperation>();
PolicyOperation policyOperation = new PolicyOperation();
policyOperation.setEnabled(true);
policyOperation.setType(org.wso2.carbon.device.mgt.common.operation.mgt.Operation.Type.POLICY);
policyOperation.setCode(PolicyOperation.POLICY_OPERATION_CODE);
if (policy.getPolicyType() != null &&
PolicyManagementConstants.GENERAL_POLICY_TYPE.equals(policy.getPolicyType()) &&
policy.getCorrectiveActions() != null) {
for (CorrectiveAction correctiveAction : policy.getCorrectiveActions()) {
if (PolicyManagementConstants.POLICY_CORRECTIVE_ACTION_TYPE
.equalsIgnoreCase(correctiveAction.getActionType())) {
PolicyAdministratorPoint pap = new PolicyAdministratorPointImpl();
try {
Policy correctivePolicy = pap.getPolicy(correctiveAction.getPolicyId());
if (correctivePolicy == null || PolicyManagementConstants.CORRECTIVE_POLICY_TYPE
.equalsIgnoreCase(correctivePolicy.getPolicyType())) {
String msg = "No corrective policy was found for the policy " + policy.getPolicyName() +
" and policy ID " + policy.getId();
log.error(msg);
throw new PolicyTransformException(msg);
} else {
List<ProfileOperation> correctiveProfileOperations = createProfileOperations(
correctivePolicy.getProfile().getProfileFeaturesList());
ProfileFeature correctivePolicyFeature = new ProfileFeature();
correctivePolicyFeature.setProfileId(correctivePolicy.getProfileId());
correctivePolicyFeature.setContent(new Gson().toJson(correctiveProfileOperations));
correctivePolicyFeature.setDeviceType(correctivePolicy.getProfile().getDeviceType());
correctivePolicyFeature.setFeatureCode(
PolicyManagementConstants.CORRECTIVE_POLICY_FEATURE_CODE);
correctivePolicyFeature.setId(correctivePolicy.getId());
effectiveFeatures.add(correctivePolicyFeature);
}
} catch (PolicyManagementException e) {
String msg = "Error occurred while retrieving corrective policy for policy " +
policy.getPolicyName() + " and policy ID " + policy.getId();
log.error(msg, e);
throw new PolicyTransformException(msg, e);
}
// Currently only supported POLICY corrective action type so the break is added. This should be
// removed when we start supporting other corrective action types
break;
}
}
}
policyOperation.setProfileOperations(createProfileOperations(effectiveFeatures));
policyOperation.setPayLoad(policyOperation.getProfileOperations());
return policyOperation;
}
public static List<ProfileOperation> createProfileOperations(List<ProfileFeature> effectiveFeatures) {
List<ProfileOperation> profileOperations = new ArrayList<>();
for (ProfileFeature feature : effectiveFeatures) {
ProfileOperation profileOperation = new ProfileOperation();
profileOperation.setCode(feature.getFeatureCode());
profileOperation.setEnabled(true);
profileOperation.setStatus(org.wso2.carbon.device.mgt.common.operation.mgt.Operation.Status.PENDING);
profileOperation.setType(org.wso2.carbon.device.mgt.common.operation.mgt.Operation.Type.PROFILE);
profileOperation.setPayLoad(feature.getContent());
profileOperationList.add(profileOperation);
profileOperations.add(profileOperation);
}
policyOperation.setProfileOperations(profileOperationList);
policyOperation.setPayLoad(policyOperation.getProfileOperations());
return policyOperation;
return profileOperations;
}

@ -209,6 +209,19 @@ CREATE TABLE IF NOT EXISTS DM_POLICY (
ON UPDATE NO ACTION
);
CREATE TABLE IF NOT EXISTS DM_POLICY_CORRECTIVE_ACTION (
ID INT(11) NOT NULL AUTO_INCREMENT,
ACTION_TYPE VARCHAR(45) NOT NULL,
CORRECTIVE_POLICY_ID INT(11) DEFAULT NULL,
POLICY_ID INT(11) NOT NULL,
PRIMARY KEY (ID),
CONSTRAINT FK_DM_POLICY_DM_POLICY_CORRECTIVE_ACTION
FOREIGN KEY (POLICY_ID )
REFERENCES DM_POLICY (ID )
ON DELETE NO ACTION
ON UPDATE NO ACTION
);
DROP TABLE IF EXISTS DM_DEVICE_POLICY;
CREATE TABLE IF NOT EXISTS DM_DEVICE_POLICY (
ID INT(11) NOT NULL AUTO_INCREMENT ,

@ -77,6 +77,23 @@ CREATE TABLE IF NOT EXISTS `WSO2CDM`.`DM_POLICY` (
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;
-- -----------------------------------------------------
-- Table `WSO2CDM`.`DM_POLICY_CORRECTIVE_ACTION`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `WSO2CDM`.`DM_POLICY_CORRECTIVE_ACTION` (
`ID` INT(11) NOT NULL AUTO_INCREMENT,
`ACTION_TYPE` VARCHAR(45) NOT NULL,
`CORRECTIVE_POLICY_ID` INT(11) DEFAULT NULL,
`POLICY_ID` INT(11) NOT NULL,
PRIMARY KEY (ID),
CONSTRAINT FK_DM_POLICY_DM_POLICY_CORRECTIVE_ACTION
FOREIGN KEY (POLICY_ID)
REFERENCES DM_POLICY (ID)
ON DELETE NO ACTION
ON UPDATE NO ACTION
)ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;
-- -----------------------------------------------------
-- Table `WSO2CDM`.`DM_DATE`

@ -202,6 +202,19 @@ CREATE TABLE IF NOT EXISTS DM_POLICY (
ON UPDATE NO ACTION
);
CREATE TABLE IF NOT EXISTS DM_POLICY_CORRECTIVE_ACTION (
ID INT(11) NOT NULL AUTO_INCREMENT,
ACTION_TYPE VARCHAR(45) NOT NULL,
CORRECTIVE_POLICY_ID INT(11) DEFAULT NULL,
POLICY_ID INT(11) NOT NULL,
PRIMARY KEY (ID),
CONSTRAINT FK_DM_POLICY_DM_POLICY_CORRECTIVE_ACTION
FOREIGN KEY (POLICY_ID )
REFERENCES DM_POLICY (ID )
ON DELETE NO ACTION
ON UPDATE NO ACTION
);
CREATE TABLE IF NOT EXISTS DM_DEVICE_POLICY (
ID INT(11) NOT NULL AUTO_INCREMENT ,
DEVICE_ID INT(11) NOT NULL ,

@ -252,6 +252,20 @@ CREATE TABLE DM_POLICY (
ON DELETE NO ACTION ON UPDATE NO ACTION
);
IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[DM_POLICY_CORRECTIVE_ACTION]') AND TYPE IN (N'U'))
CREATE TABLE DM_POLICY_CORRECTIVE_ACTION (
ID INTEGER IDENTITY(1,1) NOT NULL,
ACTION_TYPE VARCHAR(45) NOT NULL,
CORRECTIVE_POLICY_ID INTEGER DEFAULT NULL,
POLICY_ID INTEGER NOT NULL,
PRIMARY KEY (ID),
CONSTRAINT FK_DM_POLICY_DM_POLICY_CORRECTIVE_ACTION
FOREIGN KEY (POLICY_ID)
REFERENCES DM_POLICY (ID)
ON DELETE NO ACTION
ON UPDATE NO ACTION
);
IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[DM_DEVICE_POLICY]') AND TYPE IN (N'U'))
CREATE TABLE DM_DEVICE_POLICY (
ID INTEGER IDENTITY(1,1) NOT NULL,

@ -233,6 +233,19 @@ CREATE TABLE IF NOT EXISTS DM_POLICY (
ON UPDATE NO ACTION
)ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS DM_POLICY_CORRECTIVE_ACTION (
ID INT(11) NOT NULL AUTO_INCREMENT,
ACTION_TYPE VARCHAR(45) NOT NULL,
CORRECTIVE_POLICY_ID INT(11) DEFAULT NULL,
POLICY_ID INT(11) NOT NULL,
PRIMARY KEY (ID),
CONSTRAINT FK_DM_POLICY_DM_POLICY_CORRECTIVE_ACTION
FOREIGN KEY (POLICY_ID)
REFERENCES DM_POLICY (ID)
ON DELETE NO ACTION
ON UPDATE NO ACTION
)ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS DM_DEVICE_POLICY (
ID INT(11) NOT NULL AUTO_INCREMENT ,

@ -364,6 +364,19 @@ CREATE TABLE DM_POLICY (
REFERENCES DM_PROFILE (ID )
)
/
CREATE TABLE DM_POLICY_CORRECTIVE_ACTION (
ID NUMBER(10) NOT NULL,
ACTION_TYPE VARCHAR2(45) NOT NULL,
CORRECTIVE_POLICY_ID NUMBER(10) DEFAULT NULL,
POLICY_ID NUMBER(10) NOT NULL,
CONSTRAINT PK_DM_POLICY_CORRECTIVE_ACTION PRIMARY KEY (ID),
CONSTRAINT FK_DM_POLICY_DM_POLICY_CORRECTIVE_ACTION
FOREIGN KEY (POLICY_ID)
REFERENCES DM_POLICY (ID)
)
/
-- Generate ID using sequence and trigger
CREATE SEQUENCE DM_POLICY_seq START WITH 1 INCREMENT BY 1 NOCACHE
/

@ -202,6 +202,18 @@ CREATE TABLE IF NOT EXISTS DM_POLICY (
ON UPDATE NO ACTION
);
CREATE TABLE IF NOT EXISTS DM_POLICY_CORRECTIVE_ACTION (
ID BIGSERIAL NOT NULL PRIMARY KEY,
ACTION_TYPE VARCHAR(45) NOT NULL,
CORRECTIVE_POLICY_ID INTEGER DEFAULT NULL,
POLICY_ID INTEGER NOT NULL,
CONSTRAINT FK_DM_POLICY_DM_POLICY_CORRECTIVE_ACTION
FOREIGN KEY (POLICY_ID)
REFERENCES DM_POLICY (ID)
ON DELETE NO ACTION
ON UPDATE NO ACTION
);
CREATE TABLE IF NOT EXISTS DM_DEVICE_POLICY (
ID BIGSERIAL NOT NULL PRIMARY KEY,
DEVICE_ID INTEGER NOT NULL ,

Loading…
Cancel
Save