From 25add9e3773b90180af3885d00ee12fcb7aa067f Mon Sep 17 00:00:00 2001 From: savindi7 Date: Thu, 26 Oct 2023 16:59:43 +0530 Subject: [PATCH 1/4] add multi attr login to the login & reg page --- .../configs/server-configuration.tsx | 8 +- .../src/features/core/configs/routes.tsx | 35 ++-- .../features/core/constants/app-constants.ts | 1 + .../src/features/core/utils/route-utils.ts | 6 +- .../dynamic-governance-connector.tsx | 18 +- .../pages/connector-listing-page.tsx | 33 +++- .../pages/governance-connectors.tsx | 4 +- .../pages/multi-attribute-login-edit.tsx | 185 ++++++++++++++++++ 8 files changed, 257 insertions(+), 33 deletions(-) create mode 100644 apps/console/src/features/server-configurations/pages/multi-attribute-login-edit.tsx diff --git a/apps/console/src/extensions/configs/server-configuration.tsx b/apps/console/src/extensions/configs/server-configuration.tsx index 9cc06102a43..ff72e53a27c 100644 --- a/apps/console/src/extensions/configs/server-configuration.tsx +++ b/apps/console/src/extensions/configs/server-configuration.tsx @@ -64,9 +64,11 @@ export const serverConfigurationConfig: ServerConfigurationConfig = { ], connectorToggleName: {}, connectorsToHide: [ - "analytics-engine", - "elastic-analytics-engine", - "pii-controller" + ServerConfigurationsConstants.WSO2_ANALYTICS_ENGINE_CONNECTOR_CATEGORY_ID, + ServerConfigurationsConstants.ELK_ANALYTICS_CONNECTOR_ID, + ServerConfigurationsConstants.LITE_USER_REGISTRATION_CONNECTOR_ID, + ServerConfigurationsConstants.MULTI_ATTRIBUTE_LOGIN_CONNECTOR_ID, + ServerConfigurationsConstants.CONSENT_INFO_CONNECTOR_ID ], connectorsToShow: [ "all" ], customConnectors: [ diff --git a/apps/console/src/features/core/configs/routes.tsx b/apps/console/src/features/core/configs/routes.tsx index f13b2124c87..7a401b40141 100644 --- a/apps/console/src/features/core/configs/routes.tsx +++ b/apps/console/src/features/core/configs/routes.tsx @@ -20,7 +20,11 @@ import { ArrowRightToBracketPencilIcon, BoltIcon, EnvelopeGearIcon, + EnvelopeIcon, HierarchyIcon, + LightbulbOnIcon, + LinearNodesIcon, + UserCircleDotIcon, UserGroupIcon } from "@oxygen-ui/react-icons"; import { RouteInterface } from "@wso2is/core/models"; @@ -124,17 +128,6 @@ export const getAppViewRoutes = (useExtendedRoutes: boolean = false): RouteInter protected: true, showOnSidePanel: true }, - { - component: lazy(() => import("../../server-configurations/pages/governance-connectors")), - exact: true, - icon: null, - id: "governanceConnectors", - name: "console:manage.features.sidePanel.governanceConnectors", - order: 11, - path: AppConstants.getPaths().get("GOVERNANCE_CONNECTORS"), - protected: true, - showOnSidePanel: false - }, { category: "console:develop.features.sidePanel.categories.application", children: [ @@ -351,7 +344,7 @@ export const getAppViewRoutes = (useExtendedRoutes: boolean = false): RouteInter component: lazy(() => import("../../oidc-scopes/pages/oidc-scopes")), exact: true, icon: { - icon: getSidePanelIcons().scopes + icon: }, id: "oidcScopes", name: "console:develop.features.sidePanel.oidcScopes", @@ -458,7 +451,7 @@ export const getAppViewRoutes = (useExtendedRoutes: boolean = false): RouteInter import("../../../features/email-management/" + "pages/email-customization") ), exact: true, - icon: { icon: getSidePanelIcons().emailTemplates }, + icon: { icon: }, id: "communication-management", name: "Email", order: 14, @@ -876,7 +869,7 @@ export const getAppViewRoutes = (useExtendedRoutes: boolean = false): RouteInter featureStatus: "BETA", featureStatusLabel: "common:beta", icon: { - icon: getSidePanelIcons().insights + icon: }, id: "insights", name: "Insights", @@ -894,7 +887,7 @@ export const getAppViewRoutes = (useExtendedRoutes: boolean = false): RouteInter ), exact: true, icon: { - icon: getSidePanelIcons().insights + icon: }, id: "analytics", name: "Analytics", @@ -990,6 +983,18 @@ export const getAppViewRoutes = (useExtendedRoutes: boolean = false): RouteInter path: AppConstants.getPaths().get("GOVERNANCE_CONNECTORS"), protected: true, showOnSidePanel: false + }, + { + component: lazy(() => import("../../server-configurations/pages/multi-attribute-login-edit")), + exact: true, + icon: null, + id: "multiAttributeLogin", + name: "console:manage.features.governanceConnectors.connectorCategories.accountManagement." + + "connectors.multiattributeLoginHandler.friendlyName", + order: 999, + path: AppConstants.getPaths().get("MULTI_ATTRIBUTE_LOGIN"), + protected: true, + showOnSidePanel: false } ]), "id" diff --git a/apps/console/src/features/core/constants/app-constants.ts b/apps/console/src/features/core/constants/app-constants.ts index 3833350b65e..267a7b8dd35 100644 --- a/apps/console/src/features/core/constants/app-constants.ts +++ b/apps/console/src/features/core/constants/app-constants.ts @@ -333,6 +333,7 @@ export class AppConstants { [ "ROLE_EDIT", `${ AppConstants.getAdminViewBasePath() }/roles/:id` ], [ "ROOT", "/" ], [ "GOVERNANCE_CONNECTORS", `${AppConstants.getAdminViewBasePath()}/governance-connectors/:id` ], + [ "MULTI_ATTRIBUTE_LOGIN", `${AppConstants.getAdminViewBasePath()}/multi-attribute-login` ], [ "UNAUTHORIZED", `${AppConstants.getMainViewBasePath()}/unauthorized` ], [ "USERS", `${AppConstants.getAdminViewBasePath()}/users` ], [ "USER_EDIT", `${AppConstants.getAdminViewBasePath()}/users/:id` ], diff --git a/apps/console/src/features/core/utils/route-utils.ts b/apps/console/src/features/core/utils/route-utils.ts index a6db94f30cd..37b5684ce46 100644 --- a/apps/console/src/features/core/utils/route-utils.ts +++ b/apps/console/src/features/core/utils/route-utils.ts @@ -18,6 +18,7 @@ import { BuildingGearIcon, + DatabaseDocumentIcon, PaletteIcon, SquareUserIcon } from "@oxygen-ui/react-icons"; @@ -262,7 +263,7 @@ export class RouteUtils { }; const userAttributesAndStores: Omit = { - icon: BuildingGearIcon, + icon: DatabaseDocumentIcon, id: "userAttributesAndStores", name: "User Attributes & Stores" }; @@ -370,16 +371,19 @@ export class RouteUtils { { category: manage, id: "userStores", + order: 2, parent: userAttributesAndStores }, { category: manage, id: "attributeDialects", + order: 1, parent: userAttributesAndStores }, { category: manage, id: "oidcScopes", + order: 3, parent: userAttributesAndStores }, { diff --git a/apps/console/src/features/server-configurations/components/governance-connectors/dynamic-governance-connector.tsx b/apps/console/src/features/server-configurations/components/governance-connectors/dynamic-governance-connector.tsx index 9889b679297..7c029f31417 100644 --- a/apps/console/src/features/server-configurations/components/governance-connectors/dynamic-governance-connector.tsx +++ b/apps/console/src/features/server-configurations/components/governance-connectors/dynamic-governance-connector.tsx @@ -129,7 +129,7 @@ export const DynamicGovernanceConnector: FunctionComponent { dispatch( addAlert({ description: t( "console:manage.features.governanceConnectors.notifications." + "updateConnector.success.description", - { name: connector.friendlyName } + { name: connector?.friendlyName } ), level: AlertLevels.SUCCESS, message: t( @@ -197,15 +197,15 @@ export const DynamicGovernanceConnector: FunctionComponent serverConfigurationConfig.connectorPropertiesToShow.includes(property.name) || serverConfigurationConfig.connectorPropertiesToShow .includes(ServerConfigurationsConstants.ALL))) } } - form={ kebabCase(connector.friendlyName) + "-form" } + form={ kebabCase(connector?.friendlyName) + "-form" } initialValues={ getConnectorInitialValues(connector) } - data-testid={ `${ testId }-${ connector.name }-form` } + data-testid={ `${ testId }-${ connector?.name }-form` } isSubmitting={ isSubmitting } /> ); @@ -245,7 +245,7 @@ export const DynamicGovernanceConnector: FunctionComponent { diff --git a/apps/console/src/features/server-configurations/pages/connector-listing-page.tsx b/apps/console/src/features/server-configurations/pages/connector-listing-page.tsx index 6f7a5c69766..a37f37b338a 100644 --- a/apps/console/src/features/server-configurations/pages/connector-listing-page.tsx +++ b/apps/console/src/features/server-configurations/pages/connector-listing-page.tsx @@ -36,6 +36,7 @@ import { I18n } from "@wso2is/i18n"; import { PageLayout } from "@wso2is/react-components"; import { AxiosError } from "axios"; import camelCase from "lodash-es/camelCase"; +import lowerCase from "lodash-es/lowerCase"; import React, { FunctionComponent, MutableRefObject, ReactElement, useEffect, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; import { useDispatch, useSelector } from "react-redux"; @@ -320,6 +321,10 @@ export const ConnectorListingPage: FunctionComponent { + history.push(AppConstants.getPaths().get("MULTI_ATTRIBUTE_LOGIN")); + }; + /** * Get connector categories which generate the connector forms dynamically. */ @@ -387,6 +392,11 @@ export const ConnectorListingPage: FunctionComponent - - + <> + + + + + } + header={ + t("console:manage.features.governanceConnectors." + + "connectorCategories.accountManagement.connectors." + + "multiattributeLoginHandler.friendlyName") + } + onPrimaryActionClick={ handleMultiAttributeLoginAction } + primaryAction={ t("common:configure") } + /> + + ) : ( <> diff --git a/apps/console/src/features/server-configurations/pages/governance-connectors.tsx b/apps/console/src/features/server-configurations/pages/governance-connectors.tsx index c75904d246a..99394c06a8a 100644 --- a/apps/console/src/features/server-configurations/pages/governance-connectors.tsx +++ b/apps/console/src/features/server-configurations/pages/governance-connectors.tsx @@ -31,7 +31,7 @@ import { Grid, Menu, Rail, Ref, Sticky } from "semantic-ui-react"; import { serverConfigurationConfig } from "../../../extensions"; import { AppConstants, AppState, FeatureConfigInterface, UIConstants, history } from "../../core"; import { OrganizationUtils } from "../../organizations/utils"; -import { getConnectorCategory } from "../api"; +import { getConnectorCategory } from "../api/governance-connectors"; import { DynamicGovernanceConnector } from "../components"; import { ServerConfigurationsConstants } from "../constants"; import { GovernanceConnectorCategoryInterface, GovernanceConnectorInterface } from "../models"; @@ -206,7 +206,7 @@ export const GovernanceConnectorsPage: FunctionComponent diff --git a/apps/console/src/features/server-configurations/pages/multi-attribute-login-edit.tsx b/apps/console/src/features/server-configurations/pages/multi-attribute-login-edit.tsx new file mode 100644 index 00000000000..fd3fdaeba0d --- /dev/null +++ b/apps/console/src/features/server-configurations/pages/multi-attribute-login-edit.tsx @@ -0,0 +1,185 @@ +/** + * Copyright (c) 2023, 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 + * 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 { hasRequiredScopes } from "@wso2is/core/helpers"; +import { AlertLevels, TestableComponentInterface } from "@wso2is/core/models"; +import { addAlert } from "@wso2is/core/store"; +import { ContentLoader, PageLayout } from "@wso2is/react-components"; +import { AxiosError } from "axios"; +import React, { FunctionComponent, MutableRefObject, ReactElement, useEffect, useRef, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { useDispatch, useSelector } from "react-redux"; +import { Dispatch } from "redux"; +import { Grid, Ref } from "semantic-ui-react"; +import { AppConstants, AppState, FeatureConfigInterface, history } from "../../core"; +import { getConnectorDetails } from "../api/governance-connectors"; +import { DynamicGovernanceConnector } from "../components/governance-connectors/dynamic-governance-connector"; +import { ServerConfigurationsConstants } from "../constants/server-configurations-constants"; +import { GovernanceConnectorInterface } from "../models/governance-connectors"; + +/** + * Props for the Server Configurations page. + */ +type GovernanceConnectorsPageInterface = TestableComponentInterface; + +/** + * Multi Attribute Login connector edit page. + * + * @param props - Props injected to the component. + * @returns Multi Attribute Login connector edit page. + */ +export const MultiAttributeLoginEdit: FunctionComponent = ( + props: GovernanceConnectorsPageInterface +): ReactElement => { + const { [ "data-testid" ]: testId } = props; + + const dispatch: Dispatch = useDispatch(); + const pageContextRef: MutableRefObject = useRef(null); + + const { t } = useTranslation(); + + const featureConfig: FeatureConfigInterface = useSelector((state: AppState) => state.config.ui.features); + const allowedScopes: string = useSelector((state: AppState) => state?.auth?.allowedScopes); + const categoryId: string = ServerConfigurationsConstants.ACCOUNT_MANAGEMENT_CATEGORY_ID; + const connectorId: string = ServerConfigurationsConstants.MULTI_ATTRIBUTE_LOGIN_CONNECTOR_ID; + + const [ connector, setConnector ] = useState(undefined); + const [ isConnectorRequestLoading, setConnectorRequestLoading ] = useState(false); + + useEffect(() => { + // If Governance Connector read permission is not available, prevent from trying to load the connectors. + if (!hasRequiredScopes(featureConfig?.governanceConnectors, + featureConfig?.governanceConnectors?.scopes?.read, + allowedScopes)) { + + return; + } + + loadConnectorDetails(); + }, []); + + /** + * Load multi attribute login connector. + */ + const loadConnectorDetails = () => { + + setConnectorRequestLoading(true); + + getConnectorDetails( + categoryId, + connectorId + ) + .then((response: GovernanceConnectorInterface) => { + response.categoryId = categoryId; + setConnector(response); + }) + .catch((error: AxiosError) => { + if (error.response && error.response.data && error.response.data.detail) { + dispatch( + addAlert({ + description: t( + "console:manage.features.governanceConnectors.notifications." + + "getConnector.error.description", + { description: error.response.data.description } + ), + level: AlertLevels.ERROR, + message: t( + "console:manage.features.governanceConnectors.notifications." + + "getConnector.error.message" + ) + }) + ); + } else { + // Generic error message + dispatch( + addAlert({ + description: t( + "console:manage.features.governanceConnectors.notifications." + + "getConnector.genericError.description" + ), + level: AlertLevels.ERROR, + message: t( + "console:manage.features.governanceConnectors.notifications." + + "getConnector.genericError.message" + ) + }) + ); + } + }) + .finally(() => { + setConnectorRequestLoading(false); + }); + }; + + const onBackButtonClick = (): void => { + history.push(AppConstants.getPaths().get("LOGIN_AND_REGISTRATION")); + }; + + if(isConnectorRequestLoading && !connector) { + return ; + } + + return ( + onBackButtonClick(), + text: t("console:manage.features.governanceConnectors.goBackLoginAndRegistration") + } } + data-testid={ `${testId}-page-layout` } + > + + + + + + + loadConnectorDetails() } + /> + + + + + + + + ); +}; + +/** + * Default props for the component. + */ +MultiAttributeLoginEdit.defaultProps = { + "data-testid": "multi-attribute-login-edit" +}; + +/** + * A default export was added to support React.lazy. + * TODO: Change this to a named export once react starts supporting named exports for code splitting. + * @see {@link https://reactjs.org/docs/code-splitting.html#reactlazy} + */ +export default MultiAttributeLoginEdit; From 49fbc3e3db953eb9fc840721f205175d7b11bd25 Mon Sep 17 00:00:00 2001 From: savindi7 Date: Thu, 26 Oct 2023 17:01:56 +0530 Subject: [PATCH 2/4] update selected state condition of navbar item --- apps/console/src/features/core/utils/route-utils.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/console/src/features/core/utils/route-utils.ts b/apps/console/src/features/core/utils/route-utils.ts index 37b5684ce46..fcee481f0f6 100644 --- a/apps/console/src/features/core/utils/route-utils.ts +++ b/apps/console/src/features/core/utils/route-utils.ts @@ -316,7 +316,8 @@ export class RouteUtils { AppConstants.getPaths().get("LOGIN_AND_REGISTRATION"), AppConstants.getPaths().get("USERNAME_VALIDATION_EDIT"), AppConstants.getPaths().get("ALTERNATIVE_LOGIN_IDENTIFIER_EDIT"), - AppConstants.getPaths().get("ADMIN_ADVISORY_BANNER_EDIT") + AppConstants.getPaths().get("ADMIN_ADVISORY_BANNER_EDIT"), + AppConstants.getPaths().get("MULTI_ATTRIBUTE_LOGIN") ]; const CategoryMappedRoutes: Omit[] = [ From 0e1e2925ada4082fa04ceaf5d69a837547264c82 Mon Sep 17 00:00:00 2001 From: savindi7 Date: Thu, 26 Oct 2023 18:11:16 +0530 Subject: [PATCH 3/4] fix lint issue --- .../server-configurations/pages/multi-attribute-login-edit.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/console/src/features/server-configurations/pages/multi-attribute-login-edit.tsx b/apps/console/src/features/server-configurations/pages/multi-attribute-login-edit.tsx index fd3fdaeba0d..519ad64fd54 100644 --- a/apps/console/src/features/server-configurations/pages/multi-attribute-login-edit.tsx +++ b/apps/console/src/features/server-configurations/pages/multi-attribute-login-edit.tsx @@ -130,7 +130,7 @@ export const MultiAttributeLoginEdit: FunctionComponent; } From dd77136f3a0ab9ab7fbfcbfa336ef83c90628a8d Mon Sep 17 00:00:00 2001 From: savindi7 Date: Thu, 26 Oct 2023 18:12:03 +0530 Subject: [PATCH 4/4] Add Changeset --- .changeset/silver-beans-rule.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/silver-beans-rule.md diff --git a/.changeset/silver-beans-rule.md b/.changeset/silver-beans-rule.md new file mode 100644 index 00000000000..bb5108c04c7 --- /dev/null +++ b/.changeset/silver-beans-rule.md @@ -0,0 +1,5 @@ +--- +"@wso2is/console": patch +--- + +Move Multi Attribute Login connector to Login & Registration