Fix policy form roles; add JSON edit mode
- Replace stale "service" role option with correct set: admin, user, guest, viewer, editor, commenter (matches model.go) - Add Form/JSON tab toggle to policy create form - JSON tab accepts raw RuleBody JSON with description/priority - Handler detects rule_json field and parses/validates it directly, falling back to field-by-field form mode otherwise
This commit is contained in:
@@ -129,46 +129,69 @@ func (u *UIServer) handleCreatePolicyRule(w http.ResponseWriter, r *http.Request
|
||||
priority = p
|
||||
}
|
||||
|
||||
effectStr := r.FormValue("effect")
|
||||
if effectStr != string(policy.Allow) && effectStr != string(policy.Deny) {
|
||||
u.renderError(w, r, http.StatusBadRequest, "effect must be 'allow' or 'deny'")
|
||||
return
|
||||
}
|
||||
var ruleJSON []byte
|
||||
|
||||
body := policy.RuleBody{
|
||||
Effect: policy.Effect(effectStr),
|
||||
}
|
||||
|
||||
// Multi-value fields.
|
||||
if roles := r.Form["roles"]; len(roles) > 0 {
|
||||
body.Roles = roles
|
||||
}
|
||||
if types := r.Form["account_types"]; len(types) > 0 {
|
||||
body.AccountTypes = types
|
||||
}
|
||||
if actions := r.Form["actions"]; len(actions) > 0 {
|
||||
acts := make([]policy.Action, len(actions))
|
||||
for i, a := range actions {
|
||||
acts[i] = policy.Action(a)
|
||||
if rawJSON := strings.TrimSpace(r.FormValue("rule_json")); rawJSON != "" {
|
||||
// JSON mode: parse and re-marshal to normalise and validate the input.
|
||||
var body policy.RuleBody
|
||||
if err := json.Unmarshal([]byte(rawJSON), &body); err != nil {
|
||||
u.renderError(w, r, http.StatusBadRequest, fmt.Sprintf("invalid rule JSON: %v", err))
|
||||
return
|
||||
}
|
||||
if body.Effect != policy.Allow && body.Effect != policy.Deny {
|
||||
u.renderError(w, r, http.StatusBadRequest, "rule JSON must include effect 'allow' or 'deny'")
|
||||
return
|
||||
}
|
||||
var err error
|
||||
ruleJSON, err = json.Marshal(body)
|
||||
if err != nil {
|
||||
u.renderError(w, r, http.StatusInternalServerError, "internal error")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// Form mode: build RuleBody from individual fields.
|
||||
effectStr := r.FormValue("effect")
|
||||
if effectStr != string(policy.Allow) && effectStr != string(policy.Deny) {
|
||||
u.renderError(w, r, http.StatusBadRequest, "effect must be 'allow' or 'deny'")
|
||||
return
|
||||
}
|
||||
body.Actions = acts
|
||||
}
|
||||
if resType := r.FormValue("resource_type"); resType != "" {
|
||||
body.ResourceType = policy.ResourceType(resType)
|
||||
}
|
||||
body.SubjectUUID = strings.TrimSpace(r.FormValue("subject_uuid"))
|
||||
body.OwnerMatchesSubject = r.FormValue("owner_matches_subject") == "1"
|
||||
if svcNames := r.FormValue("service_names"); svcNames != "" {
|
||||
body.ServiceNames = splitCommas(svcNames)
|
||||
}
|
||||
if tags := r.FormValue("required_tags"); tags != "" {
|
||||
body.RequiredTags = splitCommas(tags)
|
||||
}
|
||||
|
||||
ruleJSON, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
u.renderError(w, r, http.StatusInternalServerError, "internal error")
|
||||
return
|
||||
body := policy.RuleBody{
|
||||
Effect: policy.Effect(effectStr),
|
||||
}
|
||||
|
||||
// Multi-value fields.
|
||||
if roles := r.Form["roles"]; len(roles) > 0 {
|
||||
body.Roles = roles
|
||||
}
|
||||
if types := r.Form["account_types"]; len(types) > 0 {
|
||||
body.AccountTypes = types
|
||||
}
|
||||
if actions := r.Form["actions"]; len(actions) > 0 {
|
||||
acts := make([]policy.Action, len(actions))
|
||||
for i, a := range actions {
|
||||
acts[i] = policy.Action(a)
|
||||
}
|
||||
body.Actions = acts
|
||||
}
|
||||
if resType := r.FormValue("resource_type"); resType != "" {
|
||||
body.ResourceType = policy.ResourceType(resType)
|
||||
}
|
||||
body.SubjectUUID = strings.TrimSpace(r.FormValue("subject_uuid"))
|
||||
body.OwnerMatchesSubject = r.FormValue("owner_matches_subject") == "1"
|
||||
if svcNames := r.FormValue("service_names"); svcNames != "" {
|
||||
body.ServiceNames = splitCommas(svcNames)
|
||||
}
|
||||
if tags := r.FormValue("required_tags"); tags != "" {
|
||||
body.RequiredTags = splitCommas(tags)
|
||||
}
|
||||
|
||||
var err error
|
||||
ruleJSON, err = json.Marshal(body)
|
||||
if err != nil {
|
||||
u.renderError(w, r, http.StatusInternalServerError, "internal error")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Parse optional time-scoped validity window from datetime-local inputs.
|
||||
|
||||
Reference in New Issue
Block a user