This is an automated email from the ASF dual-hosted git repository. dhavaljrajpara pushed a commit to branch RANGER-5860 in repository https://gitbox.apache.org/repos/asf/ranger.git
commit 684fd928ec3af1fb2032925a144120a46bbecaaa Author: Dhaval Rajpara <[email protected]> AuthorDate: Wed Oct 28 16:59:15 2026 +0530 RANGER-5852 : Improvice Parameter in Access step --- .../ConstraintPolicyParameterFields.jsx | 244 +++++++++++++++++++++ .../PolicyPermissionItemVertical.jsx | 100 +++------ 2 files changed, 276 insertions(+), 68 deletions(-) diff --git a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/NewPolicyForm/PolicyCreateStepperStepComp/ConstraintPolicyParameterFields.jsx b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/NewPolicyForm/PolicyCreateStepperStepComp/ConstraintPolicyParameterFields.jsx new file mode 100644 index 000000000..26007f6c6 --- /dev/null +++ b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/NewPolicyForm/PolicyCreateStepperStepComp/ConstraintPolicyParameterFields.jsx @@ -0,0 +1,244 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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. + */ + +import React from "react"; +import { Field } from "react-final-form"; +import { Row, Col, Form as FormB } from "react-bootstrap"; +import BootstrapSwitchButton from "bootstrap-switch-button-react"; + +const required = (value) => + value !== undefined && value !== null && value !== "" ? undefined : "Required"; + +export const getInitialParameterValue = (param) => { + if (param.defaultValue === undefined || param.defaultValue === null) { + if (param.type === "boolean") { + return false; + } + return ""; + } + if (param.type === "boolean") { + return ( + param.defaultValue === true || + String(param.defaultValue).toLowerCase() === "true" + ); + } + if (param.type === "int") { + return String(param.defaultValue); + } + return param.defaultValue; +}; + +/** Defaults applied only when the user picks a constraint name (not on step remount). */ +export const buildDefaultConstraintParameters = (parameters = []) => { + const defaults = {}; + parameters.forEach((param) => { + if (param.type === "boolean") { + defaults[param.name] = getInitialParameterValue(param); + return; + } + const initial = getInitialParameterValue(param); + if (initial !== "" && initial != null) { + defaults[param.name] = initial; + } + }); + return defaults; +}; + +const validateParameter = (param) => (value) => { + if (!param.mandatory) { + return undefined; + } + if (param.type === "boolean") { + return undefined; + } + if (param.type === "list") { + if (Array.isArray(value)) { + return value.length > 0 ? undefined : "Required"; + } + return value != null && String(value).trim() !== "" ? undefined : "Required"; + } + return required(value); +}; + +const principalPlaceholder = (type) => { + if (type === "user") { + return "Enter user name"; + } + if (type === "group") { + return "Enter group name"; + } + if (type === "role") { + return "Enter role name"; + } + return ""; +}; + +const ParameterControl = ({ param, input, meta }) => { + const inputId = `${param.name}-constraint-param`; + const showInvalid = meta.touched && meta.error; + + switch (param.type) { + case "int": + return ( + <> + <FormB.Control + id={inputId} + type="number" + {...input} + value={input.value ?? ""} + placeholder={param.defaultValue ? String(param.defaultValue) : ""} + isInvalid={showInvalid} + /> + {showInvalid && ( + <FormB.Control.Feedback type="invalid"> + {meta.error} + </FormB.Control.Feedback> + )} + </> + ); + + case "boolean": + return ( + <> + <BootstrapSwitchButton + id={inputId} + checked={ + input.value === true || String(input.value).toLowerCase() === "true" + } + onChange={(checked) => input.onChange(checked)} + onlabel="Yes" + offlabel="No" + width={90} + height={30} + /> + {showInvalid && ( + <div className="text-danger small mt-1">{meta.error}</div> + )} + </> + ); + + case "list": + return ( + <> + <FormB.Control + id={inputId} + as="textarea" + rows={2} + {...input} + value={input.value ?? ""} + placeholder="Enter values separated by commas" + isInvalid={showInvalid} + /> + {showInvalid && ( + <FormB.Control.Feedback type="invalid"> + {meta.error} + </FormB.Control.Feedback> + )} + </> + ); + + case "user": + case "group": + case "role": + return ( + <> + <FormB.Control + id={inputId} + type="text" + {...input} + value={input.value ?? ""} + placeholder={principalPlaceholder(param.type)} + isInvalid={showInvalid} + /> + {showInvalid && ( + <FormB.Control.Feedback type="invalid"> + {meta.error} + </FormB.Control.Feedback> + )} + </> + ); + + case "string": + default: + return ( + <> + <FormB.Control + id={inputId} + type="text" + {...input} + value={input.value ?? ""} + placeholder={ + param.defaultValue != null + ? String(param.defaultValue) + : `Enter ${param.label || param.name}` + } + isInvalid={showInvalid} + /> + {showInvalid && ( + <FormB.Control.Feedback type="invalid"> + {meta.error} + </FormB.Control.Feedback> + )} + </> + ); + } +}; + +/** + * Renders constraint definition parameters in the same row layout as Constraint Name. + */ +const ConstraintPolicyParameterFields = ({ parameters = [], fieldNamePrefix }) => { + if (!parameters.length) { + return ( + <p className="text-muted mb-0">No parameters for this constraint.</p> + ); + } + + return ( + <> + {parameters.map((param) => ( + <Row key={param.name} className="mb-4"> + <Col className="column-1-fixed text-end"> + <FormB.Label htmlFor={`${param.name}-constraint-param`} className="mb-0"> + {param.label || param.name} + {param.mandatory ? ( + <span className="required-mark">*</span> + ) : null} + </FormB.Label> + </Col> + <> + <Col> + <Field + name={`${fieldNamePrefix}.${param.name}`} + validate={validateParameter(param)} + > + {({ input, meta }) => ( + <ParameterControl param={param} input={input} meta={meta} /> + )} + </Field> + </Col> + <Col className="column-3-fixed"></Col> + </> + </Row> + ))} + </> + ); +}; + +export default ConstraintPolicyParameterFields; diff --git a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/NewPolicyForm/PolicyCreateStepperStepComp/PolicyPermissionItemVertical.jsx b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/NewPolicyForm/PolicyCreateStepperStepComp/PolicyPermissionItemVertical.jsx index d153cfe5a..76ba5e34f 100644 --- a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/NewPolicyForm/PolicyCreateStepperStepComp/PolicyPermissionItemVertical.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/NewPolicyForm/PolicyCreateStepperStepComp/PolicyPermissionItemVertical.jsx @@ -33,6 +33,9 @@ import { RangerPolicyType } from "Utils/XAEnums"; import { find, isEmpty, isArray, toUpper, map } from "lodash"; import PolicyConditionsComp from "../../PolicyConditionsComp"; import UsersGroupsAndRolesSelectionComponent from "./UsersGroupsAndRolesSelectionComponent"; +import ConstraintPolicyParameterFields, { + buildDefaultConstraintParameters +} from "./ConstraintPolicyParameterFields"; import TagBasePermissionItem from "../../TagBasePermissionItem"; import { getAccessTypesByResource, @@ -147,7 +150,15 @@ export default function PolicyPermissionItemVertical({ const handleConstraintNameChange = (input, fieldName, option) => { input.onChange(option || null); form.change(`${fieldName}.accesses`, undefined); - form.change(`${fieldName}.constraintInfo.parameters`, undefined); + if (!option?.value) { + form.change(`${fieldName}.constraintInfo.parameters`, undefined); + return; + } + const def = getConstraintDefByName(serviceCompDetails, option.value); + form.change( + `${fieldName}.constraintInfo.parameters`, + buildDefaultConstraintParameters(def?.parameters) + ); }; // Helper function to clear all data from a permission item @@ -675,73 +686,26 @@ export default function PolicyPermissionItemVertical({ {isConstraintPolicy && ( <Col xs={12} className="mb-4"> - <Row> - <Col className="column-1-fixed text-end"> - <FormB.Label>Parameters</FormB.Label> - </Col> - <Col> - {!rowConstraintName ? ( - <p className="text-muted mb-0"> - {constraintSelectFirstMsg} - </p> - ) : ( - (rowConstraintDef?.parameters || []).map( - (param) => ( - <Row key={param.name} className="mb-3"> - <Col sm={4} md={3} className="text-end"> - <FormB.Label className="mb-0"> - {param.label || param.name} - {param.mandatory ? ( - <span className="required-mark"> - * - </span> - ) : null} - </FormB.Label> - </Col> - <Col sm={8} md={6}> - <Field - name={`${name}.constraintInfo.parameters.${param.name}`} - validate={ - param.mandatory ? required : undefined - } - > - {({ input, meta }) => ( - <> - <FormB.Control - {...input} - value={input.value ?? ""} - type={ - param.type === "int" - ? "number" - : "text" - } - placeholder={ - param.type === "user" || - param.subType === "user" || - param.type === "group" || - param.type === "role" - ? "Enter user, group, or role" - : `Enter ${param.label || param.name}` - } - isInvalid={ - meta.touched && meta.error - } - /> - {meta.touched && meta.error && ( - <FormB.Control.Feedback type="invalid"> - {meta.error} - </FormB.Control.Feedback> - )} - </> - )} - </Field> - </Col> - </Row> - ) - ) - )} - </Col> - </Row> + {!rowConstraintName ? ( + <Row> + <Col className="column-1-fixed text-end"> + <FormB.Label>Parameters</FormB.Label> + </Col> + <> + <Col> + <p className="text-muted mb-0"> + {constraintSelectFirstMsg} + </p> + </Col> + <Col className="column-3-fixed"></Col> + </> + </Row> + ) : ( + <ConstraintPolicyParameterFields + parameters={rowConstraintDef?.parameters || []} + fieldNamePrefix={`${name}.constraintInfo.parameters`} + /> + )} </Col> )}
