From cabbe9555774b0e1a5766e731ce6f7acbc8c4556 Mon Sep 17 00:00:00 2001 From: Jon Koops Date: Fri, 8 Apr 2022 19:32:44 +0200 Subject: [PATCH] Replace development server with nightly version of Keycloak (#2395) --- README.md | 76 +- images/realm-settings.png | Bin 56926 -> 0 bytes import.mjs | 27 - package-lock.json | 805 ++++++++++++++++++ package.json | 10 +- scripts/import-client.mjs | 43 + .../security-admin-console-v2.json | 0 scripts/start-server.mjs | 87 ++ start.mjs | 123 --- 9 files changed, 989 insertions(+), 182 deletions(-) delete mode 100644 images/realm-settings.png delete mode 100755 import.mjs create mode 100755 scripts/import-client.mjs rename security-admin-console-v2.json => scripts/security-admin-console-v2.json (100%) create mode 100755 scripts/start-server.mjs delete mode 100755 start.mjs diff --git a/README.md b/README.md index ea548bc7c8..9e01e44bcf 100644 --- a/README.md +++ b/README.md @@ -1,43 +1,60 @@ -# Keycloak Admin Console V2 +# Keycloak Admin UI -This project is the next generation of the Keycloak Administration Console. It is written with React and [PatternFly 4][1]. +This project is the next generation of the Keycloak Administration UI. It is written with React and [PatternFly 4](https://www.patternfly.org/v4/). -## Development Instructions +## Development -For development on this project you will need a running Keycloak server listening on port 8180. +### Prerequisites -1. Install modules +Make sure that you have Node.js version 16 (or later) installed on your system. If you do not have Node.js installed we recommend using [Node Version Manager](https://github.com/nvm-sh/nvm) to install it. - ```bash - $> npm install - ``` +You can find out which version of Node.js you are using by running the following command: -1. Start Keycloak - * Download and run with one command +```bash +node --version +``` - ```bash - $> ./start.mjs - ``` +In order to run the Keycloak server you will also have to install the Java Development Kit (JDK). We recommend that you use the same version of the JDK as [required by the Keycloak server]((https://github.com/keycloak/keycloak/blob/main/docs/building.md#building-from-source)). - * or download Keycloak server from [keycloak downloads page][2] unpack and run it like: +### Running the Keycloak server - ```bash - $> cd /bin - $> standalone -Djboss.socket.binding.port-offset=100 - ``` +First, ensure that all dependencies are installed locally using NPM by running: -1. Go to the clients section of the existing Keycloak Admin Console and add the client - * like this: - ![realm settings](images/realm-settings.png "Realm Settings") - * or click on the "Select file" button and import `security-admin-console-v2.json` - * or run `$> ./import.mjs` +```bash +npm install +``` -1. Install dependencies and run: +After the dependencies are installed we can start the Keycloak server by running the following command: - ```bash - $> npm install - $> npm run start - ``` +```bash +npm run server:start +``` + +This will download the [Nightly version](https://github.com/keycloak/keycloak/releases/tag/nightly) of the Keycloak server and run it locally on port `8180`. If a previously downloaded version was found in the `server/` directory then that one will be used instead. If you want to download the latest Nightly version you can remove the server directory before running the command to start the server. + +In order for the development version of the Admin UI to work you will have to import a custom client to the Keycloak server. This is only required during development as the development server for the Admin UI runs on a different port (more on that later). + +Wait for the Keycloak server to be up and running and run the following command in a new terminal: + +```bash +npm run server:import-client +``` + +You'll only have to run this command once, unless you remove the server directory or Keycloak server data. + +### Running the development server + +Now that the Keycloak sever is running it's time to run the development server for the Admin UI. This server is used to build the Admin UI in a manner that it can be iterated on quickly in a browser, using features such as [Hot Module Replacement (HMR) and Fast Refresh](https://www.snowpack.dev/concepts/hot-module-replacement). + +To start the development server run the following command: + +```bash +npm run start +``` + +Once the process of optimization is done your browser will automatically open your local host on port `8080`. From here you will be redirected to the Keycloak server to authenticate, which you can do with the default username and password (`admin`). + +You can now start making changes to the source code, and they will be reflected in your browser. ## Building as a Keycloak theme @@ -159,6 +176,3 @@ Read more about [how to write tests](./cypress/WRITING_TESTS.md) ## License * [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) - -[1]: https://www.patternfly.org/v4/ -[2]: https://www.keycloak.org/downloads diff --git a/images/realm-settings.png b/images/realm-settings.png deleted file mode 100644 index ed643e3aff96ef73d9a63886f6b258dc9a403f63..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 56926 zcmeFZcT`jD*DV^mf>>S!6)B=1(k*lZR74EDBcUls?_EN*AOZp!n$mkO(o1OSiwH<3 zARR>n5;}xl&e|$|zk9|V_pdw7x#i1ns0kt2`zdS9HRoK9ucEvZ6$LE?3WcIV-@UDj zLLJzJLhaExxF23|^V@S4{@H7P3$1z(9&QI8zJTXv93<~Ks8}00I6ts6L>XIITN-lN z8`v2dTG^XeJIw5<7DJ)Vq0qN)sy>RE95B5fLg@K4XO25|u;(+yvu9jc`4`}`{C4lY z6`%V=-M?48mEDZ`eL(qR#|hGY_FncbbuEkcs6)H+pGhvsg}w7;IdtgR!_WMO&_-8h zd@A1l6I>&ULw_FGUQYh_MQE%lwti)TC{*{bq;G0BT-@)+{nHHOft@EPlvl6h!GnLF zo<7WU?(dWPm!En4ed6{0*zW)Oko^+>ul=RxM|PGC1IP6Rvk{?3t4lk%sSzaWmaiPk~fNszUdkqt_LOrc`Af zJczGa`A*5DQ(o8}{cLM%i&o67)TlWs{ZqhMjk3U6ecQcHC47#k^%YwV5U%cAz~vYF zPwd`ukt#Q`6y%81F=HIh&ZFN=;BVFPR>$M){0gUKbDWY!InwG0jHV_bu~mYv(vMs2 zA;v9mtWQ4-+$x-^;P3CqtI{enVrFGEZ;27bC5<+QleX4p!s{PqjOAztM?_>8$GF_7 z3t|k1$Nr-XSylt(^(`$5r?|CS-(E8=wCv-L7Wdrp+ZD&Wy0VhyJTutP*r>Abvxzi* zC}XKpMPXv8&$>IiWDqlyy>s1O?7T0I&3+U;gT-!Y^3A^*tmc#MSbx@#h?Bjq@_lW!lqr%eckW6jYWKbs=?9?cHJ zdfd4r?e~11toQZR&7 z8HMYgu#eI$_?KJLFSo+TGOurnos%;w7!zKA$@U8fP-_h1qObD`^M2CY(9)uT_9YDk z4_G;~hu|ZYhdlMt)6A^Id_Y_T0m(W#JRTM{$=Gs;^Qq$0=ug@6e-DB@pSy4GF zV3pO?yK{|kRyqqJyTp5g-zl;`aW@ zz9I&bonY-n#HUEyz)J@;h9nIwQ)L%9Hic&in{jt~Z}{P3s;--KZRQ#Om|zOA>lX0f0H6YuKe52)<;i=w2HX#K) z`l_^*r0Y|j?=o+>N$-hrA6pz86J@c%LTKzX@!`?>$?t>pNC+&hczp|5!c^xNxmb&MR` z-0~_Zvgr=;c6Rv;*l{KZ(UOvqrk!a@>}+gpLE>9!XRaBUeE-*1t;;_ssJoy=j3crs zWw6pU)1WR8B0xtVy$G)(QFY+aNB}pv`oYKjJr?|qGlM!X4YsD!q0B5SYUMIlcz6_o z#MaXO`RAXL)YQqoCs^5GC*z%_+96VXb9LH{blx!bKfQ9qJ`CPAz@(`;Zk0_ILN}v%E8O4nvE&4%W^4-qu$v^ zo!REXd#_vPu?v;li@9ieHz~G{M9+7M7(aviF*X$+P)$tI{kBc@lZLUr{l^=Xa_iMI z(NTkP9)qI_%A%1PS=EeJIksW~X=%wry7m+@4kYm)^RY5F_k13SmLq1|XpCTa(Y&AZ zkL_j;KJ&?RPX!B&_*hTIruO6Z@eGs46RHDEb*2k$Me5Xj@uo1Dj5(pxS7gqLAIO2g z)~R{y(R9C%($bC@21U8mX(!Z=j&OE?8oHY$pnq^nW}a6FPm$mTt2%WcPnQ

wor=IB;p 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 diff --git a/import.mjs b/import.mjs deleted file mode 100755 index 55d3f32200..0000000000 --- a/import.mjs +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env node -import { readFile } from "node:fs/promises"; -import KcAdminClient from "@keycloak/keycloak-admin-client"; - -const consoleClientConfig = JSON.parse( - await readFile(new URL("./security-admin-console-v2.json", import.meta.url)) -); - -const adminClient = new KcAdminClient.default({ - baseUrl: "http://localhost:8180", - realmName: "master", -}); - -await adminClient.auth({ - username: "admin", - password: "admin", - grantType: "password", - clientId: "admin-cli", -}); - -const adminConsoleClient = await adminClient.clients.find({ - clientId: "security-admin-console-v2", -}); - -if (adminConsoleClient.length === 0) { - adminClient.clients.create(consoleClientConfig); -} diff --git a/package-lock.json b/package-lock.json index cd7cc09754..681bbcfcc0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,6 +32,7 @@ "@cypress/webpack-batteries-included-preprocessor": "^2.2.3", "@cypress/webpack-preprocessor": "^5.11.1", "@jest/types": "^27.5.1", + "@octokit/rest": "^18.12.0", "@snowpack/app-scripts-react": "^2.0.1", "@snowpack/plugin-postcss": "^1.4.3", "@snowpack/plugin-react-refresh": "^2.5.0", @@ -43,12 +44,14 @@ "@types/dagre": "^0.7.47", "@types/file-saver": "^2.0.5", "@types/flat": "^5.0.2", + "@types/gunzip-maybe": "^1.4.0", "@types/lodash-es": "^4.17.6", "@types/node": "^17.0.23", "@types/react": "^17.0.43", "@types/react-dom": "^17.0.14", "@types/react-router-dom": "^5.3.3", "@types/snowpack-env": "^2.3.4", + "@types/tar-fs": "^2.0.1", "@typescript-eslint/eslint-plugin": "^5.17.0", "@typescript-eslint/parser": "^5.17.0", "cli-progress": "^3.10.0", @@ -63,16 +66,19 @@ "eslint-plugin-prettier": "^4.0.0", "eslint-plugin-react": "^7.29.4", "fork-ts-checker-webpack-plugin": "^7.2.3", + "gunzip-maybe": "^1.4.2", "http2-proxy": "^5.0.53", "husky": "^7.0.4", "jest": "^27.5.1", "lint-staged": "^12.3.7", + "node-fetch": "^3.2.3", "postcss": "^8.4.12", "postcss-import": "^14.1.0", "postcss-svg": "^3.0.0", "prettier": "^2.6.2", "progress-promise": "^0.0.6", "snowpack": "^3.8.6", + "tar-fs": "^2.1.1", "ts-jest": "^27.1.4", "ts-node": "^10.7.0", "typescript": "^4.6.3" @@ -3719,6 +3725,180 @@ "read-package-json-fast": "^2.0.1" } }, + "node_modules/@octokit/auth-token": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", + "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", + "dev": true, + "dependencies": { + "@octokit/types": "^6.0.3" + } + }, + "node_modules/@octokit/core": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", + "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", + "dev": true, + "dependencies": { + "@octokit/auth-token": "^2.4.4", + "@octokit/graphql": "^4.5.8", + "@octokit/request": "^5.6.3", + "@octokit/request-error": "^2.0.5", + "@octokit/types": "^6.0.3", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/endpoint": { + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", + "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", + "dev": true, + "dependencies": { + "@octokit/types": "^6.0.3", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/graphql": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", + "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", + "dev": true, + "dependencies": { + "@octokit/request": "^5.6.0", + "@octokit/types": "^6.0.3", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-11.2.0.tgz", + "integrity": "sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA==", + "dev": true + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.17.0.tgz", + "integrity": "sha512-tzMbrbnam2Mt4AhuyCHvpRkS0oZ5MvwwcQPYGtMv4tUa5kkzG58SVB0fcsLulOZQeRnOgdkZWkRUiyBlh0Bkyw==", + "dev": true, + "dependencies": { + "@octokit/types": "^6.34.0" + }, + "peerDependencies": { + "@octokit/core": ">=2" + } + }, + "node_modules/@octokit/plugin-request-log": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", + "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", + "dev": true, + "peerDependencies": { + "@octokit/core": ">=3" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.13.0.tgz", + "integrity": "sha512-uJjMTkN1KaOIgNtUPMtIXDOjx6dGYysdIFhgA52x4xSadQCz3b/zJexvITDVpANnfKPW/+E0xkOvLntqMYpviA==", + "dev": true, + "dependencies": { + "@octokit/types": "^6.34.0", + "deprecation": "^2.3.1" + }, + "peerDependencies": { + "@octokit/core": ">=3" + } + }, + "node_modules/@octokit/request": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", + "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", + "dev": true, + "dependencies": { + "@octokit/endpoint": "^6.0.1", + "@octokit/request-error": "^2.1.0", + "@octokit/types": "^6.16.1", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.7", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/request-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", + "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", + "dev": true, + "dependencies": { + "@octokit/types": "^6.0.3", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "node_modules/@octokit/request/node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/@octokit/request/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "dev": true + }, + "node_modules/@octokit/request/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", + "dev": true + }, + "node_modules/@octokit/request/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/@octokit/rest": { + "version": "18.12.0", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.12.0.tgz", + "integrity": "sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==", + "dev": true, + "dependencies": { + "@octokit/core": "^3.5.1", + "@octokit/plugin-paginate-rest": "^2.16.8", + "@octokit/plugin-request-log": "^1.0.4", + "@octokit/plugin-rest-endpoint-methods": "^5.12.0" + } + }, + "node_modules/@octokit/types": { + "version": "6.34.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.34.0.tgz", + "integrity": "sha512-s1zLBjWhdEI2zwaoSgyOFoKSl109CUcVBCc7biPJ3aAf6LGLU6szDvi31JPU7bxfla2lqfhjbbg/5DdFNxOwHw==", + "dev": true, + "dependencies": { + "@octokit/openapi-types": "^11.2.0" + } + }, "node_modules/@patternfly/patternfly": { "version": "4.185.1", "resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-4.185.1.tgz", @@ -4704,6 +4884,15 @@ "@types/node": "*" } }, + "node_modules/@types/gunzip-maybe": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@types/gunzip-maybe/-/gunzip-maybe-1.4.0.tgz", + "integrity": "sha512-dFP9GrYAR9KhsjTkWJ8q8Gsfql75YIKcg9DuQOj/IrlPzR7W+1zX+cclw1McV82UXAQ+Lpufvgk3e9bC8+HzgA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/history": { "version": "4.7.11", "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", @@ -4941,6 +5130,25 @@ "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", "dev": true }, + "node_modules/@types/tar-fs": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/tar-fs/-/tar-fs-2.0.1.tgz", + "integrity": "sha512-qlsQyIY9sN7p221xHuXKNoMfUenOcvEBN4zI8dGsYbYCqHtTarXOEXSIgUnK+GcR0fZDse6pAIc5pIrCh9NefQ==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/tar-stream": "*" + } + }, + "node_modules/@types/tar-stream": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@types/tar-stream/-/tar-stream-2.2.2.tgz", + "integrity": "sha512-1AX+Yt3icFuU6kxwmPakaiGrJUwG44MpuiqPg4dSolRFk6jmvs4b3IbUol9wKDLIgU76gevn3EwE8y/DkSJCZQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/testing-library__jest-dom": { "version": "5.14.1", "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.1.tgz", @@ -6561,6 +6769,12 @@ "tweetnacl": "^0.14.3" } }, + "node_modules/before-after-hook": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz", + "integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==", + "dev": true + }, "node_modules/big-integer": { "version": "1.6.49", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.49.tgz", @@ -8416,6 +8630,15 @@ "node": ">=0.10" } }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", + "integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, "node_modules/data-urls": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", @@ -8756,6 +8979,12 @@ "node": ">= 0.6" } }, + "node_modules/deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", + "dev": true + }, "node_modules/des.js": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", @@ -10244,6 +10473,29 @@ "integrity": "sha512-IgTtZwL52tx2wqWeuGDzXYTnNsEjNLahZpJw30hCQDyVnoHXwY5acNDnjGImTTL1R0z1PCyLw20VAbE5qLic3Q==", "dev": true }, + "node_modules/fetch-blob": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.1.5.tgz", + "integrity": "sha512-N64ZpKqoLejlrwkIAnb9iLSA3Vx/kjgzpcDhygcqJ2KKjky8nCgUQ+dzXtbrLaWZGZNmNfQTsiQ0weZ1svglHg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, "node_modules/figgy-pudding": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", @@ -10637,6 +10889,18 @@ "node": ">= 0.12" } }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dev": true, + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", @@ -11031,6 +11295,38 @@ "lodash": "^4.17.15" } }, + "node_modules/gunzip-maybe": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/gunzip-maybe/-/gunzip-maybe-1.4.2.tgz", + "integrity": "sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw==", + "dev": true, + "dependencies": { + "browserify-zlib": "^0.1.4", + "is-deflate": "^1.0.0", + "is-gzip": "^1.0.0", + "peek-stream": "^1.1.0", + "pumpify": "^1.3.3", + "through2": "^2.0.3" + }, + "bin": { + "gunzip-maybe": "bin.js" + } + }, + "node_modules/gunzip-maybe/node_modules/browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", + "dev": true, + "dependencies": { + "pako": "~0.2.0" + } + }, + "node_modules/gunzip-maybe/node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", + "dev": true + }, "node_modules/har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -11822,6 +12118,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-deflate": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-deflate/-/is-deflate-1.0.0.tgz", + "integrity": "sha1-yGKQHDwWH7CdrHzcfnhPgOmPLxQ=", + "dev": true + }, "node_modules/is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", @@ -11914,6 +12216,15 @@ "node": ">=0.10.0" } }, + "node_modules/is-gzip": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-gzip/-/is-gzip-1.0.0.tgz", + "integrity": "sha1-bKiwe5nHeZgCWQDlVc7Y7YCHmoM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-installed-globally": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", @@ -15384,6 +15695,12 @@ "node": ">=10" } }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true + }, "node_modules/mkdirp-infer-owner": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mkdirp-infer-owner/-/mkdirp-infer-owner-2.0.0.tgz", @@ -15550,6 +15867,43 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.2.3.tgz", + "integrity": "sha512-AXP18u4pidSZ1xYXRDPY/8jdv3RAozIt/WLNR/MBGZAz+xjtlr90RvCnsvHQRiXyWliZF/CpytExp32UU67/SA==", + "dev": true, + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, "node_modules/node-gyp": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-7.1.2.tgz", @@ -16523,6 +16877,17 @@ "node": ">=0.12" } }, + "node_modules/peek-stream": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/peek-stream/-/peek-stream-1.1.3.tgz", + "integrity": "sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "duplexify": "^3.5.0", + "through2": "^2.0.3" + } + }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -19746,6 +20111,65 @@ "node": ">= 10" } }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dev": true, + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-fs/node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "node_modules/tar-fs/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/tar-fs/node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/tar-stream": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", @@ -20721,6 +21145,12 @@ "imurmurhash": "^0.1.4" } }, + "node_modules/universal-user-agent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", + "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", + "dev": true + }, "node_modules/universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", @@ -21357,6 +21787,15 @@ "node": ">=0.10.0" } }, + "node_modules/web-streams-polyfill": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz", + "integrity": "sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, "node_modules/webidl-conversions": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", @@ -24564,6 +25003,163 @@ "read-package-json-fast": "^2.0.1" } }, + "@octokit/auth-token": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", + "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", + "dev": true, + "requires": { + "@octokit/types": "^6.0.3" + } + }, + "@octokit/core": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", + "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", + "dev": true, + "requires": { + "@octokit/auth-token": "^2.4.4", + "@octokit/graphql": "^4.5.8", + "@octokit/request": "^5.6.3", + "@octokit/request-error": "^2.0.5", + "@octokit/types": "^6.0.3", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/endpoint": { + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", + "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", + "dev": true, + "requires": { + "@octokit/types": "^6.0.3", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/graphql": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", + "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", + "dev": true, + "requires": { + "@octokit/request": "^5.6.0", + "@octokit/types": "^6.0.3", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/openapi-types": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-11.2.0.tgz", + "integrity": "sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA==", + "dev": true + }, + "@octokit/plugin-paginate-rest": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.17.0.tgz", + "integrity": "sha512-tzMbrbnam2Mt4AhuyCHvpRkS0oZ5MvwwcQPYGtMv4tUa5kkzG58SVB0fcsLulOZQeRnOgdkZWkRUiyBlh0Bkyw==", + "dev": true, + "requires": { + "@octokit/types": "^6.34.0" + } + }, + "@octokit/plugin-request-log": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", + "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", + "dev": true, + "requires": {} + }, + "@octokit/plugin-rest-endpoint-methods": { + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.13.0.tgz", + "integrity": "sha512-uJjMTkN1KaOIgNtUPMtIXDOjx6dGYysdIFhgA52x4xSadQCz3b/zJexvITDVpANnfKPW/+E0xkOvLntqMYpviA==", + "dev": true, + "requires": { + "@octokit/types": "^6.34.0", + "deprecation": "^2.3.1" + } + }, + "@octokit/request": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", + "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", + "dev": true, + "requires": { + "@octokit/endpoint": "^6.0.1", + "@octokit/request-error": "^2.1.0", + "@octokit/types": "^6.16.1", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.7", + "universal-user-agent": "^6.0.0" + }, + "dependencies": { + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "dev": true + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", + "dev": true + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dev": true, + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } + }, + "@octokit/request-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", + "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", + "dev": true, + "requires": { + "@octokit/types": "^6.0.3", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "@octokit/rest": { + "version": "18.12.0", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.12.0.tgz", + "integrity": "sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==", + "dev": true, + "requires": { + "@octokit/core": "^3.5.1", + "@octokit/plugin-paginate-rest": "^2.16.8", + "@octokit/plugin-request-log": "^1.0.4", + "@octokit/plugin-rest-endpoint-methods": "^5.12.0" + } + }, + "@octokit/types": { + "version": "6.34.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.34.0.tgz", + "integrity": "sha512-s1zLBjWhdEI2zwaoSgyOFoKSl109CUcVBCc7biPJ3aAf6LGLU6szDvi31JPU7bxfla2lqfhjbbg/5DdFNxOwHw==", + "dev": true, + "requires": { + "@octokit/openapi-types": "^11.2.0" + } + }, "@patternfly/patternfly": { "version": "4.185.1", "resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-4.185.1.tgz", @@ -25348,6 +25944,15 @@ "@types/node": "*" } }, + "@types/gunzip-maybe": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@types/gunzip-maybe/-/gunzip-maybe-1.4.0.tgz", + "integrity": "sha512-dFP9GrYAR9KhsjTkWJ8q8Gsfql75YIKcg9DuQOj/IrlPzR7W+1zX+cclw1McV82UXAQ+Lpufvgk3e9bC8+HzgA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/history": { "version": "4.7.11", "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", @@ -25585,6 +26190,25 @@ "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", "dev": true }, + "@types/tar-fs": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/tar-fs/-/tar-fs-2.0.1.tgz", + "integrity": "sha512-qlsQyIY9sN7p221xHuXKNoMfUenOcvEBN4zI8dGsYbYCqHtTarXOEXSIgUnK+GcR0fZDse6pAIc5pIrCh9NefQ==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/tar-stream": "*" + } + }, + "@types/tar-stream": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@types/tar-stream/-/tar-stream-2.2.2.tgz", + "integrity": "sha512-1AX+Yt3icFuU6kxwmPakaiGrJUwG44MpuiqPg4dSolRFk6jmvs4b3IbUol9wKDLIgU76gevn3EwE8y/DkSJCZQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/testing-library__jest-dom": { "version": "5.14.1", "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.1.tgz", @@ -26874,6 +27498,12 @@ "tweetnacl": "^0.14.3" } }, + "before-after-hook": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz", + "integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==", + "dev": true + }, "big-integer": { "version": "1.6.49", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.49.tgz", @@ -28342,6 +28972,12 @@ "assert-plus": "^1.0.0" } }, + "data-uri-to-buffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", + "integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==", + "dev": true + }, "data-urls": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", @@ -28605,6 +29241,12 @@ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", "dev": true }, + "deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", + "dev": true + }, "des.js": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", @@ -29769,6 +30411,16 @@ "integrity": "sha512-IgTtZwL52tx2wqWeuGDzXYTnNsEjNLahZpJw30hCQDyVnoHXwY5acNDnjGImTTL1R0z1PCyLw20VAbE5qLic3Q==", "dev": true }, + "fetch-blob": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.1.5.tgz", + "integrity": "sha512-N64ZpKqoLejlrwkIAnb9iLSA3Vx/kjgzpcDhygcqJ2KKjky8nCgUQ+dzXtbrLaWZGZNmNfQTsiQ0weZ1svglHg==", + "dev": true, + "requires": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + } + }, "figgy-pudding": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", @@ -30047,6 +30699,15 @@ "mime-types": "^2.1.12" } }, + "formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dev": true, + "requires": { + "fetch-blob": "^3.1.2" + } + }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", @@ -30361,6 +31022,37 @@ "lodash": "^4.17.15" } }, + "gunzip-maybe": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/gunzip-maybe/-/gunzip-maybe-1.4.2.tgz", + "integrity": "sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw==", + "dev": true, + "requires": { + "browserify-zlib": "^0.1.4", + "is-deflate": "^1.0.0", + "is-gzip": "^1.0.0", + "peek-stream": "^1.1.0", + "pumpify": "^1.3.3", + "through2": "^2.0.3" + }, + "dependencies": { + "browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", + "dev": true, + "requires": { + "pako": "~0.2.0" + } + }, + "pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", + "dev": true + } + } + }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -30947,6 +31639,12 @@ "has-tostringtag": "^1.0.0" } }, + "is-deflate": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-deflate/-/is-deflate-1.0.0.tgz", + "integrity": "sha1-yGKQHDwWH7CdrHzcfnhPgOmPLxQ=", + "dev": true + }, "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", @@ -31011,6 +31709,12 @@ "is-extglob": "^2.1.1" } }, + "is-gzip": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-gzip/-/is-gzip-1.0.0.tgz", + "integrity": "sha1-bKiwe5nHeZgCWQDlVc7Y7YCHmoM=", + "dev": true + }, "is-installed-globally": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", @@ -33609,6 +34313,12 @@ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true + }, "mkdirp-infer-owner": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mkdirp-infer-owner/-/mkdirp-infer-owner-2.0.0.tgz", @@ -33748,6 +34458,23 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, + "node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "dev": true + }, + "node-fetch": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.2.3.tgz", + "integrity": "sha512-AXP18u4pidSZ1xYXRDPY/8jdv3RAozIt/WLNR/MBGZAz+xjtlr90RvCnsvHQRiXyWliZF/CpytExp32UU67/SA==", + "dev": true, + "requires": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + } + }, "node-gyp": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-7.1.2.tgz", @@ -34508,6 +35235,17 @@ "sha.js": "^2.4.8" } }, + "peek-stream": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/peek-stream/-/peek-stream-1.1.3.tgz", + "integrity": "sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "duplexify": "^3.5.0", + "through2": "^2.0.3" + } + }, "pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -37020,6 +37758,61 @@ "yallist": "^4.0.0" } }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dev": true, + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + }, + "dependencies": { + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + } + } + } + }, "tar-stream": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", @@ -37740,6 +38533,12 @@ "imurmurhash": "^0.1.4" } }, + "universal-user-agent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", + "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", + "dev": true + }, "universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", @@ -38284,6 +39083,12 @@ } } }, + "web-streams-polyfill": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz", + "integrity": "sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA==", + "dev": true + }, "webidl-conversions": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", diff --git a/package.json b/package.json index 7d272deb27..3ffdef0436 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,9 @@ "test": "jest", "start:cypress": "cypress open", "start:cypress-tests": "cypress run --browser chrome", - "prepare": "husky install" + "prepare": "husky install", + "server:start": "./scripts/start-server.mjs", + "server:import-client": "./scripts/import-client.mjs" }, "dependencies": { "@keycloak/keycloak-admin-client": "^18.0.0-dev.10", @@ -48,6 +50,7 @@ "@cypress/webpack-batteries-included-preprocessor": "^2.2.3", "@cypress/webpack-preprocessor": "^5.11.1", "@jest/types": "^27.5.1", + "@octokit/rest": "^18.12.0", "@snowpack/app-scripts-react": "^2.0.1", "@snowpack/plugin-postcss": "^1.4.3", "@snowpack/plugin-react-refresh": "^2.5.0", @@ -59,12 +62,14 @@ "@types/dagre": "^0.7.47", "@types/file-saver": "^2.0.5", "@types/flat": "^5.0.2", + "@types/gunzip-maybe": "^1.4.0", "@types/lodash-es": "^4.17.6", "@types/node": "^17.0.23", "@types/react": "^17.0.43", "@types/react-dom": "^17.0.14", "@types/react-router-dom": "^5.3.3", "@types/snowpack-env": "^2.3.4", + "@types/tar-fs": "^2.0.1", "@typescript-eslint/eslint-plugin": "^5.17.0", "@typescript-eslint/parser": "^5.17.0", "cli-progress": "^3.10.0", @@ -79,16 +84,19 @@ "eslint-plugin-prettier": "^4.0.0", "eslint-plugin-react": "^7.29.4", "fork-ts-checker-webpack-plugin": "^7.2.3", + "gunzip-maybe": "^1.4.2", "http2-proxy": "^5.0.53", "husky": "^7.0.4", "jest": "^27.5.1", "lint-staged": "^12.3.7", + "node-fetch": "^3.2.3", "postcss": "^8.4.12", "postcss-import": "^14.1.0", "postcss-svg": "^3.0.0", "prettier": "^2.6.2", "progress-promise": "^0.0.6", "snowpack": "^3.8.6", + "tar-fs": "^2.1.1", "ts-jest": "^27.1.4", "ts-node": "^10.7.0", "typescript": "^4.6.3" diff --git a/scripts/import-client.mjs b/scripts/import-client.mjs new file mode 100755 index 0000000000..e888eda72b --- /dev/null +++ b/scripts/import-client.mjs @@ -0,0 +1,43 @@ +#!/usr/bin/env node +import KcAdminClient from "@keycloak/keycloak-admin-client"; +import { readFile } from "node:fs/promises"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const DIR_NAME = path.dirname(fileURLToPath(import.meta.url)); +const ADMIN_USERNAME = "admin"; +const ADMIN_PASSWORD = "admin"; + +await importClient(); + +async function importClient() { + const adminClient = new KcAdminClient.default({ + baseUrl: "http://localhost:8180", + realmName: "master", + }); + + await adminClient.auth({ + username: ADMIN_USERNAME, + password: ADMIN_PASSWORD, + grantType: "password", + clientId: "admin-cli", + }); + + const adminConsoleClient = await adminClient.clients.find({ + clientId: "security-admin-console-v2", + }); + + if (adminConsoleClient.length > 0) { + console.info("Client already exists, skipping import."); + return; + } + + console.info("Importing client…"); + + const configPath = path.join(DIR_NAME, "security-admin-console-v2.json"); + const config = JSON.parse(await readFile(configPath, "utf-8")); + + await adminClient.clients.create(config); + + console.info("Client imported successfully."); +} diff --git a/security-admin-console-v2.json b/scripts/security-admin-console-v2.json similarity index 100% rename from security-admin-console-v2.json rename to scripts/security-admin-console-v2.json diff --git a/scripts/start-server.mjs b/scripts/start-server.mjs new file mode 100755 index 0000000000..bd84261950 --- /dev/null +++ b/scripts/start-server.mjs @@ -0,0 +1,87 @@ +#!/usr/bin/env node +// @ts-check +import { Octokit } from "@octokit/rest"; +import gunzip from "gunzip-maybe"; +import fetch from "node-fetch"; +import { spawn } from "node:child_process"; +import fs from "node:fs"; +import path from "node:path"; +import { pipeline } from "node:stream/promises"; +import { fileURLToPath } from "node:url"; +import tar from "tar-fs"; + +const DIR_NAME = path.dirname(fileURLToPath(import.meta.url)); +const SERVER_DIR = path.resolve(DIR_NAME, "../server"); +const SCRIPT_EXTENSION = process.platform === "win32" ? ".bat" : ".sh"; + +await startServer(); + +async function startServer() { + await downloadServer(); + + console.info("Starting server…"); + + const args = process.argv.slice(2); + const child = spawn( + path.join(SERVER_DIR, `bin/kc${SCRIPT_EXTENSION}`), + [ + "start-dev", + "--http-port=8180", + "--features=admin2,admin-fine-grained-authz,declarative-user-profile", + ...args, + ], + { + env: { + KEYCLOAK_ADMIN: "admin", + KEYCLOAK_ADMIN_PASSWORD: "admin", + ...process.env, + }, + } + ); + + child.stdout.pipe(process.stdout); + child.stderr.pipe(process.stderr); +} + +async function downloadServer() { + const directoryExists = fs.existsSync(SERVER_DIR); + + if (directoryExists) { + console.info("Server installation found, skipping download."); + return; + } + + console.info("Downloading and extracting server…"); + + const nightlyAsset = await getNightlyAsset(); + const assetStream = await getAssetAsStream(nightlyAsset); + + await extractTarball(assetStream, SERVER_DIR, { strip: 1 }); +} + +async function getNightlyAsset() { + const api = new Octokit(); + const release = await api.repos.getReleaseByTag({ + owner: "keycloak", + repo: "keycloak", + tag: "nightly", + }); + + return release.data.assets.find( + ({ name }) => name === "keycloak-999-SNAPSHOT.tar.gz" + ); +} + +async function getAssetAsStream(asset) { + const response = await fetch(asset.browser_download_url); + + if (!response.ok) { + throw new Error("Something went wrong requesting the nightly release."); + } + + return response.body; +} + +function extractTarball(stream, path, options) { + return pipeline(stream, gunzip(), tar.extract(path, options)); +} diff --git a/start.mjs b/start.mjs deleted file mode 100755 index d0dc61c992..0000000000 --- a/start.mjs +++ /dev/null @@ -1,123 +0,0 @@ -#!/usr/bin/env node -import http from "node:https"; -import fs from "node:fs"; -import path from "node:path"; -import { spawn } from "node:child_process"; - -import decompress from "decompress"; - -import ProgressPromise from "progress-promise"; -import cliProgress from "cli-progress"; -import colors from "colors"; - -const args = process.argv.slice(2); -const version = args[0] && !args[0].startsWith("-") ? args[0] : "17.0.0"; - -const folder = "server"; -const fileName = path.join(folder, `keycloak-${version}.tar.gz`); -const serverPath = path.join(folder, `keycloak-${version}`); -const extension = process.platform === "win32" ? ".bat" : ".sh"; - -if (!fs.existsSync(folder)) { - fs.mkdirSync(folder); -} - -const progressTick = () => { - return new ProgressPromise((resolve, _, progress) => { - for (let i = 0; i < 10; i++) { - setTimeout(() => progress(i * 10), i * 1500); - } - setTimeout(resolve, 15000); - }); -}; - -async function decompressKeycloak() { - try { - const progressBar = new cliProgress.Bar({ - format: - "Decompress |" + - colors.cyan("{bar}") + - "| {percentage}% || ETA: {eta}s ", - barCompleteChar: "\u2588", - barIncompleteChar: "\u2591", - }); - progressBar.start(100); - await Promise.all([ - decompress(fileName, folder), - progressTick() - .progress((value) => progressBar.update(value)) - .then(() => { - progressBar.update(100); - progressBar.stop(); - console.log("\nFiles decompressed"); - }), - ]); - } catch (error) { - console.error(error); - } -} - -const run = () => { - const proc = spawn( - path.join(serverPath, "bin", `kc${extension}`), - [ - "start-dev", - "--http-port=8180", - "--features=admin2,admin-fine-grained-authz,declarative-user-profile", - ...args, - ], - { - env: { - KEYCLOAK_ADMIN: "admin", - KEYCLOAK_ADMIN_PASSWORD: "admin", - }, - } - ); - proc.stdout.on("data", (data) => { - console.log(data.toString()); - }); -}; - -const request = (url, file, progressBar) => { - http.get(url, (response) => { - if (response.statusCode === 302) { - request(response.headers.location, file, progressBar); - } else if (response.statusCode === 404) { - throw new Error(`version not found '${version}'`); - } else { - let data = 0; - progressBar.start(parseInt(response.headers["content-length"]), 0); - response.pipe(file); - response.on("data", (chunk) => { - progressBar.update(data); - data += chunk.length; - }); - response.on("end", () => { - console.log("\nDownloaded keycloak"); - decompressKeycloak().then(() => run()); - }); - } - }); -}; - -if (!fs.existsSync(fileName)) { - const file = fs.createWriteStream(fileName); - const progressBar = new cliProgress.Bar({ - format: - "Download |" + - colors.cyan("{bar}") + - "| {percentage}% || {value}/{total} Chunks", - barCompleteChar: "\u2588", - barIncompleteChar: "\u2591", - }); - - request( - `https://github.com/keycloak/keycloak/releases/download/${version}/keycloak-${version}.tar.gz`, - file, - progressBar - ); -} else if (!fs.existsSync(serverPath)) { - decompressKeycloak().then(() => run()); -} else { - run(); -}