Added permissions tab for idp (#2597)
This commit is contained in:
parent
5427eaf6ff
commit
e1639f3283
6 changed files with 116 additions and 42 deletions
85
package-lock.json
generated
85
package-lock.json
generated
|
@ -7,7 +7,7 @@
|
|||
"name": "keycloak-admin-ui",
|
||||
"license": "Apache",
|
||||
"dependencies": {
|
||||
"@keycloak/keycloak-admin-client": "^19.0.0-dev.0",
|
||||
"@keycloak/keycloak-admin-client": "^19.0.0-dev.3",
|
||||
"@patternfly/patternfly": "^4.185.1",
|
||||
"@patternfly/react-code-editor": "^4.43.16",
|
||||
"@patternfly/react-core": "^4.202.16",
|
||||
|
@ -3567,11 +3567,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@keycloak/keycloak-admin-client": {
|
||||
"version": "19.0.0-dev.0",
|
||||
"resolved": "https://registry.npmjs.org/@keycloak/keycloak-admin-client/-/keycloak-admin-client-19.0.0-dev.0.tgz",
|
||||
"integrity": "sha512-QkCPuWUxf0rVw/V24VoaLC4luDLePGScyT12pVYaujZX9VaWQTNdZS3Ipm47W2+kNQQvL2NPWxKkWJmEWXyMiQ==",
|
||||
"version": "19.0.0-dev.3",
|
||||
"resolved": "https://registry.npmjs.org/@keycloak/keycloak-admin-client/-/keycloak-admin-client-19.0.0-dev.3.tgz",
|
||||
"integrity": "sha512-L484+2mDOYGhIXJqIS+zQ1LmJfawrf40nfjNOV9x8kThtpnf0te7zy7am8yDHJlDcTZv66PLu9DotF8t8kdKEw==",
|
||||
"dependencies": {
|
||||
"axios": "^0.26.1",
|
||||
"axios": "^0.27.2",
|
||||
"camelize-ts": "^1.0.8",
|
||||
"keycloak-js": "^18.0.0",
|
||||
"lodash": "^4.17.21",
|
||||
|
@ -6255,8 +6255,7 @@
|
|||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
|
||||
"dev": true
|
||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
|
||||
},
|
||||
"node_modules/at-least-node": {
|
||||
"version": "1.0.0",
|
||||
|
@ -6313,11 +6312,25 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "0.26.1",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz",
|
||||
"integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
|
||||
"integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.14.8"
|
||||
"follow-redirects": "^1.14.9",
|
||||
"form-data": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/axios/node_modules/form-data": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/babel-jest": {
|
||||
|
@ -7943,7 +7956,6 @@
|
|||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
|
@ -9154,7 +9166,6 @@
|
|||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
|
@ -10859,9 +10870,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.14.9",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz",
|
||||
"integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==",
|
||||
"version": "1.15.0",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.0.tgz",
|
||||
"integrity": "sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
|
@ -25452,11 +25463,11 @@
|
|||
}
|
||||
},
|
||||
"@keycloak/keycloak-admin-client": {
|
||||
"version": "19.0.0-dev.0",
|
||||
"resolved": "https://registry.npmjs.org/@keycloak/keycloak-admin-client/-/keycloak-admin-client-19.0.0-dev.0.tgz",
|
||||
"integrity": "sha512-QkCPuWUxf0rVw/V24VoaLC4luDLePGScyT12pVYaujZX9VaWQTNdZS3Ipm47W2+kNQQvL2NPWxKkWJmEWXyMiQ==",
|
||||
"version": "19.0.0-dev.3",
|
||||
"resolved": "https://registry.npmjs.org/@keycloak/keycloak-admin-client/-/keycloak-admin-client-19.0.0-dev.3.tgz",
|
||||
"integrity": "sha512-L484+2mDOYGhIXJqIS+zQ1LmJfawrf40nfjNOV9x8kThtpnf0te7zy7am8yDHJlDcTZv66PLu9DotF8t8kdKEw==",
|
||||
"requires": {
|
||||
"axios": "^0.26.1",
|
||||
"axios": "^0.27.2",
|
||||
"camelize-ts": "^1.0.8",
|
||||
"keycloak-js": "^18.0.0",
|
||||
"lodash": "^4.17.21",
|
||||
|
@ -27680,8 +27691,7 @@
|
|||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
|
||||
"dev": true
|
||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
|
||||
},
|
||||
"at-least-node": {
|
||||
"version": "1.0.0",
|
||||
|
@ -27723,11 +27733,24 @@
|
|||
"dev": true
|
||||
},
|
||||
"axios": {
|
||||
"version": "0.26.1",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz",
|
||||
"integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
|
||||
"integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
|
||||
"requires": {
|
||||
"follow-redirects": "^1.14.8"
|
||||
"follow-redirects": "^1.14.9",
|
||||
"form-data": "^4.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"form-data": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"babel-jest": {
|
||||
|
@ -29017,7 +29040,6 @@
|
|||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
}
|
||||
|
@ -29976,8 +29998,7 @@
|
|||
"delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
|
||||
"dev": true
|
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
|
||||
},
|
||||
"delegates": {
|
||||
"version": "1.0.0",
|
||||
|
@ -31302,9 +31323,9 @@
|
|||
}
|
||||
},
|
||||
"follow-redirects": {
|
||||
"version": "1.14.9",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz",
|
||||
"integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w=="
|
||||
"version": "1.15.0",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.0.tgz",
|
||||
"integrity": "sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ=="
|
||||
},
|
||||
"for-in": {
|
||||
"version": "1.0.2",
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
"server:import-client": "./scripts/import-client.mjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"@keycloak/keycloak-admin-client": "^19.0.0-dev.0",
|
||||
"@keycloak/keycloak-admin-client": "^19.0.0-dev.3",
|
||||
"@patternfly/patternfly": "^4.185.1",
|
||||
"@patternfly/react-code-editor": "^4.43.16",
|
||||
"@patternfly/react-core": "^4.202.16",
|
||||
|
|
|
@ -93,6 +93,7 @@
|
|||
"clientsPermissionsHint": "Fine grained permissions for administrators that want to manage this client or apply roles defined by this client.",
|
||||
"groupsPermissionsHint": "Determines if fine grained permissions are enabled for managing this role. Disabling will delete all current permissions that have been set up.",
|
||||
"rolesPermissionsHint": "Determines if fine grained permissions are enabled for managing this role. Disabling will delete all current permissions that have been set up.",
|
||||
"identityProvidersPermissionsHint": "Determines if fine grained permissions are enabled for managing this role. Disabling will delete all current permissions that have been set up.",
|
||||
"permissionsScopeName": "Scope-name",
|
||||
"permissionsEnabled": "Permissions enabled",
|
||||
"permissionsDisable": "Disable permissions?",
|
||||
|
@ -126,6 +127,9 @@
|
|||
"map-role-description": "Policies that decide if an administrator can map this role to a user or group",
|
||||
"map-role-client-scope-description": "Policies that decide if an administrator can apply this role to the client scope of a client",
|
||||
"map-role-composite-description": "Policies that decide if an administrator can apply this role as a composite to another role"
|
||||
},
|
||||
"identityProviders": {
|
||||
"token-exchange-description": "Policies that decide which clients are allowed exchange tokens for an external token minted by this identity provider."
|
||||
}
|
||||
},
|
||||
"configure": "Configure",
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, { createContext, FunctionComponent, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { AlertVariant } from "@patternfly/react-core";
|
||||
import axios from "axios";
|
||||
import type { AxiosError } from "axios";
|
||||
|
||||
import useRequiredContext from "../../utils/useRequiredContext";
|
||||
|
@ -42,15 +43,10 @@ export const AlertProvider: FunctionComponent = ({ children }) => {
|
|||
setAlerts([{ key, message, variant, description }, ...alerts]);
|
||||
};
|
||||
|
||||
const addError = (message: string, error: Error | AxiosError) => {
|
||||
const addError = (message: string, error: Error | AxiosError | string) => {
|
||||
addAlert(
|
||||
t(message, {
|
||||
error:
|
||||
"response" in error
|
||||
? error.response?.data?.error_description ||
|
||||
error.response?.data?.errorMessage ||
|
||||
error.response?.data?.error
|
||||
: error,
|
||||
error: getErrorMessage(error),
|
||||
}),
|
||||
AlertVariant.danger
|
||||
);
|
||||
|
@ -63,3 +59,27 @@ export const AlertProvider: FunctionComponent = ({ children }) => {
|
|||
</AlertContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
function getErrorMessage(
|
||||
error: Error | AxiosError<Record<string, unknown>> | string
|
||||
) {
|
||||
if (typeof error === "string") {
|
||||
return error;
|
||||
}
|
||||
|
||||
if (!axios.isAxiosError(error)) {
|
||||
return error.message;
|
||||
}
|
||||
|
||||
const responseData = error.response?.data ?? {};
|
||||
|
||||
for (const key of ["error_description", "errorMessage", "error"]) {
|
||||
const value = responseData[key];
|
||||
|
||||
if (typeof value === "string") {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return error.message;
|
||||
}
|
||||
|
|
|
@ -31,7 +31,12 @@ import { useConfirmDialog } from "../confirm-dialog/ConfirmDialog";
|
|||
|
||||
import "./permissions-tab.css";
|
||||
|
||||
type PermissionScreenType = "clients" | "users" | "groups" | "roles";
|
||||
type PermissionScreenType =
|
||||
| "clients"
|
||||
| "users"
|
||||
| "groups"
|
||||
| "roles"
|
||||
| "identityProviders";
|
||||
|
||||
type PermissionsTabProps = {
|
||||
id?: string;
|
||||
|
@ -63,6 +68,11 @@ export const PermissionsTab = ({ id, type }: PermissionsTabProps) => {
|
|||
return adminClient.groups.updatePermission({ id: id! }, { enabled });
|
||||
case "roles":
|
||||
return adminClient.roles.updatePermission({ id: id! }, { enabled });
|
||||
case "identityProviders":
|
||||
return adminClient.identityProviders.updatePermission(
|
||||
{ alias: id! },
|
||||
{ enabled }
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -85,6 +95,10 @@ export const PermissionsTab = ({ id, type }: PermissionsTabProps) => {
|
|||
return adminClient.groups.listPermissions({ id: id! });
|
||||
case "roles":
|
||||
return adminClient.roles.listPermissions({ id: id! });
|
||||
case "identityProviders":
|
||||
return adminClient.identityProviders.listPermissions({
|
||||
alias: id!,
|
||||
});
|
||||
}
|
||||
})(),
|
||||
]),
|
||||
|
@ -154,7 +168,13 @@ export const PermissionsTab = ({ id, type }: PermissionsTabProps) => {
|
|||
<CardBody>
|
||||
<Trans i18nKey="common:permissionsListIntro">
|
||||
{" "}
|
||||
<strong>{{ realm: `${realm}-realm` }}</strong>.
|
||||
<strong>
|
||||
{{
|
||||
realm:
|
||||
realm === "master" ? "master-realm" : "realm-management",
|
||||
}}
|
||||
</strong>
|
||||
.
|
||||
</Trans>
|
||||
</CardBody>
|
||||
</Card>
|
||||
|
|
|
@ -47,6 +47,7 @@ import {
|
|||
IdentityProviderParams,
|
||||
toIdentityProvider,
|
||||
} from "../routes/IdentityProvider";
|
||||
import { PermissionsTab } from "../../components/permission-tab/PermissionTab";
|
||||
|
||||
type HeaderProps = {
|
||||
onChange: (value: boolean) => void;
|
||||
|
@ -420,6 +421,14 @@ export default function DetailSettings() {
|
|||
]}
|
||||
/>
|
||||
</Tab>
|
||||
<Tab
|
||||
id="permissions"
|
||||
data-testid="permissionsTab"
|
||||
eventKey="permissions"
|
||||
title={<TabTitleText>{t("common:permissions")}</TabTitleText>}
|
||||
>
|
||||
<PermissionsTab id={alias} type="identityProviders" />
|
||||
</Tab>
|
||||
</KeycloakTabs>
|
||||
</FormProvider>
|
||||
</PageSection>
|
||||
|
|
Loading…
Reference in a new issue