Split out role form for realm and client in seperate components (#4141)
This commit is contained in:
parent
84da38789d
commit
b4fef326de
13 changed files with 287 additions and 223 deletions
|
@ -243,13 +243,6 @@ describe("Realm roles test", () => {
|
|||
createRealmRolePage.checkDescription(updateDescription);
|
||||
});
|
||||
|
||||
it("should revert realm role", () => {
|
||||
listingPage.itemExist(editRoleName).goToItemDetails(editRoleName);
|
||||
createRealmRolePage.checkDescription(updateDescription);
|
||||
createRealmRolePage.updateDescription("going to revert").cancel();
|
||||
createRealmRolePage.checkDescription(updateDescription);
|
||||
});
|
||||
|
||||
const keyValue = new KeyValueInput("attributes");
|
||||
it("should add attribute", () => {
|
||||
listingPage.itemExist(editRoleName).goToItemDetails(editRoleName);
|
||||
|
|
|
@ -93,9 +93,8 @@ export default class ProviderPage {
|
|||
private mappersTab = "ldap-mappers-tab";
|
||||
private rolesTab = "rolesTab";
|
||||
private createRoleBtn = "no-roles-for-this-client-empty-action";
|
||||
private realmRolesSaveBtn = "realm-roles-save-button";
|
||||
private roleSaveBtn = "save";
|
||||
private roleNameField = "#kc-name";
|
||||
private clientIdSelect = "#client\\.id-select-typeahead";
|
||||
|
||||
private groupName = "aa-uf-mappers-group";
|
||||
private clientName = "aa-uf-mappers-client";
|
||||
|
@ -313,7 +312,7 @@ export default class ProviderPage {
|
|||
cy.wait(1000);
|
||||
cy.get(this.roleNameField).clear().type(roleName);
|
||||
cy.wait(1000);
|
||||
cy.findByTestId(this.realmRolesSaveBtn).click();
|
||||
cy.findByTestId(this.roleSaveBtn).click();
|
||||
cy.wait(1000);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
class CreateRealmRolePage {
|
||||
private realmRoleNameInput = "#kc-name";
|
||||
private realmRoleNameError = "#kc-name-helper";
|
||||
private realmRoleDescriptionInput = "#kc-role-description";
|
||||
private saveBtn = "realm-roles-save-button";
|
||||
private realmRoleDescriptionInput = "#kc-description";
|
||||
private saveBtn = "save";
|
||||
private cancelBtn = "cancel";
|
||||
|
||||
//#region General Settings
|
||||
|
|
70
apps/admin-ui/src/clients/roles/CreateClientRole.tsx
Normal file
70
apps/admin-ui/src/clients/roles/CreateClientRole.tsx
Normal file
|
@ -0,0 +1,70 @@
|
|||
import type RoleRepresentation from "@keycloak/keycloak-admin-client/lib/defs/roleRepresentation";
|
||||
import { AlertVariant } from "@patternfly/react-core";
|
||||
import { SubmitHandler, useForm } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useNavigate, useParams } from "react-router-dom-v5-compat";
|
||||
|
||||
import { useAlerts } from "../../components/alert/Alerts";
|
||||
import { AttributeForm } from "../../components/key-value-form/AttributeForm";
|
||||
import { RoleForm } from "../../components/role-form/RoleForm";
|
||||
import { useAdminClient } from "../../context/auth/AdminClient";
|
||||
import { useRealm } from "../../context/realm-context/RealmContext";
|
||||
import { toClientRole } from "../../realm-roles/routes/ClientRole";
|
||||
import { toClient } from "../routes/Client";
|
||||
import { NewRoleParams } from "../routes/NewRole";
|
||||
|
||||
export default function CreateClientRole() {
|
||||
const { t } = useTranslation("roles");
|
||||
const form = useForm<AttributeForm>({ mode: "onChange" });
|
||||
const navigate = useNavigate();
|
||||
const { clientId } = useParams<NewRoleParams>();
|
||||
const { adminClient } = useAdminClient();
|
||||
const { realm } = useRealm();
|
||||
const { addAlert, addError } = useAlerts();
|
||||
|
||||
const onSubmit: SubmitHandler<AttributeForm> = async (formValues) => {
|
||||
const role: RoleRepresentation = {
|
||||
...formValues,
|
||||
name: formValues.name?.trim(),
|
||||
attributes: {},
|
||||
};
|
||||
|
||||
try {
|
||||
await adminClient.clients.createRole({
|
||||
id: clientId,
|
||||
...role,
|
||||
});
|
||||
|
||||
const createdRole = await adminClient.clients.findRole({
|
||||
id: clientId!,
|
||||
roleName: role.name!,
|
||||
});
|
||||
|
||||
addAlert(t("roleCreated"), AlertVariant.success);
|
||||
navigate(
|
||||
toClientRole({
|
||||
realm,
|
||||
clientId: clientId!,
|
||||
id: createdRole.id!,
|
||||
tab: "details",
|
||||
})
|
||||
);
|
||||
} catch (error) {
|
||||
addError("roles:roleCreateError", error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<RoleForm
|
||||
form={form}
|
||||
onSubmit={onSubmit}
|
||||
cancelLink={toClient({
|
||||
realm,
|
||||
clientId: clientId!,
|
||||
tab: "roles",
|
||||
})}
|
||||
role="manage-clients"
|
||||
editMode={false}
|
||||
/>
|
||||
);
|
||||
}
|
|
@ -12,6 +12,7 @@ import {
|
|||
ResourceDetailsRoute,
|
||||
ResourceDetailsWithResourceIdRoute,
|
||||
} from "./routes/Resource";
|
||||
import { NewRoleRoute } from "./routes/NewRole";
|
||||
import { NewScopeRoute } from "./routes/NewScope";
|
||||
import {
|
||||
ScopeDetailsRoute,
|
||||
|
@ -44,6 +45,7 @@ const routes: RouteDef[] = [
|
|||
NewResourceRoute,
|
||||
ResourceDetailsRoute,
|
||||
ResourceDetailsWithResourceIdRoute,
|
||||
NewRoleRoute,
|
||||
NewScopeRoute,
|
||||
ScopeDetailsRoute,
|
||||
ScopeDetailsWithScopeIdRoute,
|
||||
|
|
17
apps/admin-ui/src/clients/routes/NewRole.ts
Normal file
17
apps/admin-ui/src/clients/routes/NewRole.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { lazy } from "react";
|
||||
import type { Path } from "react-router-dom-v5-compat";
|
||||
import { generatePath } from "react-router-dom-v5-compat";
|
||||
import type { RouteDef } from "../../route-config";
|
||||
|
||||
export type NewRoleParams = { realm: string; clientId: string };
|
||||
|
||||
export const NewRoleRoute: RouteDef = {
|
||||
path: "/:realm/clients/:clientId/roles/new",
|
||||
component: lazy(() => import("../roles/CreateClientRole")),
|
||||
breadcrumb: (t) => t("roles:createRole"),
|
||||
access: "manage-clients",
|
||||
};
|
||||
|
||||
export const toCreateRole = (params: NewRoleParams): Partial<Path> => ({
|
||||
pathname: generatePath(NewRoleRoute.path, params),
|
||||
});
|
|
@ -5,32 +5,32 @@ import {
|
|||
PageSection,
|
||||
ValidatedOptions,
|
||||
} from "@patternfly/react-core";
|
||||
import type { SubmitHandler, UseFormMethods } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import type { UseFormMethods } from "react-hook-form";
|
||||
import { ViewHeader } from "../components/view-header/ViewHeader";
|
||||
import { FormAccess } from "../components/form-access/FormAccess";
|
||||
import type { AttributeForm } from "../components/key-value-form/AttributeForm";
|
||||
import { KeycloakTextInput } from "../components/keycloak-text-input/KeycloakTextInput";
|
||||
import { KeycloakTextArea } from "../components/keycloak-text-area/KeycloakTextArea";
|
||||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
import { useNavigate } from "react-router-dom-v5-compat";
|
||||
import { Link, To } from "react-router-dom-v5-compat";
|
||||
|
||||
export type RealmRoleFormProps = {
|
||||
import { FormAccess } from "../form-access/FormAccess";
|
||||
import type { AttributeForm } from "../key-value-form/AttributeForm";
|
||||
import { KeycloakTextArea } from "../keycloak-text-area/KeycloakTextArea";
|
||||
import { KeycloakTextInput } from "../keycloak-text-input/KeycloakTextInput";
|
||||
import { ViewHeader } from "../view-header/ViewHeader";
|
||||
|
||||
export type RoleFormProps = {
|
||||
form: UseFormMethods<AttributeForm>;
|
||||
save: () => void;
|
||||
onSubmit: SubmitHandler<AttributeForm>;
|
||||
cancelLink: To;
|
||||
role: "manage-realm" | "manage-clients";
|
||||
editMode: boolean;
|
||||
reset: () => void;
|
||||
};
|
||||
|
||||
export const RealmRoleForm = ({
|
||||
export const RoleForm = ({
|
||||
form: { handleSubmit, errors, register, getValues },
|
||||
save,
|
||||
onSubmit,
|
||||
cancelLink,
|
||||
role,
|
||||
editMode,
|
||||
reset,
|
||||
}: RealmRoleFormProps) => {
|
||||
}: RoleFormProps) => {
|
||||
const { t } = useTranslation("roles");
|
||||
const navigate = useNavigate();
|
||||
const { realm: realmName } = useRealm();
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -38,26 +38,27 @@ export const RealmRoleForm = ({
|
|||
<PageSection variant="light">
|
||||
<FormAccess
|
||||
isHorizontal
|
||||
onSubmit={handleSubmit(save)}
|
||||
role="manage-realm"
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
role={role}
|
||||
className="pf-u-mt-lg"
|
||||
>
|
||||
<FormGroup
|
||||
label={t("roleName")}
|
||||
fieldId="kc-name"
|
||||
isRequired
|
||||
validated={errors.name ? "error" : "default"}
|
||||
validated={
|
||||
errors.name ? ValidatedOptions.error : ValidatedOptions.default
|
||||
}
|
||||
helperTextInvalid={t("common:required")}
|
||||
isRequired={!editMode}
|
||||
>
|
||||
<KeycloakTextInput
|
||||
id="kc-name"
|
||||
name="name"
|
||||
ref={register({
|
||||
required: !editMode,
|
||||
validate: (value: string) =>
|
||||
!!value.trim() || t("common:required").toString(),
|
||||
})}
|
||||
type="text"
|
||||
id="kc-name"
|
||||
name="name"
|
||||
isReadOnly={editMode}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
@ -72,40 +73,32 @@ export const RealmRoleForm = ({
|
|||
helperTextInvalid={errors.description?.message}
|
||||
>
|
||||
<KeycloakTextArea
|
||||
id="kc-description"
|
||||
name="description"
|
||||
aria-label="description"
|
||||
isDisabled={getValues().name?.includes("default-roles")}
|
||||
ref={register({
|
||||
maxLength: {
|
||||
value: 255,
|
||||
message: t("common:maxLength", { length: 255 }),
|
||||
},
|
||||
})}
|
||||
type="text"
|
||||
validated={
|
||||
errors.description
|
||||
? ValidatedOptions.error
|
||||
: ValidatedOptions.default
|
||||
}
|
||||
id="kc-role-description"
|
||||
isDisabled={getValues().name?.includes("default-roles")}
|
||||
/>
|
||||
</FormGroup>
|
||||
<ActionGroup>
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={save}
|
||||
data-testid="realm-roles-save-button"
|
||||
>
|
||||
<Button data-testid="save" type="submit" variant="primary">
|
||||
{t("common:save")}
|
||||
</Button>
|
||||
<Button
|
||||
data-testid="cancel"
|
||||
onClick={() =>
|
||||
editMode ? reset() : navigate(`/${realmName}/roles`)
|
||||
}
|
||||
variant="link"
|
||||
component={(props) => <Link {...props} to={cancelLink} />}
|
||||
>
|
||||
{editMode ? t("common:revert") : t("common:cancel")}
|
||||
{t("common:cancel")}
|
||||
</Button>
|
||||
</ActionGroup>
|
||||
</FormAccess>
|
57
apps/admin-ui/src/realm-roles/CreateRealmRole.tsx
Normal file
57
apps/admin-ui/src/realm-roles/CreateRealmRole.tsx
Normal file
|
@ -0,0 +1,57 @@
|
|||
import type RoleRepresentation from "@keycloak/keycloak-admin-client/lib/defs/roleRepresentation";
|
||||
import { AlertVariant } from "@patternfly/react-core";
|
||||
import { SubmitHandler, useForm } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useNavigate } from "react-router-dom-v5-compat";
|
||||
|
||||
import { useAlerts } from "../components/alert/Alerts";
|
||||
import { AttributeForm } from "../components/key-value-form/AttributeForm";
|
||||
import { RoleForm } from "../components/role-form/RoleForm";
|
||||
import { useAdminClient } from "../context/auth/AdminClient";
|
||||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
import { toRealmRole } from "./routes/RealmRole";
|
||||
import { toRealmRoles } from "./routes/RealmRoles";
|
||||
|
||||
export default function CreateRealmRole() {
|
||||
const { t } = useTranslation("roles");
|
||||
const form = useForm<AttributeForm>({ mode: "onChange" });
|
||||
const navigate = useNavigate();
|
||||
const { adminClient } = useAdminClient();
|
||||
const { realm } = useRealm();
|
||||
const { addAlert, addError } = useAlerts();
|
||||
|
||||
const onSubmit: SubmitHandler<AttributeForm> = async (formValues) => {
|
||||
const role: RoleRepresentation = {
|
||||
...formValues,
|
||||
name: formValues.name?.trim(),
|
||||
attributes: {},
|
||||
};
|
||||
|
||||
try {
|
||||
await adminClient.roles.create(role);
|
||||
|
||||
const createdRole = await adminClient.roles.findOneByName({
|
||||
name: formValues.name!,
|
||||
});
|
||||
|
||||
if (!createdRole) {
|
||||
throw new Error(t("common:notFound"));
|
||||
}
|
||||
|
||||
addAlert(t("roleCreated"), AlertVariant.success);
|
||||
navigate(toRealmRole({ realm, id: createdRole.id!, tab: "details" }));
|
||||
} catch (error) {
|
||||
addError("roles:roleCreateError", error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<RoleForm
|
||||
form={form}
|
||||
onSubmit={onSubmit}
|
||||
cancelLink={toRealmRoles({ realm })}
|
||||
role="manage-realm"
|
||||
editMode={false}
|
||||
/>
|
||||
);
|
||||
}
|
|
@ -10,11 +10,12 @@ import {
|
|||
} from "@patternfly/react-core";
|
||||
import { omit } from "lodash-es";
|
||||
import { useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { SubmitHandler, useForm } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useRouteMatch } from "react-router-dom";
|
||||
import { useNavigate } from "react-router-dom-v5-compat";
|
||||
|
||||
import { toClient } from "../clients/routes/Client";
|
||||
import { useAlerts } from "../components/alert/Alerts";
|
||||
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
|
||||
import {
|
||||
|
@ -28,6 +29,7 @@ import {
|
|||
import { KeycloakSpinner } from "../components/keycloak-spinner/KeycloakSpinner";
|
||||
import { KeycloakTabs } from "../components/keycloak-tabs/KeycloakTabs";
|
||||
import { PermissionsTab } from "../components/permission-tab/PermissionTab";
|
||||
import { RoleForm } from "../components/role-form/RoleForm";
|
||||
import { AddRoleMappingModal } from "../components/role-mapping/AddRoleMappingModal";
|
||||
import { RoleMapping } from "../components/role-mapping/RoleMapping";
|
||||
import { ViewHeader } from "../components/view-header/ViewHeader";
|
||||
|
@ -35,13 +37,13 @@ import { useAdminClient, useFetch } from "../context/auth/AdminClient";
|
|||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
import { useServerInfo } from "../context/server-info/ServerInfoProvider";
|
||||
import { useParams } from "../utils/useParams";
|
||||
import { RealmRoleForm } from "./RealmRoleForm";
|
||||
import {
|
||||
ClientRoleParams,
|
||||
ClientRoleRoute,
|
||||
toClientRole,
|
||||
} from "./routes/ClientRole";
|
||||
import { toRealmRole } from "./routes/RealmRole";
|
||||
import { toRealmRoles } from "./routes/RealmRoles";
|
||||
import { UsersInRoleTab } from "./UsersInRoleTab";
|
||||
|
||||
export default function RealmRoleTabs() {
|
||||
|
@ -49,7 +51,7 @@ export default function RealmRoleTabs() {
|
|||
const form = useForm<AttributeForm>({
|
||||
mode: "onChange",
|
||||
});
|
||||
const { setValue, getValues, trigger, reset } = form;
|
||||
const { setValue, reset } = form;
|
||||
const navigate = useNavigate();
|
||||
|
||||
const { adminClient } = useAdminClient();
|
||||
|
@ -84,104 +86,67 @@ export default function RealmRoleTabs() {
|
|||
|
||||
useFetch(
|
||||
async () => {
|
||||
const realm = await adminClient.realms.findOne({ realm: realmName });
|
||||
if (!id) {
|
||||
return { realm };
|
||||
}
|
||||
const role = await adminClient.roles.findOneById({ id });
|
||||
const [realm, role] = await Promise.all([
|
||||
adminClient.realms.findOne({ realm: realmName }),
|
||||
adminClient.roles.findOneById({ id }),
|
||||
]);
|
||||
|
||||
return { realm, role };
|
||||
},
|
||||
({ realm, role }) => {
|
||||
if (!realm || (!role && id)) {
|
||||
if (!realm || !role) {
|
||||
throw new Error(t("common:notFound"));
|
||||
}
|
||||
|
||||
setRealm(realm);
|
||||
const convertedRole = convert(role);
|
||||
|
||||
if (role) {
|
||||
const convertedRole = convert(role);
|
||||
setRole(convertedRole);
|
||||
Object.entries(convertedRole).map((entry) => {
|
||||
setValue(entry[0], entry[1]);
|
||||
});
|
||||
}
|
||||
setRealm(realm);
|
||||
setRole(convertedRole);
|
||||
|
||||
Object.entries(convertedRole).map((entry) => {
|
||||
setValue(entry[0], entry[1]);
|
||||
});
|
||||
},
|
||||
[key, url]
|
||||
);
|
||||
|
||||
const save = async () => {
|
||||
const onSubmit: SubmitHandler<AttributeForm> = async (formValues) => {
|
||||
try {
|
||||
const values = getValues();
|
||||
if (
|
||||
values.attributes &&
|
||||
values.attributes[values.attributes.length - 1]?.key === ""
|
||||
formValues.attributes &&
|
||||
formValues.attributes[formValues.attributes.length - 1]?.key === ""
|
||||
) {
|
||||
setValue(
|
||||
"attributes",
|
||||
values.attributes.slice(0, values.attributes.length - 1)
|
||||
formValues.attributes.slice(0, formValues.attributes.length - 1)
|
||||
);
|
||||
}
|
||||
if (!(await trigger())) {
|
||||
return;
|
||||
}
|
||||
const { attributes, ...rest } = values;
|
||||
|
||||
const { attributes, ...rest } = formValues;
|
||||
let roleRepresentation: RoleRepresentation = rest;
|
||||
|
||||
roleRepresentation.name = roleRepresentation.name?.trim();
|
||||
|
||||
if (id) {
|
||||
if (attributes) {
|
||||
roleRepresentation.attributes = keyValueToArray(attributes);
|
||||
}
|
||||
roleRepresentation = {
|
||||
...omit(role!, "attributes"),
|
||||
...roleRepresentation,
|
||||
};
|
||||
if (!clientId) {
|
||||
await adminClient.roles.updateById({ id }, roleRepresentation);
|
||||
} else {
|
||||
await adminClient.clients.updateRole(
|
||||
{ id: clientId, roleName: values.name! },
|
||||
roleRepresentation
|
||||
);
|
||||
}
|
||||
|
||||
setRole(convert(roleRepresentation));
|
||||
if (attributes) {
|
||||
roleRepresentation.attributes = keyValueToArray(attributes);
|
||||
}
|
||||
roleRepresentation = {
|
||||
...omit(role!, "attributes"),
|
||||
...roleRepresentation,
|
||||
};
|
||||
if (!clientId) {
|
||||
await adminClient.roles.updateById({ id }, roleRepresentation);
|
||||
} else {
|
||||
let createdRole;
|
||||
if (!clientId) {
|
||||
await adminClient.roles.create(roleRepresentation);
|
||||
createdRole = await adminClient.roles.findOneByName({
|
||||
name: values.name!,
|
||||
});
|
||||
} else {
|
||||
await adminClient.clients.createRole({
|
||||
id: clientId,
|
||||
name: values.name,
|
||||
});
|
||||
if (values.description) {
|
||||
await adminClient.clients.updateRole(
|
||||
{ id: clientId, roleName: values.name! },
|
||||
roleRepresentation
|
||||
);
|
||||
}
|
||||
createdRole = await adminClient.clients.findRole({
|
||||
id: clientId,
|
||||
roleName: values.name!,
|
||||
});
|
||||
}
|
||||
if (!createdRole) {
|
||||
throw new Error(t("common:notFound"));
|
||||
}
|
||||
|
||||
setRole(convert(createdRole));
|
||||
navigate(
|
||||
url.substr(0, url.lastIndexOf("/") + 1) + createdRole.id + "/details"
|
||||
await adminClient.clients.updateRole(
|
||||
{ id: clientId, roleName: formValues.name! },
|
||||
roleRepresentation
|
||||
);
|
||||
}
|
||||
addAlert(t(id ? "roleSaveSuccess" : "roleCreated"), AlertVariant.success);
|
||||
|
||||
setRole(convert(roleRepresentation));
|
||||
addAlert(t("roleSaveSuccess"), AlertVariant.success);
|
||||
} catch (error) {
|
||||
addError(`roles:${id ? "roleSave" : "roleCreate"}Error`, error);
|
||||
addError("roles:roleSaveError", error);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -199,7 +164,7 @@ export default function RealmRoleTabs() {
|
|||
} else {
|
||||
await adminClient.clients.delRole({
|
||||
id: clientId,
|
||||
roleName: role!.name as string,
|
||||
roleName: role!.name!,
|
||||
});
|
||||
}
|
||||
addAlert(t("roleDeletedSuccess"), AlertVariant.success);
|
||||
|
@ -328,19 +293,9 @@ export default function RealmRoleTabs() {
|
|||
|
||||
const isDefaultRole = (name: string) => realm?.defaultRole!.name === name;
|
||||
|
||||
if (!realm) {
|
||||
if (!realm || !role) {
|
||||
return <KeycloakSpinner />;
|
||||
}
|
||||
if (!role) {
|
||||
return (
|
||||
<RealmRoleForm
|
||||
reset={() => reset(role)}
|
||||
form={form}
|
||||
save={save}
|
||||
editMode={false}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -356,7 +311,7 @@ export default function RealmRoleTabs() {
|
|||
/>
|
||||
)}
|
||||
<ViewHeader
|
||||
titleKey={role.name || t("createRole")}
|
||||
titleKey={role.name!}
|
||||
badges={[
|
||||
{
|
||||
id: "composite-role-badge",
|
||||
|
@ -364,73 +319,75 @@ export default function RealmRoleTabs() {
|
|||
readonly: true,
|
||||
},
|
||||
]}
|
||||
subKey={id ? "" : "roles:roleCreateExplain"}
|
||||
actionsDropdownId="roles-actions-dropdown"
|
||||
dropdownItems={dropdownItems}
|
||||
divider={!id}
|
||||
divider={false}
|
||||
/>
|
||||
<PageSection variant="light" className="pf-u-p-0">
|
||||
{id && (
|
||||
<KeycloakTabs isBox mountOnEnter>
|
||||
<KeycloakTabs isBox mountOnEnter>
|
||||
<Tab
|
||||
eventKey="details"
|
||||
title={<TabTitleText>{t("common:details")}</TabTitleText>}
|
||||
>
|
||||
<RoleForm
|
||||
form={form}
|
||||
onSubmit={onSubmit}
|
||||
role={clientRoleRouteMatch ? "manage-clients" : "manage-realm"}
|
||||
cancelLink={
|
||||
clientRoleRouteMatch
|
||||
? toClient({ realm: realmName, clientId, tab: "roles" })
|
||||
: toRealmRoles({ realm: realmName })
|
||||
}
|
||||
editMode={true}
|
||||
/>
|
||||
</Tab>
|
||||
{role.composite && (
|
||||
<Tab
|
||||
eventKey="details"
|
||||
title={<TabTitleText>{t("common:details")}</TabTitleText>}
|
||||
eventKey="associated-roles"
|
||||
className="kc-associated-roles-tab"
|
||||
title={<TabTitleText>{t("associatedRolesText")}</TabTitleText>}
|
||||
>
|
||||
<RealmRoleForm
|
||||
reset={() => reset(role)}
|
||||
form={form}
|
||||
save={save}
|
||||
editMode={true}
|
||||
<RoleMapping
|
||||
name={role.name!}
|
||||
id={role.id!}
|
||||
type="roles"
|
||||
isManager
|
||||
save={(rows) => addComposites(rows.map((r) => r.role))}
|
||||
/>
|
||||
</Tab>
|
||||
{role.composite && (
|
||||
<Tab
|
||||
eventKey="associated-roles"
|
||||
className="kc-associated-roles-tab"
|
||||
title={<TabTitleText>{t("associatedRolesText")}</TabTitleText>}
|
||||
>
|
||||
<RoleMapping
|
||||
name={role.name!}
|
||||
id={role.id!}
|
||||
type="roles"
|
||||
isManager
|
||||
save={(rows) => addComposites(rows.map((r) => r.role))}
|
||||
/>
|
||||
</Tab>
|
||||
)}
|
||||
{!isDefaultRole(role.name!) && (
|
||||
<Tab
|
||||
eventKey="attributes"
|
||||
className="kc-attributes-tab"
|
||||
title={<TabTitleText>{t("common:attributes")}</TabTitleText>}
|
||||
>
|
||||
<AttributesForm
|
||||
form={form}
|
||||
save={save}
|
||||
reset={() => reset(role)}
|
||||
/>
|
||||
</Tab>
|
||||
)}
|
||||
{!isDefaultRole(role.name!) && (
|
||||
<Tab
|
||||
eventKey="users-in-role"
|
||||
title={<TabTitleText>{t("usersInRole")}</TabTitleText>}
|
||||
>
|
||||
<UsersInRoleTab data-cy="users-in-role-tab" />
|
||||
</Tab>
|
||||
)}
|
||||
{!profileInfo?.disabledFeatures?.includes(
|
||||
"ADMIN_FINE_GRAINED_AUTHZ"
|
||||
) && (
|
||||
<Tab
|
||||
eventKey="permissions"
|
||||
title={<TabTitleText>{t("common:permissions")}</TabTitleText>}
|
||||
>
|
||||
<PermissionsTab id={role.id} type="roles" />
|
||||
</Tab>
|
||||
)}
|
||||
</KeycloakTabs>
|
||||
)}
|
||||
)}
|
||||
{!isDefaultRole(role.name!) && (
|
||||
<Tab
|
||||
eventKey="attributes"
|
||||
className="kc-attributes-tab"
|
||||
title={<TabTitleText>{t("common:attributes")}</TabTitleText>}
|
||||
>
|
||||
<AttributesForm
|
||||
form={form}
|
||||
save={onSubmit}
|
||||
reset={() => reset(role)}
|
||||
/>
|
||||
</Tab>
|
||||
)}
|
||||
{!isDefaultRole(role.name!) && (
|
||||
<Tab
|
||||
eventKey="users-in-role"
|
||||
title={<TabTitleText>{t("usersInRole")}</TabTitleText>}
|
||||
>
|
||||
<UsersInRoleTab data-cy="users-in-role-tab" />
|
||||
</Tab>
|
||||
)}
|
||||
{!profileInfo?.disabledFeatures?.includes(
|
||||
"ADMIN_FINE_GRAINED_AUTHZ"
|
||||
) && (
|
||||
<Tab
|
||||
eventKey="permissions"
|
||||
title={<TabTitleText>{t("common:permissions")}</TabTitleText>}
|
||||
>
|
||||
<PermissionsTab id={role.id} type="roles" />
|
||||
</Tab>
|
||||
)}
|
||||
</KeycloakTabs>
|
||||
</PageSection>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -116,7 +116,7 @@ export const RolesList = ({
|
|||
},
|
||||
});
|
||||
|
||||
const goToCreate = () => navigate(`${url}/add-role`);
|
||||
const goToCreate = () => navigate(`${url}/new`);
|
||||
|
||||
if (!realm) {
|
||||
return <KeycloakSpinner />;
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
import type { RouteDef } from "../route-config";
|
||||
import { AddRoleRoute } from "./routes/AddRole";
|
||||
import { AddRoleToClientRoute } from "./routes/AddRoleToClient";
|
||||
import { ClientRoleRoute, ClientRoleRouteWithTab } from "./routes/ClientRole";
|
||||
import { RealmRoleRoute, RealmRoleRouteWithTab } from "./routes/RealmRole";
|
||||
import { RealmRolesRoute } from "./routes/RealmRoles";
|
||||
|
||||
const routes: RouteDef[] = [
|
||||
AddRoleToClientRoute,
|
||||
ClientRoleRoute,
|
||||
ClientRoleRouteWithTab,
|
||||
RealmRolesRoute,
|
||||
|
|
|
@ -6,8 +6,8 @@ import type { RouteDef } from "../../route-config";
|
|||
export type AddRoleParams = { realm: string };
|
||||
|
||||
export const AddRoleRoute: RouteDef = {
|
||||
path: "/:realm/roles/add-role",
|
||||
component: lazy(() => import("../RealmRoleTabs")),
|
||||
path: "/:realm/roles/new",
|
||||
component: lazy(() => import("../CreateRealmRole")),
|
||||
breadcrumb: (t) => t("roles:createRole"),
|
||||
access: "manage-realm",
|
||||
};
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
import { lazy } from "react";
|
||||
import type { Path } from "react-router-dom-v5-compat";
|
||||
import { generatePath } from "react-router-dom-v5-compat";
|
||||
import type { RouteDef } from "../../route-config";
|
||||
|
||||
export type AddRoleToClientParams = {
|
||||
realm: string;
|
||||
clientId: string;
|
||||
};
|
||||
|
||||
export const AddRoleToClientRoute: RouteDef = {
|
||||
path: "/:realm/clients/:clientId/roles/add-role",
|
||||
component: lazy(() => import("../RealmRoleTabs")),
|
||||
breadcrumb: (t) => t("roles:createRole"),
|
||||
access: "manage-realm",
|
||||
};
|
||||
|
||||
export const toAddRoleToClient = (
|
||||
params: AddRoleToClientParams
|
||||
): Partial<Path> => ({
|
||||
pathname: generatePath(AddRoleToClientRoute.path, params),
|
||||
});
|
Loading…
Reference in a new issue