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 25, 2023
1 parent 7297518 commit 79e95b0
Show file tree
Hide file tree
Showing 4 changed files with 202 additions and 7 deletions.
45 changes: 45 additions & 0 deletions src/components/Form/IpaCheckbox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React from "react";
// PatternFly
import { Checkbox } from "@patternfly/react-core";
// Utils
import {
IPAParamDefinition,
getParamPropertiesCheckBox,
} from "src/utils/ipaObjectUtils";

const IpaCheckbox = (props: IPAParamDefinition) => {
const { required, readOnly, onChange } = getParamPropertiesCheckBox(props);
const [isChecked, setIsChecked] = React.useState(false);

React.useEffect(() => {
if (props.ipaObject !== undefined && props.value !== undefined) {
const checkboxesStateList = props.ipaObject[props.name] as string[];
if (checkboxesStateList !== undefined) {
const index = checkboxesStateList.indexOf(props.value);

if (index > -1) {
setIsChecked(true);
} else {
setIsChecked(false);
}
}
}
}, [props.ipaObject]);

return (
<Checkbox
id={props.id || ""}
name={props.name}
label={props.value || ""}
onChange={onChange}
isRequired={required}
readOnly={readOnly}
isChecked={isChecked}
aria-label={props.name}
className={props.className}
isDisabled={readOnly}
/>
);
};

export default IpaCheckbox;
80 changes: 73 additions & 7 deletions src/components/UsersSections/UsersAccountSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import CertificateMappingDataModal from "src/components/modals/CertificateMappin
import { asRecord } from "src/utils/userUtils";
// Form
import IpaTextInput from "src/components/Form/IpaTextInput";
import IpaCheckbox from "../Form/IpaCheckbox";

interface PropsToUsersAccountSettings {
user: Partial<User>;
Expand Down Expand Up @@ -331,12 +332,12 @@ const UsersAccountSettings = (props: PropsToUsersAccountSettings) => {
];

// 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);
// 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);
Expand Down Expand Up @@ -641,7 +642,7 @@ const UsersAccountSettings = (props: PropsToUsersAccountSettings) => {
<PopoverWithIconLayout message={userAuthTypesMessage} />
}
>
<Checkbox
{/* <Checkbox
label="Password"
isChecked={passwordCheckbox}
aria-label="password from user authentication types"
Expand Down Expand Up @@ -693,6 +694,71 @@ const UsersAccountSettings = (props: PropsToUsersAccountSettings) => {
id="extIdentityProvCheckbox"
name="ipauserauthtype"
value="idp"
/> */}
<IpaCheckbox
id="password"
label="Password"
name="ipauserauthtype"
value="password"
ipaObject={ipaObject}
onChange={recordOnChange}
objectName="user"
metadata={props.metadata}
className="pf-u-mt-xs pf-u-mb-sm"
/>
<IpaCheckbox
id="radius"
label="RADIUS"
name="ipauserauthtype"
value="radius"
ipaObject={ipaObject}
onChange={recordOnChange}
objectName="user"
metadata={props.metadata}
className="pf-u-mt-xs pf-u-mb-sm"
/>
<IpaCheckbox
id="otp"
label="Two-factor authentication (password + OTP)"
name="ipauserauthtype"
value="otp"
ipaObject={ipaObject}
onChange={recordOnChange}
objectName="user"
metadata={props.metadata}
className="pf-u-mt-xs pf-u-mb-sm"
/>
<IpaCheckbox
id="pkinit"
label="PKINIT"
name="ipauserauthtype"
value="pkinit"
ipaObject={ipaObject}
onChange={recordOnChange}
objectName="user"
metadata={props.metadata}
className="pf-u-mt-xs pf-u-mb-sm"
/>
<IpaCheckbox
id="hardened"
label="Hardened password (by SPAKE or FAST)"
name="ipauserauthtype"
value="hardened"
ipaObject={ipaObject}
onChange={recordOnChange}
objectName="user"
metadata={props.metadata}
className="pf-u-mt-xs pf-u-mb-sm"
/>
<IpaCheckbox
id="idp"
label="External Identity Provider"
name="ipauserauthtype"
value="idp"
ipaObject={ipaObject}
onChange={recordOnChange}
objectName="user"
metadata={props.metadata}
/>
</FormGroup>
<FormGroup
Expand Down
78 changes: 78 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";
// Utils
import { isSimpleValue } from "./userUtils";

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

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

export interface ParamProperties {
Expand Down Expand Up @@ -147,6 +153,78 @@ export function getParamProperties(
parDef.onChange({ ...parDef.ipaObject, [propName]: value });
}
};

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

export function getParamPropertiesCheckBox(
parDef: IPAParamDefinition
): ParamProperties {
const propName = parDef.propertyName || parDef.name;
const paramMetadata = getParamMetadata(
parDef.metadata,
parDef.objectName,
propName
);
if (!paramMetadata) {
return {
writable: false,
required: false,
readOnly: true,
value: "",
// eslint-disable-next-line @typescript-eslint/no-empty-function
onChange: () => {},
paramMetadata: {} as ParamMetadata,
};
}
const writable = isWritable(
paramMetadata,
parDef.ipaObject,
parDef.alwaysWritable
);
const required = isRequired(parDef, paramMetadata, writable);
const readOnly = parDef.readOnly === undefined ? !writable : parDef.readOnly;

const value = parDef.value;

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const onChange = (value: BasicType) => {
if (parDef.onChange) {
if (!isSimpleValue(propName)) {
if (parDef.ipaObject !== undefined) {
// Modify array
const objToModify = [...(parDef.ipaObject[propName] as string[])];
const elementToChange = parDef.value;
const elementToChangeStatus = value;

// Modify object
if (elementToChange !== undefined) {
if (elementToChangeStatus === true) {
objToModify.push(elementToChange);
} else {
const index = objToModify.indexOf(elementToChange);
if (index > -1) {
objToModify.splice(index, 1);
}
}
}

// Apply changes
parDef.onChange({ ...parDef.ipaObject, [propName]: objToModify });

return elementToChangeStatus;
}
}
}
};

return {
writable,
required,
Expand Down
6 changes: 6 additions & 0 deletions src/utils/userUtils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,9 @@ const dateValues = new Set(["krbpasswordexpiration", "krbprincipalexpiration"]);
export function apiToUser(apiRecord: Record<string, unknown>) {
return convertApiObj(apiRecord, simpleValues, dateValues) as Partial<User>;
}

// Determines whether a given property name is a simple value or is it multivalue (Array)
// - Returns: boolean
export const isSimpleValue = (propertyName) => {
return simpleValues.has(propertyName);
};

0 comments on commit 79e95b0

Please sign in to comment.