Add button on authentication flows (#1119)
This commit is contained in:
parent
0fc832e641
commit
f1f0c362b4
12 changed files with 518 additions and 53 deletions
|
@ -56,4 +56,26 @@ describe("Authentication test", () => {
|
||||||
|
|
||||||
cy.get(".react-flow").should("exist");
|
cy.get(".react-flow").should("exist");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should add a execution", () => {
|
||||||
|
listingPage.goToItemDetails("Copy of browser");
|
||||||
|
detailPage.addExecution(
|
||||||
|
"Copy of browser forms",
|
||||||
|
"console-username-password"
|
||||||
|
);
|
||||||
|
|
||||||
|
masthead.checkNotificationMessage("Flow successfully updated");
|
||||||
|
detailPage.executionExists("Username Password Challenge");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should add a condition", () => {
|
||||||
|
listingPage.goToItemDetails("Copy of browser");
|
||||||
|
detailPage.addCondition(
|
||||||
|
"Copy of browser Browser - Conditional OTP",
|
||||||
|
"conditional-user-role"
|
||||||
|
);
|
||||||
|
|
||||||
|
masthead.checkNotificationMessage("Flow successfully updated");
|
||||||
|
detailPage.executionExists("Username Password Challenge");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -36,4 +36,28 @@ export default class FlowDetails {
|
||||||
cy.get("#diagramView").click();
|
cy.get("#diagramView").click();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private clickEditDropdownForFlow(subFlowName: string, option: string) {
|
||||||
|
cy.getId(`${subFlowName}-edit-dropdown`).click().contains(option).click();
|
||||||
|
}
|
||||||
|
|
||||||
|
addExecution(subFlowName: string, executionTestId: string) {
|
||||||
|
this.clickEditDropdownForFlow(subFlowName, "Add step");
|
||||||
|
|
||||||
|
cy.get(".pf-c-pagination").should("exist");
|
||||||
|
cy.getId(executionTestId).click();
|
||||||
|
cy.getId("modal-add").click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
addCondition(subFlowName: string, executionTestId: string) {
|
||||||
|
this.clickEditDropdownForFlow(subFlowName, "Add condition");
|
||||||
|
|
||||||
|
cy.get(".pf-c-pagination").should("not.exist");
|
||||||
|
cy.getId(executionTestId).click();
|
||||||
|
cy.getId("modal-add").click();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
93
package-lock.json
generated
93
package-lock.json
generated
|
@ -8,7 +8,7 @@
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"license": "Apache",
|
"license": "Apache",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@keycloak/keycloak-admin-client": "^16.0.0-dev.2",
|
"@keycloak/keycloak-admin-client": "^16.0.0-dev.4",
|
||||||
"@patternfly/patternfly": "^4.132.2",
|
"@patternfly/patternfly": "^4.132.2",
|
||||||
"@patternfly/react-core": "4.152.4",
|
"@patternfly/react-core": "4.152.4",
|
||||||
"@patternfly/react-icons": "4.11.14",
|
"@patternfly/react-icons": "4.11.14",
|
||||||
|
@ -2541,9 +2541,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@keycloak/keycloak-admin-client": {
|
"node_modules/@keycloak/keycloak-admin-client": {
|
||||||
"version": "16.0.0-dev.2",
|
"version": "16.0.0-dev.4",
|
||||||
"resolved": "https://registry.npmjs.org/@keycloak/keycloak-admin-client/-/keycloak-admin-client-16.0.0-dev.2.tgz",
|
"resolved": "https://registry.npmjs.org/@keycloak/keycloak-admin-client/-/keycloak-admin-client-16.0.0-dev.4.tgz",
|
||||||
"integrity": "sha512-eLeN4/O5OWjU0fIIvndv0oLSRQN3q0bdMep19E+09/qL4jeNeBR4ltxLKd0mnW1FY53cZJ+QWLaq/lfgRXFfzA==",
|
"integrity": "sha512-8Wp/hqi6TWnt+woxoRwhklPP1SBw+EGzMGQQdErHrkTvfXCd0JFeECRzIZyGcmeFLbvpyLMwLPYFYknC20CENQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^0.21.0",
|
"axios": "^0.21.0",
|
||||||
"camelize": "^1.0.0",
|
"camelize": "^1.0.0",
|
||||||
|
@ -2587,9 +2587,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@npmcli/arborist": {
|
"node_modules/@npmcli/arborist": {
|
||||||
"version": "2.7.1",
|
"version": "2.8.2",
|
||||||
"resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-2.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-2.8.2.tgz",
|
||||||
"integrity": "sha512-EGDHJs6dna/52BrStr/6aaRcMLrYxGbSjT4V3JzvoTBY9/w5i2+1KNepmsG80CAsGADdo6nuNnFwb7sDRm8ZAw==",
|
"integrity": "sha512-6E1XJ0YXBaI9J+25gcTF110MGNx3jv6npr4Rz1U0UAqkuVV7bbDznVJvNqi6F0p8vgrE+Smf9jDTn1DR+7uBjQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@npmcli/installed-package-contents": "^1.0.7",
|
"@npmcli/installed-package-contents": "^1.0.7",
|
||||||
|
@ -2608,10 +2608,10 @@
|
||||||
"mkdirp": "^1.0.4",
|
"mkdirp": "^1.0.4",
|
||||||
"mkdirp-infer-owner": "^2.0.0",
|
"mkdirp-infer-owner": "^2.0.0",
|
||||||
"npm-install-checks": "^4.0.0",
|
"npm-install-checks": "^4.0.0",
|
||||||
"npm-package-arg": "^8.1.0",
|
"npm-package-arg": "^8.1.5",
|
||||||
"npm-pick-manifest": "^6.1.0",
|
"npm-pick-manifest": "^6.1.0",
|
||||||
"npm-registry-fetch": "^11.0.0",
|
"npm-registry-fetch": "^11.0.0",
|
||||||
"pacote": "^11.2.6",
|
"pacote": "^11.3.5",
|
||||||
"parse-conflict-json": "^1.1.1",
|
"parse-conflict-json": "^1.1.1",
|
||||||
"proc-log": "^1.0.0",
|
"proc-log": "^1.0.0",
|
||||||
"promise-all-reject-late": "^1.0.0",
|
"promise-all-reject-late": "^1.0.0",
|
||||||
|
@ -2621,7 +2621,6 @@
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"semver": "^7.3.5",
|
"semver": "^7.3.5",
|
||||||
"ssri": "^8.0.1",
|
"ssri": "^8.0.1",
|
||||||
"tar": "^6.1.0",
|
|
||||||
"treeverse": "^1.0.4",
|
"treeverse": "^1.0.4",
|
||||||
"walk-up-path": "^1.0.0"
|
"walk-up-path": "^1.0.0"
|
||||||
},
|
},
|
||||||
|
@ -8277,6 +8276,20 @@
|
||||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
|
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/fsevents": {
|
||||||
|
"version": "2.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||||
|
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||||
|
"dev": true,
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/function-bind": {
|
"node_modules/function-bind": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
|
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
|
||||||
|
@ -14975,6 +14988,21 @@
|
||||||
"@rollup/plugin-inject": "^4.0.0"
|
"@rollup/plugin-inject": "^4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/rollup/node_modules/fsevents": {
|
||||||
|
"version": "2.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
|
||||||
|
"integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
|
||||||
|
"deprecated": "\"Please update to latest v2.3 or v2.2\"",
|
||||||
|
"dev": true,
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/rsvp": {
|
"node_modules/rsvp": {
|
||||||
"version": "4.8.5",
|
"version": "4.8.5",
|
||||||
"integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==",
|
"integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==",
|
||||||
|
@ -16504,9 +16532,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/tar": {
|
"node_modules/tar": {
|
||||||
"version": "6.1.8",
|
"version": "6.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/tar/-/tar-6.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz",
|
||||||
"integrity": "sha512-sb9b0cp855NbkMJcskdSYA7b11Q8JsX4qe4pyUAfHp+Y6jBjJeek2ZVlwEfWayshEIwlIzXx0Fain3QG9JPm2A==",
|
"integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chownr": "^2.0.0",
|
"chownr": "^2.0.0",
|
||||||
|
@ -19360,9 +19388,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@keycloak/keycloak-admin-client": {
|
"@keycloak/keycloak-admin-client": {
|
||||||
"version": "16.0.0-dev.2",
|
"version": "16.0.0-dev.4",
|
||||||
"resolved": "https://registry.npmjs.org/@keycloak/keycloak-admin-client/-/keycloak-admin-client-16.0.0-dev.2.tgz",
|
"resolved": "https://registry.npmjs.org/@keycloak/keycloak-admin-client/-/keycloak-admin-client-16.0.0-dev.4.tgz",
|
||||||
"integrity": "sha512-eLeN4/O5OWjU0fIIvndv0oLSRQN3q0bdMep19E+09/qL4jeNeBR4ltxLKd0mnW1FY53cZJ+QWLaq/lfgRXFfzA==",
|
"integrity": "sha512-8Wp/hqi6TWnt+woxoRwhklPP1SBw+EGzMGQQdErHrkTvfXCd0JFeECRzIZyGcmeFLbvpyLMwLPYFYknC20CENQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"axios": "^0.21.0",
|
"axios": "^0.21.0",
|
||||||
"camelize": "^1.0.0",
|
"camelize": "^1.0.0",
|
||||||
|
@ -19397,9 +19425,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@npmcli/arborist": {
|
"@npmcli/arborist": {
|
||||||
"version": "2.7.1",
|
"version": "2.8.2",
|
||||||
"resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-2.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-2.8.2.tgz",
|
||||||
"integrity": "sha512-EGDHJs6dna/52BrStr/6aaRcMLrYxGbSjT4V3JzvoTBY9/w5i2+1KNepmsG80CAsGADdo6nuNnFwb7sDRm8ZAw==",
|
"integrity": "sha512-6E1XJ0YXBaI9J+25gcTF110MGNx3jv6npr4Rz1U0UAqkuVV7bbDznVJvNqi6F0p8vgrE+Smf9jDTn1DR+7uBjQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@npmcli/installed-package-contents": "^1.0.7",
|
"@npmcli/installed-package-contents": "^1.0.7",
|
||||||
|
@ -19418,10 +19446,10 @@
|
||||||
"mkdirp": "^1.0.4",
|
"mkdirp": "^1.0.4",
|
||||||
"mkdirp-infer-owner": "^2.0.0",
|
"mkdirp-infer-owner": "^2.0.0",
|
||||||
"npm-install-checks": "^4.0.0",
|
"npm-install-checks": "^4.0.0",
|
||||||
"npm-package-arg": "^8.1.0",
|
"npm-package-arg": "^8.1.5",
|
||||||
"npm-pick-manifest": "^6.1.0",
|
"npm-pick-manifest": "^6.1.0",
|
||||||
"npm-registry-fetch": "^11.0.0",
|
"npm-registry-fetch": "^11.0.0",
|
||||||
"pacote": "^11.2.6",
|
"pacote": "^11.3.5",
|
||||||
"parse-conflict-json": "^1.1.1",
|
"parse-conflict-json": "^1.1.1",
|
||||||
"proc-log": "^1.0.0",
|
"proc-log": "^1.0.0",
|
||||||
"promise-all-reject-late": "^1.0.0",
|
"promise-all-reject-late": "^1.0.0",
|
||||||
|
@ -19431,7 +19459,6 @@
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"semver": "^7.3.5",
|
"semver": "^7.3.5",
|
||||||
"ssri": "^8.0.1",
|
"ssri": "^8.0.1",
|
||||||
"tar": "^6.1.0",
|
|
||||||
"treeverse": "^1.0.4",
|
"treeverse": "^1.0.4",
|
||||||
"walk-up-path": "^1.0.0"
|
"walk-up-path": "^1.0.0"
|
||||||
},
|
},
|
||||||
|
@ -23837,6 +23864,13 @@
|
||||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
|
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"fsevents": {
|
||||||
|
"version": "2.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||||
|
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"function-bind": {
|
"function-bind": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
|
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
|
||||||
|
@ -28791,6 +28825,15 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"fsevents": "~2.1.2"
|
"fsevents": "~2.1.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"fsevents": {
|
||||||
|
"version": "2.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
|
||||||
|
"integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rollup-plugin-polyfill-node": {
|
"rollup-plugin-polyfill-node": {
|
||||||
|
@ -30003,9 +30046,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tar": {
|
"tar": {
|
||||||
"version": "6.1.8",
|
"version": "6.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/tar/-/tar-6.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz",
|
||||||
"integrity": "sha512-sb9b0cp855NbkMJcskdSYA7b11Q8JsX4qe4pyUAfHp+Y6jBjJeek2ZVlwEfWayshEIwlIzXx0Fain3QG9JPm2A==",
|
"integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"chownr": "^2.0.0",
|
"chownr": "^2.0.0",
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
"prepare": "husky install"
|
"prepare": "husky install"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@keycloak/keycloak-admin-client": "^16.0.0-dev.2",
|
"@keycloak/keycloak-admin-client": "^16.0.0-dev.4",
|
||||||
"@patternfly/patternfly": "^4.132.2",
|
"@patternfly/patternfly": "^4.132.2",
|
||||||
"@patternfly/react-core": "4.152.4",
|
"@patternfly/react-core": "4.152.4",
|
||||||
"@patternfly/react-icons": "4.11.14",
|
"@patternfly/react-icons": "4.11.14",
|
||||||
|
|
|
@ -14,6 +14,7 @@ import {
|
||||||
import { CheckCircleIcon, TableIcon } from "@patternfly/react-icons";
|
import { CheckCircleIcon, TableIcon } from "@patternfly/react-icons";
|
||||||
|
|
||||||
import type AuthenticationExecutionInfoRepresentation from "@keycloak/keycloak-admin-client/lib/defs/authenticationExecutionInfoRepresentation";
|
import type AuthenticationExecutionInfoRepresentation from "@keycloak/keycloak-admin-client/lib/defs/authenticationExecutionInfoRepresentation";
|
||||||
|
import type { AuthenticationProviderRepresentation } from "@keycloak/keycloak-admin-client/lib/defs/authenticatorConfigRepresentation";
|
||||||
import type AuthenticationFlowRepresentation from "@keycloak/keycloak-admin-client/lib/defs/authenticationFlowRepresentation";
|
import type AuthenticationFlowRepresentation from "@keycloak/keycloak-admin-client/lib/defs/authenticationFlowRepresentation";
|
||||||
import type { FlowParams } from "./routes/Flow";
|
import type { FlowParams } from "./routes/Flow";
|
||||||
import { ViewHeader } from "../components/view-header/ViewHeader";
|
import { ViewHeader } from "../components/view-header/ViewHeader";
|
||||||
|
@ -22,14 +23,23 @@ import { EmptyExecutionState } from "./EmptyExecutionState";
|
||||||
import { toUpperCase } from "../util";
|
import { toUpperCase } from "../util";
|
||||||
import { FlowHeader } from "./components/FlowHeader";
|
import { FlowHeader } from "./components/FlowHeader";
|
||||||
import { FlowRow } from "./components/FlowRow";
|
import { FlowRow } from "./components/FlowRow";
|
||||||
import { ExecutionList, IndexChange, LevelChange } from "./execution-model";
|
import {
|
||||||
|
ExecutionList,
|
||||||
|
ExpandableExecution,
|
||||||
|
IndexChange,
|
||||||
|
LevelChange,
|
||||||
|
} from "./execution-model";
|
||||||
import { FlowDiagram } from "./components/FlowDiagram";
|
import { FlowDiagram } from "./components/FlowDiagram";
|
||||||
import { useAlerts } from "../components/alert/Alerts";
|
import { useAlerts } from "../components/alert/Alerts";
|
||||||
|
|
||||||
|
export const providerConditionFilter = (
|
||||||
|
value: AuthenticationProviderRepresentation
|
||||||
|
) => value.displayName?.startsWith("Condition ");
|
||||||
|
|
||||||
export const FlowDetails = () => {
|
export const FlowDetails = () => {
|
||||||
const { t } = useTranslation("authentication");
|
const { t } = useTranslation("authentication");
|
||||||
const adminClient = useAdminClient();
|
const adminClient = useAdminClient();
|
||||||
const { addAlert } = useAlerts();
|
const { addAlert, addError } = useAlerts();
|
||||||
const { id, usedBy, builtIn } = useParams<FlowParams>();
|
const { id, usedBy, builtIn } = useParams<FlowParams>();
|
||||||
const [key, setKey] = useState(0);
|
const [key, setKey] = useState(0);
|
||||||
const refresh = () => setKey(new Date().getTime());
|
const refresh = () => setKey(new Date().getTime());
|
||||||
|
@ -94,12 +104,7 @@ export const FlowDetails = () => {
|
||||||
refresh();
|
refresh();
|
||||||
addAlert(t("updateFlowSuccess"), AlertVariant.success);
|
addAlert(t("updateFlowSuccess"), AlertVariant.success);
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
addAlert(
|
addError("authentication:updateFlowError", error);
|
||||||
t("updateFlowError", {
|
|
||||||
error: error.response?.data?.errorMessage || error,
|
|
||||||
}),
|
|
||||||
AlertVariant.danger
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -114,12 +119,23 @@ export const FlowDetails = () => {
|
||||||
refresh();
|
refresh();
|
||||||
addAlert(t("updateFlowSuccess"), AlertVariant.success);
|
addAlert(t("updateFlowSuccess"), AlertVariant.success);
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
addAlert(
|
addError("authentication:updateFlowError", error);
|
||||||
t("updateFlowError", {
|
}
|
||||||
error: error.response?.data?.errorMessage || error,
|
};
|
||||||
}),
|
|
||||||
AlertVariant.danger
|
const addExecution = async (
|
||||||
);
|
execution: ExpandableExecution,
|
||||||
|
type: AuthenticationProviderRepresentation
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
await adminClient.authenticationManagement.addExecutionToFlow({
|
||||||
|
flow: execution.displayName!,
|
||||||
|
provider: type.id!,
|
||||||
|
});
|
||||||
|
refresh();
|
||||||
|
addAlert(t("updateFlowSuccess"), AlertVariant.success);
|
||||||
|
} catch (error) {
|
||||||
|
addError("authentication:updateFlowError", error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -215,6 +231,7 @@ export const FlowDetails = () => {
|
||||||
setExecutionList(executionList.clone());
|
setExecutionList(executionList.clone());
|
||||||
}}
|
}}
|
||||||
onRowChange={update}
|
onRowChange={update}
|
||||||
|
onAddExecution={addExecution}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
|
|
91
src/authentication/components/EditFlowDropdown.tsx
Normal file
91
src/authentication/components/EditFlowDropdown.tsx
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { Dropdown, DropdownItem, DropdownToggle } from "@patternfly/react-core";
|
||||||
|
import { PlusIcon } from "@patternfly/react-icons";
|
||||||
|
|
||||||
|
import type { AuthenticationProviderRepresentation } from "@keycloak/keycloak-admin-client/lib/defs/authenticatorConfigRepresentation";
|
||||||
|
import type { ExpandableExecution } from "../execution-model";
|
||||||
|
import { AddStepModal, FlowType } from "./modals/AddStepModal";
|
||||||
|
import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
|
||||||
|
import { AddSubFlowModal } from "./modals/AddSubFlowModal";
|
||||||
|
|
||||||
|
type EditFlowDropdownProps = {
|
||||||
|
execution: ExpandableExecution;
|
||||||
|
onAddExecution: (
|
||||||
|
execution: ExpandableExecution,
|
||||||
|
type: AuthenticationProviderRepresentation
|
||||||
|
) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const EditFlowDropdown = ({
|
||||||
|
execution,
|
||||||
|
onAddExecution,
|
||||||
|
}: EditFlowDropdownProps) => {
|
||||||
|
const { t } = useTranslation("authentication");
|
||||||
|
const adminClient = useAdminClient();
|
||||||
|
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const [type, setType] = useState<FlowType>();
|
||||||
|
const [providerId, setProviderId] = useState<string>();
|
||||||
|
|
||||||
|
useFetch(
|
||||||
|
() =>
|
||||||
|
adminClient.authenticationManagement.getFlow({
|
||||||
|
flowId: execution.flowId!,
|
||||||
|
}),
|
||||||
|
({ providerId }) => setProviderId(providerId),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Dropdown
|
||||||
|
isPlain
|
||||||
|
position="right"
|
||||||
|
data-testid={`${execution.displayName}-edit-dropdown`}
|
||||||
|
isOpen={open}
|
||||||
|
toggle={
|
||||||
|
<DropdownToggle onToggle={(open) => setOpen(open)}>
|
||||||
|
<PlusIcon />
|
||||||
|
</DropdownToggle>
|
||||||
|
}
|
||||||
|
dropdownItems={[
|
||||||
|
<DropdownItem
|
||||||
|
key="addStep"
|
||||||
|
onClick={() =>
|
||||||
|
setType(providerId === "form-flow" ? "form" : "basic")
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{t("addStep")}
|
||||||
|
</DropdownItem>,
|
||||||
|
<DropdownItem key="addCondition" onClick={() => setType("condition")}>
|
||||||
|
{t("addCondition")}
|
||||||
|
</DropdownItem>,
|
||||||
|
<DropdownItem key="addSubFlow" onClick={() => setType("subFlow")}>
|
||||||
|
{t("addSubFlow")}
|
||||||
|
</DropdownItem>,
|
||||||
|
]}
|
||||||
|
onSelect={() => setOpen(false)}
|
||||||
|
/>
|
||||||
|
{type && type !== "subFlow" && (
|
||||||
|
<AddStepModal
|
||||||
|
name={execution.displayName!}
|
||||||
|
type={type}
|
||||||
|
onSelect={(type) => {
|
||||||
|
if (type) {
|
||||||
|
onAddExecution(execution, type);
|
||||||
|
}
|
||||||
|
setType(undefined);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{type === "subFlow" && (
|
||||||
|
<AddSubFlowModal
|
||||||
|
name={execution.displayName!}
|
||||||
|
onCancel={() => setType(undefined)}
|
||||||
|
onConfirm={() => setType(undefined)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
|
@ -26,6 +26,7 @@ import { EndSubFlowNode, StartSubFlowNode } from "./diagram/SubFlowNode";
|
||||||
import { ConditionalNode } from "./diagram/ConditionalNode";
|
import { ConditionalNode } from "./diagram/ConditionalNode";
|
||||||
import { ButtonEdge } from "./diagram/ButtonEdge";
|
import { ButtonEdge } from "./diagram/ButtonEdge";
|
||||||
import { getLayoutedElements } from "./diagram/auto-layout";
|
import { getLayoutedElements } from "./diagram/auto-layout";
|
||||||
|
import { providerConditionFilter } from "../FlowDetails";
|
||||||
|
|
||||||
import "./flow-diagram.css";
|
import "./flow-diagram.css";
|
||||||
|
|
||||||
|
@ -54,7 +55,7 @@ const createNode = (ex: ExpandableExecution) => {
|
||||||
if (ex.executionList) {
|
if (ex.executionList) {
|
||||||
nodeType = "startSubFlow";
|
nodeType = "startSubFlow";
|
||||||
}
|
}
|
||||||
if (ex.displayName?.startsWith("Condition")) {
|
if (providerConditionFilter(ex)) {
|
||||||
nodeType = "conditional";
|
nodeType = "conditional";
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -13,26 +13,34 @@ import {
|
||||||
} from "@patternfly/react-core";
|
} from "@patternfly/react-core";
|
||||||
|
|
||||||
import type AuthenticationExecutionInfoRepresentation from "@keycloak/keycloak-admin-client/lib/defs/authenticationExecutionInfoRepresentation";
|
import type AuthenticationExecutionInfoRepresentation from "@keycloak/keycloak-admin-client/lib/defs/authenticationExecutionInfoRepresentation";
|
||||||
|
import type { AuthenticationProviderRepresentation } from "@keycloak/keycloak-admin-client/lib/defs/authenticatorConfigRepresentation";
|
||||||
import type { ExpandableExecution } from "../execution-model";
|
import type { ExpandableExecution } from "../execution-model";
|
||||||
import { FlowTitle } from "./FlowTitle";
|
import { FlowTitle } from "./FlowTitle";
|
||||||
import { FlowRequirementDropdown } from "./FlowRequirementDropdown";
|
import { FlowRequirementDropdown } from "./FlowRequirementDropdown";
|
||||||
|
import { ExecutionConfigModal } from "./ExecutionConfigModal";
|
||||||
|
import { EditFlowDropdown } from "./EditFlowDropdown";
|
||||||
|
|
||||||
import "./flow-row.css";
|
import "./flow-row.css";
|
||||||
import { ExecutionConfigModal } from "./ExecutionConfigModal";
|
|
||||||
|
|
||||||
type FlowRowProps = {
|
type FlowRowProps = {
|
||||||
execution: ExpandableExecution;
|
execution: ExpandableExecution;
|
||||||
onRowClick: (execution: ExpandableExecution) => void;
|
onRowClick: (execution: ExpandableExecution) => void;
|
||||||
onRowChange: (execution: AuthenticationExecutionInfoRepresentation) => void;
|
onRowChange: (execution: AuthenticationExecutionInfoRepresentation) => void;
|
||||||
|
onAddExecution: (
|
||||||
|
execution: ExpandableExecution,
|
||||||
|
type: AuthenticationProviderRepresentation
|
||||||
|
) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FlowRow = ({
|
export const FlowRow = ({
|
||||||
execution,
|
execution,
|
||||||
onRowClick,
|
onRowClick,
|
||||||
onRowChange,
|
onRowChange,
|
||||||
|
onAddExecution,
|
||||||
}: FlowRowProps) => {
|
}: FlowRowProps) => {
|
||||||
const { t } = useTranslation("authentication");
|
const { t } = useTranslation("authentication");
|
||||||
const hasSubList = !!execution.executionList?.length;
|
const hasSubList = !!execution.executionList?.length;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DataListItem
|
<DataListItem
|
||||||
|
@ -86,6 +94,12 @@ export const FlowRow = ({
|
||||||
{execution.configurable && (
|
{execution.configurable && (
|
||||||
<ExecutionConfigModal execution={execution} />
|
<ExecutionConfigModal execution={execution} />
|
||||||
)}
|
)}
|
||||||
|
{execution.authenticationFlow && (
|
||||||
|
<EditFlowDropdown
|
||||||
|
execution={execution}
|
||||||
|
onAddExecution={onAddExecution}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</DataListCell>,
|
</DataListCell>,
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
@ -99,6 +113,7 @@ export const FlowRow = ({
|
||||||
execution={execution}
|
execution={execution}
|
||||||
onRowClick={onRowClick}
|
onRowClick={onRowClick}
|
||||||
onRowChange={onRowChange}
|
onRowChange={onRowChange}
|
||||||
|
onAddExecution={onAddExecution}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
|
|
142
src/authentication/components/modals/AddStepModal.tsx
Normal file
142
src/authentication/components/modals/AddStepModal.tsx
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
ButtonVariant,
|
||||||
|
Form,
|
||||||
|
Modal,
|
||||||
|
ModalVariant,
|
||||||
|
PageSection,
|
||||||
|
Radio,
|
||||||
|
} from "@patternfly/react-core";
|
||||||
|
|
||||||
|
import type { AuthenticationProviderRepresentation } from "@keycloak/keycloak-admin-client/lib/defs/authenticatorConfigRepresentation";
|
||||||
|
import { PaginatingTableToolbar } from "../../../components/table-toolbar/PaginatingTableToolbar";
|
||||||
|
import { useAdminClient, useFetch } from "../../../context/auth/AdminClient";
|
||||||
|
import { providerConditionFilter } from "../../FlowDetails";
|
||||||
|
|
||||||
|
type AuthenticationProviderListProps = {
|
||||||
|
list?: AuthenticationProviderRepresentation[];
|
||||||
|
setValue: (provider?: AuthenticationProviderRepresentation) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const AuthenticationProviderList = ({
|
||||||
|
list,
|
||||||
|
setValue,
|
||||||
|
}: AuthenticationProviderListProps) => {
|
||||||
|
return (
|
||||||
|
<PageSection variant="light" className="pf-u-py-lg">
|
||||||
|
<Form isHorizontal>
|
||||||
|
{list?.map((provider) => (
|
||||||
|
<Radio
|
||||||
|
id={provider.id!}
|
||||||
|
key={provider.id}
|
||||||
|
name="provider"
|
||||||
|
label={provider.displayName}
|
||||||
|
data-testid={provider.id}
|
||||||
|
description={provider.description}
|
||||||
|
onChange={(_val, event) => {
|
||||||
|
const { id } = event.currentTarget;
|
||||||
|
const value = list.find((p) => p.id === id);
|
||||||
|
setValue(value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Form>
|
||||||
|
</PageSection>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export type FlowType = "client" | "form" | "basic" | "condition" | "subFlow";
|
||||||
|
|
||||||
|
type AddStepModalProps = {
|
||||||
|
name: string;
|
||||||
|
type: FlowType;
|
||||||
|
onSelect: (value?: AuthenticationProviderRepresentation) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const AddStepModal = ({ name, type, onSelect }: AddStepModalProps) => {
|
||||||
|
const { t } = useTranslation("authentication");
|
||||||
|
const adminClient = useAdminClient();
|
||||||
|
|
||||||
|
const [value, setValue] = useState<AuthenticationProviderRepresentation>();
|
||||||
|
const [providers, setProviders] =
|
||||||
|
useState<AuthenticationProviderRepresentation[]>();
|
||||||
|
const [max, setMax] = useState(10);
|
||||||
|
const [first, setFirst] = useState(0);
|
||||||
|
|
||||||
|
useFetch(
|
||||||
|
async () => {
|
||||||
|
switch (type) {
|
||||||
|
case "client":
|
||||||
|
return adminClient.authenticationManagement.getClientAuthenticatorProviders();
|
||||||
|
case "form":
|
||||||
|
return adminClient.authenticationManagement.getFormActionProviders();
|
||||||
|
case "condition": {
|
||||||
|
const providers =
|
||||||
|
await adminClient.authenticationManagement.getAuthenticatorProviders();
|
||||||
|
return providers.filter(providerConditionFilter);
|
||||||
|
}
|
||||||
|
case "basic":
|
||||||
|
default: {
|
||||||
|
const providers =
|
||||||
|
await adminClient.authenticationManagement.getAuthenticatorProviders();
|
||||||
|
return providers.filter((p) => !providerConditionFilter(p));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(providers) => setProviders(providers),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
const page = providers?.slice(first, first + max + 1);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
variant={ModalVariant.medium}
|
||||||
|
isOpen={true}
|
||||||
|
title={t("addStepTo", { name })}
|
||||||
|
onClose={() => onSelect()}
|
||||||
|
actions={[
|
||||||
|
<Button
|
||||||
|
id="modal-add"
|
||||||
|
data-testid="modal-add"
|
||||||
|
key="add"
|
||||||
|
onClick={() => onSelect(value)}
|
||||||
|
>
|
||||||
|
{t("common:add")}
|
||||||
|
</Button>,
|
||||||
|
<Button
|
||||||
|
data-testid="cancel"
|
||||||
|
id="modal-cancel"
|
||||||
|
key="cancel"
|
||||||
|
variant={ButtonVariant.link}
|
||||||
|
onClick={() => {
|
||||||
|
onSelect();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t("common:cancel")}
|
||||||
|
</Button>,
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{providers && providers.length > max && (
|
||||||
|
<PaginatingTableToolbar
|
||||||
|
count={page?.length || 0}
|
||||||
|
first={first}
|
||||||
|
max={max}
|
||||||
|
onNextClick={setFirst}
|
||||||
|
onPreviousClick={setFirst}
|
||||||
|
onPerPageSelect={(first, max) => {
|
||||||
|
setFirst(first);
|
||||||
|
setMax(max);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AuthenticationProviderList list={page} setValue={setValue} />
|
||||||
|
</PaginatingTableToolbar>
|
||||||
|
)}
|
||||||
|
{providers && providers.length <= max && (
|
||||||
|
<AuthenticationProviderList list={providers} setValue={setValue} />
|
||||||
|
)}
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
113
src/authentication/components/modals/AddSubFlowModal.tsx
Normal file
113
src/authentication/components/modals/AddSubFlowModal.tsx
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
import React from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
ButtonVariant,
|
||||||
|
Form,
|
||||||
|
FormGroup,
|
||||||
|
Modal,
|
||||||
|
ModalVariant,
|
||||||
|
TextInput,
|
||||||
|
ValidatedOptions,
|
||||||
|
} from "@patternfly/react-core";
|
||||||
|
|
||||||
|
import { HelpItem } from "../../../components/help-enabler/HelpItem";
|
||||||
|
|
||||||
|
type AddSubFlowProps = {
|
||||||
|
name: string;
|
||||||
|
onConfirm: () => void;
|
||||||
|
onCancel: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const AddSubFlowModal = ({
|
||||||
|
name,
|
||||||
|
onConfirm,
|
||||||
|
onCancel,
|
||||||
|
}: AddSubFlowProps) => {
|
||||||
|
const { t } = useTranslation("authentication");
|
||||||
|
const { register, errors, handleSubmit } = useForm();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
variant={ModalVariant.medium}
|
||||||
|
isOpen={true}
|
||||||
|
title={t("addStepTo", { name })}
|
||||||
|
onClose={() => onCancel()}
|
||||||
|
actions={[
|
||||||
|
<Button
|
||||||
|
id="modal-add"
|
||||||
|
data-testid="modal-add"
|
||||||
|
key="add"
|
||||||
|
onClick={() => onConfirm()}
|
||||||
|
>
|
||||||
|
{t("common:add")}
|
||||||
|
</Button>,
|
||||||
|
<Button
|
||||||
|
data-testid="cancel"
|
||||||
|
id="modal-cancel"
|
||||||
|
key="cancel"
|
||||||
|
variant={ButtonVariant.link}
|
||||||
|
onClick={() => {
|
||||||
|
onCancel();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t("common:cancel")}
|
||||||
|
</Button>,
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Form
|
||||||
|
id="execution-config-form"
|
||||||
|
isHorizontal
|
||||||
|
onSubmit={handleSubmit(onConfirm)}
|
||||||
|
>
|
||||||
|
<FormGroup
|
||||||
|
label={t("common:name")}
|
||||||
|
fieldId="name"
|
||||||
|
helperTextInvalid={t("common:required")}
|
||||||
|
validated={
|
||||||
|
errors.name ? ValidatedOptions.error : ValidatedOptions.default
|
||||||
|
}
|
||||||
|
isRequired
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText="authentication-help:name"
|
||||||
|
forLabel={t("name")}
|
||||||
|
forID="name"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
type="text"
|
||||||
|
id="name"
|
||||||
|
name="name"
|
||||||
|
data-testid="name"
|
||||||
|
ref={register({ required: true })}
|
||||||
|
validated={
|
||||||
|
errors.name ? ValidatedOptions.error : ValidatedOptions.default
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("common:description")}
|
||||||
|
fieldId="description"
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText="authentication-help:description"
|
||||||
|
forLabel={t("common:description")}
|
||||||
|
forID="description"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
type="text"
|
||||||
|
id="description"
|
||||||
|
name="description"
|
||||||
|
data-testid="description"
|
||||||
|
ref={register}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
|
@ -41,6 +41,9 @@ export default {
|
||||||
addExecution: "Add execution",
|
addExecution: "Add execution",
|
||||||
addSubFlowTitle: "Add a sub-flow",
|
addSubFlowTitle: "Add a sub-flow",
|
||||||
addSubFlow: "Add sub-flow",
|
addSubFlow: "Add sub-flow",
|
||||||
|
addCondition: "Add condition",
|
||||||
|
addStep: "Add step",
|
||||||
|
addStepTo: "Add step to {{name}}",
|
||||||
steps: "Steps",
|
steps: "Steps",
|
||||||
requirement: "Requirement",
|
requirement: "Requirement",
|
||||||
requirements: {
|
requirements: {
|
||||||
|
|
|
@ -18,6 +18,7 @@ import {
|
||||||
SplitItem,
|
SplitItem,
|
||||||
} from "@patternfly/react-core";
|
} from "@patternfly/react-core";
|
||||||
import type CredentialRepresentation from "@keycloak/keycloak-admin-client/lib/defs/credentialRepresentation";
|
import type CredentialRepresentation from "@keycloak/keycloak-admin-client/lib/defs/credentialRepresentation";
|
||||||
|
import type { AuthenticationProviderRepresentation } from "@keycloak/keycloak-admin-client/lib/defs/authenticatorConfigRepresentation";
|
||||||
|
|
||||||
import { useAlerts } from "../../components/alert/Alerts";
|
import { useAlerts } from "../../components/alert/Alerts";
|
||||||
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
|
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
|
||||||
|
@ -29,11 +30,6 @@ import { ClientSecret } from "./ClientSecret";
|
||||||
import { SignedJWT } from "./SignedJWT";
|
import { SignedJWT } from "./SignedJWT";
|
||||||
import { X509 } from "./X509";
|
import { X509 } from "./X509";
|
||||||
|
|
||||||
type ClientAuthenticatorProviders = {
|
|
||||||
id: string;
|
|
||||||
displayName: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type AccessToken = {
|
type AccessToken = {
|
||||||
registrationAccessToken: string;
|
registrationAccessToken: string;
|
||||||
};
|
};
|
||||||
|
@ -48,9 +44,9 @@ export const Credentials = ({ clientId, save }: CredentialsProps) => {
|
||||||
const adminClient = useAdminClient();
|
const adminClient = useAdminClient();
|
||||||
const { addAlert, addError } = useAlerts();
|
const { addAlert, addError } = useAlerts();
|
||||||
|
|
||||||
const [providers, setProviders] = useState<ClientAuthenticatorProviders[]>(
|
const [providers, setProviders] = useState<
|
||||||
[]
|
AuthenticationProviderRepresentation[]
|
||||||
);
|
>([]);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
control,
|
control,
|
||||||
|
@ -69,9 +65,7 @@ export const Credentials = ({ clientId, save }: CredentialsProps) => {
|
||||||
useFetch(
|
useFetch(
|
||||||
async () => {
|
async () => {
|
||||||
const providers =
|
const providers =
|
||||||
await adminClient.authenticationManagement.getClientAuthenticatorProviders(
|
await adminClient.authenticationManagement.getClientAuthenticatorProviders();
|
||||||
{ id: clientId }
|
|
||||||
);
|
|
||||||
|
|
||||||
const secret = await adminClient.clients.getClientSecret({
|
const secret = await adminClient.clients.getClientSecret({
|
||||||
id: clientId,
|
id: clientId,
|
||||||
|
|
Loading…
Reference in a new issue