Use react-form-hook
v7 for user IDP modal (#3771)
This commit is contained in:
parent
27d8b35d70
commit
d0b224cae7
4 changed files with 89 additions and 116 deletions
|
@ -11,7 +11,6 @@ export default class IdentityProviderLinksTab {
|
||||||
private linkAccountModalIdentityProviderInput = "idpNameInput";
|
private linkAccountModalIdentityProviderInput = "idpNameInput";
|
||||||
private linkAccountModalUserIdInput = "userIdInput";
|
private linkAccountModalUserIdInput = "userIdInput";
|
||||||
private linkAccountModalUsernameInput = "usernameInput";
|
private linkAccountModalUsernameInput = "usernameInput";
|
||||||
private linkAccountModalLinkBtn = "Link";
|
|
||||||
|
|
||||||
public clickLinkAccount(idpName: string) {
|
public clickLinkAccount(idpName: string) {
|
||||||
cy.get(this.availableProvidersSection + " tr")
|
cy.get(this.availableProvidersSection + " tr")
|
||||||
|
@ -47,7 +46,7 @@ export default class IdentityProviderLinksTab {
|
||||||
}
|
}
|
||||||
|
|
||||||
public clickLinkAccountModalLinkBtn() {
|
public clickLinkAccountModalLinkBtn() {
|
||||||
cy.findByTestId(this.linkAccountModalLinkBtn).click();
|
modalUtils.confirmModal();
|
||||||
cy.intercept("/admin/realms/master").as("load");
|
cy.intercept("/admin/realms/master").as("load");
|
||||||
cy.wait(["@load"]);
|
cy.wait(["@load"]);
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import type FederatedIdentityRepresentation from "@keycloak/keycloak-admin-client/lib/defs/federatedIdentityRepresentation";
|
||||||
import {
|
import {
|
||||||
AlertVariant,
|
AlertVariant,
|
||||||
Button,
|
Button,
|
||||||
|
@ -8,28 +9,26 @@ import {
|
||||||
ModalVariant,
|
ModalVariant,
|
||||||
ValidatedOptions,
|
ValidatedOptions,
|
||||||
} from "@patternfly/react-core";
|
} from "@patternfly/react-core";
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { useForm } from "react-hook-form";
|
|
||||||
|
|
||||||
import type GroupRepresentation from "@keycloak/keycloak-admin-client/lib/defs/groupRepresentation";
|
|
||||||
import { useAdminClient } from "../context/auth/AdminClient";
|
|
||||||
import { useAlerts } from "../components/alert/Alerts";
|
|
||||||
import { capitalize } from "lodash-es";
|
import { capitalize } from "lodash-es";
|
||||||
import { useParams } from "react-router-dom";
|
import { useForm } from "react-hook-form-v7";
|
||||||
import type FederatedIdentityRepresentation from "@keycloak/keycloak-admin-client/lib/defs/federatedIdentityRepresentation";
|
import { useTranslation } from "react-i18next";
|
||||||
import type { UserParams } from "./routes/User";
|
|
||||||
|
import { useAlerts } from "../components/alert/Alerts";
|
||||||
import { KeycloakTextInput } from "../components/keycloak-text-input/KeycloakTextInput";
|
import { KeycloakTextInput } from "../components/keycloak-text-input/KeycloakTextInput";
|
||||||
|
import { useAdminClient } from "../context/auth/AdminClient";
|
||||||
|
|
||||||
type UserIdpModalProps = {
|
type UserIdpModalProps = {
|
||||||
federatedId?: string;
|
userId: string;
|
||||||
handleModalToggle: () => void;
|
federatedId: string;
|
||||||
refresh: (group?: GroupRepresentation) => void;
|
onClose: () => void;
|
||||||
|
onRefresh: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const UserIdpModal = ({
|
export const UserIdpModal = ({
|
||||||
|
userId,
|
||||||
federatedId,
|
federatedId,
|
||||||
handleModalToggle,
|
onClose,
|
||||||
refresh,
|
onRefresh,
|
||||||
}: UserIdpModalProps) => {
|
}: UserIdpModalProps) => {
|
||||||
const { t } = useTranslation("users");
|
const { t } = useTranslation("users");
|
||||||
const { adminClient } = useAdminClient();
|
const { adminClient } = useAdminClient();
|
||||||
|
@ -38,22 +37,22 @@ export const UserIdpModal = ({
|
||||||
register,
|
register,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
formState: { isValid, errors },
|
formState: { isValid, errors },
|
||||||
} = useForm({
|
} = useForm<FederatedIdentityRepresentation>({
|
||||||
mode: "onChange",
|
mode: "onChange",
|
||||||
});
|
});
|
||||||
|
|
||||||
const { id } = useParams<UserParams>();
|
const onSubmit = async (
|
||||||
|
federatedIdentity: FederatedIdentityRepresentation
|
||||||
const submitForm = async (fedIdentity: FederatedIdentityRepresentation) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
await adminClient.users.addToFederatedIdentity({
|
await adminClient.users.addToFederatedIdentity({
|
||||||
id: id!,
|
id: userId,
|
||||||
federatedIdentityId: federatedId!,
|
federatedIdentityId: federatedId,
|
||||||
federatedIdentity: fedIdentity,
|
federatedIdentity,
|
||||||
});
|
});
|
||||||
addAlert(t("users:idpLinkSuccess"), AlertVariant.success);
|
addAlert(t("users:idpLinkSuccess"), AlertVariant.success);
|
||||||
handleModalToggle();
|
onClose();
|
||||||
refresh();
|
onRefresh();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
addError("users:couldNotLinkIdP", error);
|
addError("users:couldNotLinkIdP", error);
|
||||||
}
|
}
|
||||||
|
@ -65,12 +64,11 @@ export const UserIdpModal = ({
|
||||||
title={t("users:linkAccountTitle", {
|
title={t("users:linkAccountTitle", {
|
||||||
provider: capitalize(federatedId),
|
provider: capitalize(federatedId),
|
||||||
})}
|
})}
|
||||||
isOpen={true}
|
onClose={onClose}
|
||||||
onClose={handleModalToggle}
|
|
||||||
actions={[
|
actions={[
|
||||||
<Button
|
<Button
|
||||||
data-testid={t("link")}
|
|
||||||
key="confirm"
|
key="confirm"
|
||||||
|
data-testid="confirm"
|
||||||
variant="primary"
|
variant="primary"
|
||||||
type="submit"
|
type="submit"
|
||||||
form="group-form"
|
form="group-form"
|
||||||
|
@ -79,51 +77,31 @@ export const UserIdpModal = ({
|
||||||
{t("link")}
|
{t("link")}
|
||||||
</Button>,
|
</Button>,
|
||||||
<Button
|
<Button
|
||||||
id="modal-cancel"
|
|
||||||
data-testid="cancel"
|
|
||||||
key="cancel"
|
key="cancel"
|
||||||
|
data-testid="cancel"
|
||||||
variant={ButtonVariant.link}
|
variant={ButtonVariant.link}
|
||||||
onClick={() => {
|
onClick={onClose}
|
||||||
handleModalToggle();
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{t("common:cancel")}
|
{t("common:cancel")}
|
||||||
</Button>,
|
</Button>,
|
||||||
]}
|
]}
|
||||||
|
isOpen
|
||||||
>
|
>
|
||||||
<Form id="group-form" onSubmit={handleSubmit(submitForm)}>
|
<Form id="group-form" onSubmit={handleSubmit(onSubmit)}>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
name="idp-name-group"
|
|
||||||
label={t("users:identityProvider")}
|
label={t("users:identityProvider")}
|
||||||
fieldId="idp-name"
|
fieldId="identityProvider"
|
||||||
helperTextInvalid={t("common:required")}
|
|
||||||
validated={
|
|
||||||
errors.identityProvider
|
|
||||||
? ValidatedOptions.error
|
|
||||||
: ValidatedOptions.default
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<KeycloakTextInput
|
<KeycloakTextInput
|
||||||
|
id="identityProvider"
|
||||||
data-testid="idpNameInput"
|
data-testid="idpNameInput"
|
||||||
aria-label="Identity provider name input"
|
|
||||||
ref={register({ required: true })}
|
|
||||||
autoFocus
|
|
||||||
isReadOnly
|
|
||||||
type="text"
|
|
||||||
id="link-idp-name"
|
|
||||||
name="identityProvider"
|
|
||||||
value={capitalize(federatedId)}
|
value={capitalize(federatedId)}
|
||||||
validated={
|
isReadOnly
|
||||||
errors.identityProvider
|
|
||||||
? ValidatedOptions.error
|
|
||||||
: ValidatedOptions.default
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
name="user-id-group"
|
|
||||||
label={t("users:userID")}
|
label={t("users:userID")}
|
||||||
fieldId="user-id"
|
fieldId="userID"
|
||||||
helperText={t("users-help:userIdHelperText")}
|
helperText={t("users-help:userIdHelperText")}
|
||||||
helperTextInvalid={t("common:required")}
|
helperTextInvalid={t("common:required")}
|
||||||
validated={
|
validated={
|
||||||
|
@ -132,40 +110,34 @@ export const UserIdpModal = ({
|
||||||
isRequired
|
isRequired
|
||||||
>
|
>
|
||||||
<KeycloakTextInput
|
<KeycloakTextInput
|
||||||
|
id="userID"
|
||||||
data-testid="userIdInput"
|
data-testid="userIdInput"
|
||||||
aria-label="user ID input"
|
|
||||||
ref={register({ required: true })}
|
|
||||||
autoFocus
|
|
||||||
type="text"
|
|
||||||
id="link-idp-user-id"
|
|
||||||
name="userId"
|
|
||||||
validated={
|
validated={
|
||||||
errors.userId ? ValidatedOptions.error : ValidatedOptions.default
|
errors.userId ? ValidatedOptions.error : ValidatedOptions.default
|
||||||
}
|
}
|
||||||
|
autoFocus
|
||||||
|
{...register("userId", { required: true })}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
name="username-group"
|
|
||||||
label={t("users:username")}
|
label={t("users:username")}
|
||||||
fieldId="username"
|
fieldId="username"
|
||||||
helperText={t("users-help:usernameHelperText")}
|
helperText={t("users-help:usernameHelperText")}
|
||||||
helperTextInvalid={t("common:required")}
|
helperTextInvalid={t("common:required")}
|
||||||
validated={
|
validated={
|
||||||
errors.name ? ValidatedOptions.error : ValidatedOptions.default
|
errors.userName ? ValidatedOptions.error : ValidatedOptions.default
|
||||||
}
|
}
|
||||||
isRequired
|
isRequired
|
||||||
>
|
>
|
||||||
<KeycloakTextInput
|
<KeycloakTextInput
|
||||||
|
id="username"
|
||||||
data-testid="usernameInput"
|
data-testid="usernameInput"
|
||||||
aria-label="username input"
|
|
||||||
ref={register({ required: true })}
|
|
||||||
autoFocus
|
|
||||||
type="text"
|
|
||||||
id="link-idp-username"
|
|
||||||
name="userName"
|
|
||||||
validated={
|
validated={
|
||||||
errors.name ? ValidatedOptions.error : ValidatedOptions.default
|
errors.userName
|
||||||
|
? ValidatedOptions.error
|
||||||
|
: ValidatedOptions.default
|
||||||
}
|
}
|
||||||
|
{...register("userName", { required: true })}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { useState } from "react";
|
import type FederatedIdentityRepresentation from "@keycloak/keycloak-admin-client/lib/defs/federatedIdentityRepresentation";
|
||||||
import { useTranslation } from "react-i18next";
|
import type IdentityProviderRepresentation from "@keycloak/keycloak-admin-client/lib/defs/identityProviderRepresentation";
|
||||||
import {
|
import {
|
||||||
AlertVariant,
|
AlertVariant,
|
||||||
Button,
|
Button,
|
||||||
|
@ -9,40 +9,41 @@ import {
|
||||||
Text,
|
Text,
|
||||||
TextContent,
|
TextContent,
|
||||||
} from "@patternfly/react-core";
|
} from "@patternfly/react-core";
|
||||||
|
import { cellWidth } from "@patternfly/react-table";
|
||||||
|
import { capitalize } from "lodash-es";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { Link } from "react-router-dom-v5-compat";
|
||||||
|
|
||||||
|
import { useAlerts } from "../components/alert/Alerts";
|
||||||
|
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
|
||||||
import { FormPanel } from "../components/scroll-form/FormPanel";
|
import { FormPanel } from "../components/scroll-form/FormPanel";
|
||||||
import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable";
|
import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable";
|
||||||
import { cellWidth } from "@patternfly/react-table";
|
|
||||||
import { useParams } from "react-router-dom";
|
|
||||||
import { Link } from "react-router-dom-v5-compat";
|
|
||||||
import { useAdminClient } from "../context/auth/AdminClient";
|
import { useAdminClient } from "../context/auth/AdminClient";
|
||||||
import { emptyFormatter, upperCaseFormatter } from "../util";
|
|
||||||
import type IdentityProviderRepresentation from "@keycloak/keycloak-admin-client/lib/defs/identityProviderRepresentation";
|
|
||||||
import type FederatedIdentityRepresentation from "@keycloak/keycloak-admin-client/lib/defs/federatedIdentityRepresentation";
|
|
||||||
import { useRealm } from "../context/realm-context/RealmContext";
|
import { useRealm } from "../context/realm-context/RealmContext";
|
||||||
import { useServerInfo } from "../context/server-info/ServerInfoProvider";
|
import { useServerInfo } from "../context/server-info/ServerInfoProvider";
|
||||||
import { capitalize } from "lodash-es";
|
|
||||||
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
|
|
||||||
import { useAlerts } from "../components/alert/Alerts";
|
|
||||||
import { UserIdpModal } from "./UserIdPModal";
|
|
||||||
import { toIdentityProvider } from "../identity-providers/routes/IdentityProvider";
|
import { toIdentityProvider } from "../identity-providers/routes/IdentityProvider";
|
||||||
|
import { emptyFormatter, upperCaseFormatter } from "../util";
|
||||||
|
import { UserIdpModal } from "./UserIdPModal";
|
||||||
|
|
||||||
export const UserIdentityProviderLinks = () => {
|
type UserIdentityProviderLinksProps = {
|
||||||
|
userId: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const UserIdentityProviderLinks = ({
|
||||||
|
userId,
|
||||||
|
}: UserIdentityProviderLinksProps) => {
|
||||||
const [key, setKey] = useState(0);
|
const [key, setKey] = useState(0);
|
||||||
const [federatedId, setFederatedId] = useState("");
|
const [federatedId, setFederatedId] = useState("");
|
||||||
const [isLinkIdPModalOpen, setIsLinkIdPModalOpen] = useState(false);
|
const [isLinkIdPModalOpen, setIsLinkIdPModalOpen] = useState(false);
|
||||||
|
|
||||||
const { adminClient } = useAdminClient();
|
const { adminClient } = useAdminClient();
|
||||||
const { id } = useParams<{ id: string }>();
|
|
||||||
const { realm } = useRealm();
|
const { realm } = useRealm();
|
||||||
const { addAlert, addError } = useAlerts();
|
const { addAlert, addError } = useAlerts();
|
||||||
const { t } = useTranslation("users");
|
const { t } = useTranslation("users");
|
||||||
|
|
||||||
const refresh = () => setKey(new Date().getTime());
|
const refresh = () => setKey(new Date().getTime());
|
||||||
|
|
||||||
const handleModalToggle = () => {
|
|
||||||
setIsLinkIdPModalOpen(!isLinkIdPModalOpen);
|
|
||||||
};
|
|
||||||
|
|
||||||
type WithProviderId = FederatedIdentityRepresentation & {
|
type WithProviderId = FederatedIdentityRepresentation & {
|
||||||
providerId: string;
|
providerId: string;
|
||||||
};
|
};
|
||||||
|
@ -53,7 +54,7 @@ export const UserIdentityProviderLinks = () => {
|
||||||
const allProviders = await adminClient.identityProviders.find();
|
const allProviders = await adminClient.identityProviders.find();
|
||||||
|
|
||||||
const allFedIds = (await adminClient.users.listFederatedIdentities({
|
const allFedIds = (await adminClient.users.listFederatedIdentities({
|
||||||
id,
|
id: userId,
|
||||||
})) as WithProviderId[];
|
})) as WithProviderId[];
|
||||||
for (const element of allFedIds) {
|
for (const element of allFedIds) {
|
||||||
element.providerId = allProviders.find(
|
element.providerId = allProviders.find(
|
||||||
|
@ -94,7 +95,7 @@ export const UserIdentityProviderLinks = () => {
|
||||||
onConfirm: async () => {
|
onConfirm: async () => {
|
||||||
try {
|
try {
|
||||||
await adminClient.users.delFromFederatedIdentity({
|
await adminClient.users.delFromFederatedIdentity({
|
||||||
id,
|
id: userId,
|
||||||
federatedIdentityId: federatedId,
|
federatedIdentityId: federatedId,
|
||||||
});
|
});
|
||||||
addAlert(t("users:idpUnlinkSuccess"), AlertVariant.success);
|
addAlert(t("users:idpUnlinkSuccess"), AlertVariant.success);
|
||||||
|
@ -180,9 +181,10 @@ export const UserIdentityProviderLinks = () => {
|
||||||
<>
|
<>
|
||||||
{isLinkIdPModalOpen && (
|
{isLinkIdPModalOpen && (
|
||||||
<UserIdpModal
|
<UserIdpModal
|
||||||
|
userId={userId}
|
||||||
federatedId={federatedId}
|
federatedId={federatedId}
|
||||||
handleModalToggle={handleModalToggle}
|
onClose={() => setIsLinkIdPModalOpen(false)}
|
||||||
refresh={refresh}
|
onRefresh={refresh}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<UnlinkConfirm />
|
<UnlinkConfirm />
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { useState } from "react";
|
import type GroupRepresentation from "@keycloak/keycloak-admin-client/lib/defs/groupRepresentation";
|
||||||
|
import type UserRepresentation from "@keycloak/keycloak-admin-client/lib/defs/userRepresentation";
|
||||||
import {
|
import {
|
||||||
AlertVariant,
|
AlertVariant,
|
||||||
ButtonVariant,
|
ButtonVariant,
|
||||||
|
@ -7,31 +8,30 @@ import {
|
||||||
Tab,
|
Tab,
|
||||||
TabTitleText,
|
TabTitleText,
|
||||||
} from "@patternfly/react-core";
|
} from "@patternfly/react-core";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useState } from "react";
|
||||||
import { Controller, FormProvider, useForm } from "react-hook-form";
|
import { Controller, FormProvider, useForm } from "react-hook-form";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
import type UserRepresentation from "@keycloak/keycloak-admin-client/lib/defs/userRepresentation";
|
|
||||||
import type GroupRepresentation from "@keycloak/keycloak-admin-client/lib/defs/groupRepresentation";
|
|
||||||
import { ViewHeader } from "../components/view-header/ViewHeader";
|
|
||||||
import { BruteForced, UserForm } from "./UserForm";
|
|
||||||
import { useAlerts } from "../components/alert/Alerts";
|
|
||||||
import { useAdminClient, useFetch } from "../context/auth/AdminClient";
|
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { useNavigate } from "react-router-dom-v5-compat";
|
import { useNavigate } from "react-router-dom-v5-compat";
|
||||||
import { KeycloakTabs } from "../components/keycloak-tabs/KeycloakTabs";
|
|
||||||
import { UserGroups } from "./UserGroups";
|
import { useAlerts } from "../components/alert/Alerts";
|
||||||
import { UserConsents } from "./UserConsents";
|
|
||||||
import { useRealm } from "../context/realm-context/RealmContext";
|
|
||||||
import { UserIdentityProviderLinks } from "./UserIdentityProviderLinks";
|
|
||||||
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
|
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
|
||||||
import { toUser } from "./routes/User";
|
|
||||||
import { toUsers } from "./routes/Users";
|
|
||||||
import { UserRoleMapping } from "./UserRoleMapping";
|
|
||||||
import { UserAttributes } from "./UserAttributes";
|
|
||||||
import { UserCredentials } from "./UserCredentials";
|
|
||||||
import { UserSessions } from "./UserSessions";
|
|
||||||
import { useAccess } from "../context/access/Access";
|
|
||||||
import { KeycloakSpinner } from "../components/keycloak-spinner/KeycloakSpinner";
|
import { KeycloakSpinner } from "../components/keycloak-spinner/KeycloakSpinner";
|
||||||
|
import { KeycloakTabs } from "../components/keycloak-tabs/KeycloakTabs";
|
||||||
|
import { ViewHeader } from "../components/view-header/ViewHeader";
|
||||||
|
import { useAccess } from "../context/access/Access";
|
||||||
|
import { useAdminClient, useFetch } from "../context/auth/AdminClient";
|
||||||
|
import { useRealm } from "../context/realm-context/RealmContext";
|
||||||
|
import { toUser, UserParams } from "./routes/User";
|
||||||
|
import { toUsers } from "./routes/Users";
|
||||||
|
import { UserAttributes } from "./UserAttributes";
|
||||||
|
import { UserConsents } from "./UserConsents";
|
||||||
|
import { UserCredentials } from "./UserCredentials";
|
||||||
|
import { BruteForced, UserForm } from "./UserForm";
|
||||||
|
import { UserGroups } from "./UserGroups";
|
||||||
|
import { UserIdentityProviderLinks } from "./UserIdentityProviderLinks";
|
||||||
|
import { UserRoleMapping } from "./UserRoleMapping";
|
||||||
|
import { UserSessions } from "./UserSessions";
|
||||||
|
|
||||||
const UsersTabs = () => {
|
const UsersTabs = () => {
|
||||||
const { t } = useTranslation("users");
|
const { t } = useTranslation("users");
|
||||||
|
@ -42,7 +42,7 @@ const UsersTabs = () => {
|
||||||
|
|
||||||
const { adminClient } = useAdminClient();
|
const { adminClient } = useAdminClient();
|
||||||
const userForm = useForm<UserRepresentation>({ mode: "onChange" });
|
const userForm = useForm<UserRepresentation>({ mode: "onChange" });
|
||||||
const { id } = useParams<{ id: string }>();
|
const { id } = useParams<UserParams>();
|
||||||
const [user, setUser] = useState<UserRepresentation>();
|
const [user, setUser] = useState<UserRepresentation>();
|
||||||
const [bruteForced, setBruteForced] = useState<BruteForced>();
|
const [bruteForced, setBruteForced] = useState<BruteForced>();
|
||||||
const [addedGroups, setAddedGroups] = useState<GroupRepresentation[]>([]);
|
const [addedGroups, setAddedGroups] = useState<GroupRepresentation[]>([]);
|
||||||
|
@ -247,7 +247,7 @@ const UsersTabs = () => {
|
||||||
<TabTitleText>{t("identityProviderLinks")}</TabTitleText>
|
<TabTitleText>{t("identityProviderLinks")}</TabTitleText>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<UserIdentityProviderLinks />
|
<UserIdentityProviderLinks userId={id} />
|
||||||
</Tab>
|
</Tab>
|
||||||
)}
|
)}
|
||||||
<Tab
|
<Tab
|
||||||
|
|
Loading…
Reference in a new issue