Add JavaScript admin client to repository (#16697)
* Add JavaScript admin client to repository * Apply review feedback Co-authored-by: Stian Thorgersen <stian@redhat.com> --------- Co-authored-by: Stian Thorgersen <stian@redhat.com>
This commit is contained in:
parent
0fa209c29a
commit
8cb202eb29
132 changed files with 16113 additions and 4 deletions
9
.github/actions/conditional/action.yml
vendored
9
.github/actions/conditional/action.yml
vendored
|
@ -5,6 +5,12 @@ outputs:
|
|||
ci:
|
||||
description: Should "ci.yml" execute
|
||||
value: ${{ steps.changes.outputs.ci }}
|
||||
operator:
|
||||
description: Should "operator-ci.yml" execute
|
||||
value: ${{ steps.changes.outputs.operator }}
|
||||
js:
|
||||
description: Should "js-ci.yml" execute
|
||||
value: ${{ steps.changes.outputs.js }}
|
||||
codeql-java:
|
||||
description: Should "codeql-analysis.yml / java" execute
|
||||
value: ${{ steps.changes.outputs.codeql-java }}
|
||||
|
@ -14,9 +20,6 @@ outputs:
|
|||
codeql-js_adapter:
|
||||
description: Should "codeql-analysis.yml / js-adapter" execute
|
||||
value: ${{ steps.changes.outputs.codeql-js_adapter }}
|
||||
operator:
|
||||
description: Should "operator-ci.yml" execute
|
||||
value: ${{ steps.changes.outputs.operator }}
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
|
|
5
.github/actions/conditional/conditions
vendored
5
.github/actions/conditional/conditions
vendored
|
@ -2,16 +2,19 @@
|
|||
#
|
||||
# To test a pattern run '.github/actions/conditional/conditional.sh <remote name> <branch>'
|
||||
|
||||
.github/actions/ ci operator codeql-java codeql-themes codeql-js_adapter
|
||||
.github/actions/ ci operator js codeql-java codeql-themes codeql-js_adapter
|
||||
|
||||
.github/workflows/ci.yml ci
|
||||
.github/workflows/operator-ci.yml operator
|
||||
.github/workflows/js-ci.yml js
|
||||
.github/workflows/codeql-analysis.yml codeql-java codeql-themes codeql-js_adapter
|
||||
|
||||
*/src/main/ ci operator
|
||||
*/src/test/ ci operator
|
||||
pom.xml ci operator
|
||||
|
||||
js/ js
|
||||
|
||||
*.java codeql-java
|
||||
themes/ codeql-themes
|
||||
adapters/oidc/js/ codeql-js_adapter
|
||||
|
|
24
.github/dependabot.yml
vendored
24
.github/dependabot.yml
vendored
|
@ -20,6 +20,30 @@ updates:
|
|||
labels:
|
||||
- area/dependencies
|
||||
- area/admin/ui
|
||||
- team/ui
|
||||
ignore:
|
||||
- dependency-name: bootstrap
|
||||
update-types: ["version-update:semver-major"]
|
||||
- package-ecosystem: npm
|
||||
directory: js
|
||||
open-pull-requests-limit: 999
|
||||
rebase-strategy: disabled
|
||||
versioning-strategy: increase
|
||||
schedule:
|
||||
interval: weekly
|
||||
labels:
|
||||
- area/dependencies
|
||||
- team/ui
|
||||
ignore:
|
||||
- dependency-name: react
|
||||
update-types: ["version-update:semver-major"]
|
||||
- dependency-name: react-dom
|
||||
update-types: ["version-update:semver-major"]
|
||||
- dependency-name: "@types/react"
|
||||
update-types: ["version-update:semver-major"]
|
||||
- dependency-name: "@types/react-dom"
|
||||
update-types: ["version-update:semver-major"]
|
||||
- dependency-name: vite
|
||||
update-types: ["version-update:semver-major"]
|
||||
- dependency-name: "@vitejs/plugin-react"
|
||||
update-types: ["version-update:semver-major"]
|
||||
|
|
96
.github/workflows/js-ci.yml
vendored
Normal file
96
.github/workflows/js-ci.yml
vendored
Normal file
|
@ -0,0 +1,96 @@
|
|||
name: Keycloak JavaScript CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches-ignore:
|
||||
- main
|
||||
- dependabot/**
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: 0 20,23,2,5 * * *
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
NODE_VERSION: 18
|
||||
|
||||
concurrency:
|
||||
# Only cancel jobs for PR updates
|
||||
group: js-ci-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
conditional:
|
||||
name: Check conditional workflows and jobs
|
||||
if: github.event_name != 'schedule' || github.repository == 'keycloak/keycloak'
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
js-ci: ${{ steps.conditional.outputs.js }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- id: conditional
|
||||
uses: ./.github/actions/conditional
|
||||
|
||||
npm-run:
|
||||
needs: conditional
|
||||
if: needs.conditional.outputs.js-ci == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
# Keycloak Admin Client
|
||||
- workspace: "@keycloak/keycloak-admin-client"
|
||||
command: lint
|
||||
- workspace: "@keycloak/keycloak-admin-client"
|
||||
command: build
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
check-latest: true
|
||||
cache: npm
|
||||
cache-dependency-path: js/package-lock.json
|
||||
|
||||
- name: Install dependencies
|
||||
working-directory: js
|
||||
run: npm ci
|
||||
|
||||
- name: Run ${{ matrix.command }} task
|
||||
working-directory: js
|
||||
run: npm run ${{ matrix.command }} --workspace=${{ matrix.workspace }}
|
||||
|
||||
check-set-status:
|
||||
name: Set check conclusion
|
||||
needs:
|
||||
- npm-run
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
conclusion: ${{ steps.check.outputs.conclusion }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- id: check
|
||||
uses: ./.github/actions/checks-success
|
||||
|
||||
check:
|
||||
name: Status Check - Keycloak JavaScript CI
|
||||
if: always() && ( github.event_name != 'schedule' || github.repository == 'keycloak/keycloak' )
|
||||
needs:
|
||||
- conditional
|
||||
- check-set-status
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Check status
|
||||
uses: ./.github/actions/checks-job-pass
|
||||
with:
|
||||
required: ${{ needs.conditional.outputs.ci }}
|
||||
conclusion: ${{ needs.check-set-status.outputs.conclusion }}
|
96
js/.eslintrc.js
Normal file
96
js/.eslintrc.js
Normal file
|
@ -0,0 +1,96 @@
|
|||
/** @type {import("eslint").Linter.Config } */
|
||||
module.exports = {
|
||||
root: true,
|
||||
ignorePatterns: [
|
||||
"node_modules",
|
||||
"dist",
|
||||
// Keycloak JS follows a completely different and outdated style, so we'll exclude it for now.
|
||||
// TODO: Eventually align the code-style for Keycloak JS.
|
||||
"libs/keycloak-js",
|
||||
],
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: "./tsconfig.eslint.json",
|
||||
extraFileExtensions: [".mjs"],
|
||||
},
|
||||
env: {
|
||||
node: true,
|
||||
},
|
||||
plugins: ["lodash"],
|
||||
extends: [
|
||||
"eslint:recommended",
|
||||
"plugin:import/recommended",
|
||||
"plugin:import/typescript",
|
||||
"plugin:react/recommended",
|
||||
"plugin:react/jsx-runtime",
|
||||
"plugin:@typescript-eslint/base",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:prettier/recommended",
|
||||
],
|
||||
settings: {
|
||||
react: {
|
||||
version: "detect",
|
||||
},
|
||||
"import/resolver": {
|
||||
typescript: true,
|
||||
node: true,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
// Prefer using `includes()` to check if values exist over `indexOf() === -1`, as it's a more appropriate API for this.
|
||||
"@typescript-eslint/prefer-includes": "error",
|
||||
// Prefer using an optional chain expression, as it's more concise and easier to read.
|
||||
"@typescript-eslint/prefer-optional-chain": "error",
|
||||
"no-unused-vars": "off",
|
||||
"@typescript-eslint/no-empty-function": "error",
|
||||
"@typescript-eslint/no-unnecessary-condition": "warn",
|
||||
"@typescript-eslint/no-unused-vars": "error",
|
||||
"lodash/import-scope": ["error", "member"],
|
||||
// react/prop-types cannot handle generic props, so we need to disable it.
|
||||
// https://github.com/yannickcr/eslint-plugin-react/issues/2777#issuecomment-814968432
|
||||
"react/prop-types": "off",
|
||||
// Prevent fragments from being added that have only a single child.
|
||||
"react/jsx-no-useless-fragment": "error",
|
||||
"prefer-arrow-callback": "error",
|
||||
"prettier/prettier": [
|
||||
"error",
|
||||
{
|
||||
endOfLine: "auto",
|
||||
},
|
||||
],
|
||||
// Prevent default imports from React, named imports should be used instead.
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
paths: [
|
||||
{
|
||||
name: "react",
|
||||
importNames: ["default"],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ["*.test.*"],
|
||||
rules: {
|
||||
// For tests it can make sense to pass empty functions as mocks.
|
||||
"@typescript-eslint/no-empty-function": "off",
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["**/cypress/**/*"],
|
||||
extends: ["plugin:cypress/recommended", "plugin:mocha/recommended"],
|
||||
// TODO: Set these rules to "error" when issues have been resolved.
|
||||
rules: {
|
||||
"cypress/no-unnecessary-waiting": "warn",
|
||||
"mocha/max-top-level-suites": "off",
|
||||
"mocha/no-exclusive-tests": "error",
|
||||
"mocha/no-identical-title": "off",
|
||||
"mocha/no-mocha-arrows": "off",
|
||||
"mocha/no-setup-in-describe": "off",
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
38
js/.gitignore
vendored
Normal file
38
js/.gitignore
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# NPM
|
||||
node_modules
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
# Cypress
|
||||
assets
|
||||
**/cypress.env.json
|
||||
**/cypress/downloads
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Wireit
|
||||
.wireit
|
||||
|
||||
# Vite
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
1
js/.husky/.gitignore
vendored
Normal file
1
js/.husky/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
_
|
4
js/.husky/pre-commit
Executable file
4
js/.husky/pre-commit
Executable file
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
cd js
|
||||
npx lint-staged
|
14
js/README.md
Normal file
14
js/README.md
Normal file
|
@ -0,0 +1,14 @@
|
|||
# Keycloak JavaScript
|
||||
|
||||
This directory contains an [NPM workspace](https://docs.npmjs.com/cli/v9/using-npm/workspaces) with JavaScript (and TypeScript) code related to the UIs and libraries of the Keycloak project.
|
||||
|
||||
## Repository structure
|
||||
|
||||
├── apps
|
||||
│ ├── account-ui # Account UI for account management i.e controlling password and account access, tracking and managing permissions
|
||||
│ └── admin-ui # Admin UI for handling login, registration, administration, and account management
|
||||
├── libs
|
||||
│ ├── keycloak-admin-client # Keycloak Admin Client library for Keycloak REST API
|
||||
│ ├── keycloak-js # Keycloak JS library for securing HTML5/JavaScript applications
|
||||
│ └── keycloak-masthead # Keycloak Masthead library for an easy way to bring applications into the Keycloak ecosystem, allow users to access
|
||||
│ # and manage security for those applications and manage authorization of resources
|
1
js/libs/keycloak-admin-client/.eslintignore
Normal file
1
js/libs/keycloak-admin-client/.eslintignore
Normal file
|
@ -0,0 +1 @@
|
|||
lib
|
1
js/libs/keycloak-admin-client/.gitignore
vendored
Normal file
1
js/libs/keycloak-admin-client/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
lib
|
5
js/libs/keycloak-admin-client/.mocharc.json
Normal file
5
js/libs/keycloak-admin-client/.mocharc.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"node-option": [
|
||||
"loader=ts-node/esm"
|
||||
]
|
||||
}
|
201
js/libs/keycloak-admin-client/LICENSE
Normal file
201
js/libs/keycloak-admin-client/LICENSE
Normal file
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
455
js/libs/keycloak-admin-client/README.md
Normal file
455
js/libs/keycloak-admin-client/README.md
Normal file
|
@ -0,0 +1,455 @@
|
|||
## Keycloak Admin Client
|
||||
|
||||
## Features
|
||||
|
||||
- TypeScript supported
|
||||
- Latest Keycloak version supported
|
||||
- [Complete resource definitions](./src/defs)
|
||||
- [Well-tested for supported APIs](./test)
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
npm install @keycloak/keycloak-admin-client
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
import KcAdminClient from '@keycloak/keycloak-admin-client';
|
||||
|
||||
// To configure the client, pass an object to override any of these options:
|
||||
// {
|
||||
// baseUrl: 'http://127.0.0.1:8080',
|
||||
// realmName: 'master',
|
||||
// requestOptions: {
|
||||
// /* Fetch request options https://developer.mozilla.org/en-US/docs/Web/API/fetch#options */
|
||||
// },
|
||||
// }
|
||||
const kcAdminClient = new KcAdminClient();
|
||||
|
||||
// Authorize with username / password
|
||||
await kcAdminClient.auth({
|
||||
username: 'admin',
|
||||
password: 'admin',
|
||||
grantType: 'password',
|
||||
clientId: 'admin-cli',
|
||||
totp: '123456', // optional Time-based One-time Password if OTP is required in authentication flow
|
||||
});
|
||||
|
||||
// List all users
|
||||
const users = await kcAdminClient.users.find();
|
||||
|
||||
// Override client configuration for all further requests:
|
||||
kcAdminClient.setConfig({
|
||||
realmName: 'another-realm',
|
||||
});
|
||||
|
||||
// This operation will now be performed in 'another-realm' if the user has access.
|
||||
const groups = await kcAdminClient.groups.find();
|
||||
|
||||
// Set a `realm` property to override the realm for only a single operation.
|
||||
// For example, creating a user in another realm:
|
||||
await this.kcAdminClient.users.create({
|
||||
realm: 'a-third-realm',
|
||||
username: 'username',
|
||||
email: 'user@example.com',
|
||||
});
|
||||
```
|
||||
|
||||
To refresh the access token provided by Keycloak, an OpenID client like [panva/node-openid-client](https://github.com/panva/node-openid-client) can be used like this:
|
||||
|
||||
```js
|
||||
import {Issuer} from 'openid-client';
|
||||
|
||||
const keycloakIssuer = await Issuer.discover(
|
||||
'http://localhost:8080/realms/master',
|
||||
);
|
||||
|
||||
const client = new keycloakIssuer.Client({
|
||||
client_id: 'admin-cli', // Same as `clientId` passed to client.auth()
|
||||
token_endpoint_auth_method: 'none', // to send only client_id in the header
|
||||
});
|
||||
|
||||
// Use the grant type 'password'
|
||||
let tokenSet = await client.grant({
|
||||
grant_type: 'password',
|
||||
username: 'admin',
|
||||
password: 'admin',
|
||||
});
|
||||
|
||||
// Periodically using refresh_token grant flow to get new access token here
|
||||
setInterval(async () => {
|
||||
const refreshToken = tokenSet.refresh_token;
|
||||
tokenSet = await client.refresh(refreshToken);
|
||||
kcAdminClient.setAccessToken(tokenSet.access_token);
|
||||
}, 58 * 1000); // 58 seconds
|
||||
```
|
||||
|
||||
In cases where you don't have a refresh token, eg. in a client credentials flow, you can simply call `kcAdminClient.auth` to get a new access token, like this:
|
||||
|
||||
```js
|
||||
const credentials = {
|
||||
grantType: 'client_credentials',
|
||||
clientId: 'clientId',
|
||||
clientSecret: 'some-client-secret-uuid',
|
||||
};
|
||||
await kcAdminClient.auth(credentials);
|
||||
|
||||
setInterval(() => kcAdminClient.auth(credentials), 58 * 1000); // 58 seconds
|
||||
```
|
||||
|
||||
## Building and running the tests
|
||||
|
||||
To build the source do a build:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
Start the Keycloak server:
|
||||
|
||||
```bash
|
||||
npm run server:start
|
||||
```
|
||||
|
||||
If you started your container manually make sure there is an admin user named 'admin' with password 'admin'.
|
||||
Then start the tests with:
|
||||
|
||||
```bash
|
||||
npm test
|
||||
```
|
||||
|
||||
## Supported APIs
|
||||
|
||||
### [Realm admin](https://www.keycloak.org/docs-api/20.0.2/rest-api/index.html#_realms_admin_resource)
|
||||
|
||||
Demo code: https://github.com/keycloak/keycloak/blob/main/js/libs/keycloak-admin-client/test/realms.spec.ts
|
||||
|
||||
- Import a realm from a full representation of that realm (`POST /`)
|
||||
- Get the top-level representation of the realm (`GET /{realm}`)
|
||||
- Update the top-level information of the realm (`PUT /{realm}`)
|
||||
- Delete the realm (`DELETE /{realm}`)
|
||||
- Partial export of existing realm into a JSON file (`POST /{realm}/partial-export`)
|
||||
- Get users management permissions (`GET /{realm}/users-management-permissions`)
|
||||
- Enable users management permissions (`PUT /{realm}/users-management-permissions`)
|
||||
- Get events (`GET /{realm}/events`)
|
||||
- Get admin events (`GET /{realm}/admin-events`)
|
||||
- Remove all user sessions (`POST /{realm}/logout-all`)
|
||||
- Remove a specific user session (`DELETE /{realm}/sessions/{session}`)
|
||||
- Get client policies policies (`GET /{realm}/client-policies/policies`)
|
||||
- Update client policies policies (`PUT /{realm}/client-policies/policies`)
|
||||
- Get client policies profiles (`GET /{realm}/client-policies/profiles`)
|
||||
- Update client policies profiles (`PUT /{realm}/client-policies/profiles`)
|
||||
- Get a group by path (`GET /{realm}/group-by-path/{path}`)
|
||||
### [Role](https://www.keycloak.org/docs-api/20.0.2/rest-api/index.html#_roles_resource)
|
||||
|
||||
Demo code: https://github.com/keycloak/keycloak/blob/main/js/libs/keycloak-admin-client/test/roles.spec.ts
|
||||
|
||||
- Create a new role for the realm (`POST /{realm}/roles`)
|
||||
- Get all roles for the realm (`GET /{realm}/roles`)
|
||||
- Get a role by name (`GET /{realm}/roles/{role-name}`)
|
||||
- Update a role by name (`PUT /{realm}/roles/{role-name}`)
|
||||
- Delete a role by name (`DELETE /{realm}/roles/{role-name}`)
|
||||
- Get all users in a role by name for the realm (`GET /{realm}/roles/{role-name}/users`)
|
||||
|
||||
### [Roles (by ID)](https://www.keycloak.org/docs-api/20.0.2/rest-api/index.html#_roles_by_id_resource)
|
||||
|
||||
- Get a specific role (`GET /{realm}/roles-by-id/{role-id}`)
|
||||
- Update the role (`PUT /{realm}/roles-by-id/{role-id}`)
|
||||
- Delete the role (`DELETE /{realm}/roles-by-id/{role-id}`)
|
||||
- Make the role a composite role by associating some child roles(`POST /{realm}/roles-by-id/{role-id}/composites`)
|
||||
- Get role’s children Returns a set of role’s children provided the role is a composite. (`GET /{realm}/roles-by-id/{role-id}/composites`)
|
||||
- Remove a set of roles from the role’s composite (`DELETE /{realm}/roles-by-id/{role-id}/composites`)
|
||||
- Get client-level roles for the client that are in the role’s composite (`GET /{realm}/roles-by-id/{role-id}/composites/clients/{client}`)
|
||||
- Get realm-level roles that are in the role’s composite (`GET /{realm}/roles-by-id/{role-id}/composites/realm`)
|
||||
|
||||
### [User](https://www.keycloak.org/docs-api/20.0.2/rest-api/index.html#_users_resource)
|
||||
|
||||
Demo code: https://github.com/keycloak/keycloak/blob/main/js/libs/keycloak-admin-client/test/users.spec.ts
|
||||
|
||||
- Create a new user (`POST /{realm}/users`)
|
||||
- Get users Returns a list of users, filtered according to query parameters (`GET /{realm}/users`)
|
||||
- Get representation of the user (`GET /{realm}/users/{id}`)
|
||||
- Update the user (`PUT /{realm}/users/{id}`)
|
||||
- Delete the user (`DELETE /{realm}/users/{id}`)
|
||||
- Count users (`GET /{realm}/users/count`)
|
||||
- Send a update account email to the user An email contains a link the user can click to perform a set of required actions. (`PUT /{realm}/users/{id}/execute-actions-email`)
|
||||
- Get user groups (`GET /{realm}/users/{id}/groups`)
|
||||
- Add user to group (`PUT /{realm}/users/{id}/groups/{groupId}`)
|
||||
- Delete user from group (`DELETE /{realm}/users/{id}/groups/{groupId}`)
|
||||
- Remove TOTP from the user (`PUT /{realm}/users/{id}/remove-totp`)
|
||||
- Set up a temporary password for the user User will have to reset the temporary password next time they log in. (`PUT /{realm}/users/{id}/reset-password`)
|
||||
- Send an email-verification email to the user An email contains a link the user can click to verify their email address. (`PUT /{realm}/users/{id}/send-verify-email`)
|
||||
- Update a credential label for a user (`PUT /{realm}/users/{id}/credentials/{credentialId}/userLabel`)
|
||||
- Move a credential to a position behind another credential (`POST /{realm}/users/{id}/credentials/{credentialId}/moveAfter/{newPreviousCredentialId}`)
|
||||
- Move a credential to a first position in the credentials list of the user (`PUT /{realm}/users/{id}/credentials/{credentialId}/moveToFirst`)
|
||||
|
||||
### User group-mapping
|
||||
|
||||
Demo code: https://github.com/keycloak/keycloak/blob/main/js/libs/keycloak-admin-client/test/users.spec.ts#L178
|
||||
|
||||
- Add user to group (`PUT /{id}/groups/{groupId}`)
|
||||
- List all user groups (`GET /{id}/groups`)
|
||||
- Count user groups (`GET /{id}/groups/count`)
|
||||
- Remove user from group (`DELETE /{id}/groups/{groupId}`)
|
||||
|
||||
### User role-mapping
|
||||
|
||||
Demo code: https://github.com/keycloak/keycloak/blob/main/js/libs/keycloak-admin-client/test/users.spec.ts#L352
|
||||
|
||||
- Get user role-mappings (`GET /{realm}/users/{id}/role-mappings`)
|
||||
- Add realm-level role mappings to the user (`POST /{realm}/users/{id}/role-mappings/realm`)
|
||||
- Get realm-level role mappings (`GET /{realm}/users/{id}/role-mappings/realm`)
|
||||
- Delete realm-level role mappings (`DELETE /{realm}/users/{id}/role-mappings/realm`)
|
||||
- Get realm-level roles that can be mapped (`GET /{realm}/users/{id}/role-mappings/realm/available`)
|
||||
- Get effective realm-level role mappings This will recurse all composite roles to get the result. (`GET /{realm}/users/{id}/role-mappings/realm/composite`)
|
||||
|
||||
### [Group](https://www.keycloak.org/docs-api/20.0.2/rest-api/index.html#_groups_resource)
|
||||
|
||||
Demo code: https://github.com/keycloak/keycloak/blob/main/js/libs/keycloak-admin-client/test/groups.spec.ts
|
||||
|
||||
- Create (`POST /{realm}/groups`)
|
||||
- List (`GET /{realm}/groups`)
|
||||
- Get one (`GET /{realm}/groups/{id}`)
|
||||
- Update (`PUT /{realm}/groups/{id}`)
|
||||
- Delete (`DELETE /{realm}/groups/{id}`)
|
||||
- Count (`GET /{realm}/groups/count`)
|
||||
- List members (`GET /{realm}/groups/{id}/members`)
|
||||
- Set or create child (`POST /{realm}/groups/{id}/children`)
|
||||
|
||||
### Group role-mapping
|
||||
|
||||
Demo code: https://github.com/keycloak/keycloak/blob/main/js/libs/keycloak-admin-client/test/groups.spec.ts#L103
|
||||
|
||||
- Get group role-mappings (`GET /{realm}/groups/{id}/role-mappings`)
|
||||
- Add realm-level role mappings to the group (`POST /{realm}/groups/{id}/role-mappings/realm`)
|
||||
- Get realm-level role mappings (`GET /{realm}/groups/{id}/role-mappings/realm`)
|
||||
- Delete realm-level role mappings (`DELETE /{realm}/groups/{id}/role-mappings/realm`)
|
||||
- Get realm-level roles that can be mapped (`GET /{realm}/groups/{id}/role-mappings/realm/available`)
|
||||
- Get effective realm-level role mappings This will recurse all composite roles to get the result. (`GET /{realm}/groups/{id}/role-mappings/realm/composite`)
|
||||
|
||||
### [Client](https://www.keycloak.org/docs-api/20.0.2/rest-api/index.html#_clients_resource)
|
||||
|
||||
Demo code: https://github.com/keycloak/keycloak/blob/main/js/libs/keycloak-admin-client/test/clients.spec.ts
|
||||
|
||||
- Create a new client (`POST /{realm}/clients`)
|
||||
- Get clients belonging to the realm (`GET /{realm}/clients`)
|
||||
- Get representation of the client (`GET /{realm}/clients/{id}`)
|
||||
- Update the client (`PUT /{realm}/clients/{id}`)
|
||||
- Delete the client (`DELETE /{realm}/clients/{id}`)
|
||||
|
||||
### [Client roles](https://www.keycloak.org/docs-api/20.0.2/rest-api/index.html#_roles_resource)
|
||||
|
||||
Demo code: https://github.com/keycloak/keycloak/blob/main/js/libs/keycloak-admin-client/test/clients.spec.ts
|
||||
|
||||
- Create a new role for the client (`POST /{realm}/clients/{id}/roles`)
|
||||
- Get all roles for the client (`GET /{realm}/clients/{id}/roles`)
|
||||
- Get a role by name (`GET /{realm}/clients/{id}/roles/{role-name}`)
|
||||
- Update a role by name (`PUT /{realm}/clients/{id}/roles/{role-name}`)
|
||||
- Delete a role by name (`DELETE /{realm}/clients/{id}/roles/{role-name}`)
|
||||
|
||||
### [Client role-mapping for group](https://www.keycloak.org/docs-api/20.0.2/rest-api/index.html#_client_role_mappings_resource)
|
||||
|
||||
Demo code: https://github.com/keycloak/keycloak/blob/main/js/libs/keycloak-admin-client/test/groups.spec.ts#L192
|
||||
|
||||
- Add client-level roles to the group role mapping (`POST /{realm}/groups/{id}/role-mappings/clients/{client}`)
|
||||
- Get client-level role mappings for the group (`GET /{realm}/groups/{id}/role-mappings/clients/{client}`)
|
||||
- Delete client-level roles from group role mapping (`DELETE /{realm}/groups/{id}/role-mappings/clients/{client}`)
|
||||
- Get available client-level roles that can be mapped to the group (`GET /{realm}/groups/{id}/role-mappings/clients/{client}/available`)
|
||||
- Get effective client-level role mappings This will recurse all composite roles to get the result. (`GET /{realm}/groups/{id}/role-mappings/clients/{client}/composite`)
|
||||
|
||||
### [Client role-mapping for user](https://www.keycloak.org/docs-api/20.0.2/rest-api/index.html#_client_role_mappings_resource)
|
||||
|
||||
Demo code: https://github.com/keycloak/keycloak/blob/main/js/libs/keycloak-admin-client/test/users.spec.ts#L352
|
||||
|
||||
- Add client-level roles to the user role mapping (`POST /{realm}/users/{id}/role-mappings/clients/{client}`)
|
||||
- Get client-level role mappings for the user (`GET /{realm}/users/{id}/role-mappings/clients/{client}`)
|
||||
- Delete client-level roles from user role mapping (`DELETE /{realm}/users/{id}/role-mappings/clients/{client}`)
|
||||
- Get available client-level roles that can be mapped to the user (`GET /{realm}/users/{id}/role-mappings/clients/{client}/available`)
|
||||
- Get effective client-level role mappings This will recurse all composite roles to get the result. (`GET /{realm}/users/{id}/role-mappings/clients/{client}/composite`)
|
||||
|
||||
### [Client Attribute Certificate](https://www.keycloak.org/docs-api/20.0.2/rest-api/index.html#_client_attribute_certificate_resource)
|
||||
|
||||
- Get key info (`GET /{realm}/clients/{id}/certificates/{attr}`)
|
||||
- Get a keystore file for the client, containing private key and public certificate (`POST /{realm}/clients/{id}/certificates/{attr}/download`)
|
||||
- Generate a new certificate with new key pair (`POST /{realm}/clients/{id}/certificates/{attr}/generate`)
|
||||
- Generate a new keypair and certificate, and get the private key file Generates a keypair and certificate and serves the private key in a specified keystore format. (`POST /{realm}/clients/{id}/certificates/{attr}/generate-and-download`)
|
||||
- Upload certificate and eventually private key (`POST /{realm}/clients/{id}/certificates/{attr}/upload`)
|
||||
- Upload only certificate, not private key (`POST /{realm}/clients/{id}/certificates/{attr}/upload-certificate`)
|
||||
|
||||
### [Identity Providers](https://www.keycloak.org/docs-api/20.0.2/rest-api/index.html#_identity_providers_resource)
|
||||
|
||||
Demo code: https://github.com/keycloak/keycloak/blob/main/js/libs/keycloak-admin-client/test/idp.spec.ts
|
||||
|
||||
- Create a new identity provider (`POST /{realm}/identity-provider/instances`)
|
||||
- Get identity providers (`GET /{realm}/identity-provider/instances`)
|
||||
- Get the identity provider (`GET /{realm}/identity-provider/instances/{alias}`)
|
||||
- Update the identity provider (`PUT /{realm}/identity-provider/instances/{alias}`)
|
||||
- Delete the identity provider (`DELETE /{realm}/identity-provider/instances/{alias}`)
|
||||
- Find identity provider factory (`GET /{realm}/identity-provider/providers/{providerId}`)
|
||||
- Create a new identity provider mapper (`POST /{realm}/identity-provider/instances/{alias}/mappers`)
|
||||
- Get identity provider mappers (`GET /{realm}/identity-provider/instances/{alias}/mappers`)
|
||||
- Get the identity provider mapper (`GET /{realm}/identity-provider/instances/{alias}/mappers/{id}`)
|
||||
- Update the identity provider mapper (`PUT /{realm}/identity-provider/instances/{alias}/mappers/{id}`)
|
||||
- Delete the identity provider mapper (`DELETE /{realm}/identity-provider/instances/{alias}/mappers/{id}`)
|
||||
- Find the identity provider mapper types (`GET /{realm}/identity-provider/instances/{alias}/mapper-types`)
|
||||
|
||||
### [Client Scopes](https://www.keycloak.org/docs-api/20.0.2/rest-api/index.html#_client_scopes_resource)
|
||||
|
||||
Demo code: https://github.com/keycloak/keycloak/blob/main/js/libs/keycloak-admin-client/test/clientScopes.spec.ts
|
||||
|
||||
- Create a new client scope (`POST /{realm}/client-scopes`)
|
||||
- Get client scopes belonging to the realm (`GET /{realm}/client-scopes`)
|
||||
- Get representation of the client scope (`GET /{realm}/client-scopes/{id}`)
|
||||
- Update the client scope (`PUT /{realm}/client-scopes/{id}`)
|
||||
- Delete the client scope (`DELETE /{realm}/client-scopes/{id}`)
|
||||
|
||||
### [Client Scopes for realm](https://www.keycloak.org/docs-api/20.0.2/rest-api/index.html#_client_scopes_resource)
|
||||
|
||||
Demo code: https://github.com/keycloak/keycloak/blob/main/js/libs/keycloak-admin-client/test/clientScopes.spec.ts
|
||||
|
||||
- Get realm default client scopes (`GET /{realm}/default-default-client-scopes`)
|
||||
- Add realm default client scope (`PUT /{realm}/default-default-client-scopes/{id}`)
|
||||
- Delete realm default client scope (`DELETE /{realm}/default-default-client-scopes/{id}`)
|
||||
- Get realm optional client scopes (`GET /{realm}/default-optional-client-scopes`)
|
||||
- Add realm optional client scope (`PUT /{realm}/default-optional-client-scopes/{id}`)
|
||||
- Delete realm optional client scope (`DELETE /{realm}/default-optional-client-scopes/{id}`)
|
||||
|
||||
### [Client Scopes for client](https://www.keycloak.org/docs-api/20.0.2/rest-api/index.html#_client_scopes_resource)
|
||||
|
||||
Demo code: https://github.com/keycloak/keycloak/blob/main/js/libs/keycloak-admin-client/test/clientScopes.spec.ts
|
||||
|
||||
- Get default client scopes (`GET /{realm}/clients/{id}/default-client-scopes`)
|
||||
- Add default client scope (`PUT /{realm}/clients/{id}/default-client-scopes/{clientScopeId}`)
|
||||
- Delete default client scope (`DELETE /{realm}/clients/{id}/default-client-scopes/{clientScopeId}`)
|
||||
- Get optional client scopes (`GET /{realm}/clients/{id}/optional-client-scopes`)
|
||||
- Add optional client scope (`PUT /{realm}/clients/{id}/optional-client-scopes/{clientScopeId}`)
|
||||
- Delete optional client scope (`DELETE /{realm}/clients/{id}/optional-client-scopes/{clientScopeId}`)
|
||||
|
||||
### [Scope Mappings for client scopes](https://www.keycloak.org/docs-api/20.0.2/rest-api/index.html#_scope_mappings_resource)
|
||||
|
||||
Demo code: https://github.com/keycloak/keycloak/blob/main/js/libs/keycloak-admin-client/test/clientScopes.spec.ts
|
||||
|
||||
- Get all scope mappings for the client (`GET /{realm}/client-scopes/{id}/scope-mappings`)
|
||||
- Add client-level roles to the client’s scope (`POST /{realm}/client-scopes/{id}/scope-mappings/clients/{client}`)
|
||||
- Get the roles associated with a client’s scope (`GET /{realm}/client-scopes/{id}/scope-mappings/clients/{client}`)
|
||||
- The available client-level roles (`GET /{realm}/client-scopes/{id}/scope-mappings/clients/{client}/available`)
|
||||
- Get effective client roles (`GET /{realm}/client-scopes/{id}/scope-mappings/clients/{client}/composite`)
|
||||
- Remove client-level roles from the client’s scope. (`DELETE /{realm}/client-scopes/{id}/scope-mappings/clients/{client}`)
|
||||
- Add a set of realm-level roles to the client’s scope (`POST /{realm}/client-scopes/{id}/scope-mappings/realm`)
|
||||
- Get realm-level roles associated with the client’s scope (`GET /{realm}/client-scopes/{id}/scope-mappings/realm`)
|
||||
- Remove a set of realm-level roles from the client’s scope (`DELETE /{realm}/client-scopes/{id}/scope-mappings/realm`)
|
||||
- Get realm-level roles that are available to attach to this client’s scope (`GET /{realm}/client-scopes/{id}/scope-mappings/realm/available`)
|
||||
- Get effective realm-level roles associated with the client’s scope (`GET /{realm}/client-scopes/{id}/scope-mappings/realm/composite`)
|
||||
|
||||
### [Scope Mappings for clients](https://www.keycloak.org/docs-api/20.0.2/rest-api/index.html#_scope_mappings_resource)
|
||||
|
||||
Demo code: https://github.com/keycloak/keycloak/blob/main/js/libs/keycloak-admin-client/test/clientScopes.spec.ts
|
||||
|
||||
- Get all scope mappings for the client (`GET /{realm}/clients/{id}/scope-mappings`)
|
||||
- Add client-level roles to the client’s scope (`POST /{realm}/clients/{id}/scope-mappings/clients/{client}`)
|
||||
- Get the roles associated with a client’s scope (`GET /{realm}/clients/{id}/scope-mappings/clients/{client}`)
|
||||
- Remove client-level roles from the client’s scope. (`DELETE /{realm}/clients/{id}/scope-mappings/clients/{client}`)
|
||||
- The available client-level roles (`GET /{realm}/clients/{id}/scope-mappings/clients/{client}/available`)
|
||||
- Get effective client roles (`GET /{realm}/clients/{id}/scope-mappings/clients/{client}/composite`)
|
||||
- Add a set of realm-level roles to the client’s scope (`POST /{realm}/clients/{id}/scope-mappings/realm`)
|
||||
- Get realm-level roles associated with the client’s scope (`GET /{realm}/clients/{id}/scope-mappings/realm`)
|
||||
- Remove a set of realm-level roles from the client’s scope (`DELETE /{realm}/clients/{id}/scope-mappings/realm`)
|
||||
- Get realm-level roles that are available to attach to this client’s scope (`GET /{realm}/clients/{id}/scope-mappings/realm/available`)
|
||||
- Get effective realm-level roles associated with the client’s scope (`GET /{realm}/clients/{id}/scope-mappings/realm/composite`)
|
||||
|
||||
### [Protocol Mappers for client scopes](https://www.keycloak.org/docs-api/20.0.2/rest-api/index.html#_protocol_mappers_resource)
|
||||
|
||||
Demo code: https://github.com/keycloak/keycloak/blob/main/js/libs/keycloak-admin-client/test/clientScopes.spec.ts
|
||||
|
||||
- Create multiple mappers (`POST /{realm}/client-scopes/{id}/protocol-mappers/add-models`)
|
||||
- Create a mapper (`POST /{realm}/client-scopes/{id}/protocol-mappers/models`)
|
||||
- Get mappers (`GET /{realm}/client-scopes/{id}/protocol-mappers/models`)
|
||||
- Get mapper by id (`GET /{realm}/client-scopes/{id}/protocol-mappers/models/{mapperId}`)
|
||||
- Update the mapper (`PUT /{realm}/client-scopes/{id}/protocol-mappers/models/{mapperId}`)
|
||||
- Delete the mapper (`DELETE /{realm}/client-scopes/{id}/protocol-mappers/models/{mapperId}`)
|
||||
- Get mappers by name for a specific protocol (`GET /{realm}/client-scopes/{id}/protocol-mappers/protocol/{protocol}`)
|
||||
|
||||
### [Protocol Mappers for clients](https://www.keycloak.org/docs-api/20.0.2/rest-api/index.html#_protocol_mappers_resource)
|
||||
|
||||
Demo code: https://github.com/keycloak/keycloak/blob/main/js/libs/keycloak-admin-client/test/clients.spec.ts
|
||||
|
||||
- Create multiple mappers (`POST /{realm}/clients/{id}/protocol-mappers/add-models`)
|
||||
- Create a mapper (`POST /{realm}/clients/{id}/protocol-mappers/models`)
|
||||
- Get mappers (`GET /{realm}/clients/{id}/protocol-mappers/models`)
|
||||
- Get mapper by id (`GET /{realm}/clients/{id}/protocol-mappers/models/{mapperId}`)
|
||||
- Update the mapper (`PUT /{realm}/clients/{id}/protocol-mappers/models/{mapperId}`)
|
||||
- Delete the mapper (`DELETE /{realm}/clients/{id}/protocol-mappers/models/{mapperId}`)
|
||||
- Get mappers by name for a specific protocol (`GET /{realm}/clients/{id}/protocol-mappers/protocol/{protocol}`)
|
||||
|
||||
### [Component]()
|
||||
|
||||
Supported for [user federation](https://www.keycloak.org/docs/latest/server_admin/index.html#_user-storage-federation). Demo code: https://github.com/keycloak/keycloak/blob/main/js/libs/keycloak-admin-client/test/components.spec.ts
|
||||
|
||||
- Create (`POST /{realm}/components`)
|
||||
- List (`GET /{realm}/components`)
|
||||
- Get (`GET /{realm}/components/{id}`)
|
||||
- Update (`PUT /{realm}/components/{id}`)
|
||||
- Delete (`DELETE /{realm}/components/{id}`)
|
||||
|
||||
### [Sessions for clients]()
|
||||
|
||||
Demo code: https://github.com/keycloak/keycloak/blob/main/js/libs/keycloak-admin-client/test/clients.spec.ts
|
||||
|
||||
- List user sessions for a specific client (`GET /{realm}/clients/{id}/user-sessions`)
|
||||
- List offline sessions for a specific client (`GET /{realm}/clients/{id}/offline-sessions`)
|
||||
- Get user session count for a specific client (`GET /{realm}/clients/{id}/session-count`)
|
||||
- List offline session count for a specific client (`GET /{realm}/clients/{id}/offline-session-count`)
|
||||
|
||||
### [Authentication Management: Required actions](https://www.keycloak.org/docs-api/20.0.2/rest-api/index.html#_authentication_management_resource)
|
||||
|
||||
Demo code: https://github.com/keycloak/keycloak/blob/main/js/libs/keycloak-admin-client/test/authenticationManagement.spec.ts
|
||||
|
||||
- Register a new required action (`POST /{realm}/authentication/register-required-action`)
|
||||
- Get required actions. Returns a list of required actions. (`GET /{realm}/authentication/required-actions`)
|
||||
- Get required action for alias (`GET /{realm}/authentication/required-actions/{alias}`)
|
||||
- Update required action (`PUT /{realm}/authentication/required-actions/{alias}`)
|
||||
- Delete required action (`DELETE /{realm}/authentication/required-actions/{alias}`)
|
||||
- Lower required action’s priority (`POST /{realm}/authentication/required-actions/{alias}/lower-priority`)
|
||||
- Raise required action’s priority (`POST /{realm}/authentication/required-actions/{alias}/raise-priority`)
|
||||
- Get unregistered required actions Returns a list of unregistered required actions. (`GET /{realm}/authentication/unregistered-required-actions`)
|
||||
|
||||
### [Authorization: Permission](https://www.keycloak.org/docs/8.0/authorization_services/#_overview)
|
||||
|
||||
Demo code: https://github.com/keycloak/keycloak/blob/main/js/libs/keycloak-admin-client/test/clients.spec.ts
|
||||
|
||||
- Create permission (`POST /{realm}/clients/{id}/authz/resource-server/permission/{type}`)
|
||||
- Get permission (`GET /{realm}/clients/{id}/authz/resource-server/permission/{type}/{permissionId}`)
|
||||
- Update permission (`PUT /{realm}/clients/{id}/authz/resource-server/permission/{type}/{permissionId}`)
|
||||
- Delete permission (`DELETE /{realm}/clients/{id}/authz/resource-server/permission/{type}/{permissionId}`)
|
||||
|
||||
### [Authorization: Policy](https://www.keycloak.org/docs/8.0/authorization_services/#_overview)
|
||||
|
||||
Demo code: https://github.com/keycloak/keycloak/blob/main/js/libs/keycloak-admin-client/test/clients.spec.ts
|
||||
|
||||
- Create policy (`POST /{realm}/clients/{id}/authz/resource-server/policy/{type}`)
|
||||
- Get policy (`GET /{realm}/clients/{id}/authz/resource-server/policy/{type}/{policyId}`)
|
||||
- Get policy by name (`GET /{realm}/clients/{id}/authz/resource-server/policy/search`)
|
||||
- Update policy (`PUT /{realm}/clients/{id}/authz/resource-server/policy/{type}/{policyId}`)
|
||||
- Delete policy (`DELETE /{realm}/clients/{id}/authz/resource-server/policy/{policyId}`)
|
||||
|
||||
### [Attack Detection](https://www.keycloak.org/docs-api/20.0.2/rest-api/index.html#_attack_detection_resource)
|
||||
|
||||
Demo code: https://github.com/keycloak/keycloak/blob/main/js/libs/keycloak-admin-client/test/attackDetection.spec.ts
|
||||
|
||||
- Clear any user login failures for all users This can release temporary disabled users (`DELETE /{realm}/attack-detection/brute-force/users`)
|
||||
- Get status of a username in brute force detection (`GET /{realm}/attack-detection/brute-force/users/{userId}`)
|
||||
- Clear any user login failures for the user This can release temporary disabled user (`DELETE /{realm}/attack-detection/brute-force/users/{userId}`)
|
||||
|
||||
## Not yet supported
|
||||
|
||||
- [Authentication Management](https://www.keycloak.org/docs-api/20.0.2/rest-api/index.html#_authentication_management_resource)
|
||||
- [Client Initial Access](https://www.keycloak.org/docs-api/20.0.2/rest-api/index.html#_client_initial_access_resource)
|
||||
- [Client Registration Policy](https://www.keycloak.org/docs-api/20.0.2/rest-api/index.html#_client_registration_policy_resource)
|
||||
- [Key](https://www.keycloak.org/docs-api/20.0.2/rest-api/index.html#_key_resource)
|
||||
- [User Storage Provider](https://www.keycloak.org/docs-api/20.0.2/rest-api/index.html#_user_storage_provider_resource)
|
||||
|
||||
## Maintainers
|
||||
|
||||
This repo is originally developed by [Canner](https://www.cannercms.com) and [InfuseAI](https://infuseai.io) before being transferred under keycloak organization.
|
65
js/libs/keycloak-admin-client/package.json
Normal file
65
js/libs/keycloak-admin-client/package.json
Normal file
|
@ -0,0 +1,65 @@
|
|||
{
|
||||
"name": "@keycloak/keycloak-admin-client",
|
||||
"version": "999.0.0-dev",
|
||||
"description": "A client to interact with Keycloak's Administration API",
|
||||
"type": "module",
|
||||
"main": "lib/index.js",
|
||||
"files": [
|
||||
"lib"
|
||||
],
|
||||
"types": "lib/index.d.ts",
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "wireit",
|
||||
"lint": "wireit",
|
||||
"test": "wireit",
|
||||
"prepublishOnly": "npm run build"
|
||||
},
|
||||
"wireit": {
|
||||
"build": {
|
||||
"command": "tsc --pretty",
|
||||
"files": [
|
||||
"src/**",
|
||||
"package.json",
|
||||
"tsconfig.json"
|
||||
],
|
||||
"output": [
|
||||
"lib/**"
|
||||
]
|
||||
},
|
||||
"lint": {
|
||||
"command": "eslint . --ext js,jsx,mjs,ts,tsx"
|
||||
},
|
||||
"test": {
|
||||
"command": "TS_NODE_PROJECT=tsconfig.test.json mocha --recursive \"test/**/*.spec.ts\" --timeout 10000"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"camelize-ts": "^2.2.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"url-join": "^5.0.0",
|
||||
"url-template": "^3.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@faker-js/faker": "^7.6.0",
|
||||
"@types/chai": "^4.3.4",
|
||||
"@types/lodash-es": "^4.17.6",
|
||||
"@types/mocha": "^10.0.1",
|
||||
"@types/node": "^18.11.18",
|
||||
"chai": "^4.3.7",
|
||||
"mocha": "^10.2.0",
|
||||
"ts-node": "^10.9.1"
|
||||
},
|
||||
"author": {
|
||||
"name": "Red Hat, Inc.",
|
||||
"url": "https://www.keycloak.org/"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/keycloak/keycloak.git"
|
||||
},
|
||||
"homepage": "https://www.keycloak.org/"
|
||||
}
|
143
js/libs/keycloak-admin-client/src/client.ts
Normal file
143
js/libs/keycloak-admin-client/src/client.ts
Normal file
|
@ -0,0 +1,143 @@
|
|||
import type { RequestArgs } from "./resources/agent.js";
|
||||
import { AttackDetection } from "./resources/attackDetection.js";
|
||||
import { AuthenticationManagement } from "./resources/authenticationManagement.js";
|
||||
import { Cache } from "./resources/cache.js";
|
||||
import { ClientPolicies } from "./resources/clientPolicies.js";
|
||||
import { Clients } from "./resources/clients.js";
|
||||
import { ClientScopes } from "./resources/clientScopes.js";
|
||||
import { Components } from "./resources/components.js";
|
||||
import { Groups } from "./resources/groups.js";
|
||||
import { IdentityProviders } from "./resources/identityProviders.js";
|
||||
import { Realms } from "./resources/realms.js";
|
||||
import { Roles } from "./resources/roles.js";
|
||||
import { ServerInfo } from "./resources/serverInfo.js";
|
||||
import { Sessions } from "./resources/sessions.js";
|
||||
import { Users } from "./resources/users.js";
|
||||
import { UserStorageProvider } from "./resources/userStorageProvider.js";
|
||||
import { WhoAmI } from "./resources/whoAmI.js";
|
||||
import { Credentials, getToken } from "./utils/auth.js";
|
||||
import { defaultBaseUrl, defaultRealm } from "./utils/constants.js";
|
||||
|
||||
export interface TokenProvider {
|
||||
getAccessToken: () => Promise<string | undefined>;
|
||||
}
|
||||
|
||||
export interface ConnectionConfig {
|
||||
baseUrl?: string;
|
||||
realmName?: string;
|
||||
requestOptions?: RequestInit;
|
||||
requestArgOptions?: Pick<RequestArgs, "catchNotFound">;
|
||||
}
|
||||
|
||||
export class KeycloakAdminClient {
|
||||
// Resources
|
||||
public users: Users;
|
||||
public userStorageProvider: UserStorageProvider;
|
||||
public groups: Groups;
|
||||
public roles: Roles;
|
||||
public clients: Clients;
|
||||
public realms: Realms;
|
||||
public clientScopes: ClientScopes;
|
||||
public clientPolicies: ClientPolicies;
|
||||
public identityProviders: IdentityProviders;
|
||||
public components: Components;
|
||||
public serverInfo: ServerInfo;
|
||||
public whoAmI: WhoAmI;
|
||||
public attackDetection: AttackDetection;
|
||||
public sessions: Sessions;
|
||||
public authenticationManagement: AuthenticationManagement;
|
||||
public cache: Cache;
|
||||
|
||||
// Members
|
||||
public baseUrl: string;
|
||||
public realmName: string;
|
||||
public accessToken?: string;
|
||||
public refreshToken?: string;
|
||||
|
||||
private requestOptions?: RequestInit;
|
||||
private globalRequestArgOptions?: Pick<RequestArgs, "catchNotFound">;
|
||||
private tokenProvider?: TokenProvider;
|
||||
|
||||
constructor(connectionConfig?: ConnectionConfig) {
|
||||
this.baseUrl = connectionConfig?.baseUrl || defaultBaseUrl;
|
||||
this.realmName = connectionConfig?.realmName || defaultRealm;
|
||||
this.requestOptions = connectionConfig?.requestOptions;
|
||||
this.globalRequestArgOptions = connectionConfig?.requestArgOptions;
|
||||
|
||||
// Initialize resources
|
||||
this.users = new Users(this);
|
||||
this.userStorageProvider = new UserStorageProvider(this);
|
||||
this.groups = new Groups(this);
|
||||
this.roles = new Roles(this);
|
||||
this.clients = new Clients(this);
|
||||
this.realms = new Realms(this);
|
||||
this.clientScopes = new ClientScopes(this);
|
||||
this.clientPolicies = new ClientPolicies(this);
|
||||
this.identityProviders = new IdentityProviders(this);
|
||||
this.components = new Components(this);
|
||||
this.authenticationManagement = new AuthenticationManagement(this);
|
||||
this.serverInfo = new ServerInfo(this);
|
||||
this.whoAmI = new WhoAmI(this);
|
||||
this.sessions = new Sessions(this);
|
||||
this.attackDetection = new AttackDetection(this);
|
||||
this.cache = new Cache(this);
|
||||
}
|
||||
|
||||
public async auth(credentials: Credentials) {
|
||||
const { accessToken, refreshToken } = await getToken({
|
||||
baseUrl: this.baseUrl,
|
||||
realmName: this.realmName,
|
||||
credentials,
|
||||
requestOptions: this.requestOptions,
|
||||
});
|
||||
this.accessToken = accessToken;
|
||||
this.refreshToken = refreshToken;
|
||||
}
|
||||
|
||||
public registerTokenProvider(provider: TokenProvider) {
|
||||
if (this.tokenProvider) {
|
||||
throw new Error("An existing token provider was already registered.");
|
||||
}
|
||||
|
||||
this.tokenProvider = provider;
|
||||
}
|
||||
|
||||
public setAccessToken(token: string) {
|
||||
this.accessToken = token;
|
||||
}
|
||||
|
||||
public async getAccessToken() {
|
||||
if (this.tokenProvider) {
|
||||
return this.tokenProvider.getAccessToken();
|
||||
}
|
||||
|
||||
return this.accessToken;
|
||||
}
|
||||
|
||||
public getRequestOptions() {
|
||||
return this.requestOptions;
|
||||
}
|
||||
|
||||
public getGlobalRequestArgOptions():
|
||||
| Pick<RequestArgs, "catchNotFound">
|
||||
| undefined {
|
||||
return this.globalRequestArgOptions;
|
||||
}
|
||||
|
||||
public setConfig(connectionConfig: ConnectionConfig) {
|
||||
if (
|
||||
typeof connectionConfig.baseUrl === "string" &&
|
||||
connectionConfig.baseUrl
|
||||
) {
|
||||
this.baseUrl = connectionConfig.baseUrl;
|
||||
}
|
||||
|
||||
if (
|
||||
typeof connectionConfig.realmName === "string" &&
|
||||
connectionConfig.realmName
|
||||
) {
|
||||
this.realmName = connectionConfig.realmName;
|
||||
}
|
||||
this.requestOptions = connectionConfig.requestOptions;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
export default interface AccessTokenAccess {
|
||||
roles?: string[];
|
||||
verify_caller?: boolean;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
export default interface PermissionRepresentation {
|
||||
claims?: { [index: string]: string };
|
||||
rsid?: string;
|
||||
rsname?: string;
|
||||
scopes?: string[];
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
export default interface AccessTokenCertConf {
|
||||
"x5t#S256"?: string;
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
import type AccessTokenAccess from "./AccessTokenAccess.js";
|
||||
import type AccessTokenCertConf from "./accessTokenCertConf.js";
|
||||
import type AddressClaimSet from "./addressClaimSet.js";
|
||||
import type { Category } from "./resourceServerRepresentation.js";
|
||||
|
||||
export default interface AccessTokenRepresentation {
|
||||
acr?: string;
|
||||
address?: AddressClaimSet;
|
||||
"allowed-origins"?: string[];
|
||||
at_hash?: string;
|
||||
auth_time?: number;
|
||||
authorization?: AccessTokenRepresentation;
|
||||
azp?: string;
|
||||
birthdate?: string;
|
||||
c_hash?: string;
|
||||
category?: Category;
|
||||
claims_locales?: string;
|
||||
cnf?: AccessTokenCertConf;
|
||||
email?: string;
|
||||
email_verified?: boolean;
|
||||
exp?: number;
|
||||
family_name?: string;
|
||||
gender: string;
|
||||
given_name?: string;
|
||||
iat?: number;
|
||||
iss?: string;
|
||||
jti?: string;
|
||||
locale?: string;
|
||||
middle_name?: string;
|
||||
name?: string;
|
||||
nbf?: number;
|
||||
nickname?: string;
|
||||
nonce?: string;
|
||||
otherClaims?: { [index: string]: string };
|
||||
phone_number?: string;
|
||||
phone_number_verified?: boolean;
|
||||
picture?: string;
|
||||
preferred_username?: string;
|
||||
profile?: string;
|
||||
realm_access?: AccessTokenAccess;
|
||||
s_hash?: string;
|
||||
scope?: string;
|
||||
session_state?: string;
|
||||
sub?: string;
|
||||
"trusted-certs"?: string[];
|
||||
typ?: string;
|
||||
updated_at?: number;
|
||||
website?: string;
|
||||
zoneinfo?: string;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
export default interface AddressClaimSet {
|
||||
country?: string;
|
||||
formatted?: string;
|
||||
locality?: string;
|
||||
postal_code?: string;
|
||||
region?: string;
|
||||
street_address?: string;
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
import type AuthDetailsRepresentation from "./authDetailsRepresentation.js";
|
||||
|
||||
export default interface AdminEventRepresentation {
|
||||
authDetails?: AuthDetailsRepresentation;
|
||||
error?: string;
|
||||
operationType?: string;
|
||||
realmId?: string;
|
||||
representation?: string;
|
||||
resourcePath?: string;
|
||||
resourceType?: string;
|
||||
time?: number;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
export default interface AuthDetailsRepresentation {
|
||||
clientId?: string;
|
||||
ipAddress?: string;
|
||||
realmId?: string;
|
||||
userId?: string;
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_authenticationexecutionexportrepresentation
|
||||
*/
|
||||
export default interface AuthenticationExecutionExportRepresentation {
|
||||
flowAlias?: string;
|
||||
userSetupAllowed?: boolean;
|
||||
authenticatorConfig?: string;
|
||||
authenticator?: string;
|
||||
requirement?: string;
|
||||
priority?: number;
|
||||
autheticatorFlow?: boolean;
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_authenticationexecutioninforepresentation
|
||||
*/
|
||||
export default interface AuthenticationExecutionInfoRepresentation {
|
||||
id?: string;
|
||||
requirement?: string;
|
||||
displayName?: string;
|
||||
alias?: string;
|
||||
description?: string;
|
||||
requirementChoices?: string[];
|
||||
configurable?: boolean;
|
||||
authenticationFlow?: boolean;
|
||||
providerId?: string;
|
||||
authenticationConfig?: string;
|
||||
flowId?: string;
|
||||
level?: number;
|
||||
index?: number;
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
import type AuthenticationExecutionExportRepresentation from "./authenticationExecutionExportRepresentation.js";
|
||||
|
||||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_authenticationflowrepresentation
|
||||
*/
|
||||
export default interface AuthenticationFlowRepresentation {
|
||||
id?: string;
|
||||
alias?: string;
|
||||
description?: string;
|
||||
providerId?: string;
|
||||
topLevel?: boolean;
|
||||
builtIn?: boolean;
|
||||
authenticationExecutions?: AuthenticationExecutionExportRepresentation[];
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_authenticatorconfiginforepresentation
|
||||
*/
|
||||
export default interface AuthenticatorConfigInfoRepresentation {
|
||||
name?: string;
|
||||
providerId?: string;
|
||||
helpText?: string;
|
||||
properties?: ConfigPropertyRepresentation[];
|
||||
}
|
||||
|
||||
export interface ConfigPropertyRepresentation {
|
||||
name?: string;
|
||||
label?: string;
|
||||
helpText?: string;
|
||||
type?: string;
|
||||
defaultValue?: any;
|
||||
options?: string[];
|
||||
secret?: boolean;
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_authenticatorconfigrepresentation
|
||||
*/
|
||||
export default interface AuthenticatorConfigRepresentation {
|
||||
id?: string;
|
||||
alias?: string;
|
||||
config?: { [index: string]: string };
|
||||
}
|
||||
|
||||
// we defined this type ourself as the original is just `{[index: string]: any}[]`
|
||||
// but the admin console does assume these properties are there.
|
||||
export interface AuthenticationProviderRepresentation {
|
||||
id?: string;
|
||||
displayName?: string;
|
||||
description?: string;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/#_certificaterepresentation
|
||||
*/
|
||||
export default interface CertificateRepresentation {
|
||||
privateKey?: string;
|
||||
publicKey?: string;
|
||||
certificate?: string;
|
||||
kid?: string;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_clientinitialaccesspresentation
|
||||
*/
|
||||
export default interface ClientInitialAccessPresentation {
|
||||
id?: string;
|
||||
token?: string;
|
||||
timestamp?: number;
|
||||
expiration?: number;
|
||||
count?: number;
|
||||
remainingCount?: number;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
import type ClientPolicyRepresentation from "./clientPolicyRepresentation.js";
|
||||
|
||||
/**
|
||||
* https://www.keycloak.org/docs-api/15.0/rest-api/#_clientpoliciesrepresentation
|
||||
*/
|
||||
export default interface ClientPoliciesRepresentation {
|
||||
policies?: ClientPolicyRepresentation[];
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/15.0/rest-api/#_clientpolicyconditionrepresentation
|
||||
*/
|
||||
export default interface ClientPolicyConditionRepresentation {
|
||||
condition?: string;
|
||||
configuration?: object;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/15.0/rest-api/#_clientpolicyexecutorrepresentation
|
||||
*/
|
||||
export default interface ClientPolicyExecutorRepresentation {
|
||||
configuration?: object;
|
||||
executor?: string;
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
import type ClientPolicyConditionRepresentation from "./clientPolicyConditionRepresentation.js";
|
||||
|
||||
/**
|
||||
* https://www.keycloak.org/docs-api/15.0/rest-api/#_clientpolicyrepresentation
|
||||
*/
|
||||
export default interface ClientPolicyRepresentation {
|
||||
conditions?: ClientPolicyConditionRepresentation[];
|
||||
description?: string;
|
||||
enabled?: boolean;
|
||||
name?: string;
|
||||
profiles?: string[];
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
import type ClientPolicyExecutorRepresentation from "./clientPolicyExecutorRepresentation.js";
|
||||
|
||||
/**
|
||||
* https://www.keycloak.org/docs-api/15.0/rest-api/#_clientprofilerepresentation
|
||||
*/
|
||||
export default interface ClientProfileRepresentation {
|
||||
description?: string;
|
||||
executors?: ClientPolicyExecutorRepresentation[];
|
||||
name?: string;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
import type ClientProfileRepresentation from "./clientProfileRepresentation.js";
|
||||
|
||||
/**
|
||||
* https://www.keycloak.org/docs-api/15.0/rest-api/#_clientprofilesrepresentation
|
||||
*/
|
||||
export default interface ClientProfilesRepresentation {
|
||||
globalProfiles?: ClientProfileRepresentation[];
|
||||
profiles?: ClientProfileRepresentation[];
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_clientrepresentation
|
||||
*/
|
||||
import type ResourceServerRepresentation from "./resourceServerRepresentation.js";
|
||||
import type ProtocolMapperRepresentation from "./protocolMapperRepresentation.js";
|
||||
|
||||
export default interface ClientRepresentation {
|
||||
access?: Record<string, boolean>;
|
||||
adminUrl?: string;
|
||||
attributes?: Record<string, any>;
|
||||
authenticationFlowBindingOverrides?: Record<string, any>;
|
||||
authorizationServicesEnabled?: boolean;
|
||||
authorizationSettings?: ResourceServerRepresentation;
|
||||
baseUrl?: string;
|
||||
bearerOnly?: boolean;
|
||||
clientAuthenticatorType?: string;
|
||||
clientId?: string;
|
||||
consentRequired?: boolean;
|
||||
defaultClientScopes?: string[];
|
||||
defaultRoles?: string[];
|
||||
description?: string;
|
||||
directAccessGrantsEnabled?: boolean;
|
||||
enabled?: boolean;
|
||||
alwaysDisplayInConsole?: boolean;
|
||||
frontchannelLogout?: boolean;
|
||||
fullScopeAllowed?: boolean;
|
||||
id?: string;
|
||||
implicitFlowEnabled?: boolean;
|
||||
name?: string;
|
||||
nodeReRegistrationTimeout?: number;
|
||||
notBefore?: number;
|
||||
optionalClientScopes?: string[];
|
||||
origin?: string;
|
||||
protocol?: string;
|
||||
protocolMappers?: ProtocolMapperRepresentation[];
|
||||
publicClient?: boolean;
|
||||
redirectUris?: string[];
|
||||
registeredNodes?: Record<string, any>;
|
||||
registrationAccessToken?: string;
|
||||
rootUrl?: string;
|
||||
secret?: string;
|
||||
serviceAccountsEnabled?: boolean;
|
||||
standardFlowEnabled?: boolean;
|
||||
surrogateAuthRequired?: boolean;
|
||||
webOrigins?: string[];
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_clientscoperepresentation
|
||||
*/
|
||||
import type ProtocolMapperRepresentation from "./protocolMapperRepresentation.js";
|
||||
|
||||
export default interface ClientScopeRepresentation {
|
||||
attributes?: Record<string, any>;
|
||||
description?: string;
|
||||
id?: string;
|
||||
name?: string;
|
||||
protocol?: string;
|
||||
protocolMappers?: ProtocolMapperRepresentation[];
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_componentexportrepresentation
|
||||
*/
|
||||
|
||||
export default interface ComponentExportRepresentation {
|
||||
id?: string;
|
||||
name?: string;
|
||||
providerId?: string;
|
||||
subType?: string;
|
||||
subComponents?: { [index: string]: ComponentExportRepresentation };
|
||||
config?: { [index: string]: string };
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_componentrepresentation
|
||||
*/
|
||||
|
||||
export default interface ComponentRepresentation {
|
||||
id?: string;
|
||||
name?: string;
|
||||
providerId?: string;
|
||||
providerType?: string;
|
||||
parentId?: string;
|
||||
subType?: string;
|
||||
config?: { [index: string]: string | string[] };
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
import type { ConfigPropertyRepresentation } from "./configPropertyRepresentation.js";
|
||||
|
||||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_componenttyperepresentation
|
||||
*/
|
||||
export default interface ComponentTypeRepresentation {
|
||||
id: string;
|
||||
helpText: string;
|
||||
properties: ConfigPropertyRepresentation[];
|
||||
metadata: { [index: string]: any };
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_configpropertyrepresentation
|
||||
*/
|
||||
export interface ConfigPropertyRepresentation {
|
||||
name?: string;
|
||||
label?: string;
|
||||
helpText?: string;
|
||||
type?: string;
|
||||
defaultValue?: object;
|
||||
options?: string[];
|
||||
secret?: boolean;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_credentialrepresentation
|
||||
*/
|
||||
|
||||
export default interface CredentialRepresentation {
|
||||
createdDate?: number;
|
||||
credentialData?: string;
|
||||
id?: string;
|
||||
priority?: number;
|
||||
secretData?: string;
|
||||
temporary?: boolean;
|
||||
type?: string;
|
||||
userLabel?: string;
|
||||
value?: string;
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
import type { DecisionEffect } from "./policyRepresentation.js";
|
||||
import type PolicyResultRepresentation from "./policyResultRepresentation.js";
|
||||
import type ResourceRepresentation from "./resourceRepresentation.js";
|
||||
import type ScopeRepresentation from "./scopeRepresentation.js";
|
||||
|
||||
export default interface EvaluationResultRepresentation {
|
||||
resource?: ResourceRepresentation;
|
||||
scopes?: ScopeRepresentation[];
|
||||
policies?: PolicyResultRepresentation[];
|
||||
status?: DecisionEffect;
|
||||
allowedScopes?: ScopeRepresentation[];
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_eventrepresentation
|
||||
*/
|
||||
import type EventType from "./eventTypes.js";
|
||||
|
||||
export default interface EventRepresentation {
|
||||
clientId?: string;
|
||||
details?: Record<string, any>;
|
||||
error?: string;
|
||||
ipAddress?: string;
|
||||
realmId?: string;
|
||||
sessionId?: string;
|
||||
time?: number;
|
||||
type?: EventType;
|
||||
userId?: string;
|
||||
}
|
89
js/libs/keycloak-admin-client/src/defs/eventTypes.ts
Normal file
89
js/libs/keycloak-admin-client/src/defs/eventTypes.ts
Normal file
|
@ -0,0 +1,89 @@
|
|||
type EventType =
|
||||
| "LOGIN"
|
||||
| "LOGIN_ERROR"
|
||||
| "REGISTER"
|
||||
| "REGISTER_ERROR"
|
||||
| "LOGOUT"
|
||||
| "LOGOUT_ERROR"
|
||||
| "CODE_TO_TOKEN"
|
||||
| "CODE_TO_TOKEN_ERROR"
|
||||
| "CLIENT_LOGIN"
|
||||
| "CLIENT_LOGIN_ERROR"
|
||||
| "REFRESH_TOKEN"
|
||||
| "REFRESH_TOKEN_ERROR"
|
||||
| "VALIDATE_ACCESS_TOKEN"
|
||||
| "VALIDATE_ACCESS_TOKEN_ERROR"
|
||||
| "INTROSPECT_TOKEN"
|
||||
| "INTROSPECT_TOKEN_ERROR"
|
||||
| "FEDERATED_IDENTITY_LINK"
|
||||
| "FEDERATED_IDENTITY_LINK_ERROR"
|
||||
| "REMOVE_FEDERATED_IDENTITY"
|
||||
| "REMOVE_FEDERATED_IDENTITY_ERROR"
|
||||
| "UPDATE_EMAIL"
|
||||
| "UPDATE_EMAIL_ERROR"
|
||||
| "UPDATE_PROFILE"
|
||||
| "UPDATE_PROFILE_ERROR"
|
||||
| "UPDATE_PASSWORD"
|
||||
| "UPDATE_PASSWORD_ERROR"
|
||||
| "UPDATE_TOTP"
|
||||
| "UPDATE_TOTP_ERROR"
|
||||
| "VERIFY_EMAIL"
|
||||
| "VERIFY_EMAIL_ERROR"
|
||||
| "REMOVE_TOTP"
|
||||
| "REMOVE_TOTP_ERROR"
|
||||
| "REVOKE_GRANT"
|
||||
| "REVOKE_GRANT_ERROR"
|
||||
| "SEND_VERIFY_EMAIL"
|
||||
| "SEND_VERIFY_EMAIL_ERROR"
|
||||
| "SEND_RESET_PASSWORD"
|
||||
| "SEND_RESET_PASSWORD_ERROR"
|
||||
| "SEND_IDENTITY_PROVIDER_LINK"
|
||||
| "SEND_IDENTITY_PROVIDER_LINK_ERROR"
|
||||
| "RESET_PASSWORD"
|
||||
| "RESET_PASSWORD_ERROR"
|
||||
| "RESTART_AUTHENTICATION"
|
||||
| "RESTART_AUTHENTICATION_ERROR"
|
||||
| "INVALID_SIGNATURE"
|
||||
| "INVALID_SIGNATURE_ERROR"
|
||||
| "REGISTER_NODE"
|
||||
| "REGISTER_NODE_ERROR"
|
||||
| "UNREGISTER_NODE"
|
||||
| "UNREGISTER_NODE_ERROR"
|
||||
| "USER_INFO_REQUEST"
|
||||
| "USER_INFO_REQUEST_ERROR"
|
||||
| "IDENTITY_PROVIDER_LINK_ACCOUNT"
|
||||
| "IDENTITY_PROVIDER_LINK_ACCOUNT_ERROR"
|
||||
| "IDENTITY_PROVIDER_LOGIN"
|
||||
| "IDENTITY_PROVIDER_LOGIN_ERROR"
|
||||
| "IDENTITY_PROVIDER_FIRST_LOGIN"
|
||||
| "IDENTITY_PROVIDER_FIRST_LOGIN_ERROR"
|
||||
| "IDENTITY_PROVIDER_POST_LOGIN"
|
||||
| "IDENTITY_PROVIDER_POST_LOGIN_ERROR"
|
||||
| "IDENTITY_PROVIDER_RESPONSE"
|
||||
| "IDENTITY_PROVIDER_RESPONSE_ERROR"
|
||||
| "IDENTITY_PROVIDER_RETRIEVE_TOKEN"
|
||||
| "IDENTITY_PROVIDER_RETRIEVE_TOKEN_ERROR"
|
||||
| "IMPERSONATE"
|
||||
| "IMPERSONATE_ERROR"
|
||||
| "CUSTOM_REQUIRED_ACTION"
|
||||
| "CUSTOM_REQUIRED_ACTION_ERROR"
|
||||
| "EXECUTE_ACTIONS"
|
||||
| "EXECUTE_ACTIONS_ERROR"
|
||||
| "EXECUTE_ACTION_TOKEN"
|
||||
| "EXECUTE_ACTION_TOKEN_ERROR"
|
||||
| "CLIENT_INFO"
|
||||
| "CLIENT_INFO_ERROR"
|
||||
| "CLIENT_REGISTER"
|
||||
| "CLIENT_REGISTER_ERROR"
|
||||
| "CLIENT_UPDATE"
|
||||
| "CLIENT_UPDATE_ERROR"
|
||||
| "CLIENT_DELETE"
|
||||
| "CLIENT_DELETE_ERROR"
|
||||
| "CLIENT_INITIATED_ACCOUNT_LINKING"
|
||||
| "CLIENT_INITIATED_ACCOUNT_LINKING_ERROR"
|
||||
| "TOKEN_EXCHANGE"
|
||||
| "TOKEN_EXCHANGE_ERROR"
|
||||
| "PERMISSION_TOKEN"
|
||||
| "PERMISSION_TOKEN_ERROR";
|
||||
|
||||
export default EventType;
|
|
@ -0,0 +1,9 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_federatedidentityrepresentation
|
||||
*/
|
||||
|
||||
export default interface FederatedIdentityRepresentation {
|
||||
identityProvider?: string;
|
||||
userId?: string;
|
||||
userName?: string;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_globalrequestresult
|
||||
*/
|
||||
export default interface GlobalRequestResult {
|
||||
successRequests?: string[];
|
||||
failedRequests?: string[];
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_grouprepresentation
|
||||
*/
|
||||
|
||||
export default interface GroupRepresentation {
|
||||
id?: string;
|
||||
name?: string;
|
||||
path?: string;
|
||||
subGroups?: GroupRepresentation[];
|
||||
|
||||
// optional in response
|
||||
access?: Record<string, boolean>;
|
||||
attributes?: Record<string, any>;
|
||||
clientRoles?: Record<string, any>;
|
||||
realmRoles?: string[];
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_identityprovidermapperrepresentation
|
||||
*/
|
||||
|
||||
export default interface IdentityProviderMapperRepresentation {
|
||||
config?: any;
|
||||
id?: string;
|
||||
identityProviderAlias?: string;
|
||||
identityProviderMapper?: string;
|
||||
name?: string;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
import type { ConfigPropertyRepresentation } from "./configPropertyRepresentation.js";
|
||||
|
||||
export interface IdentityProviderMapperTypeRepresentation {
|
||||
id?: string;
|
||||
name?: string;
|
||||
category?: string;
|
||||
helpText?: string;
|
||||
properties?: ConfigPropertyRepresentation[];
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_identityproviderrepresentation
|
||||
*/
|
||||
|
||||
export default interface IdentityProviderRepresentation {
|
||||
addReadTokenRoleOnCreate?: boolean;
|
||||
alias?: string;
|
||||
config?: Record<string, any>;
|
||||
displayName?: string;
|
||||
enabled?: boolean;
|
||||
firstBrokerLoginFlowAlias?: string;
|
||||
internalId?: string;
|
||||
linkOnly?: boolean;
|
||||
postBrokerLoginFlowAlias?: string;
|
||||
providerId?: string;
|
||||
storeToken?: boolean;
|
||||
trustEmail?: boolean;
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_keysmetadatarepresentation-keymetadatarepresentation
|
||||
*/
|
||||
export default interface KeysMetadataRepresentation {
|
||||
active?: { [index: string]: string };
|
||||
keys?: KeyMetadataRepresentation[];
|
||||
}
|
||||
|
||||
export interface KeyMetadataRepresentation {
|
||||
providerId?: string;
|
||||
providerPriority?: number;
|
||||
kid?: string;
|
||||
status?: string;
|
||||
type?: string;
|
||||
algorithm?: string;
|
||||
publicKey?: string;
|
||||
certificate?: string;
|
||||
}
|
11
js/libs/keycloak-admin-client/src/defs/keystoreConfig.ts
Normal file
11
js/libs/keycloak-admin-client/src/defs/keystoreConfig.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/#_keystoreconfig
|
||||
*/
|
||||
export default interface KeyStoreConfig {
|
||||
realmCertificate?: boolean;
|
||||
storePassword?: string;
|
||||
keyPassword?: string;
|
||||
keyAlias?: string;
|
||||
realmAlias?: string;
|
||||
format?: string;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
export interface ManagementPermissionReference {
|
||||
enabled?: boolean;
|
||||
resource?: string;
|
||||
scopePermissions?: Record<string, string>;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_mappingsrepresentation
|
||||
*/
|
||||
import type RoleRepresentation from "./roleRepresentation.js";
|
||||
|
||||
export default interface MappingsRepresentation {
|
||||
clientMappings?: Record<string, any>;
|
||||
realmMappings?: RoleRepresentation[];
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_passwordpolicytyperepresentation
|
||||
*/
|
||||
export default interface PasswordPolicyTypeRepresentation {
|
||||
id?: string;
|
||||
displayName?: string;
|
||||
configType?: string;
|
||||
defaultValue?: string;
|
||||
multipleSupported?: boolean;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
import type AccessTokenRepresentation from "./accessTokenRepresentation.js";
|
||||
import type EvaluationResultRepresentation from "./evaluationResultRepresentation.js";
|
||||
import type { DecisionEffect } from "./policyRepresentation.js";
|
||||
|
||||
export default interface PolicyEvaluationResponse {
|
||||
results?: EvaluationResultRepresentation[];
|
||||
entitlements?: boolean;
|
||||
status?: DecisionEffect;
|
||||
rpt?: AccessTokenRepresentation;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
export default interface PolicyProviderRepresentation {
|
||||
type?: string;
|
||||
name?: string;
|
||||
group?: string;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_policyrepresentation
|
||||
*/
|
||||
|
||||
export enum DecisionStrategy {
|
||||
AFFIRMATIVE = "AFFIRMATIVE",
|
||||
UNANIMOUS = "UNANIMOUS",
|
||||
CONSENSUS = "CONSENSUS",
|
||||
}
|
||||
|
||||
export enum DecisionEffect {
|
||||
Permit = "PERMIT",
|
||||
Deny = "DENY",
|
||||
}
|
||||
|
||||
export enum Logic {
|
||||
POSITIVE = "POSITIVE",
|
||||
NEGATIVE = "NEGATIVE",
|
||||
}
|
||||
|
||||
export interface PolicyRoleRepresentation {
|
||||
id: string;
|
||||
required?: boolean;
|
||||
}
|
||||
|
||||
export default interface PolicyRepresentation {
|
||||
config?: Record<string, any>;
|
||||
decisionStrategy?: DecisionStrategy;
|
||||
description?: string;
|
||||
id?: string;
|
||||
logic?: Logic;
|
||||
name?: string;
|
||||
owner?: string;
|
||||
policies?: string[];
|
||||
resources?: string[];
|
||||
scopes?: string[];
|
||||
type?: string;
|
||||
users?: string[];
|
||||
roles?: PolicyRoleRepresentation[];
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
import type PolicyRepresentation from "./policyRepresentation.js";
|
||||
import type { DecisionEffect } from "./policyRepresentation.js";
|
||||
|
||||
export default interface PolicyResultRepresentation {
|
||||
policy?: PolicyRepresentation;
|
||||
status?: DecisionEffect;
|
||||
associatedPolicies?: PolicyResultRepresentation[];
|
||||
scopes?: string[];
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_profileinforepresentation
|
||||
*/
|
||||
export default interface ProfileInfoRepresentation {
|
||||
name?: string;
|
||||
disabledFeatures?: string[];
|
||||
previewFeatures?: string[];
|
||||
experimentalFeatures?: string[];
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_protocolmapperrepresentation
|
||||
*/
|
||||
|
||||
export default interface ProtocolMapperRepresentation {
|
||||
config?: Record<string, any>;
|
||||
id?: string;
|
||||
name?: string;
|
||||
protocol?: string;
|
||||
protocolMapper?: string;
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/#_realmeventsconfigrepresentation
|
||||
*/
|
||||
|
||||
export interface RealmEventsConfigRepresentation {
|
||||
eventsEnabled?: boolean;
|
||||
eventsExpiration?: number;
|
||||
eventsListeners?: string[];
|
||||
enabledEventTypes?: string[];
|
||||
adminEventsEnabled?: boolean;
|
||||
adminEventsDetailsEnabled?: boolean;
|
||||
}
|
144
js/libs/keycloak-admin-client/src/defs/realmRepresentation.ts
Normal file
144
js/libs/keycloak-admin-client/src/defs/realmRepresentation.ts
Normal file
|
@ -0,0 +1,144 @@
|
|||
import type ClientRepresentation from "./clientRepresentation.js";
|
||||
import type ComponentExportRepresentation from "./componentExportRepresentation.js";
|
||||
import type UserRepresentation from "./userRepresentation.js";
|
||||
import type GroupRepresentation from "./groupRepresentation.js";
|
||||
import type IdentityProviderRepresentation from "./identityProviderRepresentation.js";
|
||||
import type RequiredActionProviderRepresentation from "./requiredActionProviderRepresentation.js";
|
||||
import type RolesRepresentation from "./rolesRepresentation.js";
|
||||
import type ClientProfilesRepresentation from "./clientProfilesRepresentation.js";
|
||||
import type ClientPoliciesRepresentation from "./clientPoliciesRepresentation.js";
|
||||
import type RoleRepresentation from "./roleRepresentation.js";
|
||||
|
||||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_realmrepresentation
|
||||
*/
|
||||
|
||||
export default interface RealmRepresentation {
|
||||
accessCodeLifespan?: number;
|
||||
accessCodeLifespanLogin?: number;
|
||||
accessCodeLifespanUserAction?: number;
|
||||
accessTokenLifespan?: number;
|
||||
accessTokenLifespanForImplicitFlow?: number;
|
||||
accountTheme?: string;
|
||||
actionTokenGeneratedByAdminLifespan?: number;
|
||||
actionTokenGeneratedByUserLifespan?: number;
|
||||
adminEventsDetailsEnabled?: boolean;
|
||||
adminEventsEnabled?: boolean;
|
||||
adminTheme?: string;
|
||||
attributes?: Record<string, any>;
|
||||
// AuthenticationFlowRepresentation
|
||||
authenticationFlows?: any[];
|
||||
// AuthenticatorConfigRepresentation
|
||||
authenticatorConfig?: any[];
|
||||
browserFlow?: string;
|
||||
browserSecurityHeaders?: Record<string, any>;
|
||||
bruteForceProtected?: boolean;
|
||||
clientAuthenticationFlow?: string;
|
||||
clientScopeMappings?: Record<string, any>;
|
||||
// ClientScopeRepresentation
|
||||
clientScopes?: any[];
|
||||
clients?: ClientRepresentation[];
|
||||
clientPolicies?: ClientPoliciesRepresentation;
|
||||
clientProfiles?: ClientProfilesRepresentation;
|
||||
components?: { [index: string]: ComponentExportRepresentation };
|
||||
defaultDefaultClientScopes?: string[];
|
||||
defaultGroups?: string[];
|
||||
defaultLocale?: string;
|
||||
defaultOptionalClientScopes?: string[];
|
||||
defaultRoles?: string[];
|
||||
defaultRole?: RoleRepresentation;
|
||||
defaultSignatureAlgorithm?: string;
|
||||
directGrantFlow?: string;
|
||||
displayName?: string;
|
||||
displayNameHtml?: string;
|
||||
dockerAuthenticationFlow?: string;
|
||||
duplicateEmailsAllowed?: boolean;
|
||||
editUsernameAllowed?: boolean;
|
||||
emailTheme?: string;
|
||||
enabled?: boolean;
|
||||
enabledEventTypes?: string[];
|
||||
eventsEnabled?: boolean;
|
||||
eventsExpiration?: number;
|
||||
eventsListeners?: string[];
|
||||
failureFactor?: number;
|
||||
federatedUsers?: UserRepresentation[];
|
||||
groups?: GroupRepresentation[];
|
||||
id?: string;
|
||||
// IdentityProviderMapperRepresentation
|
||||
identityProviderMappers?: any[];
|
||||
identityProviders?: IdentityProviderRepresentation[];
|
||||
internationalizationEnabled?: boolean;
|
||||
keycloakVersion?: string;
|
||||
loginTheme?: string;
|
||||
loginWithEmailAllowed?: boolean;
|
||||
maxDeltaTimeSeconds?: number;
|
||||
maxFailureWaitSeconds?: number;
|
||||
minimumQuickLoginWaitSeconds?: number;
|
||||
notBefore?: number;
|
||||
oauth2DeviceCodeLifespan?: number;
|
||||
oauth2DevicePollingInterval?: number;
|
||||
offlineSessionIdleTimeout?: number;
|
||||
offlineSessionMaxLifespan?: number;
|
||||
offlineSessionMaxLifespanEnabled?: boolean;
|
||||
otpPolicyAlgorithm?: string;
|
||||
otpPolicyDigits?: number;
|
||||
otpPolicyInitialCounter?: number;
|
||||
otpPolicyLookAheadWindow?: number;
|
||||
otpPolicyPeriod?: number;
|
||||
otpPolicyType?: string;
|
||||
otpSupportedApplications?: string[];
|
||||
otpPolicyCodeReusable?: boolean;
|
||||
passwordPolicy?: string;
|
||||
permanentLockout?: boolean;
|
||||
// ProtocolMapperRepresentation
|
||||
protocolMappers?: any[];
|
||||
quickLoginCheckMilliSeconds?: number;
|
||||
realm?: string;
|
||||
refreshTokenMaxReuse?: number;
|
||||
registrationAllowed?: boolean;
|
||||
registrationEmailAsUsername?: boolean;
|
||||
registrationFlow?: string;
|
||||
rememberMe?: boolean;
|
||||
requiredActions?: RequiredActionProviderRepresentation[];
|
||||
resetCredentialsFlow?: string;
|
||||
resetPasswordAllowed?: boolean;
|
||||
revokeRefreshToken?: boolean;
|
||||
roles?: RolesRepresentation;
|
||||
// ScopeMappingRepresentation
|
||||
scopeMappings?: any[];
|
||||
smtpServer?: Record<string, any>;
|
||||
sslRequired?: string;
|
||||
ssoSessionIdleTimeout?: number;
|
||||
ssoSessionIdleTimeoutRememberMe?: number;
|
||||
ssoSessionMaxLifespan?: number;
|
||||
ssoSessionMaxLifespanRememberMe?: number;
|
||||
clientSessionIdleTimeout?: number;
|
||||
clientSessionMaxLifespan?: number;
|
||||
supportedLocales?: string[];
|
||||
// UserFederationMapperRepresentation
|
||||
userFederationMappers?: any[];
|
||||
// UserFederationProviderRepresentation
|
||||
userFederationProviders?: any[];
|
||||
userManagedAccessAllowed?: boolean;
|
||||
users?: UserRepresentation[];
|
||||
verifyEmail?: boolean;
|
||||
waitIncrementSeconds?: number;
|
||||
}
|
||||
|
||||
export type PartialImportRealmRepresentation = RealmRepresentation & {
|
||||
ifResourceExists: "FAIL" | "SKIP" | "OVERWRITE";
|
||||
};
|
||||
|
||||
export type PartialImportResponse = {
|
||||
overwritten: number;
|
||||
added: number;
|
||||
skipped: number;
|
||||
results: PartialImportResult[];
|
||||
};
|
||||
|
||||
export type PartialImportResult = {
|
||||
action: string;
|
||||
resourceType: string;
|
||||
resourceName: string;
|
||||
id: string;
|
||||
};
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_requiredactionproviderrepresentation
|
||||
*/
|
||||
|
||||
export enum RequiredActionAlias {
|
||||
VERIFY_EMAIL = "VERIFY_EMAIL",
|
||||
UPDATE_PROFILE = "UPDATE_PROFILE",
|
||||
CONFIGURE_TOTP = "CONFIGURE_TOTP",
|
||||
UPDATE_PASSWORD = "UPDATE_PASSWORD",
|
||||
terms_and_conditions = "terms_and_conditions",
|
||||
}
|
||||
|
||||
export default interface RequiredActionProviderRepresentation {
|
||||
alias?: string;
|
||||
config?: Record<string, any>;
|
||||
defaultAction?: boolean;
|
||||
enabled?: boolean;
|
||||
name?: string;
|
||||
providerId?: string;
|
||||
priority?: number;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
export default interface RequiredActionProviderSimpleRepresentation {
|
||||
id?: string;
|
||||
name?: string;
|
||||
providerId?: string;
|
||||
}
|
14
js/libs/keycloak-admin-client/src/defs/resourceEvaluation.ts
Normal file
14
js/libs/keycloak-admin-client/src/defs/resourceEvaluation.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
import type ResourceRepresentation from "./resourceRepresentation.js";
|
||||
|
||||
export default interface ResourceEvaluation {
|
||||
roleIds?: string[];
|
||||
clientId: string;
|
||||
userId: string;
|
||||
resources?: ResourceRepresentation[];
|
||||
entitlements: boolean;
|
||||
context: {
|
||||
attributes: {
|
||||
[key: string]: string;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_resourcerepresentation
|
||||
*/
|
||||
import type { ResourceOwnerRepresentation } from "./resourceServerRepresentation.js";
|
||||
import type ScopeRepresentation from "./scopeRepresentation.js";
|
||||
|
||||
export default interface ResourceRepresentation {
|
||||
name?: string;
|
||||
type?: string;
|
||||
owner?: ResourceOwnerRepresentation;
|
||||
ownerManagedAccess?: boolean;
|
||||
displayName?: string;
|
||||
attributes?: { [index: string]: string[] };
|
||||
_id?: string;
|
||||
uris?: string[];
|
||||
scopes?: ScopeRepresentation[];
|
||||
icon_uri?: string;
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_policyrepresentation
|
||||
*/
|
||||
import type PolicyRepresentation from "./policyRepresentation.js";
|
||||
import type ResourceRepresentation from "./resourceRepresentation.js";
|
||||
import type ScopeRepresentation from "./scopeRepresentation.js";
|
||||
|
||||
export default interface ResourceServerRepresentation {
|
||||
id?: string;
|
||||
clientId?: string;
|
||||
name?: string;
|
||||
allowRemoteResourceManagement?: boolean;
|
||||
policyEnforcementMode?: PolicyEnforcementMode;
|
||||
resources?: ResourceRepresentation[];
|
||||
policies?: PolicyRepresentation[];
|
||||
scopes?: ScopeRepresentation[];
|
||||
decisionStrategy?: DecisionStrategy;
|
||||
}
|
||||
export interface ResourceOwnerRepresentation {
|
||||
id?: string;
|
||||
name?: string;
|
||||
}
|
||||
export interface AbstractPolicyRepresentation {
|
||||
id?: string;
|
||||
name?: string;
|
||||
description?: string;
|
||||
type?: string;
|
||||
policies?: string[];
|
||||
resources?: string[];
|
||||
scopes?: string[];
|
||||
logic?: Logic;
|
||||
decisionStrategy?: DecisionStrategy;
|
||||
owner?: string;
|
||||
resourcesData?: ResourceRepresentation[];
|
||||
scopesData?: ScopeRepresentation[];
|
||||
}
|
||||
|
||||
export type PolicyEnforcementMode = "ENFORCING" | "PERMISSIVE" | "DISABLED";
|
||||
|
||||
export type DecisionStrategy = "AFFIRMATIVE" | "UNANIMOUS" | "CONSENSUS";
|
||||
|
||||
export type Logic = "POSITIVE" | "NEGATIVE";
|
||||
|
||||
export type Category = "INTERNAL" | "ACCESS" | "ID" | "ADMIN" | "USERINFO";
|
27
js/libs/keycloak-admin-client/src/defs/roleRepresentation.ts
Normal file
27
js/libs/keycloak-admin-client/src/defs/roleRepresentation.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_rolerepresentation
|
||||
*/
|
||||
|
||||
export default interface RoleRepresentation {
|
||||
id?: string;
|
||||
name?: string;
|
||||
description?: string;
|
||||
scopeParamRequired?: boolean;
|
||||
composite?: boolean;
|
||||
composites?: Composites;
|
||||
clientRole?: boolean;
|
||||
containerId?: string;
|
||||
attributes?: { [index: string]: string[] };
|
||||
}
|
||||
|
||||
export interface Composites {
|
||||
realm?: string[];
|
||||
client?: { [index: string]: string[] };
|
||||
application?: { [index: string]: string[] };
|
||||
}
|
||||
|
||||
// when requesting to role-mapping api (create, delete), id and name are required
|
||||
export interface RoleMappingPayload extends RoleRepresentation {
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_rolesrepresentation
|
||||
*/
|
||||
|
||||
import type RoleRepresentation from "./roleRepresentation.js";
|
||||
|
||||
export default interface RolesRepresentation {
|
||||
realm?: RoleRepresentation[];
|
||||
client?: { [index: string]: RoleRepresentation[] };
|
||||
application?: { [index: string]: RoleRepresentation[] };
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_scoperepresentation
|
||||
*/
|
||||
import type PolicyRepresentation from "./policyRepresentation.js";
|
||||
import type ResourceRepresentation from "./resourceRepresentation.js";
|
||||
|
||||
export default interface ScopeRepresentation {
|
||||
displayName?: string;
|
||||
iconUri?: string;
|
||||
id?: string;
|
||||
name?: string;
|
||||
policies?: PolicyRepresentation[];
|
||||
resources?: ResourceRepresentation[];
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
import type ComponentTypeRepresentation from "./componentTypeRepresentation.js";
|
||||
import type { ConfigPropertyRepresentation } from "./configPropertyRepresentation.js";
|
||||
import type PasswordPolicyTypeRepresentation from "./passwordPolicyTypeRepresentation.js";
|
||||
import type ProfileInfoRepresentation from "./profileInfoRepresentation.js";
|
||||
import type ProtocolMapperRepresentation from "./protocolMapperRepresentation.js";
|
||||
import type SystemInfoRepresentation from "./systemInfoRepersantation.js";
|
||||
|
||||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_serverinforepresentation
|
||||
*/
|
||||
export interface ServerInfoRepresentation {
|
||||
systemInfo?: SystemInfoRepresentation;
|
||||
memoryInfo?: MemoryInfoRepresentation;
|
||||
profileInfo?: ProfileInfoRepresentation;
|
||||
cryptoInfo?: CryptoInfoRepresentation;
|
||||
themes?: { [index: string]: ThemeInfoRepresentation[] };
|
||||
socialProviders?: { [index: string]: string }[];
|
||||
identityProviders?: { [index: string]: string }[];
|
||||
clientImporters?: { [index: string]: string }[];
|
||||
providers?: { [index: string]: SpiInfoRepresentation };
|
||||
protocolMapperTypes?: { [index: string]: ProtocolMapperTypeRepresentation[] };
|
||||
builtinProtocolMappers?: { [index: string]: ProtocolMapperRepresentation[] };
|
||||
clientInstallations?: { [index: string]: ClientInstallationRepresentation[] };
|
||||
componentTypes?: { [index: string]: ComponentTypeRepresentation[] };
|
||||
passwordPolicies?: PasswordPolicyTypeRepresentation[];
|
||||
enums?: { [index: string]: string[] };
|
||||
}
|
||||
|
||||
export interface ThemeInfoRepresentation {
|
||||
name: string;
|
||||
locales?: string[];
|
||||
}
|
||||
|
||||
export interface SpiInfoRepresentation {
|
||||
internal: boolean;
|
||||
providers: { [index: string]: ProviderRepresentation };
|
||||
}
|
||||
|
||||
export interface ProviderRepresentation {
|
||||
order: number;
|
||||
operationalInfo?: Record<string, string>;
|
||||
}
|
||||
|
||||
export interface ClientInstallationRepresentation {
|
||||
id: string;
|
||||
protocol: string;
|
||||
downloadOnly: boolean;
|
||||
displayType: string;
|
||||
helpText: string;
|
||||
filename: string;
|
||||
mediaType: string;
|
||||
}
|
||||
|
||||
export interface MemoryInfoRepresentation {
|
||||
total: number;
|
||||
totalFormated: string;
|
||||
used: number;
|
||||
usedFormated: string;
|
||||
free: number;
|
||||
freePercentage: number;
|
||||
freeFormated: string;
|
||||
}
|
||||
|
||||
export interface ProtocolMapperTypeRepresentation {
|
||||
id: string;
|
||||
name: string;
|
||||
category: string;
|
||||
helpText: string;
|
||||
priority: number;
|
||||
properties: ConfigPropertyRepresentation[];
|
||||
}
|
||||
|
||||
export interface CryptoInfoRepresentation {
|
||||
cryptoProvider: string;
|
||||
supportedKeystoreTypes: string[];
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_synchronizationresult
|
||||
*/
|
||||
|
||||
export default interface SynchronizationResultRepresentation {
|
||||
ignored?: boolean;
|
||||
added?: number;
|
||||
updated?: number;
|
||||
removed?: number;
|
||||
failed?: number;
|
||||
status?: string;
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_systeminforepresentation
|
||||
*/
|
||||
|
||||
export default interface SystemInfoRepresentation {
|
||||
version?: string;
|
||||
serverTime?: string;
|
||||
uptime?: string;
|
||||
uptimeMillis?: number;
|
||||
javaVersion?: string;
|
||||
javaVendor?: string;
|
||||
javaVm?: string;
|
||||
javaVmVersion?: string;
|
||||
javaRuntime?: string;
|
||||
javaHome?: string;
|
||||
osName?: string;
|
||||
osArchitecture?: string;
|
||||
osVersion?: string;
|
||||
fileEncoding?: string;
|
||||
userName?: string;
|
||||
userDir?: string;
|
||||
userTimezone?: string;
|
||||
userLocale?: string;
|
||||
}
|
15
js/libs/keycloak-admin-client/src/defs/testLdapConnection.ts
Normal file
15
js/libs/keycloak-admin-client/src/defs/testLdapConnection.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/#_testldapconnectionrepresentation
|
||||
*/
|
||||
|
||||
export default interface TestLdapConnectionRepresentation {
|
||||
action?: string;
|
||||
connectionUrl?: string;
|
||||
bindDn?: string;
|
||||
bindCredential?: string;
|
||||
useTruststoreSpi?: string;
|
||||
connectionTimeout?: string;
|
||||
componentId?: string;
|
||||
startTls?: string;
|
||||
authType?: string;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
/**
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/#_userconsentrepresentation
|
||||
*/
|
||||
|
||||
export default interface UserConsentRepresentation {
|
||||
clientId?: string;
|
||||
createDate?: string;
|
||||
grantedClientScopes?: string[];
|
||||
lastUpdatedDate?: number;
|
||||
}
|
42
js/libs/keycloak-admin-client/src/defs/userProfileConfig.ts
Normal file
42
js/libs/keycloak-admin-client/src/defs/userProfileConfig.ts
Normal file
|
@ -0,0 +1,42 @@
|
|||
// See: https://github.com/keycloak/keycloak/blob/main/services/src/main/java/org/keycloak/userprofile/config/UPConfig.java
|
||||
export default interface UserProfileConfig {
|
||||
attributes?: UserProfileAttribute[];
|
||||
groups?: UserProfileGroup[];
|
||||
}
|
||||
|
||||
// See: https://github.com/keycloak/keycloak/blob/main/services/src/main/java/org/keycloak/userprofile/config/UPAttribute.java
|
||||
export interface UserProfileAttribute {
|
||||
name?: string;
|
||||
validations?: Record<string, Record<string, unknown>>;
|
||||
annotations?: Record<string, unknown>[];
|
||||
required?: UserProfileAttributeRequired;
|
||||
permissions?: UserProfileAttributePermissions;
|
||||
selector?: UserProfileAttributeSelector;
|
||||
displayName?: string;
|
||||
group?: string;
|
||||
}
|
||||
|
||||
// See: https://github.com/keycloak/keycloak/blob/main/services/src/main/java/org/keycloak/userprofile/config/UPAttributeRequired.java
|
||||
export interface UserProfileAttributeRequired {
|
||||
roles?: string[];
|
||||
scopes?: string[];
|
||||
}
|
||||
|
||||
// See: https://github.com/keycloak/keycloak/blob/main/services/src/main/java/org/keycloak/userprofile/config/UPAttributePermissions.java
|
||||
export interface UserProfileAttributePermissions {
|
||||
view?: string[];
|
||||
edit?: string[];
|
||||
}
|
||||
|
||||
// See: https://github.com/keycloak/keycloak/blob/main/services/src/main/java/org/keycloak/userprofile/config/UPAttributeSelector.java
|
||||
export interface UserProfileAttributeSelector {
|
||||
scopes?: string[];
|
||||
}
|
||||
|
||||
// See: https://github.com/keycloak/keycloak/blob/main/services/src/main/java/org/keycloak/userprofile/config/UPGroup.java
|
||||
export interface UserProfileGroup {
|
||||
name?: string;
|
||||
displayHeader?: string;
|
||||
displayDescription?: string;
|
||||
annotations?: Record<string, unknown>;
|
||||
}
|
33
js/libs/keycloak-admin-client/src/defs/userRepresentation.ts
Normal file
33
js/libs/keycloak-admin-client/src/defs/userRepresentation.ts
Normal file
|
@ -0,0 +1,33 @@
|
|||
import type UserConsentRepresentation from "./userConsentRepresentation.js";
|
||||
import type CredentialRepresentation from "./credentialRepresentation.js";
|
||||
import type FederatedIdentityRepresentation from "./federatedIdentityRepresentation.js";
|
||||
import type { RequiredActionAlias } from "./requiredActionProviderRepresentation.js";
|
||||
|
||||
export default interface UserRepresentation {
|
||||
id?: string;
|
||||
createdTimestamp?: number;
|
||||
username?: string;
|
||||
enabled?: boolean;
|
||||
totp?: boolean;
|
||||
emailVerified?: boolean;
|
||||
disableableCredentialTypes?: string[];
|
||||
requiredActions?: (RequiredActionAlias | string)[];
|
||||
notBefore?: number;
|
||||
access?: Record<string, boolean>;
|
||||
|
||||
// optional from response
|
||||
attributes?: Record<string, any>;
|
||||
clientConsents?: UserConsentRepresentation[];
|
||||
clientRoles?: Record<string, any>;
|
||||
credentials?: CredentialRepresentation[];
|
||||
email?: string;
|
||||
federatedIdentities?: FederatedIdentityRepresentation[];
|
||||
federationLink?: string;
|
||||
firstName?: string;
|
||||
groups?: string[];
|
||||
lastName?: string;
|
||||
origin?: string;
|
||||
realmRoles?: string[];
|
||||
self?: string;
|
||||
serviceAccountClientId?: string;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
export default interface UserSessionRepresentation {
|
||||
id?: string;
|
||||
clients?: Record<string, string>;
|
||||
ipAddress?: string;
|
||||
lastAccess?: number;
|
||||
start?: number;
|
||||
userId?: string;
|
||||
username?: string;
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
export type AccessType =
|
||||
| "view-realm"
|
||||
| "view-identity-providers"
|
||||
| "manage-identity-providers"
|
||||
| "impersonation"
|
||||
| "create-client"
|
||||
| "manage-users"
|
||||
| "query-realms"
|
||||
| "view-authorization"
|
||||
| "query-clients"
|
||||
| "query-users"
|
||||
| "manage-events"
|
||||
| "manage-realm"
|
||||
| "view-events"
|
||||
| "view-users"
|
||||
| "view-clients"
|
||||
| "manage-authorization"
|
||||
| "manage-clients"
|
||||
| "query-groups"
|
||||
| "anyone";
|
||||
|
||||
export default interface WhoAmIRepresentation {
|
||||
userId: string;
|
||||
realm: string;
|
||||
displayName: string;
|
||||
locale: string;
|
||||
createRealm: boolean;
|
||||
realm_access: { [key: string]: AccessType[] };
|
||||
}
|
7
js/libs/keycloak-admin-client/src/index.ts
Normal file
7
js/libs/keycloak-admin-client/src/index.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { KeycloakAdminClient } from "./client.js";
|
||||
import { RequiredActionAlias } from "./defs/requiredActionProviderRepresentation.js";
|
||||
|
||||
export const requiredAction = RequiredActionAlias;
|
||||
export default KeycloakAdminClient;
|
||||
export { NetworkError } from "./utils/fetchWithError.js";
|
||||
export type { NetworkErrorOptions } from "./utils/fetchWithError.js";
|
300
js/libs/keycloak-admin-client/src/resources/agent.ts
Normal file
300
js/libs/keycloak-admin-client/src/resources/agent.ts
Normal file
|
@ -0,0 +1,300 @@
|
|||
import { isUndefined, last, omit, pick } from "lodash-es";
|
||||
import urlJoin from "url-join";
|
||||
import { parseTemplate } from "url-template";
|
||||
import type { KeycloakAdminClient } from "../client.js";
|
||||
import {
|
||||
fetchWithError,
|
||||
NetworkError,
|
||||
parseResponse,
|
||||
} from "../utils/fetchWithError.js";
|
||||
import { stringifyQueryParams } from "../utils/stringifyQueryParams.js";
|
||||
|
||||
// constants
|
||||
const SLASH = "/";
|
||||
|
||||
type Method = "GET" | "POST" | "PUT" | "DELETE";
|
||||
|
||||
// interface
|
||||
export interface RequestArgs {
|
||||
method: Method;
|
||||
path?: string;
|
||||
// Keys of url params to be applied
|
||||
urlParamKeys?: string[];
|
||||
// Keys of query parameters to be applied
|
||||
queryParamKeys?: string[];
|
||||
// Mapping of key transformations to be performed on the payload
|
||||
keyTransform?: Record<string, string>;
|
||||
// If responding with 404, catch it and return null instead
|
||||
catchNotFound?: boolean;
|
||||
// The key of the value to use from the payload of request. Only works for POST & PUT.
|
||||
payloadKey?: string;
|
||||
// Whether the response header have a location field with newly created resource id
|
||||
// if this value is set, we return the field with format: {[field]: resourceId}
|
||||
// to represent the newly created resource
|
||||
// detail: keycloak/keycloak-nodejs-admin-client issue #11
|
||||
returnResourceIdInLocationHeader?: { field: string };
|
||||
/**
|
||||
* Keys to be ignored, meaning that they will not be filtered out of the request payload even if they are a part of `urlParamKeys` or `queryParamKeys`,
|
||||
*/
|
||||
ignoredKeys?: string[];
|
||||
headers?: HeadersInit;
|
||||
}
|
||||
|
||||
export class Agent {
|
||||
private client: KeycloakAdminClient;
|
||||
private basePath: string;
|
||||
private getBaseParams?: () => Record<string, any>;
|
||||
private getBaseUrl?: () => string;
|
||||
|
||||
constructor({
|
||||
client,
|
||||
path = "/",
|
||||
getUrlParams = () => ({}),
|
||||
getBaseUrl = () => client.baseUrl,
|
||||
}: {
|
||||
client: KeycloakAdminClient;
|
||||
path?: string;
|
||||
getUrlParams?: () => Record<string, any>;
|
||||
getBaseUrl?: () => string;
|
||||
}) {
|
||||
this.client = client;
|
||||
this.getBaseParams = getUrlParams;
|
||||
this.getBaseUrl = getBaseUrl;
|
||||
this.basePath = path;
|
||||
}
|
||||
|
||||
public request({
|
||||
method,
|
||||
path = "",
|
||||
urlParamKeys = [],
|
||||
queryParamKeys = [],
|
||||
catchNotFound = false,
|
||||
keyTransform,
|
||||
payloadKey,
|
||||
returnResourceIdInLocationHeader,
|
||||
ignoredKeys,
|
||||
headers,
|
||||
}: RequestArgs) {
|
||||
return async (
|
||||
payload: any = {},
|
||||
options?: Pick<RequestArgs, "catchNotFound">
|
||||
) => {
|
||||
const baseParams = this.getBaseParams?.() ?? {};
|
||||
|
||||
// Filter query parameters by queryParamKeys
|
||||
const queryParams = queryParamKeys
|
||||
? pick(payload, queryParamKeys)
|
||||
: undefined;
|
||||
|
||||
// Add filtered payload parameters to base parameters
|
||||
const allUrlParamKeys = [...Object.keys(baseParams), ...urlParamKeys];
|
||||
const urlParams = { ...baseParams, ...pick(payload, allUrlParamKeys) };
|
||||
|
||||
// Omit url parameters and query parameters from payload
|
||||
const omittedKeys = ignoredKeys
|
||||
? [...allUrlParamKeys, ...queryParamKeys].filter(
|
||||
(key) => !ignoredKeys.includes(key)
|
||||
)
|
||||
: [...allUrlParamKeys, ...queryParamKeys];
|
||||
|
||||
payload = omit(payload, omittedKeys);
|
||||
|
||||
// Transform keys of both payload and queryParams
|
||||
if (keyTransform) {
|
||||
this.transformKey(payload, keyTransform);
|
||||
this.transformKey(queryParams, keyTransform);
|
||||
}
|
||||
|
||||
return this.requestWithParams({
|
||||
method,
|
||||
path,
|
||||
payload,
|
||||
urlParams,
|
||||
queryParams,
|
||||
// catchNotFound precedence: global > local > default
|
||||
catchNotFound,
|
||||
...(this.client.getGlobalRequestArgOptions() ?? options ?? {}),
|
||||
payloadKey,
|
||||
returnResourceIdInLocationHeader,
|
||||
headers,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
public updateRequest({
|
||||
method,
|
||||
path = "",
|
||||
urlParamKeys = [],
|
||||
queryParamKeys = [],
|
||||
catchNotFound = false,
|
||||
keyTransform,
|
||||
payloadKey,
|
||||
returnResourceIdInLocationHeader,
|
||||
headers,
|
||||
}: RequestArgs) {
|
||||
return async (query: any = {}, payload: any = {}) => {
|
||||
const baseParams = this.getBaseParams?.() ?? {};
|
||||
|
||||
// Filter query parameters by queryParamKeys
|
||||
const queryParams = queryParamKeys
|
||||
? pick(query, queryParamKeys)
|
||||
: undefined;
|
||||
|
||||
// Add filtered query parameters to base parameters
|
||||
const allUrlParamKeys = [...Object.keys(baseParams), ...urlParamKeys];
|
||||
const urlParams = {
|
||||
...baseParams,
|
||||
...pick(query, allUrlParamKeys),
|
||||
};
|
||||
|
||||
// Transform keys of queryParams
|
||||
if (keyTransform) {
|
||||
this.transformKey(queryParams, keyTransform);
|
||||
}
|
||||
|
||||
return this.requestWithParams({
|
||||
method,
|
||||
path,
|
||||
payload,
|
||||
urlParams,
|
||||
queryParams,
|
||||
catchNotFound,
|
||||
payloadKey,
|
||||
returnResourceIdInLocationHeader,
|
||||
headers,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
private async requestWithParams({
|
||||
method,
|
||||
path,
|
||||
payload,
|
||||
urlParams,
|
||||
queryParams,
|
||||
catchNotFound,
|
||||
payloadKey,
|
||||
returnResourceIdInLocationHeader,
|
||||
headers,
|
||||
}: {
|
||||
method: Method;
|
||||
path: string;
|
||||
payload: any;
|
||||
urlParams: any;
|
||||
queryParams?: Record<string, string>;
|
||||
catchNotFound: boolean;
|
||||
payloadKey?: string;
|
||||
returnResourceIdInLocationHeader?: { field: string };
|
||||
headers?: HeadersInit;
|
||||
}) {
|
||||
const newPath = urlJoin(this.basePath, path);
|
||||
|
||||
// Parse template and replace with values from urlParams
|
||||
const pathTemplate = parseTemplate(newPath);
|
||||
const parsedPath = pathTemplate.expand(urlParams);
|
||||
const url = new URL(`${this.getBaseUrl?.() ?? ""}${parsedPath}`);
|
||||
const requestOptions = { ...this.client.getRequestOptions() };
|
||||
const requestHeaders = new Headers([
|
||||
...new Headers(requestOptions.headers).entries(),
|
||||
["authorization", `Bearer ${await this.client.getAccessToken()}`],
|
||||
["accept", "application/json, text/plain, */*"],
|
||||
...new Headers(headers).entries(),
|
||||
]);
|
||||
|
||||
const searchParams: Record<string, string> = {};
|
||||
|
||||
// Add payload parameters to search params if method is 'GET'.
|
||||
if (method === "GET") {
|
||||
Object.assign(searchParams, payload);
|
||||
} else if (requestHeaders.get("content-type") === "text/plain") {
|
||||
// Pass the payload as a plain string if the content type is 'text/plain'.
|
||||
requestOptions.body = payload as unknown as string;
|
||||
} else {
|
||||
// Otherwise assume it's JSON and stringify it.
|
||||
requestOptions.body = JSON.stringify(
|
||||
payloadKey ? payload[payloadKey] : payload
|
||||
);
|
||||
}
|
||||
|
||||
if (!requestHeaders.has("content-type")) {
|
||||
requestHeaders.set("content-type", "application/json");
|
||||
}
|
||||
|
||||
if (queryParams) {
|
||||
Object.assign(searchParams, queryParams);
|
||||
}
|
||||
|
||||
url.search = stringifyQueryParams(searchParams);
|
||||
|
||||
try {
|
||||
const res = await fetchWithError(url, {
|
||||
...requestOptions,
|
||||
headers: requestHeaders,
|
||||
method,
|
||||
});
|
||||
|
||||
// now we get the response of the http request
|
||||
// if `resourceIdInLocationHeader` is true, we'll get the resourceId from the location header field
|
||||
// todo: find a better way to find the id in path, maybe some kind of pattern matching
|
||||
// for now, we simply split the last sub-path of the path returned in location header field
|
||||
if (returnResourceIdInLocationHeader) {
|
||||
const locationHeader = res.headers.get("location");
|
||||
|
||||
if (typeof locationHeader !== "string") {
|
||||
throw new Error(
|
||||
`location header is not found in request: ${res.url}`
|
||||
);
|
||||
}
|
||||
|
||||
const resourceId = last(locationHeader.split(SLASH));
|
||||
if (!resourceId) {
|
||||
// throw an error to let users know the response is not expected
|
||||
throw new Error(
|
||||
`resourceId is not found in Location header from request: ${res.url}`
|
||||
);
|
||||
}
|
||||
|
||||
// return with format {[field]: string}
|
||||
const { field } = returnResourceIdInLocationHeader;
|
||||
return { [field]: resourceId };
|
||||
}
|
||||
|
||||
if (
|
||||
Object.entries(headers || []).find(
|
||||
([key, value]) =>
|
||||
key.toLowerCase() === "accept" &&
|
||||
value === "application/octet-stream"
|
||||
)
|
||||
) {
|
||||
return res.arrayBuffer();
|
||||
}
|
||||
|
||||
return parseResponse(res);
|
||||
} catch (err) {
|
||||
if (
|
||||
err instanceof NetworkError &&
|
||||
err.response.status === 404 &&
|
||||
catchNotFound
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
private transformKey(payload: any, keyMapping: Record<string, string>) {
|
||||
if (!payload) {
|
||||
return;
|
||||
}
|
||||
|
||||
Object.keys(keyMapping).some((key) => {
|
||||
if (isUndefined(payload[key])) {
|
||||
// Skip if undefined
|
||||
return false;
|
||||
}
|
||||
const newKey = keyMapping[key];
|
||||
payload[newKey] = payload[key];
|
||||
delete payload[key];
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
import Resource from "./resource.js";
|
||||
import type KeycloakAdminClient from "../index.js";
|
||||
|
||||
export class AttackDetection extends Resource<{ realm?: string }> {
|
||||
public findOne = this.makeRequest<
|
||||
{ id: string },
|
||||
Record<string, any> | undefined
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/users/{id}",
|
||||
urlParamKeys: ["id"],
|
||||
catchNotFound: true,
|
||||
});
|
||||
|
||||
public del = this.makeRequest<{ id: string }, void>({
|
||||
method: "DELETE",
|
||||
path: "/users/{id}",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public delAll = this.makeRequest<{}, void>({
|
||||
method: "DELETE",
|
||||
path: "/users",
|
||||
});
|
||||
|
||||
constructor(client: KeycloakAdminClient) {
|
||||
super(client, {
|
||||
path: "/admin/realms/{realm}/attack-detection/brute-force",
|
||||
getUrlParams: () => ({
|
||||
realm: client.realmName,
|
||||
}),
|
||||
getBaseUrl: () => client.baseUrl,
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,286 @@
|
|||
import Resource from "./resource.js";
|
||||
import type RequiredActionProviderRepresentation from "../defs/requiredActionProviderRepresentation.js";
|
||||
import type { KeycloakAdminClient } from "../client.js";
|
||||
import type AuthenticationExecutionInfoRepresentation from "../defs/authenticationExecutionInfoRepresentation.js";
|
||||
import type AuthenticationFlowRepresentation from "../defs/authenticationFlowRepresentation.js";
|
||||
import type AuthenticatorConfigRepresentation from "../defs/authenticatorConfigRepresentation.js";
|
||||
import type { AuthenticationProviderRepresentation } from "../defs/authenticatorConfigRepresentation.js";
|
||||
import type AuthenticatorConfigInfoRepresentation from "../defs/authenticatorConfigInfoRepresentation.js";
|
||||
import type RequiredActionProviderSimpleRepresentation from "../defs/requiredActionProviderSimpleRepresentation.js";
|
||||
|
||||
export class AuthenticationManagement extends Resource {
|
||||
/**
|
||||
* Authentication Management
|
||||
* https://www.keycloak.org/docs-api/8.0/rest-api/index.html#_authentication_management_resource
|
||||
*/
|
||||
|
||||
// Register a new required action
|
||||
public registerRequiredAction = this.makeRequest<Record<string, any>>({
|
||||
method: "POST",
|
||||
path: "/register-required-action",
|
||||
});
|
||||
|
||||
// Get required actions. Returns a list of required actions.
|
||||
public getRequiredActions = this.makeRequest<
|
||||
void,
|
||||
RequiredActionProviderRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/required-actions",
|
||||
});
|
||||
|
||||
// Get required action for alias
|
||||
public getRequiredActionForAlias = this.makeRequest<{
|
||||
alias: string;
|
||||
}>({
|
||||
method: "GET",
|
||||
path: "/required-actions/{alias}",
|
||||
urlParamKeys: ["alias"],
|
||||
catchNotFound: true,
|
||||
});
|
||||
|
||||
public getClientAuthenticatorProviders = this.makeRequest<
|
||||
void,
|
||||
AuthenticationProviderRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/client-authenticator-providers",
|
||||
});
|
||||
|
||||
public getAuthenticatorProviders = this.makeRequest<
|
||||
void,
|
||||
AuthenticationProviderRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/authenticator-providers",
|
||||
});
|
||||
|
||||
public getFormActionProviders = this.makeRequest<
|
||||
void,
|
||||
AuthenticationProviderRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/form-action-providers",
|
||||
});
|
||||
|
||||
// Update required action
|
||||
public updateRequiredAction = this.makeUpdateRequest<
|
||||
{ alias: string },
|
||||
RequiredActionProviderRepresentation,
|
||||
void
|
||||
>({
|
||||
method: "PUT",
|
||||
path: "/required-actions/{alias}",
|
||||
urlParamKeys: ["alias"],
|
||||
});
|
||||
|
||||
// Delete required action
|
||||
public deleteRequiredAction = this.makeRequest<{ alias: string }, void>({
|
||||
method: "DELETE",
|
||||
path: "/required-actions/{alias}",
|
||||
urlParamKeys: ["alias"],
|
||||
});
|
||||
|
||||
// Lower required action’s priority
|
||||
public lowerRequiredActionPriority = this.makeRequest<{
|
||||
alias: string;
|
||||
}>({
|
||||
method: "POST",
|
||||
path: "/required-actions/{alias}/lower-priority",
|
||||
urlParamKeys: ["alias"],
|
||||
});
|
||||
|
||||
// Raise required action’s priority
|
||||
public raiseRequiredActionPriority = this.makeRequest<{
|
||||
alias: string;
|
||||
}>({
|
||||
method: "POST",
|
||||
path: "/required-actions/{alias}/raise-priority",
|
||||
urlParamKeys: ["alias"],
|
||||
});
|
||||
|
||||
// Get unregistered required actions Returns a list of unregistered required actions.
|
||||
public getUnregisteredRequiredActions = this.makeRequest<
|
||||
void,
|
||||
RequiredActionProviderSimpleRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/unregistered-required-actions",
|
||||
});
|
||||
|
||||
public getFlows = this.makeRequest<{}, AuthenticationFlowRepresentation[]>({
|
||||
method: "GET",
|
||||
path: "/flows",
|
||||
});
|
||||
|
||||
public getFlow = this.makeRequest<
|
||||
{ flowId: string },
|
||||
AuthenticationFlowRepresentation
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/flows/{flowId}",
|
||||
urlParamKeys: ["flowId"],
|
||||
});
|
||||
|
||||
public getFormProviders = this.makeRequest<
|
||||
void,
|
||||
AuthenticationProviderRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/form-providers",
|
||||
});
|
||||
|
||||
public createFlow = this.makeRequest<
|
||||
AuthenticationFlowRepresentation,
|
||||
AuthenticationFlowRepresentation
|
||||
>({
|
||||
method: "POST",
|
||||
path: "/flows",
|
||||
returnResourceIdInLocationHeader: { field: "id" },
|
||||
});
|
||||
|
||||
public copyFlow = this.makeRequest<{ flow: string; newName: string }>({
|
||||
method: "POST",
|
||||
path: "/flows/{flow}/copy",
|
||||
urlParamKeys: ["flow"],
|
||||
});
|
||||
|
||||
public deleteFlow = this.makeRequest<{ flowId: string }>({
|
||||
method: "DELETE",
|
||||
path: "/flows/{flowId}",
|
||||
urlParamKeys: ["flowId"],
|
||||
});
|
||||
|
||||
public updateFlow = this.makeUpdateRequest<
|
||||
{ flowId: string },
|
||||
AuthenticationFlowRepresentation
|
||||
>({
|
||||
method: "PUT",
|
||||
path: "/flows/{flowId}",
|
||||
urlParamKeys: ["flowId"],
|
||||
});
|
||||
|
||||
public getExecutions = this.makeRequest<
|
||||
{ flow: string },
|
||||
AuthenticationExecutionInfoRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/flows/{flow}/executions",
|
||||
urlParamKeys: ["flow"],
|
||||
});
|
||||
|
||||
public addExecution = this.makeUpdateRequest<
|
||||
{ flow: string },
|
||||
AuthenticationExecutionInfoRepresentation
|
||||
>({
|
||||
method: "POST",
|
||||
path: "/flows/{flow}/executions",
|
||||
urlParamKeys: ["flow"],
|
||||
});
|
||||
|
||||
public addExecutionToFlow = this.makeRequest<
|
||||
{ flow: string; provider: string },
|
||||
AuthenticationExecutionInfoRepresentation
|
||||
>({
|
||||
method: "POST",
|
||||
path: "/flows/{flow}/executions/execution",
|
||||
urlParamKeys: ["flow"],
|
||||
returnResourceIdInLocationHeader: { field: "id" },
|
||||
});
|
||||
|
||||
public addFlowToFlow = this.makeRequest<
|
||||
{
|
||||
flow: string;
|
||||
alias: string;
|
||||
type: string;
|
||||
provider: string;
|
||||
description: string;
|
||||
},
|
||||
AuthenticationFlowRepresentation
|
||||
>({
|
||||
method: "POST",
|
||||
path: "/flows/{flow}/executions/flow",
|
||||
urlParamKeys: ["flow"],
|
||||
returnResourceIdInLocationHeader: { field: "id" },
|
||||
});
|
||||
|
||||
public updateExecution = this.makeUpdateRequest<
|
||||
{ flow: string },
|
||||
AuthenticationExecutionInfoRepresentation
|
||||
>({
|
||||
method: "PUT",
|
||||
path: "/flows/{flow}/executions",
|
||||
urlParamKeys: ["flow"],
|
||||
});
|
||||
|
||||
public delExecution = this.makeRequest<{ id: string }>({
|
||||
method: "DELETE",
|
||||
path: "/executions/{id}",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public lowerPriorityExecution = this.makeRequest<{ id: string }>({
|
||||
method: "POST",
|
||||
path: "/executions/{id}/lower-priority",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public raisePriorityExecution = this.makeRequest<{ id: string }>({
|
||||
method: "POST",
|
||||
path: "/executions/{id}/raise-priority",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public getConfigDescription = this.makeRequest<
|
||||
{ providerId: string },
|
||||
AuthenticatorConfigInfoRepresentation
|
||||
>({
|
||||
method: "GET",
|
||||
path: "config-description/{providerId}",
|
||||
urlParamKeys: ["providerId"],
|
||||
});
|
||||
|
||||
public createConfig = this.makeRequest<
|
||||
AuthenticatorConfigRepresentation,
|
||||
AuthenticatorConfigRepresentation
|
||||
>({
|
||||
method: "POST",
|
||||
path: "/executions/{id}/config",
|
||||
urlParamKeys: ["id"],
|
||||
returnResourceIdInLocationHeader: { field: "id" },
|
||||
});
|
||||
|
||||
public updateConfig = this.makeRequest<
|
||||
AuthenticatorConfigRepresentation,
|
||||
void
|
||||
>({
|
||||
method: "PUT",
|
||||
path: "/config/{id}",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public getConfig = this.makeRequest<
|
||||
{ id: string },
|
||||
AuthenticatorConfigRepresentation
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/config/{id}",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public delConfig = this.makeRequest<{ id: string }>({
|
||||
method: "DELETE",
|
||||
path: "/config/{id}",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
constructor(client: KeycloakAdminClient) {
|
||||
super(client, {
|
||||
path: "/admin/realms/{realm}/authentication",
|
||||
getUrlParams: () => ({
|
||||
realm: client.realmName,
|
||||
}),
|
||||
getBaseUrl: () => client.baseUrl,
|
||||
});
|
||||
}
|
||||
}
|
19
js/libs/keycloak-admin-client/src/resources/cache.ts
Normal file
19
js/libs/keycloak-admin-client/src/resources/cache.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
import Resource from "./resource.js";
|
||||
import type { KeycloakAdminClient } from "../client.js";
|
||||
|
||||
export class Cache extends Resource<{ realm?: string }> {
|
||||
public clearUserCache = this.makeRequest<{}, void>({
|
||||
method: "POST",
|
||||
path: "/clear-user-cache",
|
||||
});
|
||||
|
||||
constructor(client: KeycloakAdminClient) {
|
||||
super(client, {
|
||||
path: "/admin/realms/{realm}",
|
||||
getUrlParams: () => ({
|
||||
realm: client.realmName,
|
||||
}),
|
||||
getBaseUrl: () => client.baseUrl,
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
import Resource from "./resource.js";
|
||||
import type { KeycloakAdminClient } from "../client.js";
|
||||
import type ClientProfilesRepresentation from "../defs/clientProfilesRepresentation.js";
|
||||
import type ClientPoliciesRepresentation from "../defs/clientPoliciesRepresentation.js";
|
||||
|
||||
/**
|
||||
* https://www.keycloak.org/docs-api/15.0/rest-api/#_client_registration_policy_resource
|
||||
*/
|
||||
export class ClientPolicies extends Resource<{ realm?: string }> {
|
||||
constructor(client: KeycloakAdminClient) {
|
||||
super(client, {
|
||||
path: "/admin/realms/{realm}/client-policies",
|
||||
getUrlParams: () => ({
|
||||
realm: client.realmName,
|
||||
}),
|
||||
getBaseUrl: () => client.baseUrl,
|
||||
});
|
||||
}
|
||||
|
||||
/* Client Profiles */
|
||||
|
||||
public listProfiles = this.makeRequest<
|
||||
{ includeGlobalProfiles?: boolean },
|
||||
ClientProfilesRepresentation
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/profiles",
|
||||
queryParamKeys: ["include-global-profiles"],
|
||||
keyTransform: {
|
||||
includeGlobalProfiles: "include-global-profiles",
|
||||
},
|
||||
});
|
||||
|
||||
public createProfiles = this.makeRequest<ClientProfilesRepresentation, void>({
|
||||
method: "PUT",
|
||||
path: "/profiles",
|
||||
});
|
||||
|
||||
/* Client Policies */
|
||||
|
||||
public listPolicies = this.makeRequest<{}, ClientPoliciesRepresentation>({
|
||||
method: "GET",
|
||||
path: "/policies",
|
||||
});
|
||||
|
||||
public updatePolicy = this.makeRequest<ClientPoliciesRepresentation, void>({
|
||||
method: "PUT",
|
||||
path: "/policies",
|
||||
});
|
||||
}
|
336
js/libs/keycloak-admin-client/src/resources/clientScopes.ts
Normal file
336
js/libs/keycloak-admin-client/src/resources/clientScopes.ts
Normal file
|
@ -0,0 +1,336 @@
|
|||
import type ClientScopeRepresentation from "../defs/clientScopeRepresentation.js";
|
||||
import Resource from "./resource.js";
|
||||
import type { KeycloakAdminClient } from "../client.js";
|
||||
import type ProtocolMapperRepresentation from "../defs/protocolMapperRepresentation.js";
|
||||
import type MappingsRepresentation from "../defs/mappingsRepresentation.js";
|
||||
import type RoleRepresentation from "../defs/roleRepresentation.js";
|
||||
|
||||
export class ClientScopes extends Resource<{ realm?: string }> {
|
||||
public find = this.makeRequest<{}, ClientScopeRepresentation[]>({
|
||||
method: "GET",
|
||||
path: "/client-scopes",
|
||||
});
|
||||
|
||||
public create = this.makeRequest<ClientScopeRepresentation, { id: string }>({
|
||||
method: "POST",
|
||||
path: "/client-scopes",
|
||||
returnResourceIdInLocationHeader: { field: "id" },
|
||||
});
|
||||
|
||||
/**
|
||||
* Client-Scopes by id
|
||||
*/
|
||||
|
||||
public findOne = this.makeRequest<
|
||||
{ id: string },
|
||||
ClientScopeRepresentation | undefined
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/client-scopes/{id}",
|
||||
urlParamKeys: ["id"],
|
||||
catchNotFound: true,
|
||||
});
|
||||
|
||||
public update = this.makeUpdateRequest<
|
||||
{ id: string },
|
||||
ClientScopeRepresentation,
|
||||
void
|
||||
>({
|
||||
method: "PUT",
|
||||
path: "/client-scopes/{id}",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public del = this.makeRequest<{ id: string }, void>({
|
||||
method: "DELETE",
|
||||
path: "/client-scopes/{id}",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
/**
|
||||
* Default Client-Scopes
|
||||
*/
|
||||
|
||||
public listDefaultClientScopes = this.makeRequest<
|
||||
void,
|
||||
ClientScopeRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/default-default-client-scopes",
|
||||
});
|
||||
|
||||
public addDefaultClientScope = this.makeRequest<{ id: string }, void>({
|
||||
method: "PUT",
|
||||
path: "/default-default-client-scopes/{id}",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public delDefaultClientScope = this.makeRequest<{ id: string }, void>({
|
||||
method: "DELETE",
|
||||
path: "/default-default-client-scopes/{id}",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
/**
|
||||
* Default Optional Client-Scopes
|
||||
*/
|
||||
|
||||
public listDefaultOptionalClientScopes = this.makeRequest<
|
||||
void,
|
||||
ClientScopeRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/default-optional-client-scopes",
|
||||
});
|
||||
|
||||
public addDefaultOptionalClientScope = this.makeRequest<{ id: string }, void>(
|
||||
{
|
||||
method: "PUT",
|
||||
path: "/default-optional-client-scopes/{id}",
|
||||
urlParamKeys: ["id"],
|
||||
}
|
||||
);
|
||||
|
||||
public delDefaultOptionalClientScope = this.makeRequest<{ id: string }, void>(
|
||||
{
|
||||
method: "DELETE",
|
||||
path: "/default-optional-client-scopes/{id}",
|
||||
urlParamKeys: ["id"],
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Protocol Mappers
|
||||
*/
|
||||
|
||||
public addMultipleProtocolMappers = this.makeUpdateRequest<
|
||||
{ id: string },
|
||||
ProtocolMapperRepresentation[],
|
||||
void
|
||||
>({
|
||||
method: "POST",
|
||||
path: "/client-scopes/{id}/protocol-mappers/add-models",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public addProtocolMapper = this.makeUpdateRequest<
|
||||
{ id: string },
|
||||
ProtocolMapperRepresentation,
|
||||
void
|
||||
>({
|
||||
method: "POST",
|
||||
path: "/client-scopes/{id}/protocol-mappers/models",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public listProtocolMappers = this.makeRequest<
|
||||
{ id: string },
|
||||
ProtocolMapperRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/client-scopes/{id}/protocol-mappers/models",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public findProtocolMapper = this.makeRequest<
|
||||
{ id: string; mapperId: string },
|
||||
ProtocolMapperRepresentation | undefined
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/client-scopes/{id}/protocol-mappers/models/{mapperId}",
|
||||
urlParamKeys: ["id", "mapperId"],
|
||||
catchNotFound: true,
|
||||
});
|
||||
|
||||
public findProtocolMappersByProtocol = this.makeRequest<
|
||||
{ id: string; protocol: string },
|
||||
ProtocolMapperRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/client-scopes/{id}/protocol-mappers/protocol/{protocol}",
|
||||
urlParamKeys: ["id", "protocol"],
|
||||
catchNotFound: true,
|
||||
});
|
||||
|
||||
public updateProtocolMapper = this.makeUpdateRequest<
|
||||
{ id: string; mapperId: string },
|
||||
ProtocolMapperRepresentation,
|
||||
void
|
||||
>({
|
||||
method: "PUT",
|
||||
path: "/client-scopes/{id}/protocol-mappers/models/{mapperId}",
|
||||
urlParamKeys: ["id", "mapperId"],
|
||||
});
|
||||
|
||||
public delProtocolMapper = this.makeRequest<
|
||||
{ id: string; mapperId: string },
|
||||
void
|
||||
>({
|
||||
method: "DELETE",
|
||||
path: "/client-scopes/{id}/protocol-mappers/models/{mapperId}",
|
||||
urlParamKeys: ["id", "mapperId"],
|
||||
});
|
||||
|
||||
/**
|
||||
* Scope Mappings
|
||||
*/
|
||||
public listScopeMappings = this.makeRequest<
|
||||
{ id: string },
|
||||
MappingsRepresentation
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/client-scopes/{id}/scope-mappings",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public addClientScopeMappings = this.makeUpdateRequest<
|
||||
{ id: string; client: string },
|
||||
RoleRepresentation[],
|
||||
void
|
||||
>({
|
||||
method: "POST",
|
||||
path: "/client-scopes/{id}/scope-mappings/clients/{client}",
|
||||
urlParamKeys: ["id", "client"],
|
||||
});
|
||||
|
||||
public listClientScopeMappings = this.makeRequest<
|
||||
{ id: string; client: string },
|
||||
RoleRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/client-scopes/{id}/scope-mappings/clients/{client}",
|
||||
urlParamKeys: ["id", "client"],
|
||||
});
|
||||
|
||||
public listAvailableClientScopeMappings = this.makeRequest<
|
||||
{ id: string; client: string },
|
||||
RoleRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/client-scopes/{id}/scope-mappings/clients/{client}/available",
|
||||
urlParamKeys: ["id", "client"],
|
||||
});
|
||||
|
||||
public listCompositeClientScopeMappings = this.makeRequest<
|
||||
{ id: string; client: string },
|
||||
RoleRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/client-scopes/{id}/scope-mappings/clients/{client}/composite",
|
||||
urlParamKeys: ["id", "client"],
|
||||
});
|
||||
|
||||
public delClientScopeMappings = this.makeUpdateRequest<
|
||||
{ id: string; client: string },
|
||||
RoleRepresentation[],
|
||||
void
|
||||
>({
|
||||
method: "DELETE",
|
||||
path: "/client-scopes/{id}/scope-mappings/clients/{client}",
|
||||
urlParamKeys: ["id", "client"],
|
||||
});
|
||||
|
||||
public addRealmScopeMappings = this.makeUpdateRequest<
|
||||
{ id: string },
|
||||
RoleRepresentation[],
|
||||
void
|
||||
>({
|
||||
method: "POST",
|
||||
path: "/client-scopes/{id}/scope-mappings/realm",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public listRealmScopeMappings = this.makeRequest<
|
||||
{ id: string },
|
||||
RoleRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/client-scopes/{id}/scope-mappings/realm",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public listAvailableRealmScopeMappings = this.makeRequest<
|
||||
{ id: string },
|
||||
RoleRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/client-scopes/{id}/scope-mappings/realm/available",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public listCompositeRealmScopeMappings = this.makeRequest<
|
||||
{ id: string },
|
||||
RoleRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/client-scopes/{id}/scope-mappings/realm/composite",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public delRealmScopeMappings = this.makeUpdateRequest<
|
||||
{ id: string },
|
||||
RoleRepresentation[],
|
||||
void
|
||||
>({
|
||||
method: "DELETE",
|
||||
path: "/client-scopes/{id}/scope-mappings/realm",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
constructor(client: KeycloakAdminClient) {
|
||||
super(client, {
|
||||
path: "/admin/realms/{realm}",
|
||||
getUrlParams: () => ({
|
||||
realm: client.realmName,
|
||||
}),
|
||||
getBaseUrl: () => client.baseUrl,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Find client scope by name.
|
||||
*/
|
||||
public async findOneByName(payload: {
|
||||
realm?: string;
|
||||
name: string;
|
||||
}): Promise<ClientScopeRepresentation | undefined> {
|
||||
const allScopes = await this.find({
|
||||
...(payload.realm ? { realm: payload.realm } : {}),
|
||||
});
|
||||
return allScopes.find((item) => item.name === payload.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete client scope by name.
|
||||
*/
|
||||
public async delByName(payload: {
|
||||
realm?: string;
|
||||
name: string;
|
||||
}): Promise<void> {
|
||||
const scope = await this.findOneByName(payload);
|
||||
|
||||
if (!scope) {
|
||||
throw new Error("Scope not found.");
|
||||
}
|
||||
|
||||
await this.del({
|
||||
...(payload.realm ? { realm: payload.realm } : {}),
|
||||
id: scope.id!,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Find single protocol mapper by name.
|
||||
*/
|
||||
public async findProtocolMapperByName(payload: {
|
||||
realm?: string;
|
||||
id: string;
|
||||
name: string;
|
||||
}): Promise<ProtocolMapperRepresentation | undefined> {
|
||||
const allProtocolMappers = await this.listProtocolMappers({
|
||||
id: payload.id,
|
||||
...(payload.realm ? { realm: payload.realm } : {}),
|
||||
});
|
||||
return allProtocolMappers.find((mapper) => mapper.name === payload.name);
|
||||
}
|
||||
}
|
1040
js/libs/keycloak-admin-client/src/resources/clients.ts
Normal file
1040
js/libs/keycloak-admin-client/src/resources/clients.ts
Normal file
File diff suppressed because it is too large
Load diff
72
js/libs/keycloak-admin-client/src/resources/components.ts
Normal file
72
js/libs/keycloak-admin-client/src/resources/components.ts
Normal file
|
@ -0,0 +1,72 @@
|
|||
import Resource from "./resource.js";
|
||||
import type ComponentRepresentation from "../defs/componentRepresentation.js";
|
||||
import type ComponentTypeRepresentation from "../defs/componentTypeRepresentation.js";
|
||||
import type { KeycloakAdminClient } from "../client.js";
|
||||
|
||||
export interface ComponentQuery {
|
||||
name?: string;
|
||||
parent?: string;
|
||||
type?: string;
|
||||
}
|
||||
|
||||
export class Components extends Resource<{ realm?: string }> {
|
||||
/**
|
||||
* components
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/#_component_resource
|
||||
*/
|
||||
|
||||
public find = this.makeRequest<ComponentQuery, ComponentRepresentation[]>({
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
public create = this.makeRequest<ComponentRepresentation, { id: string }>({
|
||||
method: "POST",
|
||||
returnResourceIdInLocationHeader: { field: "id" },
|
||||
});
|
||||
|
||||
public findOne = this.makeRequest<
|
||||
{ id: string },
|
||||
ComponentRepresentation | undefined
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{id}",
|
||||
urlParamKeys: ["id"],
|
||||
catchNotFound: true,
|
||||
});
|
||||
|
||||
public update = this.makeUpdateRequest<
|
||||
{ id: string },
|
||||
ComponentRepresentation,
|
||||
void
|
||||
>({
|
||||
method: "PUT",
|
||||
path: "/{id}",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public del = this.makeRequest<{ id: string }, void>({
|
||||
method: "DELETE",
|
||||
path: "/{id}",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public listSubComponents = this.makeRequest<
|
||||
{ id: string; type: string },
|
||||
ComponentTypeRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{id}/sub-component-types",
|
||||
urlParamKeys: ["id"],
|
||||
queryParamKeys: ["type"],
|
||||
});
|
||||
|
||||
constructor(client: KeycloakAdminClient) {
|
||||
super(client, {
|
||||
path: "/admin/realms/{realm}/components",
|
||||
getUrlParams: () => ({
|
||||
realm: client.realmName,
|
||||
}),
|
||||
getBaseUrl: () => client.baseUrl,
|
||||
});
|
||||
}
|
||||
}
|
242
js/libs/keycloak-admin-client/src/resources/groups.ts
Normal file
242
js/libs/keycloak-admin-client/src/resources/groups.ts
Normal file
|
@ -0,0 +1,242 @@
|
|||
import type { KeycloakAdminClient } from "../client.js";
|
||||
import type GroupRepresentation from "../defs/groupRepresentation.js";
|
||||
import type { ManagementPermissionReference } from "../defs/managementPermissionReference.js";
|
||||
import type MappingsRepresentation from "../defs/mappingsRepresentation.js";
|
||||
import type RoleRepresentation from "../defs/roleRepresentation.js";
|
||||
import type { RoleMappingPayload } from "../defs/roleRepresentation.js";
|
||||
import type UserRepresentation from "../defs/userRepresentation.js";
|
||||
import Resource from "./resource.js";
|
||||
|
||||
export interface GroupQuery {
|
||||
first?: number;
|
||||
max?: number;
|
||||
search?: string;
|
||||
briefRepresentation?: boolean;
|
||||
}
|
||||
|
||||
export interface GroupCountQuery {
|
||||
search?: string;
|
||||
top?: boolean;
|
||||
}
|
||||
|
||||
export class Groups extends Resource<{ realm?: string }> {
|
||||
public find = this.makeRequest<GroupQuery, GroupRepresentation[]>({
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
public create = this.makeRequest<GroupRepresentation, { id: string }>({
|
||||
method: "POST",
|
||||
returnResourceIdInLocationHeader: { field: "id" },
|
||||
});
|
||||
|
||||
/**
|
||||
* Single user
|
||||
*/
|
||||
|
||||
public findOne = this.makeRequest<
|
||||
{ id: string },
|
||||
GroupRepresentation | undefined
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{id}",
|
||||
urlParamKeys: ["id"],
|
||||
catchNotFound: true,
|
||||
});
|
||||
|
||||
public update = this.makeUpdateRequest<
|
||||
{ id: string },
|
||||
GroupRepresentation,
|
||||
void
|
||||
>({
|
||||
method: "PUT",
|
||||
path: "/{id}",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public del = this.makeRequest<{ id: string }, void>({
|
||||
method: "DELETE",
|
||||
path: "/{id}",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public count = this.makeRequest<GroupCountQuery, { count: number }>({
|
||||
method: "GET",
|
||||
path: "/count",
|
||||
});
|
||||
|
||||
/**
|
||||
* Set or create child.
|
||||
* This will just set the parent if it exists. Create it and set the parent if the group doesn’t exist.
|
||||
*/
|
||||
|
||||
public setOrCreateChild = this.makeUpdateRequest<
|
||||
{ id: string },
|
||||
GroupRepresentation,
|
||||
{ id: string }
|
||||
>({
|
||||
method: "POST",
|
||||
path: "/{id}/children",
|
||||
urlParamKeys: ["id"],
|
||||
returnResourceIdInLocationHeader: { field: "id" },
|
||||
});
|
||||
|
||||
/**
|
||||
* Members
|
||||
*/
|
||||
|
||||
public listMembers = this.makeRequest<
|
||||
{ id: string; first?: number; max?: number },
|
||||
UserRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{id}/members",
|
||||
urlParamKeys: ["id"],
|
||||
catchNotFound: true,
|
||||
});
|
||||
|
||||
/**
|
||||
* Role mappings
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/#_role_mapper_resource
|
||||
*/
|
||||
|
||||
public listRoleMappings = this.makeRequest<
|
||||
{ id: string },
|
||||
MappingsRepresentation
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{id}/role-mappings",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public addRealmRoleMappings = this.makeRequest<
|
||||
{ id: string; roles: RoleMappingPayload[] },
|
||||
void
|
||||
>({
|
||||
method: "POST",
|
||||
path: "/{id}/role-mappings/realm",
|
||||
urlParamKeys: ["id"],
|
||||
payloadKey: "roles",
|
||||
});
|
||||
|
||||
public listRealmRoleMappings = this.makeRequest<
|
||||
{ id: string },
|
||||
RoleRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{id}/role-mappings/realm",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public delRealmRoleMappings = this.makeRequest<
|
||||
{ id: string; roles: RoleMappingPayload[] },
|
||||
void
|
||||
>({
|
||||
method: "DELETE",
|
||||
path: "/{id}/role-mappings/realm",
|
||||
urlParamKeys: ["id"],
|
||||
payloadKey: "roles",
|
||||
});
|
||||
|
||||
public listAvailableRealmRoleMappings = this.makeRequest<
|
||||
{ id: string },
|
||||
RoleRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{id}/role-mappings/realm/available",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
// Get effective realm-level role mappings This will recurse all composite roles to get the result.
|
||||
public listCompositeRealmRoleMappings = this.makeRequest<
|
||||
{ id: string },
|
||||
RoleRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{id}/role-mappings/realm/composite",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
/**
|
||||
* Client role mappings
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/#_client_role_mappings_resource
|
||||
*/
|
||||
|
||||
public listClientRoleMappings = this.makeRequest<
|
||||
{ id: string; clientUniqueId: string },
|
||||
RoleRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{id}/role-mappings/clients/{clientUniqueId}",
|
||||
urlParamKeys: ["id", "clientUniqueId"],
|
||||
});
|
||||
|
||||
public addClientRoleMappings = this.makeRequest<
|
||||
{ id: string; clientUniqueId: string; roles: RoleMappingPayload[] },
|
||||
void
|
||||
>({
|
||||
method: "POST",
|
||||
path: "/{id}/role-mappings/clients/{clientUniqueId}",
|
||||
urlParamKeys: ["id", "clientUniqueId"],
|
||||
payloadKey: "roles",
|
||||
});
|
||||
|
||||
public delClientRoleMappings = this.makeRequest<
|
||||
{ id: string; clientUniqueId: string; roles: RoleMappingPayload[] },
|
||||
void
|
||||
>({
|
||||
method: "DELETE",
|
||||
path: "/{id}/role-mappings/clients/{clientUniqueId}",
|
||||
urlParamKeys: ["id", "clientUniqueId"],
|
||||
payloadKey: "roles",
|
||||
});
|
||||
|
||||
public listAvailableClientRoleMappings = this.makeRequest<
|
||||
{ id: string; clientUniqueId: string },
|
||||
RoleRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{id}/role-mappings/clients/{clientUniqueId}/available",
|
||||
urlParamKeys: ["id", "clientUniqueId"],
|
||||
});
|
||||
|
||||
public listCompositeClientRoleMappings = this.makeRequest<
|
||||
{ id: string; clientUniqueId: string },
|
||||
RoleRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{id}/role-mappings/clients/{clientUniqueId}/composite",
|
||||
urlParamKeys: ["id", "clientUniqueId"],
|
||||
});
|
||||
|
||||
/**
|
||||
* Authorization permissions
|
||||
*/
|
||||
public updatePermission = this.makeUpdateRequest<
|
||||
{ id: string },
|
||||
ManagementPermissionReference,
|
||||
ManagementPermissionReference
|
||||
>({
|
||||
method: "PUT",
|
||||
path: "/{id}/management/permissions",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public listPermissions = this.makeRequest<
|
||||
{ id: string },
|
||||
ManagementPermissionReference
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{id}/management/permissions",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
constructor(client: KeycloakAdminClient) {
|
||||
super(client, {
|
||||
path: "/admin/realms/{realm}/groups",
|
||||
getUrlParams: () => ({
|
||||
realm: client.realmName,
|
||||
}),
|
||||
getBaseUrl: () => client.baseUrl,
|
||||
});
|
||||
}
|
||||
}
|
157
js/libs/keycloak-admin-client/src/resources/identityProviders.ts
Normal file
157
js/libs/keycloak-admin-client/src/resources/identityProviders.ts
Normal file
|
@ -0,0 +1,157 @@
|
|||
import type { KeycloakAdminClient } from "../client.js";
|
||||
import type IdentityProviderMapperRepresentation from "../defs/identityProviderMapperRepresentation.js";
|
||||
import type { IdentityProviderMapperTypeRepresentation } from "../defs/identityProviderMapperTypeRepresentation.js";
|
||||
import type IdentityProviderRepresentation from "../defs/identityProviderRepresentation.js";
|
||||
import type { ManagementPermissionReference } from "../defs/managementPermissionReference.js";
|
||||
import Resource from "./resource.js";
|
||||
|
||||
export class IdentityProviders extends Resource<{ realm?: string }> {
|
||||
/**
|
||||
* Identity provider
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/#_identity_providers_resource
|
||||
*/
|
||||
|
||||
public find = this.makeRequest<{}, IdentityProviderRepresentation[]>({
|
||||
method: "GET",
|
||||
path: "/instances",
|
||||
});
|
||||
|
||||
public create = this.makeRequest<
|
||||
IdentityProviderRepresentation,
|
||||
{ id: string }
|
||||
>({
|
||||
method: "POST",
|
||||
path: "/instances",
|
||||
returnResourceIdInLocationHeader: { field: "id" },
|
||||
});
|
||||
|
||||
public findOne = this.makeRequest<
|
||||
{ alias: string },
|
||||
IdentityProviderRepresentation | undefined
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/instances/{alias}",
|
||||
urlParamKeys: ["alias"],
|
||||
catchNotFound: true,
|
||||
});
|
||||
|
||||
public update = this.makeUpdateRequest<
|
||||
{ alias: string },
|
||||
IdentityProviderRepresentation,
|
||||
void
|
||||
>({
|
||||
method: "PUT",
|
||||
path: "/instances/{alias}",
|
||||
urlParamKeys: ["alias"],
|
||||
});
|
||||
|
||||
public del = this.makeRequest<{ alias: string }, void>({
|
||||
method: "DELETE",
|
||||
path: "/instances/{alias}",
|
||||
urlParamKeys: ["alias"],
|
||||
});
|
||||
|
||||
public findFactory = this.makeRequest<{ providerId: string }, any>({
|
||||
method: "GET",
|
||||
path: "/providers/{providerId}",
|
||||
urlParamKeys: ["providerId"],
|
||||
});
|
||||
|
||||
public findMappers = this.makeRequest<
|
||||
{ alias: string },
|
||||
IdentityProviderMapperRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/instances/{alias}/mappers",
|
||||
urlParamKeys: ["alias"],
|
||||
});
|
||||
|
||||
public findOneMapper = this.makeRequest<
|
||||
{ alias: string; id: string },
|
||||
IdentityProviderMapperRepresentation | undefined
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/instances/{alias}/mappers/{id}",
|
||||
urlParamKeys: ["alias", "id"],
|
||||
catchNotFound: true,
|
||||
});
|
||||
|
||||
public createMapper = this.makeRequest<
|
||||
{
|
||||
alias: string;
|
||||
identityProviderMapper: IdentityProviderMapperRepresentation;
|
||||
},
|
||||
{ id: string }
|
||||
>({
|
||||
method: "POST",
|
||||
path: "/instances/{alias}/mappers",
|
||||
urlParamKeys: ["alias"],
|
||||
payloadKey: "identityProviderMapper",
|
||||
returnResourceIdInLocationHeader: { field: "id" },
|
||||
});
|
||||
|
||||
public updateMapper = this.makeUpdateRequest<
|
||||
{ alias: string; id: string },
|
||||
IdentityProviderMapperRepresentation,
|
||||
void
|
||||
>({
|
||||
method: "PUT",
|
||||
path: "/instances/{alias}/mappers/{id}",
|
||||
urlParamKeys: ["alias", "id"],
|
||||
});
|
||||
|
||||
public delMapper = this.makeRequest<{ alias: string; id: string }, void>({
|
||||
method: "DELETE",
|
||||
path: "/instances/{alias}/mappers/{id}",
|
||||
urlParamKeys: ["alias", "id"],
|
||||
});
|
||||
|
||||
public findMapperTypes = this.makeRequest<
|
||||
{ alias: string },
|
||||
Record<string, IdentityProviderMapperTypeRepresentation>
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/instances/{alias}/mapper-types",
|
||||
urlParamKeys: ["alias"],
|
||||
});
|
||||
|
||||
public importFromUrl = this.makeRequest<
|
||||
{
|
||||
fromUrl: string;
|
||||
providerId: string;
|
||||
},
|
||||
Record<string, string>
|
||||
>({
|
||||
method: "POST",
|
||||
path: "/import-config",
|
||||
});
|
||||
|
||||
public updatePermission = this.makeUpdateRequest<
|
||||
{ alias: string },
|
||||
ManagementPermissionReference,
|
||||
ManagementPermissionReference
|
||||
>({
|
||||
method: "PUT",
|
||||
path: "/instances/{alias}/management/permissions",
|
||||
urlParamKeys: ["alias"],
|
||||
});
|
||||
|
||||
public listPermissions = this.makeRequest<
|
||||
{ alias: string },
|
||||
ManagementPermissionReference
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/instances/{alias}/management/permissions",
|
||||
urlParamKeys: ["alias"],
|
||||
});
|
||||
|
||||
constructor(client: KeycloakAdminClient) {
|
||||
super(client, {
|
||||
path: "/admin/realms/{realm}/identity-provider",
|
||||
getUrlParams: () => ({
|
||||
realm: client.realmName,
|
||||
}),
|
||||
getBaseUrl: () => client.baseUrl,
|
||||
});
|
||||
}
|
||||
}
|
402
js/libs/keycloak-admin-client/src/resources/realms.ts
Normal file
402
js/libs/keycloak-admin-client/src/resources/realms.ts
Normal file
|
@ -0,0 +1,402 @@
|
|||
import Resource from "./resource.js";
|
||||
import type AdminEventRepresentation from "../defs/adminEventRepresentation.js";
|
||||
import type RealmRepresentation from "../defs/realmRepresentation.js";
|
||||
import type {
|
||||
PartialImportRealmRepresentation,
|
||||
PartialImportResponse,
|
||||
} from "../defs/realmRepresentation.js";
|
||||
import type EventRepresentation from "../defs/eventRepresentation.js";
|
||||
import type EventType from "../defs/eventTypes.js";
|
||||
import type KeysMetadataRepresentation from "../defs/keyMetadataRepresentation.js";
|
||||
import type ClientInitialAccessPresentation from "../defs/clientInitialAccessPresentation.js";
|
||||
import type TestLdapConnectionRepresentation from "../defs/testLdapConnection.js";
|
||||
|
||||
import type { KeycloakAdminClient } from "../client.js";
|
||||
import type { RealmEventsConfigRepresentation } from "../defs/realmEventsConfigRepresentation.js";
|
||||
import type GlobalRequestResult from "../defs/globalRequestResult.js";
|
||||
import type GroupRepresentation from "../defs/groupRepresentation.js";
|
||||
import type { ManagementPermissionReference } from "../defs/managementPermissionReference.js";
|
||||
import type ComponentTypeRepresentation from "../defs/componentTypeRepresentation.js";
|
||||
|
||||
export class Realms extends Resource {
|
||||
/**
|
||||
* Realm
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/#_realms_admin_resource
|
||||
*/
|
||||
|
||||
public find = this.makeRequest<
|
||||
{ briefRepresentation?: boolean },
|
||||
RealmRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
public create = this.makeRequest<RealmRepresentation, { realmName: string }>({
|
||||
method: "POST",
|
||||
returnResourceIdInLocationHeader: { field: "realmName" },
|
||||
});
|
||||
|
||||
public findOne = this.makeRequest<
|
||||
{ realm: string },
|
||||
RealmRepresentation | undefined
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{realm}",
|
||||
urlParamKeys: ["realm"],
|
||||
catchNotFound: true,
|
||||
});
|
||||
|
||||
public update = this.makeUpdateRequest<
|
||||
{ realm: string },
|
||||
RealmRepresentation,
|
||||
void
|
||||
>({
|
||||
method: "PUT",
|
||||
path: "/{realm}",
|
||||
urlParamKeys: ["realm"],
|
||||
});
|
||||
|
||||
public del = this.makeRequest<{ realm: string }, void>({
|
||||
method: "DELETE",
|
||||
path: "/{realm}",
|
||||
urlParamKeys: ["realm"],
|
||||
});
|
||||
|
||||
public partialImport = this.makeRequest<
|
||||
{
|
||||
realm: string;
|
||||
rep: PartialImportRealmRepresentation;
|
||||
},
|
||||
PartialImportResponse
|
||||
>({
|
||||
method: "POST",
|
||||
path: "/{realm}/partialImport",
|
||||
urlParamKeys: ["realm"],
|
||||
payloadKey: "rep",
|
||||
});
|
||||
|
||||
public export = this.makeRequest<
|
||||
{
|
||||
realm: string;
|
||||
exportClients?: boolean;
|
||||
exportGroupsAndRoles?: boolean;
|
||||
},
|
||||
RealmRepresentation
|
||||
>({
|
||||
method: "POST",
|
||||
path: "/{realm}/partial-export",
|
||||
urlParamKeys: ["realm"],
|
||||
queryParamKeys: ["exportClients", "exportGroupsAndRoles"],
|
||||
});
|
||||
|
||||
public getDefaultGroups = this.makeRequest<
|
||||
{ realm: string },
|
||||
GroupRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{realm}/default-groups",
|
||||
urlParamKeys: ["realm"],
|
||||
});
|
||||
|
||||
public addDefaultGroup = this.makeRequest<{ realm: string; id: string }>({
|
||||
method: "PUT",
|
||||
path: "/{realm}/default-groups/{id}",
|
||||
urlParamKeys: ["realm", "id"],
|
||||
});
|
||||
|
||||
public removeDefaultGroup = this.makeRequest<{ realm: string; id: string }>({
|
||||
method: "DELETE",
|
||||
path: "/{realm}/default-groups/{id}",
|
||||
urlParamKeys: ["realm", "id"],
|
||||
});
|
||||
|
||||
public getGroupByPath = this.makeRequest<
|
||||
{ path: string; realm: string },
|
||||
GroupRepresentation
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{realm}/group-by-path/{path}",
|
||||
urlParamKeys: ["realm", "path"],
|
||||
});
|
||||
|
||||
/**
|
||||
* Get events Returns all events, or filters them based on URL query parameters listed here
|
||||
*/
|
||||
public findEvents = this.makeRequest<
|
||||
{
|
||||
realm: string;
|
||||
client?: string;
|
||||
dateFrom?: string;
|
||||
dateTo?: string;
|
||||
first?: number;
|
||||
ipAddress?: string;
|
||||
max?: number;
|
||||
type?: EventType | EventType[];
|
||||
user?: string;
|
||||
},
|
||||
EventRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{realm}/events",
|
||||
urlParamKeys: ["realm"],
|
||||
queryParamKeys: [
|
||||
"client",
|
||||
"dateFrom",
|
||||
"dateTo",
|
||||
"first",
|
||||
"ipAddress",
|
||||
"max",
|
||||
"type",
|
||||
"user",
|
||||
],
|
||||
});
|
||||
|
||||
public getConfigEvents = this.makeRequest<
|
||||
{ realm: string },
|
||||
RealmEventsConfigRepresentation
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{realm}/events/config",
|
||||
urlParamKeys: ["realm"],
|
||||
});
|
||||
|
||||
public updateConfigEvents = this.makeUpdateRequest<
|
||||
{ realm: string },
|
||||
RealmEventsConfigRepresentation,
|
||||
void
|
||||
>({
|
||||
method: "PUT",
|
||||
path: "/{realm}/events/config",
|
||||
urlParamKeys: ["realm"],
|
||||
});
|
||||
|
||||
public clearEvents = this.makeRequest<{ realm: string }, void>({
|
||||
method: "DELETE",
|
||||
path: "/{realm}/events",
|
||||
urlParamKeys: ["realm"],
|
||||
});
|
||||
|
||||
public clearAdminEvents = this.makeRequest<{ realm: string }, void>({
|
||||
method: "DELETE",
|
||||
path: "/{realm}/admin-events",
|
||||
urlParamKeys: ["realm"],
|
||||
});
|
||||
|
||||
public getClientRegistrationPolicyProviders = this.makeRequest<
|
||||
{ realm: string },
|
||||
ComponentTypeRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{realm}/client-registration-policy/providers",
|
||||
urlParamKeys: ["realm"],
|
||||
});
|
||||
|
||||
public getClientsInitialAccess = this.makeRequest<
|
||||
{ realm: string },
|
||||
ClientInitialAccessPresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{realm}/clients-initial-access",
|
||||
urlParamKeys: ["realm"],
|
||||
});
|
||||
|
||||
public createClientsInitialAccess = this.makeUpdateRequest<
|
||||
{ realm: string },
|
||||
{ count?: number; expiration?: number },
|
||||
ClientInitialAccessPresentation
|
||||
>({
|
||||
method: "POST",
|
||||
path: "/{realm}/clients-initial-access",
|
||||
urlParamKeys: ["realm"],
|
||||
});
|
||||
|
||||
public delClientsInitialAccess = this.makeRequest<
|
||||
{ realm: string; id: string },
|
||||
void
|
||||
>({
|
||||
method: "DELETE",
|
||||
path: "/{realm}/clients-initial-access/{id}",
|
||||
urlParamKeys: ["realm", "id"],
|
||||
});
|
||||
|
||||
/**
|
||||
* Remove a specific user session.
|
||||
*/
|
||||
public removeSession = this.makeRequest<
|
||||
{ realm: string; sessionId: string },
|
||||
void
|
||||
>({
|
||||
method: "DELETE",
|
||||
path: "/{realm}/sessions/{session}",
|
||||
urlParamKeys: ["realm", "session"],
|
||||
catchNotFound: true,
|
||||
});
|
||||
|
||||
/**
|
||||
* Get admin events Returns all admin events, or filters events based on URL query parameters listed here
|
||||
*/
|
||||
public findAdminEvents = this.makeRequest<
|
||||
{
|
||||
realm: string;
|
||||
authClient?: string;
|
||||
authIpAddress?: string;
|
||||
authRealm?: string;
|
||||
authUser?: string;
|
||||
dateFrom?: Date;
|
||||
dateTo?: Date;
|
||||
first?: number;
|
||||
max?: number;
|
||||
operationTypes?: string;
|
||||
resourcePath?: string;
|
||||
resourceTypes?: string;
|
||||
},
|
||||
AdminEventRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{realm}/admin-events",
|
||||
urlParamKeys: ["realm"],
|
||||
queryParamKeys: [
|
||||
"authClient",
|
||||
"authIpAddress",
|
||||
"authRealm",
|
||||
"authUser",
|
||||
"dateFrom",
|
||||
"dateTo",
|
||||
"max",
|
||||
"first",
|
||||
"operationTypes",
|
||||
"resourcePath",
|
||||
"resourceTypes",
|
||||
],
|
||||
});
|
||||
|
||||
/**
|
||||
* Users management permissions
|
||||
*/
|
||||
public getUsersManagementPermissions = this.makeRequest<
|
||||
{ realm: string },
|
||||
ManagementPermissionReference
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{realm}/users-management-permissions",
|
||||
urlParamKeys: ["realm"],
|
||||
});
|
||||
|
||||
public updateUsersManagementPermissions = this.makeRequest<
|
||||
{ realm: string; enabled: boolean },
|
||||
ManagementPermissionReference
|
||||
>({
|
||||
method: "PUT",
|
||||
path: "/{realm}/users-management-permissions",
|
||||
urlParamKeys: ["realm"],
|
||||
});
|
||||
|
||||
/**
|
||||
* Sessions
|
||||
*/
|
||||
public logoutAll = this.makeRequest<{ realm: string }, void>({
|
||||
method: "POST",
|
||||
path: "/{realm}/logout-all",
|
||||
urlParamKeys: ["realm"],
|
||||
});
|
||||
|
||||
public deleteSession = this.makeRequest<
|
||||
{ realm: string; session: string },
|
||||
void
|
||||
>({
|
||||
method: "DELETE",
|
||||
path: "/{realm}/sessions/{session}",
|
||||
urlParamKeys: ["realm", "session"],
|
||||
});
|
||||
|
||||
public pushRevocation = this.makeRequest<
|
||||
{ realm: string },
|
||||
GlobalRequestResult
|
||||
>({
|
||||
method: "POST",
|
||||
path: "/{realm}/push-revocation",
|
||||
urlParamKeys: ["realm"],
|
||||
ignoredKeys: ["realm"],
|
||||
});
|
||||
|
||||
public getKeys = this.makeRequest<
|
||||
{ realm: string },
|
||||
KeysMetadataRepresentation
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{realm}/keys",
|
||||
urlParamKeys: ["realm"],
|
||||
});
|
||||
|
||||
public testLDAPConnection = this.makeUpdateRequest<
|
||||
{ realm: string },
|
||||
TestLdapConnectionRepresentation
|
||||
>({
|
||||
method: "POST",
|
||||
path: "/{realm}/testLDAPConnection",
|
||||
urlParamKeys: ["realm"],
|
||||
});
|
||||
|
||||
public testSMTPConnection = this.makeUpdateRequest<
|
||||
{ realm: string },
|
||||
Record<string, string | number>
|
||||
>({
|
||||
method: "POST",
|
||||
path: "/{realm}/testSMTPConnection",
|
||||
urlParamKeys: ["realm"],
|
||||
});
|
||||
|
||||
public ldapServerCapabilities = this.makeUpdateRequest<
|
||||
{ realm: string },
|
||||
TestLdapConnectionRepresentation
|
||||
>({
|
||||
method: "POST",
|
||||
path: "/{realm}/ldap-server-capabilities",
|
||||
urlParamKeys: ["realm"],
|
||||
});
|
||||
|
||||
public getRealmSpecificLocales = this.makeRequest<
|
||||
{ realm: string },
|
||||
string[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{realm}/localization",
|
||||
urlParamKeys: ["realm"],
|
||||
});
|
||||
|
||||
public getRealmLocalizationTexts = this.makeRequest<
|
||||
{ realm: string; selectedLocale: string; first?: number; max?: number },
|
||||
Record<string, string>
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{realm}/localization/{selectedLocale}",
|
||||
urlParamKeys: ["realm", "selectedLocale"],
|
||||
});
|
||||
|
||||
public addLocalization = this.makeUpdateRequest<
|
||||
{ realm: string; selectedLocale: string; key: string },
|
||||
string,
|
||||
void
|
||||
>({
|
||||
method: "PUT",
|
||||
path: "/{realm}/localization/{selectedLocale}/{key}",
|
||||
urlParamKeys: ["realm", "selectedLocale", "key"],
|
||||
headers: { "content-type": "text/plain" },
|
||||
});
|
||||
|
||||
public deleteRealmLocalizationTexts = this.makeRequest<
|
||||
{ realm: string; selectedLocale: string; key?: string },
|
||||
void
|
||||
>({
|
||||
method: "DELETE",
|
||||
path: "/{realm}/localization/{selectedLocale}/{key}",
|
||||
urlParamKeys: ["realm", "selectedLocale", "key"],
|
||||
});
|
||||
|
||||
constructor(client: KeycloakAdminClient) {
|
||||
super(client, {
|
||||
path: "/admin/realms",
|
||||
getBaseUrl: () => client.baseUrl,
|
||||
});
|
||||
}
|
||||
}
|
42
js/libs/keycloak-admin-client/src/resources/resource.ts
Normal file
42
js/libs/keycloak-admin-client/src/resources/resource.ts
Normal file
|
@ -0,0 +1,42 @@
|
|||
import type { KeycloakAdminClient } from "../client.js";
|
||||
import { Agent, RequestArgs } from "./agent.js";
|
||||
|
||||
export default class Resource<ParamType = {}> {
|
||||
private agent: Agent;
|
||||
constructor(
|
||||
client: KeycloakAdminClient,
|
||||
settings: {
|
||||
path?: string;
|
||||
getUrlParams?: () => Record<string, any>;
|
||||
getBaseUrl?: () => string;
|
||||
} = {}
|
||||
) {
|
||||
this.agent = new Agent({
|
||||
client,
|
||||
...settings,
|
||||
});
|
||||
}
|
||||
|
||||
public makeRequest = <PayloadType = any, ResponseType = any>(
|
||||
args: RequestArgs
|
||||
): ((
|
||||
payload?: PayloadType & ParamType,
|
||||
options?: Pick<RequestArgs, "catchNotFound">
|
||||
) => Promise<ResponseType>) => {
|
||||
return this.agent.request(args);
|
||||
};
|
||||
|
||||
// update request will take three types: query, payload and response
|
||||
public makeUpdateRequest = <
|
||||
QueryType = any,
|
||||
PayloadType = any,
|
||||
ResponseType = any
|
||||
>(
|
||||
args: RequestArgs
|
||||
): ((
|
||||
query: QueryType & ParamType,
|
||||
payload: PayloadType
|
||||
) => Promise<ResponseType>) => {
|
||||
return this.agent.updateRequest(args);
|
||||
};
|
||||
}
|
178
js/libs/keycloak-admin-client/src/resources/roles.ts
Normal file
178
js/libs/keycloak-admin-client/src/resources/roles.ts
Normal file
|
@ -0,0 +1,178 @@
|
|||
import Resource from "./resource.js";
|
||||
import type RoleRepresentation from "../defs/roleRepresentation.js";
|
||||
import type UserRepresentation from "../defs/userRepresentation.js";
|
||||
import type { KeycloakAdminClient } from "../client.js";
|
||||
import type { ManagementPermissionReference } from "../defs/managementPermissionReference.js";
|
||||
|
||||
export interface RoleQuery {
|
||||
first?: number;
|
||||
max?: number;
|
||||
search?: string;
|
||||
briefRepresentation?: boolean;
|
||||
}
|
||||
|
||||
export class Roles extends Resource<{ realm?: string }> {
|
||||
/**
|
||||
* Realm roles
|
||||
*/
|
||||
|
||||
public find = this.makeRequest<RoleQuery, RoleRepresentation[]>({
|
||||
method: "GET",
|
||||
path: "/roles",
|
||||
});
|
||||
|
||||
public create = this.makeRequest<RoleRepresentation, { roleName: string }>({
|
||||
method: "POST",
|
||||
path: "/roles",
|
||||
returnResourceIdInLocationHeader: { field: "roleName" },
|
||||
});
|
||||
|
||||
/**
|
||||
* Roles by name
|
||||
*/
|
||||
|
||||
public findOneByName = this.makeRequest<
|
||||
{ name: string },
|
||||
RoleRepresentation | undefined
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/roles/{name}",
|
||||
urlParamKeys: ["name"],
|
||||
catchNotFound: true,
|
||||
});
|
||||
|
||||
public updateByName = this.makeUpdateRequest<
|
||||
{ name: string },
|
||||
RoleRepresentation,
|
||||
void
|
||||
>({
|
||||
method: "PUT",
|
||||
path: "/roles/{name}",
|
||||
urlParamKeys: ["name"],
|
||||
});
|
||||
|
||||
public delByName = this.makeRequest<{ name: string }, void>({
|
||||
method: "DELETE",
|
||||
path: "/roles/{name}",
|
||||
urlParamKeys: ["name"],
|
||||
});
|
||||
|
||||
public findUsersWithRole = this.makeRequest<
|
||||
{ name: string; first?: number; max?: number },
|
||||
UserRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/roles/{name}/users",
|
||||
urlParamKeys: ["name"],
|
||||
catchNotFound: true,
|
||||
});
|
||||
|
||||
/**
|
||||
* Roles by id
|
||||
*/
|
||||
|
||||
public findOneById = this.makeRequest<
|
||||
{ id: string },
|
||||
RoleRepresentation | undefined
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/roles-by-id/{id}",
|
||||
urlParamKeys: ["id"],
|
||||
catchNotFound: true,
|
||||
});
|
||||
|
||||
public createComposite = this.makeUpdateRequest<
|
||||
{ roleId: string },
|
||||
RoleRepresentation[],
|
||||
void
|
||||
>({
|
||||
method: "POST",
|
||||
path: "/roles-by-id/{roleId}/composites",
|
||||
urlParamKeys: ["roleId"],
|
||||
});
|
||||
|
||||
public getCompositeRoles = this.makeRequest<
|
||||
{ id: string; search?: string; first?: number; max?: number },
|
||||
RoleRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/roles-by-id/{id}/composites",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public getCompositeRolesForRealm = this.makeRequest<
|
||||
{ id: string },
|
||||
RoleRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/roles-by-id/{id}/composites/realm",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public getCompositeRolesForClient = this.makeRequest<
|
||||
{ id: string; clientId: string },
|
||||
RoleRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/roles-by-id/{id}/composites/clients/{clientId}",
|
||||
urlParamKeys: ["id", "clientId"],
|
||||
});
|
||||
|
||||
public delCompositeRoles = this.makeUpdateRequest<
|
||||
{ id: string },
|
||||
RoleRepresentation[],
|
||||
void
|
||||
>({
|
||||
method: "DELETE",
|
||||
path: "/roles-by-id/{id}/composites",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public updateById = this.makeUpdateRequest<
|
||||
{ id: string },
|
||||
RoleRepresentation,
|
||||
void
|
||||
>({
|
||||
method: "PUT",
|
||||
path: "/roles-by-id/{id}",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public delById = this.makeRequest<{ id: string }, void>({
|
||||
method: "DELETE",
|
||||
path: "/roles-by-id/{id}",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
/**
|
||||
* Authorization permissions
|
||||
*/
|
||||
public updatePermission = this.makeUpdateRequest<
|
||||
{ id: string },
|
||||
ManagementPermissionReference,
|
||||
ManagementPermissionReference
|
||||
>({
|
||||
method: "PUT",
|
||||
path: "/roles-by-id/{id}/management/permissions",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public listPermissions = this.makeRequest<
|
||||
{ id: string },
|
||||
ManagementPermissionReference
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/roles-by-id/{id}/management/permissions",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
constructor(client: KeycloakAdminClient) {
|
||||
super(client, {
|
||||
path: "/admin/realms/{realm}",
|
||||
getUrlParams: () => ({
|
||||
realm: client.realmName,
|
||||
}),
|
||||
getBaseUrl: () => client.baseUrl,
|
||||
});
|
||||
}
|
||||
}
|
17
js/libs/keycloak-admin-client/src/resources/serverInfo.ts
Normal file
17
js/libs/keycloak-admin-client/src/resources/serverInfo.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import Resource from "./resource.js";
|
||||
import type { ServerInfoRepresentation } from "../defs/serverInfoRepesentation.js";
|
||||
import type KeycloakAdminClient from "../index.js";
|
||||
|
||||
export class ServerInfo extends Resource {
|
||||
constructor(client: KeycloakAdminClient) {
|
||||
super(client, {
|
||||
path: "/admin/serverinfo",
|
||||
getBaseUrl: () => client.baseUrl,
|
||||
});
|
||||
}
|
||||
|
||||
public find = this.makeRequest<{}, ServerInfoRepresentation>({
|
||||
method: "GET",
|
||||
path: "/",
|
||||
});
|
||||
}
|
18
js/libs/keycloak-admin-client/src/resources/sessions.ts
Normal file
18
js/libs/keycloak-admin-client/src/resources/sessions.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
import Resource from "./resource.js";
|
||||
import type KeycloakAdminClient from "../index.js";
|
||||
|
||||
export class Sessions extends Resource<{ realm?: string }> {
|
||||
public find = this.makeRequest<{}, Record<string, any>[]>({
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
constructor(client: KeycloakAdminClient) {
|
||||
super(client, {
|
||||
path: "/admin/realms/{realm}/client-session-stats",
|
||||
getUrlParams: () => ({
|
||||
realm: client.realmName,
|
||||
}),
|
||||
getBaseUrl: () => client.baseUrl,
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
import type { KeycloakAdminClient } from "../client.js";
|
||||
import type SynchronizationResultRepresentation from "../defs/synchronizationResultRepresentation.js";
|
||||
import Resource from "./resource.js";
|
||||
|
||||
type ActionType = "triggerFullSync" | "triggerChangedUsersSync";
|
||||
export type DirectionType = "fedToKeycloak" | "keycloakToFed";
|
||||
type NameResponse = {
|
||||
id: string;
|
||||
name: string;
|
||||
};
|
||||
|
||||
export class UserStorageProvider extends Resource<{ realm?: string }> {
|
||||
public name = this.makeRequest<{ id: string }, NameResponse>({
|
||||
method: "GET",
|
||||
path: "/{id}/name",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public removeImportedUsers = this.makeRequest<{ id: string }, void>({
|
||||
method: "POST",
|
||||
path: "/{id}/remove-imported-users",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public sync = this.makeRequest<
|
||||
{ id: string; action?: ActionType },
|
||||
SynchronizationResultRepresentation
|
||||
>({
|
||||
method: "POST",
|
||||
path: "/{id}/sync",
|
||||
urlParamKeys: ["id"],
|
||||
queryParamKeys: ["action"],
|
||||
});
|
||||
|
||||
public unlinkUsers = this.makeRequest<{ id: string }, void>({
|
||||
method: "POST",
|
||||
path: "/{id}/unlink-users",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public mappersSync = this.makeRequest<
|
||||
{ id: string; parentId: string; direction?: DirectionType },
|
||||
SynchronizationResultRepresentation
|
||||
>({
|
||||
method: "POST",
|
||||
path: "/{parentId}/mappers/{id}/sync",
|
||||
urlParamKeys: ["id", "parentId"],
|
||||
queryParamKeys: ["direction"],
|
||||
});
|
||||
|
||||
constructor(client: KeycloakAdminClient) {
|
||||
super(client, {
|
||||
path: "/admin/realms/{realm}/user-storage",
|
||||
getUrlParams: () => ({
|
||||
realm: client.realmName,
|
||||
}),
|
||||
getBaseUrl: () => client.baseUrl,
|
||||
});
|
||||
}
|
||||
}
|
497
js/libs/keycloak-admin-client/src/resources/users.ts
Normal file
497
js/libs/keycloak-admin-client/src/resources/users.ts
Normal file
|
@ -0,0 +1,497 @@
|
|||
import Resource from "./resource.js";
|
||||
import type UserRepresentation from "../defs/userRepresentation.js";
|
||||
import type UserConsentRepresentation from "../defs/userConsentRepresentation.js";
|
||||
import type UserSessionRepresentation from "../defs/userSessionRepresentation.js";
|
||||
import type { KeycloakAdminClient } from "../client.js";
|
||||
import type MappingsRepresentation from "../defs/mappingsRepresentation.js";
|
||||
import type RoleRepresentation from "../defs/roleRepresentation.js";
|
||||
import type { RoleMappingPayload } from "../defs/roleRepresentation.js";
|
||||
import type { RequiredActionAlias } from "../defs/requiredActionProviderRepresentation.js";
|
||||
import type FederatedIdentityRepresentation from "../defs/federatedIdentityRepresentation.js";
|
||||
import type GroupRepresentation from "../defs/groupRepresentation.js";
|
||||
import type CredentialRepresentation from "../defs/credentialRepresentation.js";
|
||||
import type UserProfileConfig from "../defs/userProfileConfig.js";
|
||||
|
||||
interface SearchQuery {
|
||||
search?: string;
|
||||
}
|
||||
|
||||
interface PaginationQuery {
|
||||
first?: number;
|
||||
max?: number;
|
||||
}
|
||||
|
||||
interface UserBaseQuery {
|
||||
email?: string;
|
||||
firstName?: string;
|
||||
lastName?: string;
|
||||
username?: string;
|
||||
}
|
||||
|
||||
export interface UserQuery extends PaginationQuery, SearchQuery, UserBaseQuery {
|
||||
exact?: boolean;
|
||||
[key: string]: string | number | undefined | boolean;
|
||||
}
|
||||
|
||||
export class Users extends Resource<{ realm?: string }> {
|
||||
public find = this.makeRequest<UserQuery, UserRepresentation[]>({
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
public create = this.makeRequest<UserRepresentation, { id: string }>({
|
||||
method: "POST",
|
||||
returnResourceIdInLocationHeader: { field: "id" },
|
||||
});
|
||||
|
||||
/**
|
||||
* Single user
|
||||
*/
|
||||
|
||||
public findOne = this.makeRequest<
|
||||
{ id: string },
|
||||
UserRepresentation | undefined
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{id}",
|
||||
urlParamKeys: ["id"],
|
||||
catchNotFound: true,
|
||||
});
|
||||
|
||||
public update = this.makeUpdateRequest<
|
||||
{ id: string },
|
||||
UserRepresentation,
|
||||
void
|
||||
>({
|
||||
method: "PUT",
|
||||
path: "/{id}",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public del = this.makeRequest<{ id: string }, void>({
|
||||
method: "DELETE",
|
||||
path: "/{id}",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public count = this.makeRequest<UserBaseQuery & SearchQuery, number>({
|
||||
method: "GET",
|
||||
path: "/count",
|
||||
});
|
||||
|
||||
public getProfile = this.makeRequest<{}, UserProfileConfig>({
|
||||
method: "GET",
|
||||
path: "/profile",
|
||||
});
|
||||
|
||||
public updateProfile = this.makeRequest<UserProfileConfig, UserProfileConfig>(
|
||||
{
|
||||
method: "PUT",
|
||||
path: "/profile",
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* role mappings
|
||||
*/
|
||||
|
||||
public listRoleMappings = this.makeRequest<
|
||||
{ id: string },
|
||||
MappingsRepresentation
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{id}/role-mappings",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public addRealmRoleMappings = this.makeRequest<
|
||||
{ id: string; roles: RoleMappingPayload[] },
|
||||
void
|
||||
>({
|
||||
method: "POST",
|
||||
path: "/{id}/role-mappings/realm",
|
||||
urlParamKeys: ["id"],
|
||||
payloadKey: "roles",
|
||||
});
|
||||
|
||||
public listRealmRoleMappings = this.makeRequest<
|
||||
{ id: string },
|
||||
RoleRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{id}/role-mappings/realm",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public delRealmRoleMappings = this.makeRequest<
|
||||
{ id: string; roles: RoleMappingPayload[] },
|
||||
void
|
||||
>({
|
||||
method: "DELETE",
|
||||
path: "/{id}/role-mappings/realm",
|
||||
urlParamKeys: ["id"],
|
||||
payloadKey: "roles",
|
||||
});
|
||||
|
||||
public listAvailableRealmRoleMappings = this.makeRequest<
|
||||
{ id: string },
|
||||
RoleRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{id}/role-mappings/realm/available",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
// Get effective realm-level role mappings This will recurse all composite roles to get the result.
|
||||
public listCompositeRealmRoleMappings = this.makeRequest<
|
||||
{ id: string },
|
||||
RoleRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{id}/role-mappings/realm/composite",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
/**
|
||||
* Client role mappings
|
||||
* https://www.keycloak.org/docs-api/11.0/rest-api/#_client_role_mappings_resource
|
||||
*/
|
||||
|
||||
public listClientRoleMappings = this.makeRequest<
|
||||
{ id: string; clientUniqueId: string },
|
||||
RoleRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{id}/role-mappings/clients/{clientUniqueId}",
|
||||
urlParamKeys: ["id", "clientUniqueId"],
|
||||
});
|
||||
|
||||
public addClientRoleMappings = this.makeRequest<
|
||||
{ id: string; clientUniqueId: string; roles: RoleMappingPayload[] },
|
||||
void
|
||||
>({
|
||||
method: "POST",
|
||||
path: "/{id}/role-mappings/clients/{clientUniqueId}",
|
||||
urlParamKeys: ["id", "clientUniqueId"],
|
||||
payloadKey: "roles",
|
||||
});
|
||||
|
||||
public delClientRoleMappings = this.makeRequest<
|
||||
{ id: string; clientUniqueId: string; roles: RoleMappingPayload[] },
|
||||
void
|
||||
>({
|
||||
method: "DELETE",
|
||||
path: "/{id}/role-mappings/clients/{clientUniqueId}",
|
||||
urlParamKeys: ["id", "clientUniqueId"],
|
||||
payloadKey: "roles",
|
||||
});
|
||||
|
||||
public listAvailableClientRoleMappings = this.makeRequest<
|
||||
{ id: string; clientUniqueId: string },
|
||||
RoleRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{id}/role-mappings/clients/{clientUniqueId}/available",
|
||||
urlParamKeys: ["id", "clientUniqueId"],
|
||||
});
|
||||
|
||||
public listCompositeClientRoleMappings = this.makeRequest<
|
||||
{ id: string; clientUniqueId: string },
|
||||
RoleRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{id}/role-mappings/clients/{clientUniqueId}/composite",
|
||||
urlParamKeys: ["id", "clientUniqueId"],
|
||||
});
|
||||
|
||||
/**
|
||||
* Send a update account email to the user
|
||||
* an email contains a link the user can click to perform a set of required actions.
|
||||
*/
|
||||
|
||||
public executeActionsEmail = this.makeRequest<
|
||||
{
|
||||
id: string;
|
||||
clientId?: string;
|
||||
lifespan?: number;
|
||||
redirectUri?: string;
|
||||
actions?: (RequiredActionAlias | string)[];
|
||||
},
|
||||
void
|
||||
>({
|
||||
method: "PUT",
|
||||
path: "/{id}/execute-actions-email",
|
||||
urlParamKeys: ["id"],
|
||||
payloadKey: "actions",
|
||||
queryParamKeys: ["lifespan", "redirectUri", "clientId"],
|
||||
keyTransform: {
|
||||
clientId: "client_id",
|
||||
redirectUri: "redirect_uri",
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Group
|
||||
*/
|
||||
|
||||
public listGroups = this.makeRequest<
|
||||
{ id: string; briefRepresentation?: boolean } & PaginationQuery &
|
||||
SearchQuery,
|
||||
GroupRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{id}/groups",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public addToGroup = this.makeRequest<{ id: string; groupId: string }, string>(
|
||||
{
|
||||
method: "PUT",
|
||||
path: "/{id}/groups/{groupId}",
|
||||
urlParamKeys: ["id", "groupId"],
|
||||
}
|
||||
);
|
||||
|
||||
public delFromGroup = this.makeRequest<
|
||||
{ id: string; groupId: string },
|
||||
string
|
||||
>({
|
||||
method: "DELETE",
|
||||
path: "/{id}/groups/{groupId}",
|
||||
urlParamKeys: ["id", "groupId"],
|
||||
});
|
||||
|
||||
public countGroups = this.makeRequest<
|
||||
{ id: string; search?: string },
|
||||
{ count: number }
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{id}/groups/count",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
/**
|
||||
* Federated Identity
|
||||
*/
|
||||
|
||||
public listFederatedIdentities = this.makeRequest<
|
||||
{ id: string },
|
||||
FederatedIdentityRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{id}/federated-identity",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public addToFederatedIdentity = this.makeRequest<
|
||||
{
|
||||
id: string;
|
||||
federatedIdentityId: string;
|
||||
federatedIdentity: FederatedIdentityRepresentation;
|
||||
},
|
||||
void
|
||||
>({
|
||||
method: "POST",
|
||||
path: "/{id}/federated-identity/{federatedIdentityId}",
|
||||
urlParamKeys: ["id", "federatedIdentityId"],
|
||||
payloadKey: "federatedIdentity",
|
||||
});
|
||||
|
||||
public delFromFederatedIdentity = this.makeRequest<
|
||||
{ id: string; federatedIdentityId: string },
|
||||
void
|
||||
>({
|
||||
method: "DELETE",
|
||||
path: "/{id}/federated-identity/{federatedIdentityId}",
|
||||
urlParamKeys: ["id", "federatedIdentityId"],
|
||||
});
|
||||
|
||||
/**
|
||||
* remove totp
|
||||
*/
|
||||
public removeTotp = this.makeRequest<{ id: string }, void>({
|
||||
method: "PUT",
|
||||
path: "/{id}/remove-totp",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
/**
|
||||
* reset password
|
||||
*/
|
||||
public resetPassword = this.makeRequest<
|
||||
{ id: string; credential: CredentialRepresentation },
|
||||
void
|
||||
>({
|
||||
method: "PUT",
|
||||
path: "/{id}/reset-password",
|
||||
urlParamKeys: ["id"],
|
||||
payloadKey: "credential",
|
||||
});
|
||||
|
||||
public getUserStorageCredentialTypes = this.makeRequest<
|
||||
{ id: string },
|
||||
string[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{id}/configured-user-storage-credential-types",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
/**
|
||||
* get user credentials
|
||||
*/
|
||||
public getCredentials = this.makeRequest<
|
||||
{ id: string },
|
||||
CredentialRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{id}/credentials",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
/**
|
||||
* delete user credentials
|
||||
*/
|
||||
public deleteCredential = this.makeRequest<
|
||||
{ id: string; credentialId: string },
|
||||
void
|
||||
>({
|
||||
method: "DELETE",
|
||||
path: "/{id}/credentials/{credentialId}",
|
||||
urlParamKeys: ["id", "credentialId"],
|
||||
});
|
||||
|
||||
/**
|
||||
* update a credential label for a user
|
||||
*/
|
||||
public updateCredentialLabel = this.makeUpdateRequest<
|
||||
{ id: string; credentialId: string },
|
||||
string,
|
||||
void
|
||||
>({
|
||||
method: "PUT",
|
||||
path: "/{id}/credentials/{credentialId}/userLabel",
|
||||
urlParamKeys: ["id", "credentialId"],
|
||||
headers: { "content-type": "text/plain" },
|
||||
});
|
||||
|
||||
// Move a credential to a position behind another credential
|
||||
public moveCredentialPositionDown = this.makeRequest<
|
||||
{
|
||||
id: string;
|
||||
credentialId: string;
|
||||
newPreviousCredentialId: string;
|
||||
},
|
||||
void
|
||||
>({
|
||||
method: "POST",
|
||||
path: "/{id}/credentials/{credentialId}/moveAfter/{newPreviousCredentialId}",
|
||||
urlParamKeys: ["id", "credentialId", "newPreviousCredentialId"],
|
||||
});
|
||||
|
||||
// Move a credential to a first position in the credentials list of the user
|
||||
public moveCredentialPositionUp = this.makeRequest<
|
||||
{
|
||||
id: string;
|
||||
credentialId: string;
|
||||
},
|
||||
void
|
||||
>({
|
||||
method: "POST",
|
||||
path: "/{id}/credentials/{credentialId}/moveToFirst",
|
||||
urlParamKeys: ["id", "credentialId"],
|
||||
});
|
||||
|
||||
/**
|
||||
* send verify email
|
||||
*/
|
||||
public sendVerifyEmail = this.makeRequest<
|
||||
{ id: string; clientId?: string; redirectUri?: string },
|
||||
void
|
||||
>({
|
||||
method: "PUT",
|
||||
path: "/{id}/send-verify-email",
|
||||
urlParamKeys: ["id"],
|
||||
queryParamKeys: ["clientId", "redirectUri"],
|
||||
keyTransform: {
|
||||
clientId: "client_id",
|
||||
redirectUri: "redirect_uri",
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* list user sessions
|
||||
*/
|
||||
public listSessions = this.makeRequest<
|
||||
{ id: string },
|
||||
UserSessionRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{id}/sessions",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
/**
|
||||
* list offline sessions associated with the user and client
|
||||
*/
|
||||
public listOfflineSessions = this.makeRequest<
|
||||
{ id: string; clientId: string },
|
||||
UserSessionRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{id}/offline-sessions/{clientId}",
|
||||
urlParamKeys: ["id", "clientId"],
|
||||
});
|
||||
|
||||
/**
|
||||
* logout user from all sessions
|
||||
*/
|
||||
public logout = this.makeRequest<{ id: string }, void>({
|
||||
method: "POST",
|
||||
path: "/{id}/logout",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
/**
|
||||
* list consents granted by the user
|
||||
*/
|
||||
public listConsents = this.makeRequest<
|
||||
{ id: string },
|
||||
UserConsentRepresentation[]
|
||||
>({
|
||||
method: "GET",
|
||||
path: "/{id}/consents",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
public impersonation = this.makeUpdateRequest<
|
||||
{ id: string },
|
||||
{ user: string; realm: string },
|
||||
Record<string, any>
|
||||
>({
|
||||
method: "POST",
|
||||
path: "/{id}/impersonation",
|
||||
urlParamKeys: ["id"],
|
||||
});
|
||||
|
||||
/**
|
||||
* revoke consent and offline tokens for particular client from user
|
||||
*/
|
||||
public revokeConsent = this.makeRequest<
|
||||
{ id: string; clientId: string },
|
||||
void
|
||||
>({
|
||||
method: "DELETE",
|
||||
path: "/{id}/consents/{clientId}",
|
||||
urlParamKeys: ["id", "clientId"],
|
||||
});
|
||||
|
||||
constructor(client: KeycloakAdminClient) {
|
||||
super(client, {
|
||||
path: "/admin/realms/{realm}/users",
|
||||
getUrlParams: () => ({
|
||||
realm: client.realmName,
|
||||
}),
|
||||
getBaseUrl: () => client.baseUrl,
|
||||
});
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue