Changed to use routable tabs (#1934)

* Changed to use routable tabs

* fixed tests
This commit is contained in:
Erik Jan de Wit 2022-01-31 08:20:35 +01:00 committed by GitHub
parent b9e79b6d75
commit 8b0327fa2c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 203 additions and 75 deletions

View file

@ -73,7 +73,7 @@ describe("Clients SAML tests", () => {
loginPage.logIn(); loginPage.logIn();
sidebarPage.goToClients(); sidebarPage.goToClients();
listingPage.searchItem(clientId).goToItemDetails(clientId); listingPage.searchItem(clientId).goToItemDetails(clientId);
cy.get("#pf-tab-keys-keys").click(); cy.findByTestId("keysTab").click();
}); });
it("doesn't disable when no", () => { it("doesn't disable when no", () => {

View file

@ -279,7 +279,7 @@ describe("Clients test", () => {
}); });
it("add mapping to openid client", () => { it("add mapping to openid client", () => {
cy.get("#pf-tab-mappers-mappers").click(); cy.findByTestId("mappersTab").click();
cy.findByText("Add predefined mapper").click(); cy.findByText("Add predefined mapper").click();
cy.get("table input").first().click(); cy.get("table input").first().click();
cy.findByTestId("modalConfirm").click(); cy.findByTestId("modalConfirm").click();
@ -343,15 +343,13 @@ describe("Clients test", () => {
it("displays the correct tabs", () => { it("displays the correct tabs", () => {
cy.findByTestId("client-tabs") cy.findByTestId("client-tabs")
.find("#pf-tab-settings-settings") .findByTestId("clientSettingsTab")
.should("exist"); .should("exist");
cy.findByTestId("client-tabs") cy.findByTestId("client-tabs").findByTestId("rolesTab").should("exist");
.find("#pf-tab-roles-roles")
.should("exist");
cy.findByTestId("client-tabs") cy.findByTestId("client-tabs")
.find("#pf-tab-advanced-advanced") .findByTestId("advancedTab")
.should("exist"); .should("exist");
cy.findByTestId("client-tabs").find("li").should("have.length", 3); cy.findByTestId("client-tabs").find("li").should("have.length", 3);

View file

@ -1,6 +1,6 @@
const expect = chai.expect; const expect = chai.expect;
export default class RoleMappingTab { export default class RoleMappingTab {
private tab = "#pf-tab-serviceAccount-serviceAccount"; private tab = "serviceAccountTab";
private scopeTab = "scopeTab"; private scopeTab = "scopeTab";
private assignEmptyRoleBtn = "no-roles-for-this-client-empty-action"; private assignEmptyRoleBtn = "no-roles-for-this-client-empty-action";
private assignRoleBtn = "assignRole"; private assignRoleBtn = "assignRole";
@ -12,7 +12,7 @@ export default class RoleMappingTab {
private confirmModalBtn = "modalConfirm"; private confirmModalBtn = "modalConfirm";
goToServiceAccountTab() { goToServiceAccountTab() {
cy.get(this.tab).click(); cy.findByTestId(this.tab).click();
return this; return this;
} }

View file

@ -17,10 +17,10 @@ export default class AdvancedTab {
private fineGrainSaveBtn = "#fineGrainSave"; private fineGrainSaveBtn = "#fineGrainSave";
private fineGrainRevertBtn = "#fineGrainRevert"; private fineGrainRevertBtn = "#fineGrainRevert";
private advancedTab = "#pf-tab-advanced-advanced"; private advancedTab = "advancedTab";
goToAdvancedTab() { goToAdvancedTab() {
cy.get(this.advancedTab).click(); cy.findByTestId(this.advancedTab).click();
return this; return this;
} }

View file

@ -5,11 +5,11 @@ import type ScopeRepresentation from "@keycloak/keycloak-admin-client/lib/defs/s
type PermissionType = "resource" | "scope"; type PermissionType = "resource" | "scope";
export default class AuthorizationTab { export default class AuthorizationTab {
private tabName = "#pf-tab-authorization-authorization"; private tabName = "authorizationTab";
private resourcesTabName = "#pf-tab-41-resources"; private resourcesTabName = "authorizationResources";
private scopeTabName = "#pf-tab-42-scopes"; private scopeTabName = "authorizationScopes";
private policyTabName = "#pf-tab-43-policies"; private policyTabName = "authorizationPolicies";
private permissionsTabName = "#pf-tab-44-permissions"; private permissionsTabName = "authorizationPermissions";
private nameColumnPrefix = "name-column-"; private nameColumnPrefix = "name-column-";
private emptyPolicyCreateButton = "no-policies-empty-action"; private emptyPolicyCreateButton = "no-policies-empty-action";
private createPolicyButton = "createPolicy"; private createPolicyButton = "createPolicy";
@ -19,27 +19,27 @@ export default class AuthorizationTab {
private permissionResourceDropdown = "#resources"; private permissionResourceDropdown = "#resources";
goToAuthenticationTab() { goToAuthenticationTab() {
cy.get(this.tabName).click(); cy.findByTestId(this.tabName).click();
return this; return this;
} }
goToResourceSubTab() { goToResourceSubTab() {
cy.get(this.resourcesTabName).click(); cy.findByTestId(this.resourcesTabName).click();
return this; return this;
} }
goToScopeSubTab() { goToScopeSubTab() {
cy.get(this.scopeTabName).click(); cy.findByTestId(this.scopeTabName).click();
return this; return this;
} }
goToPolicySubTab() { goToPolicySubTab() {
cy.get(this.policyTabName).click(); cy.findByTestId(this.policyTabName).click();
return this; return this;
} }
goToPermissionsSubTab() { goToPermissionsSubTab() {
cy.get(this.permissionsTabName).click(); cy.findByTestId(this.permissionsTabName).click();
return this; return this;
} }

View file

@ -1,8 +1,8 @@
export default class ClientScopesTab { export default class ClientScopesTab {
private clientScopesTab = "#pf-tab-clientScopes-clientScopes"; private clientScopesTab = "clientScopesTab";
goToClientScopesTab() { goToClientScopesTab() {
cy.get(this.clientScopesTab).click(); cy.findByTestId(this.clientScopesTab).click();
return this; return this;
} }
} }

View file

@ -1,5 +1,5 @@
export default class KeysTab { export default class KeysTab {
private tabName = "#pf-tab-keys-keys"; private tabName = "keysTab";
private useJwksUrl = "useJwksUrl"; private useJwksUrl = "useJwksUrl";
private saveKeys = "saveKeys"; private saveKeys = "saveKeys";
private generate = "generate"; private generate = "generate";
@ -9,7 +9,7 @@ export default class KeysTab {
private confirm = "confirm"; private confirm = "confirm";
goToTab() { goToTab() {
cy.get(this.tabName).click(); cy.findByTestId(this.tabName).click();
return this; return this;
} }

View file

@ -7,7 +7,6 @@ import {
Label, Label,
PageSection, PageSection,
Tab, Tab,
Tabs,
TabTitleText, TabTitleText,
Tooltip, Tooltip,
} from "@patternfly/react-core"; } from "@patternfly/react-core";
@ -24,7 +23,6 @@ import {
useConfirmDialog, useConfirmDialog,
} from "../components/confirm-dialog/ConfirmDialog"; } from "../components/confirm-dialog/ConfirmDialog";
import { DownloadDialog } from "../components/download-dialog/DownloadDialog"; import { DownloadDialog } from "../components/download-dialog/DownloadDialog";
import { KeycloakTabs } from "../components/keycloak-tabs/KeycloakTabs";
import type { MultiLine } from "../components/multi-line-input/multi-line-convert"; import type { MultiLine } from "../components/multi-line-input/multi-line-convert";
import { import {
ViewHeader, ViewHeader,
@ -44,7 +42,7 @@ import { AdvancedTab } from "./AdvancedTab";
import { ClientSettings } from "./ClientSettings"; import { ClientSettings } from "./ClientSettings";
import { Credentials } from "./credentials/Credentials"; import { Credentials } from "./credentials/Credentials";
import { Keys } from "./keys/Keys"; import { Keys } from "./keys/Keys";
import type { ClientParams } from "./routes/Client"; import { ClientParams, ClientTab, toClient } from "./routes/Client";
import { toClients } from "./routes/Clients"; import { toClients } from "./routes/Clients";
import { ClientScopes } from "./scopes/ClientScopes"; import { ClientScopes } from "./scopes/ClientScopes";
import { EvaluateScopes } from "./scopes/EvaluateScopes"; import { EvaluateScopes } from "./scopes/EvaluateScopes";
@ -63,6 +61,15 @@ import { AuthorizationPermissions } from "./authorization/Permissions";
import { AuthorizationEvaluate } from "./authorization/AuthorizationEvaluate"; import { AuthorizationEvaluate } from "./authorization/AuthorizationEvaluate";
import type UserRepresentation from "@keycloak/keycloak-admin-client/lib/defs/userRepresentation"; import type UserRepresentation from "@keycloak/keycloak-admin-client/lib/defs/userRepresentation";
import type RoleRepresentation from "@keycloak/keycloak-admin-client/lib/defs/roleRepresentation"; import type RoleRepresentation from "@keycloak/keycloak-admin-client/lib/defs/roleRepresentation";
import {
routableTab,
RoutableTabs,
} from "../components/routable-tabs/RoutableTabs";
import {
AuthorizationTab,
toAuthorizationTab,
} from "./routes/AuthenticationTab";
import { toClientScopesTab } from "./routes/ClientScopeTab";
type ClientDetailHeaderProps = { type ClientDetailHeaderProps = {
onChange: (value: boolean) => void; onChange: (value: boolean) => void;
@ -185,8 +192,6 @@ export default function ClientDetails() {
const [downloadDialogOpen, toggleDownloadDialogOpen] = useToggle(); const [downloadDialogOpen, toggleDownloadDialogOpen] = useToggle();
const [changeAuthenticatorOpen, toggleChangeAuthenticatorOpen] = useToggle(); const [changeAuthenticatorOpen, toggleChangeAuthenticatorOpen] = useToggle();
const [clientScopeSubTab, setClientScopeSubTab] = useState(30);
const [authorizationSubTab, setAuthorizationSubTab] = useState(40);
const form = useForm<ClientForm>({ shouldUnregister: false }); const form = useForm<ClientForm>({ shouldUnregister: false });
const { clientId } = useParams<ClientParams>(); const { clientId } = useParams<ClientParams>();
@ -341,6 +346,26 @@ export default function ClientDetails() {
return <KeycloakSpinner />; return <KeycloakSpinner />;
} }
const route = (tab: ClientTab) =>
routableTab({
to: toClient({
realm,
clientId,
tab,
}),
history,
});
const authenticationRoute = (tab: AuthorizationTab) =>
routableTab({
to: toAuthorizationTab({
realm,
clientId,
tab,
}),
history,
});
return ( return (
<> <>
<ConfirmDialogModal <ConfirmDialogModal
@ -385,11 +410,12 @@ export default function ClientDetails() {
/> />
<PageSection variant="light" className="pf-u-p-0"> <PageSection variant="light" className="pf-u-p-0">
<FormProvider {...form}> <FormProvider {...form}>
<KeycloakTabs data-testid="client-tabs" isBox mountOnEnter> <RoutableTabs data-testid="client-tabs" isBox mountOnEnter>
<Tab <Tab
id="settings" id="settings"
eventKey="settings" data-testid="clientSettingsTab"
title={<TabTitleText>{t("common:settings")}</TabTitleText>} title={<TabTitleText>{t("common:settings")}</TabTitleText>}
{...route("settings")}
> >
<ClientSettings <ClientSettings
client={client} client={client}
@ -401,8 +427,9 @@ export default function ClientDetails() {
client.protocol === "saml") && ( client.protocol === "saml") && (
<Tab <Tab
id="keys" id="keys"
eventKey="keys" data-testid="keysTab"
title={<TabTitleText>{t("keys")}</TabTitleText>} title={<TabTitleText>{t("keys")}</TabTitleText>}
{...route("keys")}
> >
{client.protocol === "openid-connect" && ( {client.protocol === "openid-connect" && (
<Keys clientId={clientId} save={save} /> <Keys clientId={clientId} save={save} />
@ -415,8 +442,8 @@ export default function ClientDetails() {
{!client.publicClient && !isRealmClient(client) && ( {!client.publicClient && !isRealmClient(client) && (
<Tab <Tab
id="credentials" id="credentials"
eventKey="credentials"
title={<TabTitleText>{t("credentials")}</TabTitleText>} title={<TabTitleText>{t("credentials")}</TabTitleText>}
{...route("credentials")}
> >
<Credentials clientId={clientId} save={() => save()} /> <Credentials clientId={clientId} save={() => save()} />
</Tab> </Tab>
@ -424,8 +451,9 @@ export default function ClientDetails() {
{!isRealmClient(client) && ( {!isRealmClient(client) && (
<Tab <Tab
id="mappers" id="mappers"
eventKey="mappers" data-testid="mappersTab"
title={<TabTitleText>{t("mappers")}</TabTitleText>} title={<TabTitleText>{t("mappers")}</TabTitleText>}
{...route("mappers")}
> >
<MapperList <MapperList
model={client} model={client}
@ -439,8 +467,9 @@ export default function ClientDetails() {
)} )}
<Tab <Tab
id="roles" id="roles"
eventKey="roles" data-testid="rolesTab"
title={<TabTitleText>{t("roles")}</TabTitleText>} title={<TabTitleText>{t("roles")}</TabTitleText>}
{...route("roles")}
> >
<RolesList <RolesList
loader={loader} loader={loader}
@ -451,17 +480,28 @@ export default function ClientDetails() {
{!isRealmClient(client) && ( {!isRealmClient(client) && (
<Tab <Tab
id="clientScopes" id="clientScopes"
eventKey="clientScopes" data-testid="clientScopesTab"
title={<TabTitleText>{t("clientScopes")}</TabTitleText>} title={<TabTitleText>{t("clientScopes")}</TabTitleText>}
{...route("clientScopes")}
> >
<Tabs <RoutableTabs
activeKey={clientScopeSubTab} defaultLocation={toClientScopesTab({
onSelect={(_, key) => setClientScopeSubTab(key as number)} realm,
clientId,
tab: "setup",
})}
> >
<Tab <Tab
id="setup" id="setup"
eventKey={30}
title={<TabTitleText>{t("setup")}</TabTitleText>} title={<TabTitleText>{t("setup")}</TabTitleText>}
{...routableTab({
to: toClientScopesTab({
realm,
clientId,
tab: "setup",
}),
history,
})}
> >
<ClientScopes <ClientScopes
clientName={client.clientId!} clientName={client.clientId!}
@ -471,68 +511,85 @@ export default function ClientDetails() {
</Tab> </Tab>
<Tab <Tab
id="evaluate" id="evaluate"
eventKey={31}
title={<TabTitleText>{t("evaluate")}</TabTitleText>} title={<TabTitleText>{t("evaluate")}</TabTitleText>}
{...routableTab({
to: toClientScopesTab({
realm,
clientId,
tab: "evaluate",
}),
history,
})}
> >
<EvaluateScopes <EvaluateScopes
clientId={clientId} clientId={clientId}
protocol={client!.protocol!} protocol={client!.protocol!}
/> />
</Tab> </Tab>
</Tabs> </RoutableTabs>
</Tab> </Tab>
)} )}
{client!.serviceAccountsEnabled && ( {client!.serviceAccountsEnabled && (
<Tab <Tab
id="authorization" id="authorization"
eventKey="authorization" data-testid="authorizationTab"
title={<TabTitleText>{t("authorization")}</TabTitleText>} title={<TabTitleText>{t("authorization")}</TabTitleText>}
{...route("authorization")}
> >
<Tabs <RoutableTabs
activeKey={authorizationSubTab}
onSelect={(_, key) => setAuthorizationSubTab(key as number)}
mountOnEnter mountOnEnter
unmountOnExit unmountOnExit
defaultLocation={toAuthorizationTab({
realm,
clientId,
tab: "settings",
})}
> >
<Tab <Tab
id="settings" id="settings"
eventKey={40} data-testid="authorizationSettings"
title={<TabTitleText>{t("settings")}</TabTitleText>} title={<TabTitleText>{t("settings")}</TabTitleText>}
{...authenticationRoute("settings")}
> >
<AuthorizationSettings clientId={clientId} /> <AuthorizationSettings clientId={clientId} />
</Tab> </Tab>
<Tab <Tab
id="resources" id="resources"
eventKey={41} data-testid="authorizationResources"
title={<TabTitleText>{t("resources")}</TabTitleText>} title={<TabTitleText>{t("resources")}</TabTitleText>}
{...authenticationRoute("resources")}
> >
<AuthorizationResources clientId={clientId} /> <AuthorizationResources clientId={clientId} />
</Tab> </Tab>
<Tab <Tab
id="scopes" id="scopes"
eventKey={42} data-testid="authorizationScopes"
title={<TabTitleText>{t("scopes")}</TabTitleText>} title={<TabTitleText>{t("scopes")}</TabTitleText>}
{...authenticationRoute("scopes")}
> >
<AuthorizationScopes clientId={clientId} /> <AuthorizationScopes clientId={clientId} />
</Tab> </Tab>
<Tab <Tab
id="policies" id="policies"
eventKey={43} data-testid="authorizationPolicies"
title={<TabTitleText>{t("policies")}</TabTitleText>} title={<TabTitleText>{t("policies")}</TabTitleText>}
{...authenticationRoute("policies")}
> >
<AuthorizationPolicies clientId={clientId} /> <AuthorizationPolicies clientId={clientId} />
</Tab> </Tab>
<Tab <Tab
id="permissions" id="permissions"
eventKey={44} data-testid="authorizationPermissions"
title={<TabTitleText>{t("permissions")}</TabTitleText>} title={<TabTitleText>{t("permissions")}</TabTitleText>}
{...authenticationRoute("permissions")}
> >
<AuthorizationPermissions clientId={clientId} /> <AuthorizationPermissions clientId={clientId} />
</Tab> </Tab>
<Tab <Tab
id="Evaluate" id="Evaluate"
eventKey={44} data-testid="authorizationEvaluate"
title={<TabTitleText>{t("evaluate")}</TabTitleText>} title={<TabTitleText>{t("evaluate")}</TabTitleText>}
{...authenticationRoute("evaluate")}
> >
<AuthorizationEvaluate <AuthorizationEvaluate
clients={clients} clients={clients}
@ -543,26 +600,28 @@ export default function ClientDetails() {
reset={() => setupForm(client)} reset={() => setupForm(client)}
/> />
</Tab> </Tab>
</Tabs> </RoutableTabs>
</Tab> </Tab>
)} )}
{client!.serviceAccountsEnabled && ( {client!.serviceAccountsEnabled && (
<Tab <Tab
id="serviceAccount" id="serviceAccount"
eventKey="serviceAccount" data-testid="serviceAccountTab"
title={<TabTitleText>{t("serviceAccount")}</TabTitleText>} title={<TabTitleText>{t("serviceAccount")}</TabTitleText>}
{...route("serviceAccount")}
> >
<ServiceAccount client={client} /> <ServiceAccount client={client} />
</Tab> </Tab>
)} )}
<Tab <Tab
id="advanced" id="advanced"
eventKey="advanced" data-testid="advancedTab"
title={<TabTitleText>{t("advanced")}</TabTitleText>} title={<TabTitleText>{t("advanced")}</TabTitleText>}
{...route("advanced")}
> >
<AdvancedTab save={save} client={client} /> <AdvancedTab save={save} client={client} />
</Tab> </Tab>
</KeycloakTabs> </RoutableTabs>
</FormProvider> </FormProvider>
</PageSection> </PageSection>
</> </>

View file

@ -27,9 +27,9 @@ import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"
import { ViewHeader } from "../../components/view-header/ViewHeader"; import { ViewHeader } from "../../components/view-header/ViewHeader";
import { FormAccess } from "../../components/form-access/FormAccess"; import { FormAccess } from "../../components/form-access/FormAccess";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import { toClient } from "../routes/Client";
import { HelpItem } from "../../components/help-enabler/HelpItem"; import { HelpItem } from "../../components/help-enabler/HelpItem";
import { ResourcesPolicySelect } from "./ResourcesPolicySelect"; import { ResourcesPolicySelect } from "./ResourcesPolicySelect";
import { toAuthorizationTab } from "../routes/AuthenticationTab";
const DECISION_STRATEGIES = ["UNANIMOUS", "AFFIRMATIVE", "CONSENSUS"] as const; const DECISION_STRATEGIES = ["UNANIMOUS", "AFFIRMATIVE", "CONSENSUS"] as const;
@ -140,7 +140,9 @@ export default function PermissionDetails() {
permissionId: permissionId, permissionId: permissionId,
}); });
addAlert(t("permissionDeletedSuccess"), AlertVariant.success); addAlert(t("permissionDeletedSuccess"), AlertVariant.success);
history.push(toClient({ realm, clientId: id, tab: "authorization" })); history.push(
toAuthorizationTab({ realm, clientId: id, tab: "permissions" })
);
} catch (error) { } catch (error) {
addError("clients:permissionDeletedError", error); addError("clients:permissionDeletedError", error);
} }
@ -329,10 +331,10 @@ export default function PermissionDetails() {
component={(props) => ( component={(props) => (
<Link <Link
{...props} {...props}
to={toClient({ to={toAuthorizationTab({
realm, realm,
clientId: id, clientId: id,
tab: "authorization", tab: "permissions",
})} })}
></Link> ></Link>
)} )}

View file

@ -31,7 +31,7 @@ import type { MultiLine } from "../../components/multi-line-input/multi-line-con
import type { KeyValueType } from "../../components/attribute-form/attribute-convert"; import type { KeyValueType } from "../../components/attribute-form/attribute-convert";
import { convertFormValuesToObject, convertToFormValues } from "../../util"; import { convertFormValuesToObject, convertToFormValues } from "../../util";
import { MultiLineInput } from "../../components/multi-line-input/MultiLineInput"; import { MultiLineInput } from "../../components/multi-line-input/MultiLineInput";
import { toClient } from "../routes/Client"; import { toAuthorizationTab } from "../routes/AuthenticationTab";
import { ScopePicker } from "./ScopePicker"; import { ScopePicker } from "./ScopePicker";
import { AttributeInput } from "../../components/attribute-input/AttributeInput"; import { AttributeInput } from "../../components/attribute-input/AttributeInput";
@ -142,7 +142,9 @@ export default function ResourceDetails() {
resourceId: resourceId!, resourceId: resourceId!,
}); });
addAlert(t("resourceDeletedSuccess"), AlertVariant.success); addAlert(t("resourceDeletedSuccess"), AlertVariant.success);
history.push(toClient({ realm, clientId: id, tab: "authorization" })); history.push(
toAuthorizationTab({ realm, clientId: id, tab: "resources" })
);
} catch (error) { } catch (error) {
addError("clients:resourceDeletedError", error); addError("clients:resourceDeletedError", error);
} }
@ -324,10 +326,10 @@ export default function ResourceDetails() {
component={(props) => ( component={(props) => (
<Link <Link
{...props} {...props}
to={toClient({ to={toAuthorizationTab({
realm, realm,
clientId: id, clientId: id,
tab: "authorization", tab: "resources",
})} })}
></Link> ></Link>
)} )}

View file

@ -19,7 +19,7 @@ import type { ScopeDetailsParams } from "../routes/Scope";
import { FormAccess } from "../../components/form-access/FormAccess"; import { FormAccess } from "../../components/form-access/FormAccess";
import { HelpItem } from "../../components/help-enabler/HelpItem"; import { HelpItem } from "../../components/help-enabler/HelpItem";
import { ViewHeader } from "../../components/view-header/ViewHeader"; import { ViewHeader } from "../../components/view-header/ViewHeader";
import { toClient } from "../routes/Client"; import { toAuthorizationTab } from "../routes/AuthenticationTab";
import { useAdminClient, useFetch } from "../../context/auth/AdminClient"; import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "../../components/alert/Alerts";
import useToggle from "../../utils/useToggle"; import useToggle from "../../utils/useToggle";
@ -77,7 +77,9 @@ export default function ScopeDetails() {
iconUri: scope.iconUri, iconUri: scope.iconUri,
} }
); );
history.push(toClient({ realm, clientId: id, tab: "authorization" })); history.push(
toAuthorizationTab({ realm, clientId: id, tab: "scopes" })
);
} }
addAlert( addAlert(
t((scopeId ? "update" : "create") + "ScopeSuccess"), t((scopeId ? "update" : "create") + "ScopeSuccess"),
@ -96,7 +98,9 @@ export default function ScopeDetails() {
toggleDialog={toggleDeleteDialog} toggleDialog={toggleDeleteDialog}
selectedScope={scope} selectedScope={scope}
refresh={() => refresh={() =>
history.push(toClient({ realm, clientId: id, tab: "authorization" })) history.push(
toAuthorizationTab({ realm, clientId: id, tab: "scopes" })
)
} }
/> />
<ViewHeader <ViewHeader
@ -183,10 +187,10 @@ export default function ScopeDetails() {
component={(props) => ( component={(props) => (
<Link <Link
{...props} {...props}
to={toClient({ to={toAuthorizationTab({
realm, realm,
clientId: id, clientId: id,
tab: "authorization", tab: "scopes",
})} })}
></Link> ></Link>
)} )}

View file

@ -22,7 +22,7 @@ import { useConfirmDialog } from "../../../components/confirm-dialog/ConfirmDial
import { useAdminClient, useFetch } from "../../../context/auth/AdminClient"; import { useAdminClient, useFetch } from "../../../context/auth/AdminClient";
import { FormAccess } from "../../../components/form-access/FormAccess"; import { FormAccess } from "../../../components/form-access/FormAccess";
import { useAlerts } from "../../../components/alert/Alerts"; import { useAlerts } from "../../../components/alert/Alerts";
import { toClient } from "../../routes/Client"; import { toAuthorizationTab } from "../../routes/AuthenticationTab";
import { Aggregate } from "./Aggregate"; import { Aggregate } from "./Aggregate";
import { Client } from "./Client"; import { Client } from "./Client";
import { User } from "./User"; import { User } from "./User";
@ -150,7 +150,9 @@ export default function PolicyDetails() {
policyId, policyId,
}); });
addAlert(t("policyDeletedSuccess"), AlertVariant.success); addAlert(t("policyDeletedSuccess"), AlertVariant.success);
history.push(toClient({ realm, clientId: id, tab: "authorization" })); history.push(
toAuthorizationTab({ realm, clientId: id, tab: "policies" })
);
} catch (error) { } catch (error) {
addError("clients:policyDeletedError", error); addError("clients:policyDeletedError", error);
} }
@ -212,10 +214,10 @@ export default function PolicyDetails() {
component={(props) => ( component={(props) => (
<Link <Link
{...props} {...props}
to={toClient({ to={toAuthorizationTab({
realm, realm,
clientId: id, clientId: id,
tab: "authorization", tab: "policies",
})} })}
/> />
)} )}

View file

@ -5,6 +5,8 @@ import { ClientsRoute } from "./routes/Clients";
import { CreateInitialAccessTokenRoute } from "./routes/CreateInitialAccessToken"; import { CreateInitialAccessTokenRoute } from "./routes/CreateInitialAccessToken";
import { ImportClientRoute } from "./routes/ImportClient"; import { ImportClientRoute } from "./routes/ImportClient";
import { MapperRoute } from "./routes/Mapper"; import { MapperRoute } from "./routes/Mapper";
import { ClientScopesRoute } from "./routes/ClientScopeTab";
import { AuthorizationRoute } from "./routes/AuthenticationTab";
import { NewResourceRoute } from "./routes/NewResource"; import { NewResourceRoute } from "./routes/NewResource";
import { ResourceDetailsRoute } from "./routes/Resource"; import { ResourceDetailsRoute } from "./routes/Resource";
import { NewScopeRoute } from "./routes/NewScope"; import { NewScopeRoute } from "./routes/NewScope";
@ -21,6 +23,8 @@ const routes: RouteDef[] = [
CreateInitialAccessTokenRoute, CreateInitialAccessTokenRoute,
ClientRoute, ClientRoute,
MapperRoute, MapperRoute,
ClientScopesRoute,
AuthorizationRoute,
NewResourceRoute, NewResourceRoute,
ResourceDetailsRoute, ResourceDetailsRoute,
NewScopeRoute, NewScopeRoute,

View file

@ -0,0 +1,30 @@
import type { LocationDescriptorObject } from "history";
import { lazy } from "react";
import { generatePath } from "react-router-dom";
import type { RouteDef } from "../../route-config";
export type AuthorizationTab =
| "settings"
| "resources"
| "scopes"
| "policies"
| "permissions"
| "evaluate";
export type AuthorizationParams = {
realm: string;
clientId: string;
tab: AuthorizationTab;
};
export const AuthorizationRoute: RouteDef = {
path: "/:realm/clients/:clientId/authorization/:tab",
component: lazy(() => import("../ClientDetails")),
breadcrumb: (t) => t("clients:clientSettings"),
access: "view-clients",
};
export const toAuthorizationTab = (
params: AuthorizationParams
): LocationDescriptorObject => ({
pathname: generatePath(AuthorizationRoute.path, params),
});

View file

@ -5,11 +5,14 @@ import type { RouteDef } from "../../route-config";
export type ClientTab = export type ClientTab =
| "settings" | "settings"
| "keys"
| "credentials"
| "roles" | "roles"
| "clientScopes" | "clientScopes"
| "advanced" | "advanced"
| "mappers" | "mappers"
| "authorization"; | "authorization"
| "serviceAccount";
export type ClientParams = { export type ClientParams = {
realm: string; realm: string;

View file

@ -0,0 +1,24 @@
import type { LocationDescriptorObject } from "history";
import { lazy } from "react";
import { generatePath } from "react-router-dom";
import type { RouteDef } from "../../route-config";
export type ClientScopesTab = "setup" | "evaluate";
export type ClientScopesParams = {
realm: string;
clientId: string;
tab: ClientScopesTab;
};
export const ClientScopesRoute: RouteDef = {
path: "/:realm/clients/:clientId/clientScopes/:tab",
component: lazy(() => import("../ClientDetails")),
breadcrumb: (t) => t("clients:clientSettings"),
access: "view-clients",
};
export const toClientScopesTab = (
params: ClientScopesParams
): LocationDescriptorObject => ({
pathname: generatePath(ClientScopesRoute.path, params),
});