Skip to content

Commit

Permalink
Add functionality for checkbox list
Browse files Browse the repository at this point in the history
The functionality for the group of checkboxes
needs to be implemented and applied to the
following field: 'User authentication types'
(`ipauserauthtype`).

Signed-off-by: Carla Martinez <carlmart@redhat.com>
  • Loading branch information
carma12 committed Aug 31, 2023
1 parent d40b2ce commit b83dadc
Show file tree
Hide file tree
Showing 3 changed files with 191 additions and 60 deletions.
78 changes: 78 additions & 0 deletions src/components/Form/IpaCheckboxes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import React from "react";
// PatternFly
import { Checkbox } from "@patternfly/react-core";
// Utils
import {
IPAParamDefinitionCheckboxes,
getParamPropertiesCheckBoxes,
updateIpaObject,
} from "src/utils/ipaObjectUtils";

export interface CheckboxOption {
value: string;
text: string;
className?: string;
}

const IpaCheckboxes = (props: IPAParamDefinitionCheckboxes) => {
const { required, readOnly, checkedValues } =
getParamPropertiesCheckBoxes(props);

const [checkedList, setCheckedList] = React.useState(checkedValues);

// Updates the 'checkedList' when 'checkedValues' changes
React.useEffect(() => {
setCheckedList(checkedValues);
}, [checkedValues]);

// Updates the list of checked values when a specific checkbox is clicked
// - This is implemented here because we need to know which specific
// value (option.value) to add/remove from the list
const updateList = (checked: boolean, elementToChange: string) => {
if (
props.ipaObject !== undefined &&
props.ipaObject[props.name] !== undefined &&
props.onChange !== undefined
) {
const updatedList = [...(props.ipaObject[props.name] as string[])];
if (checked) {
updatedList.push(elementToChange);
} else {
const index = updatedList.indexOf(elementToChange);
if (index > -1) {
updatedList.splice(index, 1);
}
}
// Update the list of checked values
setCheckedList(updatedList);
// Update the IPA object
updateIpaObject(props.ipaObject, props.onChange, updatedList, props.name);
}
};

return (
<>
{props.options.map((option) => (
<Checkbox
key={props.name + "-" + option.value}
id={props.name + "-" + option.value} // Mandatory
name={props.name}
label={option.text}
onChange={(checked) => updateList(checked, option.value)}
isRequired={required}
readOnly={readOnly}
isChecked={
checkedList.find((val) => val === option.value) !== undefined
? true
: false
}
aria-label={props.name}
className={option.className}
isDisabled={readOnly}
/>
))}
</>
);
};

export default IpaCheckboxes;
100 changes: 40 additions & 60 deletions src/components/UsersSections/UsersAccountSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
Form,
FormGroup,
TextInput,
Checkbox,
DropdownItem,
CalendarMonth,
Button,
Expand All @@ -33,6 +32,7 @@ import { asRecord } from "src/utils/userUtils";
// Form
import IpaTextInput from "src/components/Form/IpaTextInput";
import IpaSelect from "../Form/IpaSelect";
import IpaCheckboxes, { CheckboxOption } from "../Form/IpaCheckboxes";

interface PropsToUsersAccountSettings {
user: Partial<User>;
Expand Down Expand Up @@ -74,6 +74,39 @@ const UsersAccountSettings = (props: PropsToUsersAccountSettings) => {
},
]);

// Checkboxes options
const options: CheckboxOption[] = [
{
value: "password",
text: "Password",
className: "pf-u-mt-xs pf-u-mb-sm",
},
{
value: "radius",
text: "RADIUS",
className: "pf-u-mt-xs pf-u-mb-sm",
},
{
value: "otp",
text: "Two-factor authentication (password + OTP)",
className: "pf-u-mt-xs pf-u-mb-sm",
},
{
value: "pkinit",
text: "PKINIT",
className: "pf-u-mt-xs pf-u-mb-sm",
},
{
value: "hardened",
text: "Hardened password (by SPAKE or FAST)",
className: "pf-u-mt-xs pf-u-mb-sm",
},
{
value: "idp",
text: "External Identity Provider",
},
];

// Principal alias
// - 'Add principal alias' handler
const onAddPrincipalAliasFieldHandler = () => {
Expand Down Expand Up @@ -346,14 +379,6 @@ const UsersAccountSettings = (props: PropsToUsersAccountSettings) => {
</Button>,
];

// Checkboxes
const [passwordCheckbox] = useState(false);
const [radiusCheckbox] = useState(false);
const [tpaCheckbox] = useState(false);
const [pkinitCheckbox] = useState(false);
const [hardenedPassCheckbox] = useState(false);
const [extIdentityProvCheckbox] = useState(false);

// Date and time picker (Calendar)
const [isCalendarOpen, setIsCalendarOpen] = React.useState(false);
const [isTimeOpen, setIsTimeOpen] = React.useState(false);
Expand Down Expand Up @@ -626,58 +651,13 @@ const UsersAccountSettings = (props: PropsToUsersAccountSettings) => {
<PopoverWithIconLayout message={userAuthTypesMessage} />
}
>
<Checkbox
label="Password"
isChecked={passwordCheckbox}
aria-label="password from user authentication types"
id="passwordCheckbox"
<IpaCheckboxes
name="ipauserauthtype"
value="password"
className="pf-u-mt-xs pf-u-mb-sm"
/>
<Checkbox
label="RADIUS"
isChecked={radiusCheckbox}
aria-label="radius from user authentication types"
id="radiusCheckbox"
name="ipauserauthtype"
value="radius"
className="pf-u-mt-xs pf-u-mb-sm"
/>
<Checkbox
label="Two-factor authentication (password + OTP)"
isChecked={tpaCheckbox}
aria-label="two factor authentication from user authentication types"
id="tpaCheckbox"
name="ipauserauthtype"
value="otp"
className="pf-u-mt-xs pf-u-mb-sm"
/>
<Checkbox
label="PKINIT"
isChecked={pkinitCheckbox}
aria-label="pkinit from user authentication types"
id="pkinitCheckbox"
name="ipauserauthtype"
value="pkinit"
className="pf-u-mt-xs pf-u-mb-sm"
/>
<Checkbox
label="Hardened password (by SPAKE or FAST)"
isChecked={hardenedPassCheckbox}
aria-label="hardened password from user authentication types"
id="hardenedPassCheckbox"
name="ipauserauthtype"
value="hardened"
className="pf-u-mt-xs pf-u-mb-sm"
/>
<Checkbox
label="External Identity Provider"
isChecked={extIdentityProvCheckbox}
aria-label="external identity provider from user authentication types"
id="extIdentityProvCheckbox"
name="ipauserauthtype"
value="idp"
options={options}
ipaObject={ipaObject}
onChange={recordOnChange}
objectName="user"
metadata={props.metadata}
/>
</FormGroup>
<FormGroup
Expand Down
73 changes: 73 additions & 0 deletions src/utils/ipaObjectUtils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { Metadata, ParamMetadata } from "src/utils/datatypes/globalDataTypes";
// Checkboxes
import { CheckboxOption } from "src/components/Form/IpaCheckboxes";

export type BasicType = string | number | boolean | null | undefined | [];

Expand All @@ -14,6 +16,24 @@ export interface IPAParamDefinition {
alwaysWritable?: boolean;
readOnly?: boolean;
required?: boolean;
id?: string;
value?: string;
label?: string;
className?: string;
}

export interface IPAParamDefinitionCheckboxes {
name: string;
ipaObject?: Record<string, unknown>;
onChange?: (ipaObject: IPAObject) => void;
objectName: string;
metadata: Metadata;
propertyName?: string;
alwaysWritable?: boolean;
readOnly?: boolean;
required?: boolean;
className?: string;
options: CheckboxOption[];
}

export interface ParamProperties {
Expand All @@ -25,6 +45,15 @@ export interface ParamProperties {
paramMetadata: ParamMetadata;
}

export interface ParamPropertiesCheckboxes {
writable: boolean;
required: boolean;
readOnly: boolean;
value: BasicType;
paramMetadata: ParamMetadata;
checkedValues: string[];
}

export function getParamMetadata(
metadata: Metadata,
objectName: string,
Expand Down Expand Up @@ -147,6 +176,7 @@ export function getParamProperties(
parDef.onChange({ ...parDef.ipaObject, [propName]: value });
}
};

return {
writable,
required,
Expand All @@ -157,6 +187,49 @@ export function getParamProperties(
};
}

export function getParamPropertiesCheckBoxes(
parDef: IPAParamDefinitionCheckboxes
): ParamPropertiesCheckboxes {
const propName = parDef.propertyName || parDef.name;
const paramMetadata = getParamMetadata(
parDef.metadata,
parDef.objectName,
propName
);
if (!paramMetadata) {
return {
writable: false,
required: false,
readOnly: true,
value: "",
paramMetadata: {} as ParamMetadata,
checkedValues: [],
};
}
const writable = isWritable(
paramMetadata,
parDef.ipaObject,
parDef.alwaysWritable
);
const required = isRequired(parDef, paramMetadata, writable);
const readOnly = parDef.readOnly === undefined ? !writable : parDef.readOnly;

const value = getValue(parDef.ipaObject, propName);

const checkedValues = parDef.ipaObject !== undefined && parDef.ipaObject[propName] !== undefined
? parDef.ipaObject[propName] as string[]
: [];

return {
writable,
required,
readOnly,
value,
paramMetadata,
checkedValues,
};
}

export function convertToString(value: BasicType): string {
if (value === null || value === undefined) {
return "";
Expand Down

0 comments on commit b83dadc

Please sign in to comment.