Skip to content

Commit bfe3c9c

Browse files
committed
pluggable rule editing
1 parent cf5fca4 commit bfe3c9c

File tree

5 files changed

+72
-7
lines changed

5 files changed

+72
-7
lines changed

.azure.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
SENTRIUS_VERSION=1.1.56
1+
SENTRIUS_VERSION=1.1.63
22
SENTRIUS_SSH_VERSION=1.1.11
33
SENTRIUS_KEYCLOAK_VERSION=1.1.14
44
SENTRIUS_AGENT_VERSION=1.1.23

api/src/main/java/io/sentrius/sso/controllers/api/RuleApiController.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,30 @@ public ResponseEntity<String> saveRuleConfig(HttpServletRequest request, HttpSer
137137
if (null == ruleName || null == ruleClass) {
138138
return ResponseEntity.badRequest().body("Invalid rule name or class");
139139
}
140-
var rule = ProfileRule.builder().ruleClass(ruleClass).ruleName(ruleName).build();
140+
141+
// Check if we're editing an existing rule
142+
ProfileRule rule;
143+
String ruleIdStr = payload.get("ruleId");
144+
if (ruleIdStr != null && !ruleIdStr.isEmpty()) {
145+
// Editing existing rule
146+
try {
147+
Long ruleId = Long.parseLong(ruleIdStr);
148+
rule = ruleService.getRuleById(ruleId);
149+
if (rule == null) {
150+
return ResponseEntity.badRequest().body("Rule not found");
151+
}
152+
// Update the rule properties
153+
rule.setRuleClass(ruleClass);
154+
rule.setRuleName(ruleName);
155+
} catch (NumberFormatException e) {
156+
log.error("Invalid rule ID format: {}", ruleIdStr, e);
157+
return ResponseEntity.badRequest().body("Invalid rule ID format");
158+
}
159+
} else {
160+
// Creating new rule
161+
rule = ProfileRule.builder().ruleClass(ruleClass).ruleName(ruleName).build();
162+
}
163+
141164
StringBuilder ruleConfig = new StringBuilder();
142165
var globalDescription = payload.get("description_global");
143166
var globalAction = payload.get("action_global");

api/src/main/java/io/sentrius/sso/controllers/view/ZeroTrustRuleController.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import io.sentrius.sso.core.controllers.BaseController;
1010
import io.sentrius.sso.core.dto.ProfileRuleDTO;
1111
import io.sentrius.sso.core.dto.TopBarLinks;
12+
import io.sentrius.sso.core.model.hostgroup.ProfileRule;
1213
import io.sentrius.sso.core.model.users.User;
1314
import io.sentrius.sso.core.services.ErrorOutputService;
1415
import io.sentrius.sso.core.services.RuleService;
@@ -101,9 +102,25 @@ public String customRuleChat() {
101102
}
102103

103104
@GetMapping("/config/pluggable_rule")
104-
public String configurePluggableRule(@RequestParam("ruleName") String ruleName, Model model) {
105+
public String configurePluggableRule(@RequestParam("ruleName") String ruleName,
106+
@RequestParam(value = "ruleId", required = false) Long ruleId,
107+
Model model) {
105108
model.addAttribute("ruleName", ruleName);
106109
model.addAttribute("ruleClass", PluggableRuleEvaluator.class.getCanonicalName());
110+
// If ruleId is provided, fetch the rule and pass its configuration to the template
111+
if (ruleId != null) {
112+
try {
113+
ProfileRule rule = ruleService.getRuleById(ruleId);
114+
if (rule != null) {
115+
model.addAttribute("ruleId", ruleId);
116+
model.addAttribute("ruleConfig", rule.getRuleConfig());
117+
} else {
118+
log.warn("Rule not found with ID: {}", ruleId);
119+
}
120+
} catch (Exception e) {
121+
log.error("Error fetching rule with ID: {}", ruleId, e);
122+
}
123+
}
107124
return "sso/rules/pluggable_rule";
108125
}
109126

api/src/main/resources/static/js/rules.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,10 @@ function assignRule(ruleId) {
6262
*
6363
* @param {string} ruleClass - The rule class name
6464
* @param {string} ruleName - The rule name
65+
* @param {number} ruleId - The rule ID (optional, used for editing)
6566
* @returns {string|null} The configuration URL with rule name parameter, or null if unsupported
6667
*/
67-
function getRuleConfigurationUrl(ruleClass, ruleName) {
68+
function getRuleConfigurationUrl(ruleClass, ruleName, ruleId) {
6869
// Map rule classes to their configuration pages
6970
const ruleClassToUrl = {
7071
'CommandEvaluator': '/sso/v1/zerotrust/rules/config/forbidden_commands_rule',
@@ -76,7 +77,11 @@ function getRuleConfigurationUrl(ruleClass, ruleName) {
7677
const matchingKey = Object.keys(ruleClassToUrl).find(key => ruleClass.includes(key));
7778

7879
if (matchingKey) {
79-
return ruleClassToUrl[matchingKey] + "?ruleName=" + encodeURIComponent(ruleName);
80+
let url = ruleClassToUrl[matchingKey] + "?ruleName=" + encodeURIComponent(ruleName);
81+
if (ruleId) {
82+
url += "&ruleId=" + encodeURIComponent(ruleId);
83+
}
84+
return url;
8085
}
8186

8287
return null;
@@ -95,8 +100,8 @@ function editRule(ruleId) {
95100
// Fetch rule details to determine the rule class
96101
fetchRule(ruleId).then((rule) => {
97102
console.log("Fetched rule for editing:", rule);
98-
99-
const url = getRuleConfigurationUrl(rule.ruleClass, rule.ruleName);
103+
104+
const url = getRuleConfigurationUrl(rule.ruleClass, rule.ruleName, rule.id);
100105

101106
if (url) {
102107
// Redirect to the configuration page

api/src/main/resources/templates/sso/rules/pluggable_rule.html

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,26 @@ <h2 class="accordion-header" id="headingFour">
232232
}
233233
const csrf = csrfElement.value;
234234

235+
// Parse and populate existing rule configuration if editing
236+
const ruleConfig = /*[[${ruleConfig}]]*/ null;
237+
if (ruleConfig) {
238+
// Parse the ruleConfig format: expression:action:description[:sanitized]
239+
// Split with a limit to handle colons within field values
240+
const parts = ruleConfig.split(':', 4);
241+
if (parts.length >= 3) {
242+
const expression = parts[0];
243+
const action = parts[1];
244+
const description = parts[2];
245+
const sanitized = parts.length >= 4 ? parts[3] : 'true';
246+
247+
// Populate form fields
248+
document.getElementById('expression').value = expression;
249+
document.getElementById('action').value = action;
250+
document.getElementById('description').value = description;
251+
document.getElementById('sanitized').value = sanitized;
252+
}
253+
}
254+
235255
// Use the button click event listener
236256
const submitBtn = document.querySelector('.submit_btn');
237257
if (submitBtn) {

0 commit comments

Comments
 (0)