diff --git a/.changeset/wet-melons-wave.md b/.changeset/wet-melons-wave.md new file mode 100644 index 00000000000..4b2c2dff53d --- /dev/null +++ b/.changeset/wet-melons-wave.md @@ -0,0 +1,5 @@ +--- +"@wso2is/admin.userstores.v1": patch +--- + +Remove the temp fix to hide ReadOnly property in UniqueIDReadOnlyLDAPUserStoreManager diff --git a/features/admin.userstores.v1/components/add-user-store.tsx b/features/admin.userstores.v1/components/add-user-store.tsx index facbb725fc1..5cc93b76699 100644 --- a/features/admin.userstores.v1/components/add-user-store.tsx +++ b/features/admin.userstores.v1/components/add-user-store.tsx @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020, WSO2 LLC. (https://www.wso2.com). + * Copyright (c) 2020-2025, WSO2 LLC. (https://www.wso2.com). * * WSO2 LLC. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except @@ -18,13 +18,16 @@ import { AppConstants } from "@wso2is/admin.core.v1/constants/app-constants"; import { history } from "@wso2is/admin.core.v1/helpers/history"; +import { IdentityAppsError } from "@wso2is/core/errors"; import { AlertLevels, TestableComponentInterface } from "@wso2is/core/models"; import { addAlert } from "@wso2is/core/store"; import { FormValue, useTrigger } from "@wso2is/forms"; import { LinkButton, PrimaryButton, Steps, useWizardAlert } from "@wso2is/react-components"; +import { AxiosError } from "axios"; import React, { FunctionComponent, ReactElement, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { useDispatch } from "react-redux"; +import { Dispatch } from "redux"; import { Grid, Icon, Modal } from "semantic-ui-react"; import { GeneralDetailsUserstore, GroupDetails, SummaryUserStores, UserDetails } from "./wizards"; import { addUserStore } from "../api"; @@ -35,7 +38,8 @@ import { TypeProperty, UserStorePostData, UserStoreProperty, - UserstoreType + UserstoreType, + WizardStepInterface } from "../models"; import { reOrganizeProperties } from "../utils"; @@ -60,9 +64,9 @@ interface AddUserStoreProps extends TestableComponentInterface { /** * This component renders the Add Userstore Wizard. * - * @param {AddUserStoreProps} props - Props injected to the component. + * @param props - Props injected to the component. * - * @return {ReactElement} + * @returns add userstore wizard component. */ export const AddUserStore: FunctionComponent = (props: AddUserStoreProps): ReactElement => { @@ -85,7 +89,7 @@ export const AddUserStore: FunctionComponent = (props: AddUse const [ secondStep, setSecondStep ] = useTrigger(); const [ thirdStep, setThirdStep ] = useTrigger(); - const dispatch = useDispatch(); + const dispatch: Dispatch = useDispatch(); const { t } = useTranslation(); @@ -124,7 +128,7 @@ export const AddUserStore: FunctionComponent = (props: AddUse onClose(); history.push(AppConstants.getPaths().get("USERSTORES")); - }).catch(error => { + }).catch((error: AxiosError & IdentityAppsError) => { if (error.response?.status === 403 && error.response.data?.code === UserStoreManagementConstants.ERROR_CREATE_LIMIT_REACHED.getErrorCode()) { @@ -152,7 +156,7 @@ export const AddUserStore: FunctionComponent = (props: AddUse /** * This saves the General Details values along with the Type - * @param {Map} values Connection Details Values + * @param values - Connection Details Values */ const onSubmitGeneralDetails = (values: Map): void => { setGeneralDetailsData(values); @@ -180,28 +184,29 @@ export const AddUserStore: FunctionComponent = (props: AddUse }; const serializeProperties = (): UserStoreProperty[] => { - const connectionProperties: UserStoreProperty[] = properties.connection.required.map(property => { - return { - name: property.name, - value: generalDetailsData.get(property.name)?.toString() - }; - }); + const connectionProperties: UserStoreProperty[] = properties.connection.required.map( + (property: TypeProperty) => { + return { + name: property.name, + value: generalDetailsData.get(property.name)?.toString() + }; + }); - const userProperties: UserStoreProperty[] = properties.user.required.map(property => { + const userProperties: UserStoreProperty[] = properties.user.required.map((property: TypeProperty) => { return { name: property.name, value: userDetailsData.get(property.name)?.toString() }; }); - const groupProperties: UserStoreProperty[] = properties.group.required.map(property => { + const groupProperties: UserStoreProperty[] = properties.group.required.map((property: TypeProperty) => { return { name: property.name, value: groupDetailsData.get(property.name)?.toString() }; }); - const basicProperties: UserStoreProperty[] = properties.basic.required.map(property => { + const basicProperties: UserStoreProperty[] = properties.basic.required.map((property: TypeProperty) => { return { name: property.name, value: generalDetailsData.get(property.name)?.toString() @@ -230,7 +235,7 @@ export const AddUserStore: FunctionComponent = (props: AddUse }) ); - const updatedProperties = [ + const updatedProperties: UserStoreProperty[] = [ ...connectionProperties, ...userProperties, ...groupProperties, @@ -238,7 +243,7 @@ export const AddUserStore: FunctionComponent = (props: AddUse ]; return allProperties.map((property: UserStoreProperty) => { - const updatedProperty = updatedProperties + const updatedProperty: UserStoreProperty = updatedProperties .find((updatedProperty: UserStoreProperty) => updatedProperty.name === property.name); if (updatedProperty) { @@ -252,7 +257,7 @@ export const AddUserStore: FunctionComponent = (props: AddUse /** * This contains the wizard steps */ - const STEPS = [ + const STEPS: WizardStepInterface[] = [ { content: ( = (props: AddUse onSubmit={ onSubmitUserDetails } values={ userDetailsData } properties={ properties?.user?.required } - type={ type?.typeName } data-testid={ `${ testId }-user-details` } /> ), @@ -369,7 +373,7 @@ export const AddUserStore: FunctionComponent = (props: AddUse - { STEPS.map((step, index) => ( + { STEPS.map((step: WizardStepInterface, index: number) => ( = properties, readOnly, update, - type, [ "data-testid" ]: testId } = props; @@ -255,12 +250,6 @@ export const EditUserDetails: FunctionComponent = (attribute: PropertyAttribute) => attribute?.name === "type" )?.value === "boolean"; - // FIXME: Temp fix to hide the `ReadOnly` property from ReadOnly Userstores. - // This should be handled in the backend and reverted from the UI. - // Tracker: https://github.com/wso2/product-is/issues/19769#issuecomment-1957415262 - const isHidden: boolean = type.typeName === "UniqueIDReadOnlyLDAPUserStoreManager" - && property.name === "ReadOnly"; - return ( isPassword ? ( @@ -291,7 +280,6 @@ export const EditUserDetails: FunctionComponent = } ) } - hidden={ isHidden } data-testid={ `${ testId }-form-password-input-${ property.name }` } /> ) @@ -324,7 +312,6 @@ export const EditUserDetails: FunctionComponent = } ) } - hidden={ isHidden } data-testid={ `${ testId }-form-toggle-${ property.name }` } /> ) : @@ -358,7 +345,6 @@ export const EditUserDetails: FunctionComponent = } ) } - hidden={ isHidden } data-testid={ `${ testId }-form-text-input-${ property.name }` } @@ -392,7 +378,6 @@ export const EditUserDetails: FunctionComponent = } ) } - hidden={ isHidden } data-testid={ `${ testId }-form-text-input-${ property?.name }` } diff --git a/features/admin.userstores.v1/components/wizards/user-details.tsx b/features/admin.userstores.v1/components/wizards/user-details.tsx index 21eabe2028d..ca840a35e52 100644 --- a/features/admin.userstores.v1/components/wizards/user-details.tsx +++ b/features/admin.userstores.v1/components/wizards/user-details.tsx @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2024, WSO2 LLC. (https://www.wso2.com). + * Copyright (c) 2020-2025, WSO2 LLC. (https://www.wso2.com). * * WSO2 LLC. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except @@ -44,10 +44,6 @@ interface UserDetailsPropsInterface extends TestableComponentInterface { * The properties to be shown in this component. */ properties: TypeProperty[]; - /** - * The type of the userstore. - */ - type: string; } /** @@ -64,7 +60,6 @@ export const UserDetails: FunctionComponent = ( onSubmit, values, properties, - type, [ "data-testid" ]: testId } = props; @@ -89,12 +84,6 @@ export const UserDetails: FunctionComponent = ( })?.value === "boolean"; const isRequired: boolean = !isEmpty(selectedTypeDetail?.defaultValue); - // FIXME: Temp fix to hide the `ReadOnly` property from ReadOnly Userstores. - // This should be handled in the backend and reverted from the UI. - // Tracker: https://github.com/wso2/product-is/issues/19769#issuecomment-1957415262 - const isHidden: boolean = type === "UniqueIDReadOnlyLDAPUserStoreManager" - && selectedTypeDetail.name === "ReadOnly"; - if (toggle) { return ( = ( ?? selectedTypeDetail.defaultValue } toggle - hidden={ isHidden } data-testid={ `${ testId }-form-toggle-${ selectedTypeDetail.name }` } /> @@ -154,7 +142,6 @@ export const UserDetails: FunctionComponent = ( values?.get(selectedTypeDetail?.name)?.toString() ?? selectedTypeDetail.defaultValue } - hidden={ isHidden } data-testid={ `${ testId }-form-text-input-${ selectedTypeDetail.name }` } /> diff --git a/features/admin.userstores.v1/models/user-stores.ts b/features/admin.userstores.v1/models/user-stores.ts index 00fda7988c0..ef09ce2409c 100644 --- a/features/admin.userstores.v1/models/user-stores.ts +++ b/features/admin.userstores.v1/models/user-stores.ts @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2024, WSO2 LLC. (https://www.wso2.com). + * Copyright (c) 2020-2025, WSO2 LLC. (https://www.wso2.com). * * WSO2 LLC. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except @@ -16,6 +16,8 @@ * under the License. */ +import { FunctionComponent, ReactElement, SVGProps } from "react"; + /** * Type of user store type. */ @@ -261,3 +263,13 @@ export interface UserStoreItem { value: string; disabled?: boolean; } + +/** + * Interface for the wizard step. + */ +export interface WizardStepInterface { + content: ReactElement; + icon: FunctionComponent>; + title: string; + name?: string; +} diff --git a/features/admin.userstores.v1/pages/user-stores-edit.tsx b/features/admin.userstores.v1/pages/user-stores-edit.tsx index d15036b5f7e..c2404eb449a 100644 --- a/features/admin.userstores.v1/pages/user-stores-edit.tsx +++ b/features/admin.userstores.v1/pages/user-stores-edit.tsx @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020-2024, WSO2 LLC. (https://www.wso2.com). + * Copyright (c) 2020-2025, WSO2 LLC. (https://www.wso2.com). * * WSO2 LLC. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except @@ -16,13 +16,13 @@ * under the License. */ +import { useRequiredScopes } from "@wso2is/access-control"; import { AppConstants } from "@wso2is/admin.core.v1/constants/app-constants"; import { history } from "@wso2is/admin.core.v1/helpers/history"; import { FeatureConfigInterface } from "@wso2is/admin.core.v1/models/config"; import { AppState } from "@wso2is/admin.core.v1/store"; import { UserstoreConstants } from "@wso2is/core/constants"; import { IdentityAppsError } from "@wso2is/core/errors"; -import { hasRequiredScopes } from "@wso2is/core/helpers"; import { AlertLevels, TestableComponentInterface } from "@wso2is/core/models"; import { addAlert } from "@wso2is/core/store"; import { GenericIcon, ResourceTab, ResourceTabPaneInterface, TabPageLayout } from "@wso2is/react-components"; @@ -83,7 +83,8 @@ const UserStoresEditPage: FunctionComponent = ( const { t } = useTranslation(); const featureConfig: FeatureConfigInterface = useSelector((state: AppState) => state.config.ui.features); - const allowedScopes: string = useSelector((state: AppState) => state?.auth?.allowedScopes); + + const hasUserStoresUpdatePermission: boolean = useRequiredScopes(featureConfig?.userStores?.scopes?.update); /** * Fetches the userstore by its id @@ -143,8 +144,7 @@ const UserStoresEditPage: FunctionComponent = ( * @returns If an userstore is Read Only or not. */ const resolveReadOnlyState = (): boolean => { - return !hasRequiredScopes(featureConfig?.userStores, featureConfig?.userStores?.scopes?.update, - allowedScopes); + return !hasUserStoresUpdatePermission; }; /** @@ -189,7 +189,6 @@ const UserStoresEditPage: FunctionComponent = (